最近公司讓我開發微信公眾號平台掃碼登錄,同步用戶信息於PC端,所做的過程當中遇到了一些坑,做完了就總結一下需要注意的點,如若大家開發過程中遇到同樣的問題,可以借鑒!
第一:配置域名
作用:配置域名為了在微信的開發過程中,讓微信服務器可以通過域名映射到調用你的服務器接口,進行后續的邏輯處理!
配置步驟:設置 --> 公眾號設置 --> 功能設置 --> 網頁授權設置 (設置你自己的域名即可)
注意:(1)根據微信官網描述,看到 MP_verify_HAlZDt72bkvxIrb6.txt 這個文件,需要下載下來放到你的根目錄Webapp下,啟動你的服務器。此時,微信服務器會自動的根據你所配置的域名 dcm.xxxxxx.cc/MP_verify_HAlZDt72bkvxIrb6.txt 訪問這個文件,並成功讀取到該文件中的內容就意味着配置成功!
(2)要是提示失敗,有可能是你的服務器中配置了權限攔截,例如:登錄權限
第二:配置微信服務器訪問你接口的URL Token EncodingAESKey
作用:URL是開發者用來接收微信消息和事件的接口URL。Token可以由開發者任意填寫,用作生成簽名(該Token會配置在服務器中和接口URL中包含的Token進行比對,從而驗證安全性)。EncodingAESKey由開發者手動填寫或隨機生成,將用作消息體加解密密鑰。
配置步驟:開發 --> 基本設置 (填寫URL Token EncodingAESKey)
注意(重中之重):Token EncodingAESKey 需要配置在你的服務器中 WxMpService 的 Config 中,此時還需要編寫微信服務訪問你接口的代碼,返回微信服務器需要返回的結果才會提交成功(這一塊的坑我遇到了好多:Token驗證失效,URL超時之類,基本問題都是點擊提交按鈕,微信會自動訪問你配置的接口不能返回微信所需要的結果)
例如:配置的域名為:dcm.xxxxxx.cc/mp/login/notify
@Controller @RequestMapping("/mp/login") public class ValidateWeiXin extends HttpServlet { private static final long serialVersionUID = 1L; private String TOKEN = "這里隨便填入32位以內的數字英文,也就是token"; @RequestMapping("/notify") protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/plain;charset=utf-8"); // 微信加密簽名 String signature = request.getParameter("signature"); // 隨機字符串 String echostr = request.getParameter("echostr"); // 時間戳 String timestamp = request.getParameter("timestamp"); // 隨機數 String nonce = request.getParameter("nonce"); String[] str = { TOKEN, timestamp, nonce }; Arrays.sort(str); // 字典序排序 String bigStr = str[0] + str[1] + str[2]; // SHA1加密,我這里用的是common-codec的jar包,你們也可以用java自帶的消息消息摘要來寫,只不過要多寫幾行代碼,但結果都一樣的 DigestUtils.sha1Hex(bigStr); String digest = DigestUtils.sha1Hex(bigStr); // 確認請求來至微信 if (digest.equals(signature)) { response.getWriter().print(echostr); } } }
將這段代碼寫入你配置微信服務器訪問的接口中,就可以提交成功了,后續需要重構這個接口中的代碼,例如接收:微信掃碼通知、關注通知、取消關注通知、接收發送消息等業務邏輯處理!
第三:微信掃碼登錄
(1)選用第三方SDK包:https://github.com/Wechat-Group/WxJava (個人認為這個SDK第三方Jar包涵蓋了微信不同開發平台的所有功能,封裝的很好,推薦使用)可以查看一下具體封裝的特點和使用方式,可以提高開發效率!
(2)參考微信官方文檔:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1445241432
(3)需要詳細閱讀 【微信公眾平台 --> 消息管理 --> 接收事件推送】 文檔,借助第三方SDK工具包進行開發
(4)關注、取消公眾號,微信會自動訪問你配置的URL接口,根據接收的事件類型,處理不同的業務邏輯
用戶未關注時,進行關注后的事件推送 <xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[FromUser]]></FromUserName> <CreateTime>123456789</CreateTime> <MsgType><![CDATA[event]]></MsgType> <Event><![CDATA[subscribe]]></Event> <EventKey><![CDATA[qrscene_123123]]></EventKey> <Ticket><![CDATA[TICKET]]></Ticket> </xml> 用戶已關注時的事件推送(已經關注了,又掃碼登錄) <xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[FromUser]]></FromUserName> <CreateTime>123456789</CreateTime> <MsgType><![CDATA[event]]></MsgType> <Event><![CDATA[SCAN]]></Event> <EventKey><![CDATA[SCENE_VALUE]]></EventKey> <Ticket><![CDATA[TICKET]]></Ticket> </xml>
自己編寫的一段掃碼通知、關注、取消關注的Controller代碼,可以借鑒一下:
@RequestMapping("/notify") public String wxnotify(HttpServletRequest request, HttpServletResponse response) { log.info("【微信通知】wxnotify 接收到請求!"); String message = "success"; try { request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); //把微信返回的xml信息轉義成map Map<String, String> map = XmlUtil.xmlToMap(request); String fromUserName = map.get("FromUserName"); //消息來源用戶標識 String toUserName = map.get("ToUserName"); //消息目的用戶標識 String msgType = map.get("MsgType"); //消息類型 String eventType = map.get("Event"); String eventKey = map.get("EventKey"); log.info("【微信通知】fromUserName = {}, toUserName = {}, msgType = {}, eventType = {}, eventKey={}", fromUserName, toUserName, msgType, eventType, eventKey); if (WxConsts.XmlMsgType.EVENT.equals(msgType)) { //如果為事件類型 if (WxConsts.EventType.SCAN.equals(eventType)) { //掃碼通知 if (StringUtils.isNotEmpty(eventKey)) { log.info("【掃碼通知】mid = {}", eventKey); mpReceiveMessageService.scanQrCodeNotify(fromUserName, eventKey, redisTemplate); } } else if (WxConsts.EventType.SUBSCRIBE.equals(eventType)) { //關注通知 if (StringUtils.isNotEmpty(eventKey)) { String[] paramArray = eventKey.split("_"); String mid = paramArray[1]; log.info("【關注通知】mid = {}", mid); mpReceiveMessageService.subscribleNotify(fromUserName, mid, redisTemplate); message = MessageUtil.subscribeForText(toUserName, fromUserName); } } else if (WxConsts.EventType.UNSUBSCRIBE.equals(eventType)) {//取消關注通知 log.info("【取消關注通知】"); mpReceiveMessageService.unsubscribleNotify(fromUserName, redisTemplate); } } } catch (Exception e) { log.error("【微信通知】異常, message = {}", e.getMessage()); } return message; }
如有問題,可以一起討論,相互學習,我也是剛剛接觸,需要后續繼續努力!