微信公眾平台是運營者通過公眾號為微信用戶提供資訊和服務的平台,而公眾平台開發接口則是提供服務的基礎。
接入微信公眾平台開發,開發者需要按照如下步驟完成:
1、填寫服務器配置
2、驗證服務器地址的有效性
3、依據接口文檔實現業務邏輯
以上步驟可在微信開發公眾官方文檔中查看 點擊查看
下面主要說下開發過程中會接觸到的一些問題。
1.微信接入問題
開發者通過檢驗signature對請求進行校驗(下面有校驗方式)。若確認此次GET請求來自微信服務器,請原樣返回echostr參數內容,則接入生效,成為開發者成功,否則接入失敗。加密/校驗流程如下:
1)將token、timestamp、nonce三個參數進行字典序排序 2)將三個參數字符串拼接成一個字符串進行sha1加密 3)開發者獲得加密后的字符串可與signature對比,標識該請求來源於微信 |
以上為官方文檔內容,具體實現如下
1 @RequestMapping(value="/wechat.do",method = RequestMethod.GET) 2 public @ResponseBody String authGet(@RequestParam(value="signature",required=false) String signature, 3 @RequestParam("timestamp") String timestamp, 4 @RequestParam("nonce") String nonce, 5 @RequestParam("echostr") String echostr) throws Exception { 6 7 String sysytemAppid =(String)wxPropertiesBean.getProperties("system").get("system_appid"); 8 Map config = this.wxMpService.queryWxAccountByCode(sysytemAppid); 9 String token = (String) config.get("account_token"); 10 if (!WxCryptUtil.checkSignature(token,signature, timestamp, nonce)) { 11 logger.error("微信接入驗證失敗!"); 12 return null; 13 } 14 return echostr; 15 }
public static boolean checkSignature(String token, String signature, String timestamp, String nonce) { String[] arr = new String[] { token, timestamp, nonce }; Arrays.sort(arr); StringBuilder content = new StringBuilder(); for (int i = 0; i < arr.length; i++) { content.append(arr[i]); } MessageDigest md = null; String tmpStr = null; try { md = MessageDigest.getInstance("SHA-1"); byte[] digest = md.digest(content.toString().getBytes()); tmpStr = byteToStr(digest); } catch (NoSuchAlgorithmException e) { } return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false; } /** * 將字節數組轉換為十六進制字符 * * @param byteArray * @return */ public static String byteToStr(byte[] byteArray) { String strDigest = ""; for (int i = 0; i < byteArray.length; i++) { strDigest += byteToHexStr(byteArray[i]); } return strDigest; } /** * 將字節轉換為十六進制字符 * * @param mByte * @return */ public static String byteToHexStr(byte mByte) { char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; char[] tempArr = new char[2]; tempArr[0] = Digit[(mByte >>> 4) & 0X0F]; tempArr[1] = Digit[mByte & 0X0F]; String s = new String(tempArr); return s; }
2.獲取access_token
access_token是公眾號的全局唯一接口調用憑據,公眾號調用各接口時都需使用access_token。開發者需要進行妥善保存。access_token的存儲至少要保留512個字符空間。access_token的有效期目前為2個小時,需定時刷新,重復獲取將導致上次獲取的access_token失效。
接口調用請求說明
https請求方式: GET
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
參數說明
參數 | 是否必須 | 說明 |
---|---|---|
grant_type | 是 | 獲取access_token填寫client_credential |
appid | 是 | 第三方用戶唯一憑證 |
secret | 是 | 第三方用戶唯一憑證密鑰,即appsecret |
返回說明
正常情況下,微信會返回下述JSON數據包給公眾號:
{"access_token":"ACCESS_TOKEN","expires_in":7200} |
參數說明
參數 | 說明 |
---|---|
access_token | 獲取到的憑證 |
expires_in | 憑證有效時間,單位:秒 |
private String getAcessTokenEntity(Map accountConfig) { String requestUrl = (String) wxPropertiesBean.getProperties("wxpt").get("access_token_url"); Map urlParams = new HashMap(); urlParams.put("grant_type", "client_credential"); urlParams.put("appid", accountConfig.get("account_appid")); urlParams.put("secret", accountConfig.get("account_appsecret")); requestUrl = HttpUtil.getUrl(requestUrl, urlParams); try{ WxApiResult apiResult = HttpUtil.httpsRequest(requestUrl, "GET", null); Map result = HttpUtil.getCommonResult(apiResult); String accessToken = (String) result.get("access_token"); if(StringUtils.isBlank(accessToken)){ throw new WxErrorException("獲取accessToken失敗!"); } String accountId = (String) accountConfig.get("account_id"); wxMpService.updateAccessToken(accountId, accessToken); return accessToken; }catch (WxErrorException e){ throw e; }catch (Exception e){ logger.error(e.getMessage()); throw new WxErrorException("獲取accessToken失敗!"); } }
由於access_token的有效期目前為2個小時,需定時刷新,重復獲取將導致上次獲取的access_token失效。我這里是將token落地在自己的庫中,單獨一張表用於記錄和微信相關的所有的配置。
刷新token后再重新存入表中(包括存入時間記錄),每次需要獲取token的時候從表中獲取,這樣可以先判斷是否過期,再決定是否需要重新獲取。
未完待續,后面將介紹自定義菜單,oauth2認證等。