前回の記事「WeChat開発 – WeChat開発環(huán)境構(gòu)築」でWeChat開発の準(zhǔn)備作業(yè)が完了しましたので、準(zhǔn)備作業(yè)が完了したらいよいよ作業(yè)に入ります。
1. WeChat パブリック プラットフォームの基本原則
始める前に、WeChat パブリック プラットフォームの基本原則を簡(jiǎn)単に紹介しましょう。
WeChatサーバーは転送サーバーに相當(dāng)します。端末(攜帯電話、Padなど)はWeChatサーバーへのリクエストを開始し、WeChatサーバーはそのリクエストをアプリケーションサーバーに転送します。アプリケーション サーバーは処理を完了した後、応答データを WeChat サーバーに送り返し、WeChat サーバーは特定の応答情報(bào)を WeChat アプリ端末に返信します。
通信プロトコルはHTTPです
データ送信形式はXMLです
具體的なプロセスは以下の図に示されています:
より直感的に見てみましょう:
必要なことこれは、WeChat サーバーによって転送された HTTP リクエストに応答することです。特定のリクエストのコンテンツを特定の XML 形式に従って解析し、処理後、それを特定の XML 形式に従って返す必要があります。
2. WeChat パブリック アカウントへのアクセス
WeChat パブリック プラットフォーム開発者ドキュメントのアクセス ガイドに、パブリック アカウントへのアクセスに関するセクションが詳しく記載されています。その手順は次のとおりです。 :
1. サーバー構(gòu)成を入力します
2. サーバーアドレスの有効性を検証します
3. インターフェースドキュメントに基づいてビジネスロジックを?qū)g裝します
実際、3 番目のステップは、もはや接続のステップとみなすことができません公開アカウントですが、アクセス後、開発者は WeChat 公式アカウントが提供するインターフェースに基づいて開発を行うことができます。
ステップ1のサーバー設(shè)定には、サーバーアドレス(URL)、トークン、EncodingAESKeyが含まれます。
サーバーアドレスは、公式アカウントのバックエンドが提供するビジネスロジックのエントリアドレスです。現(xiàn)在、ポート80のみをサポートしています。將來(lái)的には、アクセス認(rèn)証やその他の操作(メッセージ送信、メニュー管理など)を含むリクエストもサポートされます。 、素材管理など)は必ずこちらから アドレスを入力してください。アクセス検証と他のリクエストの違いは、アクセス検証が get リクエストである場(chǎng)合と、post リクエストである場(chǎng)合があります
トークンは開発者が任意に入力でき、署名の生成に使用されます (トークンはインターフェイス URL に含まれるトークン セキュリティを検証するための比較);
EncodingAESKey は開発者によって手動(dòng)で入力されるか、ランダムに生成され、メッセージ本文の暗號(hào)化キーと復(fù)號(hào)化キーとして使用されます。 この例では、すべてのメッセージは暗號(hào)化されていないプレーン テキストであり、この構(gòu)成項(xiàng)目は関係しません。
ステップ 2、サーバー アドレスの有効性を確認(rèn)します?!杆托拧攻堀骏螭颔辚氓工毪?、WeChat サーバーは、入力したサーバー アドレスに http get リクエストを送信し、次の 4 つのパラメーターを送信します。
リクエストを受信後、以下の3ステップを行う必要があり、GETリクエストがWeChatサーバーから來(lái)ていることが確認(rèn)され、echostrパラメータの內(nèi)容がそのまま返された場(chǎng)合はアクセスが有効となり、それ以外の場(chǎng)合はアクセスが無(wú)効になります。失敗。 1. 3つのパラメータのトークン、タイムスタンプ、nonceを辭書編集順に並べ替えます 2. 3つのパラメータ文字列をsha1暗號(hào)化用の1つの文字列に結(jié)合します
IDE (Eclipse または IntelliJ IDEA) を使用して JavaWeb プロジェクトを作成します。 ここでは IntelliJ IDEA を使用します。 プロジェクトのディレクトリ構(gòu)造は次のとおりです。 servlevt を取得し、doGet メソッドで検証メソッドを定義します。具體的なコードは次のとおりです。
package me.gacl.wx.web.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; /** * Created by xdp on 2016/1/25. * 使用@WebServlet注解配置WxServlet,urlPatterns屬性指明了WxServlet的訪問(wèn)路徑 */ @WebServlet(urlPatterns="/WxServlet") public class WxServlet extends HttpServlet { /** * Token可由開發(fā)者可以任意填寫,用作生成簽名(該Token會(huì)和接口URL中包含的Token進(jìn)行比對(duì),從而驗(yàn)證安全性) * 比如這里我將Token設(shè)置為gacl */ private final String TOKEN = "gacl"; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("開始校驗(yàn)簽名"); /** * 接收微信服務(wù)器發(fā)送請(qǐng)求時(shí)傳遞過(guò)來(lái)的4個(gè)參數(shù) */ String signature = request.getParameter("signature");//微信加密簽名signature結(jié)合了開發(fā)者填寫的token參數(shù)和請(qǐng)求中的timestamp參數(shù)、nonce參數(shù)。 String timestamp = request.getParameter("timestamp");//時(shí)間戳 String nonce = request.getParameter("nonce");//隨機(jī)數(shù) String echostr = request.getParameter("echostr");//隨機(jī)字符串 //排序 String sortString = sort(TOKEN, timestamp, nonce); //加密 String mySignature = sha1(sortString); //校驗(yàn)簽名 if (mySignature != null && mySignature != "" && mySignature.equals(signature)) { System.out.println("簽名校驗(yàn)通過(guò)。"); //如果檢驗(yàn)成功輸出echostr,微信服務(wù)器接收到此輸出,才會(huì)確認(rèn)檢驗(yàn)完成。 //response.getWriter().println(echostr); response.getWriter().write(echostr); } else { System.out.println("簽名校驗(yàn)失敗."); } } /** * 排序方法 * * @param token * @param timestamp * @param nonce * @return */ public String sort(String token, String timestamp, String nonce) { String[] strArray = {token, timestamp, nonce}; Arrays.sort(strArray); StringBuilder sb = new StringBuilder(); for (String str : strArray) { sb.append(str); } return sb.toString(); } /** * 將字符串進(jìn)行sha1加密 * * @param str 需要加密的字符串 * @return 加密后的內(nèi)容 */ public String sha1(String str) { try { MessageDigest digest = MessageDigest.getInstance("SHA-1"); digest.update(str.getBytes()); byte messageDigest[] = digest.digest(); // Create Hex String StringBuffer hexString = new StringBuffer(); // 字節(jié)數(shù)組轉(zhuǎn)換為 十六進(jìn)制 數(shù) for (int i = 0; i < messageDigest.length; i++) { String shaHex = Integer.toHexString(messageDigest[i] & 0xFF); if (shaHex.length() < 2) { hexString.append(0); } hexString.append(shaHex); } return hexString.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return ""; } }ここで使用する Servlet3.0 を使用する利點(diǎn)は、
@WebServlet
アノテーション Mapping を直接使用できることです。サーブレットのアクセス パスを Web で設(shè)定する必要はなくなりました。ブログ「WeChat 開発 - WeChat 開発環(huán)境の構(gòu)築」を參照してください。下の寫真に示すように:測(cè)試是否可以通過(guò)http://xdp.ngrok.natapp.cn地址正常訪問(wèn),測(cè)試結(jié)果如下:
可以看到,我們的項(xiàng)目已經(jīng)可以被外網(wǎng)正常訪問(wèn)到了。
進(jìn)入微信測(cè)試公眾號(hào)管理界面,在接口配置信息中填入映射的外網(wǎng)地址和token,如下圖所示:
點(diǎn)擊提交按鈕,頁(yè)面會(huì)提示配置成功,
IDE的控制臺(tái)中輸出了校驗(yàn)通過(guò)的信息,如下圖所示:
到此,我們的公眾號(hào)應(yīng)用已經(jīng)能夠和微信服務(wù)器正常通信了,也就是說(shuō)我們的公眾號(hào)已經(jīng)接入到微信公眾平臺(tái)了。
三、access_token管理
3.1、access_token介紹
我們的公眾號(hào)和微信服務(wù)器對(duì)接成功之后,接下來(lái)要做的就是根據(jù)我們的業(yè)務(wù)需求調(diào)用微信公眾號(hào)提供的接口來(lái)實(shí)現(xiàn)相應(yīng)的邏輯了。在使用微信公眾號(hào)接口中都需要一個(gè)access_token。
關(guān)于access_token,在微信公眾平臺(tái)開發(fā)者文檔上的獲取接口調(diào)用憑據(jù)有比較詳細(xì)的介紹:access_token是公眾號(hào)的全局唯一票據(jù),公眾號(hào)調(diào)用各接口時(shí)都需使用access_token,開發(fā)者需要妥善保存access_token的存儲(chǔ)至少要保留512個(gè)字符空間。access_token的有效期目前為2個(gè)小時(shí),需定時(shí)刷新,重復(fù)獲取將導(dǎo)致上次獲取的access_token失效。并且每天調(diào)用獲取access_token接口的上限是2000次。
總結(jié)以上說(shuō)明,access_token需要做到以下兩點(diǎn):
1.因?yàn)閍ccess_token有2個(gè)小時(shí)的時(shí)效性,要有一個(gè)機(jī)制保證最長(zhǎng)2個(gè)小時(shí)重新獲取一次。
2.因?yàn)榻涌谡{(diào)用上限每天2000次,所以不能調(diào)用太頻繁。
3.2、微信公眾平臺(tái)提供的獲取access_token的接口
關(guān)于access_token的獲取方式,在微信公眾平臺(tái)開發(fā)者文檔上有說(shuō)明,公眾號(hào)可以調(diào)用一個(gè)叫"獲取access token"的接口來(lái)獲取access_token。
獲取access token接口調(diào)用請(qǐng)求說(shuō)明
http請(qǐng)求方式: GET
請(qǐng)求的URL地址:https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
我們可以看到,調(diào)用過(guò)程中需要傳遞appID和AppSecret,appID和AppSecret是在申請(qǐng)公眾號(hào)的時(shí)候自動(dòng)分配給公眾號(hào)的,相當(dāng)于公眾號(hào)的身份標(biāo)示,使用微信公眾號(hào)的注冊(cè)帳號(hào)登錄到騰訊提供的微信公眾號(hào)管理后臺(tái)就可以看到自己申請(qǐng)的公眾號(hào)的AppID和AppSecret,如下圖所示:
這是我申請(qǐng)公眾號(hào)測(cè)試帳號(hào)時(shí)分配到的AppID和AppSecret。
3.3、獲取access_token方案以及具體實(shí)現(xiàn)
這里采用的方案是這樣的,定義一個(gè)默認(rèn)啟動(dòng)的servlet,在init方法中啟動(dòng)一個(gè)Thread,這個(gè)進(jìn)程中定義一個(gè)無(wú)限循環(huán)的方法,用來(lái)獲取access_token,當(dāng)獲取成功后,此進(jìn)程休眠7000秒(7000秒=1.944444444444444小時(shí)),否則休眠3秒鐘繼續(xù)獲取。流程圖如下:
下面正式開始在工程中實(shí)現(xiàn)以上思路,因?yàn)榉祷氐臄?shù)據(jù)都是json格式,這里會(huì)用到阿里的fastjson庫(kù),為構(gòu)造請(qǐng)求和處理請(qǐng)求后的數(shù)據(jù)序列化和反序列化提供支持。
1.定義一個(gè)AccessToken實(shí)體類
package me.gacl.wx.entry; /** * AccessToken的數(shù)據(jù)模型 * Created by xdp on 2016/1/25. */ public class AccessToken { //獲取到的憑證 private String accessToken; //憑證有效時(shí)間,單位:秒 private int expiresin; public String getAccessToken() { return accessToken; } public void setAccessToken(String accessToken) { this.accessToken = accessToken; } public int getExpiresin() { return expiresin; } public void setExpiresin(int expiresin) { this.expiresin = expiresin; } }
2.定義一個(gè)AccessTokenInfo類,用于存放獲取到的AccessToken,代碼如下:
package me.gacl.wx.Common; import me.gacl.wx.entry.AccessToken; /** * Created by xdp on 2016/1/25. */ public class AccessTokenInfo { //注意是靜態(tài)的 public static AccessToken accessToken = null; }
3.編寫一個(gè)用于發(fā)起https請(qǐng)求的工具類NetWorkHelper,代碼如下:
package me.gacl.wx.util; import javax.net.ssl.*; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; /** * 訪問(wèn)網(wǎng)絡(luò)用到的工具類 */ public class NetWorkHelper { /** * 發(fā)起Https請(qǐng)求 * @param reqUrl 請(qǐng)求的URL地址 * @param requestMethod * @return 響應(yīng)后的字符串 */ public String getHttpsResponse(String reqUrl, String requestMethod) { URL url; InputStream is; String resultData = ""; try { url = new URL(reqUrl); HttpsURLConnection con = (HttpsURLConnection) url.openConnection(); TrustManager[] tm = {xtm}; SSLContext ctx = SSLContext.getInstance("TLS"); ctx.init(null, tm, null); con.setSSLSocketFactory(ctx.getSocketFactory()); con.setHostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String arg0, SSLSession arg1) { return true; } }); con.setDoInput(true); //允許輸入流,即允許下載 //在android中必須將此項(xiàng)設(shè)置為false con.setDoOutput(false); //允許輸出流,即允許上傳 con.setUseCaches(false); //不使用緩沖 if (null != requestMethod && !requestMethod.equals("")) { con.setRequestMethod(requestMethod); //使用指定的方式 } else { con.setRequestMethod("GET"); //使用get請(qǐng)求 } is = con.getInputStream(); //獲取輸入流,此時(shí)才真正建立鏈接 InputStreamReader isr = new InputStreamReader(is); BufferedReader bufferReader = new BufferedReader(isr); String inputLine; while ((inputLine = bufferReader.readLine()) != null) { resultData += inputLine + "\n"; } System.out.println(resultData); } catch (Exception e) { e.printStackTrace(); } return resultData; } X509TrustManager xtm = new X509TrustManager() { @Override public X509Certificate[] getAcceptedIssuers() { return null; } @Override public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { } @Override public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { } }; }
getHttpsResponse方法是請(qǐng)求一個(gè)https地址,參數(shù)requestMethod為字符串“GET”或者“POST”,傳null或者“”默認(rèn)為get方式。
4.定義一個(gè)默認(rèn)啟動(dòng)的servlet,在init方法中啟動(dòng)一個(gè)新的線程去獲取accessToken
package me.gacl.wx.web.servlet; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import me.gacl.wx.Common.AccessTokenInfo; import me.gacl.wx.entry.AccessToken; import me.gacl.wx.util.NetWorkHelper; import javax.servlet.ServletException; import javax.servlet.annotation.WebInitParam; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; /** * 用于獲取accessToken的Servlet * Created by xdp on 2016/1/25. */ @WebServlet( name = "AccessTokenServlet", urlPatterns = {"/AccessTokenServlet"}, loadOnStartup = 1, initParams = { @WebInitParam(name = "appId", value = "wxbe4d433e857e8bb1"), @WebInitParam(name = "appSecret", value = "ccbc82d560876711027b3d43a6f2ebda") }) public class AccessTokenServlet extends HttpServlet { @Override public void init() throws ServletException { System.out.println("啟動(dòng)WebServlet"); super.init(); final String appId = getInitParameter("appId"); final String appSecret = getInitParameter("appSecret"); //開啟一個(gè)新的線程 new Thread(new Runnable() { @Override public void run() { while (true) { try { //獲取accessToken AccessTokenInfo.accessToken = getAccessToken(appId, appSecret); //獲取成功 if (AccessTokenInfo.accessToken != null) { //獲取到access_token 休眠7000秒,大約2個(gè)小時(shí)左右 Thread.sleep(7000 * 1000); //Thread.sleep(10 * 1000);//10秒鐘獲取一次 } else { //獲取失敗 Thread.sleep(1000 * 3); //獲取的access_token為空 休眠3秒 } } catch (Exception e) { System.out.println("發(fā)生異常:" + e.getMessage()); e.printStackTrace(); try { Thread.sleep(1000 * 10); //發(fā)生異常休眠1秒 } catch (Exception e1) { } } } } }).start(); } /** * 獲取access_token * * @return AccessToken */ private AccessToken getAccessToken(String appId, String appSecret) { NetWorkHelper netHelper = new NetWorkHelper(); /** * 接口地址為https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET,其中g(shù)rant_type固定寫為client_credential即可。 */ String Url = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", appId, appSecret); //此請(qǐng)求為https的get請(qǐng)求,返回的數(shù)據(jù)格式為{"access_token":"ACCESS_TOKEN","expires_in":7200} String result = netHelper.getHttpsResponse(Url, ""); System.out.println("獲取到的access_token="+result); //使用FastJson將Json字符串解析成Json對(duì)象 JSONObject json = JSON.parseObject(result); AccessToken token = new AccessToken(); token.setAccessToken(json.getString("access_token")); token.setExpiresin(json.getInteger("expires_in")); return token; } }
AccessTokenServlet采用注解的方式進(jìn)行配置
至此代碼實(shí)現(xiàn)完畢,將項(xiàng)目部署,看到控制臺(tái)輸出如下:
為了方便看效果,可以把休眠時(shí)間設(shè)置短一點(diǎn),比如10秒獲取一次,然后將access_token輸出。
下面做一個(gè)測(cè)試jsp頁(yè)面,并把休眠時(shí)間設(shè)置為10秒,這樣過(guò)10秒刷新頁(yè)面,就可以看到變化
<%-- Created by IntelliJ IDEA. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ page import="me.gacl.wx.Common.AccessTokenInfo"%> <html> <head> <title></title> </head> <body> 微信學(xué)習(xí) <hr/> access_token為:<%=AccessTokenInfo.accessToken.getAccessToken()%> </body> </html>
10秒鐘后刷新頁(yè)面,access_token變了,如下圖所示:
四、接收微信服務(wù)器發(fā)送的消息并做出響應(yīng)
經(jīng)過(guò)上述的三步,我們開發(fā)前的準(zhǔn)備工作已經(jīng)完成了,接下來(lái)要做的就是接收微信服務(wù)器發(fā)送的消息并做出響應(yīng)
從微信公眾平臺(tái)接口消息指南中可以了解到,當(dāng)用戶向公眾帳號(hào)發(fā)消息時(shí),微信服務(wù)器會(huì)將消息通過(guò)POST方式提交給我們?cè)诮涌谂渲眯畔⒅刑顚懙腢RL,而我們就需要在URL所指向的請(qǐng)求處理類WxServlet的doPost方法中接收消息、處理消息和響應(yīng)消息。
4.1.編寫一個(gè)用于處理消息的工具類
編寫處理消息的工具欄,工具類代碼如下:
package me.gacl.wx.util; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; import javax.servlet.http.HttpServletRequest; import java.io.InputStream; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 消息處理工具類 * Created by xdp on 2016/1/26. */ public class MessageHandlerUtil { /** * 解析微信發(fā)來(lái)的請(qǐng)求(XML) * @param request * @return map * @throws Exception */ public static Map<String,String> parseXml(HttpServletRequest request) throws Exception { // 將解析結(jié)果存儲(chǔ)在HashMap中 Map<String,String> map = new HashMap(); // 從request中取得輸入流 InputStream inputStream = request.getInputStream(); System.out.println("獲取輸入流"); // 讀取輸入流 SAXReader reader = new SAXReader(); Document document = reader.read(inputStream); // 得到xml根元素 Element root = document.getRootElement(); // 得到根元素的所有子節(jié)點(diǎn) List<Element> elementList = root.elements(); // 遍歷所有子節(jié)點(diǎn) for (Element e : elementList) { System.out.println(e.getName() + "|" + e.getText()); map.put(e.getName(), e.getText()); } // 釋放資源 inputStream.close(); inputStream = null; return map; } // 根據(jù)消息類型 構(gòu)造返回消息 public static String buildXml(Map<String,String> map) { String result; String msgType = map.get("MsgType").toString(); System.out.println("MsgType:" + msgType); if(msgType.toUpperCase().equals("TEXT")){ result = buildTextMessage(map, "孤傲蒼狼在學(xué)習(xí)和總結(jié)微信開發(fā)了,構(gòu)建一條文本消息:Hello World!"); }else{ String fromUserName = map.get("FromUserName"); // 開發(fā)者微信號(hào) String toUserName = map.get("ToUserName"); result = String .format( "<xml>" + "<ToUserName><![CDATA[%s]]></ToUserName>" + "<FromUserName><![CDATA[%s]]></FromUserName>" + "<CreateTime>%s</CreateTime>" + "<MsgType><![CDATA[text]]></MsgType>" + "<Content><![CDATA[%s]]></Content>" + "</xml>", fromUserName, toUserName, getUtcTime(), "請(qǐng)回復(fù)如下關(guān)鍵詞:\n文本\n圖片\n語(yǔ)音\n視頻\n音樂(lè)\n圖文"); } return result; } /** * 構(gòu)造文本消息 * * @param map * @param content * @return */ private static String buildTextMessage(Map<String,String> map, String content) { //發(fā)送方帳號(hào) String fromUserName = map.get("FromUserName"); // 開發(fā)者微信號(hào) String toUserName = map.get("ToUserName"); /** * 文本消息XML數(shù)據(jù)格式 * <xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>1348831860</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[this is a test]]></Content> <MsgId>1234567890123456</MsgId> </xml> */ return String.format( "<xml>" + "<ToUserName><![CDATA[%s]]></ToUserName>" + "<FromUserName><![CDATA[%s]]></FromUserName>" + "<CreateTime>%s</CreateTime>" + "<MsgType><![CDATA[text]]></MsgType>" + "<Content><![CDATA[%s]]></Content>" + "</xml>", fromUserName, toUserName, getUtcTime(), content); } private static String getUtcTime() { Date dt = new Date();// 如果不需要格式,可直接用dt,dt就是當(dāng)前系統(tǒng)時(shí)間 DateFormat df = new SimpleDateFormat("yyyyMMddhhmm");// 設(shè)置顯示格式 String nowTime = df.format(dt); long dd = (long) 0; try { dd = df.parse(nowTime).getTime(); } catch (Exception e) { } return String.valueOf(dd); } }
為了方便解析微信服務(wù)器發(fā)送給我們的xml格式的數(shù)據(jù),這里我們借助于開源框架dom4j去解析xml(這里使用的是dom4j-2.0.0-RC1.jar)
4.2.在WxServlet的doPost方法中處理請(qǐng)求
WxServlet的doPost方法的代碼如下:
/** * 處理微信服務(wù)器發(fā)來(lái)的消息 */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO 接收、處理、響應(yīng)由微信服務(wù)器轉(zhuǎn)發(fā)的用戶發(fā)送給公眾帳號(hào)的消息 // 將請(qǐng)求、響應(yīng)的編碼均設(shè)置為UTF-8(防止中文亂碼) request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); System.out.println("請(qǐng)求進(jìn)入"); String result = ""; try { Map<String,String> map = MessageHandlerUtil.parseXml(request); System.out.println("開始構(gòu)造消息"); result = MessageHandlerUtil.buildXml(map); System.out.println(result); if(result.equals("")){ result = "未正確響應(yīng)"; } } catch (Exception e) { e.printStackTrace(); System.out.println("發(fā)生異常:"+ e.getMessage()); } response.getWriter().println(result); }
到此,我們的WxServlet已經(jīng)可以正常處理用戶的請(qǐng)求并做出響應(yīng)了.接下來(lái)我們測(cè)試一下我們開發(fā)好的公眾號(hào)應(yīng)用是否可以正常和微信用戶交互
將WxStudy部署到Tomcat服務(wù)器,啟動(dòng)服務(wù)器,記得使用ngrok將本地Tomcat服務(wù)器的8080端口映射到外網(wǎng),保證接口配置信息的URL地址:http://xdp.ngrok.natapp.cn/WxServlet可以正常與微信服務(wù)器通信
登錄到我們的測(cè)試公眾號(hào)的管理后臺(tái),然后用微信掃描一下測(cè)試號(hào)的二維碼,如下圖所示:
關(guān)注成功后,我們開發(fā)好的公眾號(hào)應(yīng)用會(huì)先給用戶發(fā)一條提示用戶操作的文本消息,微信用戶根據(jù)提示操作輸入"文本",我們的公眾號(hào)應(yīng)用接收到用戶請(qǐng)求后就給用戶回復(fù)了一條我們自己構(gòu)建好的文本消息,如下圖所示:
我們的公眾號(hào)應(yīng)用響應(yīng)給微信用戶的文本消息的XML數(shù)據(jù)如下:
<xml> <ToUserName><![CDATA[ojADgs0eDaqh7XkTM9GvDmdYPoDw]]></ToUserName> <FromUserName><![CDATA[gh_43df3882c452]]></FromUserName> <CreateTime>1453755900000</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[孤傲蒼狼在學(xué)習(xí)和總結(jié)微信開發(fā)了,構(gòu)建一條文本消息:Hello World!]]></Content> </xml>
測(cè)試公眾號(hào)的管理后臺(tái)也可以看到關(guān)注測(cè)試號(hào)的用戶列表,如下圖所示:
通過(guò)這個(gè)簡(jiǎn)單的入門程序,我們揭開了微信開發(fā)的神秘面紗了.
更多WeChat開発の入門學(xué)習(xí)のまとめ相關(guān)文章請(qǐng)關(guān)注PHP中文網(wǎng)!

ホットAIツール

Undress AI Tool
脫衣畫像を無(wú)料で

Undresser.AI Undress
リアルなヌード寫真を作成する AI 搭載アプリ

AI Clothes Remover
寫真から衣服を削除するオンライン AI ツール。

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無(wú)料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡(jiǎn)単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無(wú)料のコードエディター

SublimeText3 中國(guó)語(yǔ)版
中國(guó)語(yǔ)版、とても使いやすい

ゼンドスタジオ 13.0.1
強(qiáng)力な PHP 統(tǒng)合開発環(huán)境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

PHP は、Web 開発およびサーバーサイド プログラミング、特に WeChat 開発で広く使用されているオープン ソースのスクリプト言語(yǔ)です。現(xiàn)在、ますます多くの企業(yè)や開発者が WeChat 開発に PHP を使用し始めています。これは、PHP が本當(dāng)に學(xué)びやすく、使いやすい開発言語(yǔ)となっているためです。 WeChat の開発では、メッセージの暗號(hào)化と復(fù)號(hào)化はデータのセキュリティに関わるため、非常に重要な問(wèn)題となります。暗號(hào)化と復(fù)號(hào)化の方法を持たないメッセージの場(chǎng)合、ハッカーは簡(jiǎn)単にデータを入手でき、ユーザーに脅威を與える可能性があります。

WeChat パブリック アカウントの開発では、投票機(jī)能がよく使用されます。投票機(jī)能はユーザーが気軽に交流に參加できるほか、イベントの開催や意見調(diào)査などにも重要なツールです。この記事では、PHPを使用してWeChatの投票機(jī)能を?qū)g裝する方法を紹介します。 WeChat公式アカウントの認(rèn)証を取得する まずはWeChat公式アカウントの認(rèn)証を取得する必要があります。 WeChatパブリックプラットフォームでは、WeChatパブリックアカウント、公式アカウント、およびパブリックアカウントに対応するトークンのAPIアドレスを設(shè)定する必要があります。 PHP言語(yǔ)を使用した開発の過(guò)程では、WeChatが公式に提供するPHを使用する必要があります

WeChat の人気に伴い、マーケティング ツールとして WeChat を使用し始める企業(yè)が増えています。 WeChat グループ メッセージング機(jī)能は、企業(yè)が WeChat マーケティングを行うための重要な手段の 1 つです。ただし、手動(dòng)送信のみに頼ると、マーケターにとって非常に時(shí)間と労力がかかる作業(yè)になります。したがって、WeChat マス メッセージング ツールを開発することが特に重要です。この記事では、PHP を使用して WeChat マス メッセージング ツールを開発する方法を紹介します。 1. 準(zhǔn)備作業(yè) WeChat マス メッセージング ツールを開発するには、次の技術(shù)點(diǎn)を習(xí)得する必要があります。 PHP WeChat パブリック プラットフォーム開発の基礎(chǔ)知識(shí) 開発ツール: Sub

WeChat は現(xiàn)在、世界最大のユーザーベースを持つソーシャル プラットフォームの 1 つであり、モバイル インターネットの普及に伴い、ますます多くの企業(yè)が WeChat マーケティングの重要性を認(rèn)識(shí)し始めています。 WeChat マーケティングを?qū)g施する場(chǎng)合、顧客サービスは重要な部分です。カスタマー サービスのチャット ウィンドウをより適切に管理するために、WeChat 開発に PHP 言語(yǔ)を使用できます。 1. PHP WeChat 開発の概要 PHP は、Web 開発の分野で広く使用されているオープン ソースのサーバー側(cè)スクリプト言語(yǔ)です。 WeChat パブリック プラットフォームが提供する開発インターフェイスと組み合わせると、PHP 言語(yǔ)を使用して WeChat を?qū)g行できます。

WeChat パブリック アカウントの開発において、ユーザー タグ管理は非常に重要な機(jī)能であり、開発者がユーザーをよりよく理解し、管理できるようになります。この記事では、PHPを使用してWeChatのユーザータグ管理機(jī)能を?qū)g裝する方法を紹介します。 1. WeChat ユーザーの openid を取得する WeChat ユーザータグ管理機(jī)能を使用する前に、まずユーザーの openid を取得する必要があります。 WeChat パブリック アカウントの開発では、ユーザーの承認(rèn)を通じて openid を取得するのが一般的です。ユーザー認(rèn)証が完了したら、次のコードを通じてユーザーを取得できます。

