最近公司讓我開發微信公眾號平台掃碼登錄,同步用戶信息於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;
}
如有問題,可以一起討論,相互學習,我也是剛剛接觸,需要后續繼續努力!