WeChat が人々の生活においてますます重要なコミュニケーション ツールになるにつれ、その機(jī)敏なメッセージング機(jī)能はすぐに多くの企業(yè)や個(gè)人に支持されるようになりました。企業(yè)にとって、WeChat をマーケティング プラットフォームとして開発することがトレンドになっており、WeChat 開発の重要性が徐々に顕著になってきています。その中でも、グループ送信機(jī)能はさらに広く使用されているため、PHP プログラマとしてグループ メッセージ送信レコードを?qū)g裝するにはどうすればよいでしょうか?以下に簡(jiǎn)単に紹介します。 1. WeChat パブリック アカウントに関する開発知識(shí)を理解する グループ メッセージ送信レコードの実裝方法を理解する前に、

PHP を使用して WeChat 公開アカウントを開発する方法 WeChat 公開アカウントは、多くの企業(yè)にとってプロモーションと交流のための重要なチャネルとなっており、一般的に使用される Web 言語(yǔ)として PHP を使用して WeChat 公開アカウントを開発することもできます。この記事では、PHP を使用して WeChat 公開アカウントを開発する具體的な手順を紹介します。ステップ1:WeChat公式アカウントの開発者アカウントを取得する WeChat公式アカウントの開発を開始する前に、WeChat公式アカウントの開発者アカウントを申請(qǐng)する必要があります。具體的な登録プロセスについては、WeChat パブリック プラットフォームの公式 Web サイトを參照してください。

インターネットとモバイル スマート デバイスの発展に伴い、WeChat はソーシャルおよびマーケティング分野に欠かせないものになりました。デジタル化が進(jìn)むこの時(shí)代において、WeChat 開発に PHP を使用する方法が多くの開発者の焦點(diǎn)になっています。この記事では主に、PHP を WeChat 開発に使用する方法とそのヒントや注意事項(xiàng)を紹介します。 1. 開発環(huán)境の準(zhǔn)備 WeChat を開発する前に、まず対応する開発環(huán)境を準(zhǔn)備する必要があります。具體的には、PHP オペレーティング環(huán)境と WeChat パブリック プラットフォームをインストールする必要があります。
