微信微服務重構
阿新 • • 發佈:2018-12-24
微信微服務
1. 背景
2. 業務邏輯
3. 設計方案
1. 背景
現有業務和微信openId關聯,目前,消費者測存在多個公眾號時需要修改為:業務和unionid關聯。
此設計包含如下設計內容
2.業務邏輯
微信微服務邏輯設計
使用者:瀏覽器,手機客戶端
消費者服務:業務系統
微信微服務:所有和微信api的介面,比如監聽事件:關注事件,取消關注事件,掃碼事件,驗證網頁授權碼是否有效
3.設計方案
本次微信微服務是基於weixin-java-tools3.2.0外掛進行改造,貼出關鍵程式碼供大家進行學習,如需要整個專案,關注“IT技術論壇”公眾號,並在微信公眾中“關於我們”中加我為好友,我私發給你。
微信伺服器回撥程式碼
@RequestMapping("/wxOfficial/entrance/{appId}") public class WxOfficialController extends GenericController{ @Autowired private Environment environment; @Autowired private WeixinService wxService; @ResponseBody @GetMapping(produces = "text/plain;charset=utf-8") public String authGet(@RequestParam(name = "signature", required = false) String signature, @RequestParam(name = "timestamp", required = false) String timestamp, @RequestParam(name = "nonce", required = false) String nonce, @RequestParam(name = "echostr", required = false) String echostr, @PathVariable String appId) { this.logger.info("\n接收到來自微信伺服器的認證訊息:[{}, {}, {}, {}]", signature, timestamp, nonce, echostr); if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) { throw new IllegalArgumentException("請求引數非法,請核實!"); } final WxMpInMemoryConfigStorage wxConfig = WeixinServiceFactory.getWxConfig(appId,environment); wxService.setWxMpConfigStorage(wxConfig); if (wxService.checkSignature(timestamp, nonce, signature)) { return echostr; } return "非法請求"; } @ResponseBody @PostMapping(produces = "application/xml; charset=UTF-8") public String post(@RequestBody String requestBody, @RequestParam("signature") String signature, @RequestParam(name = "encrypt_type", required = false) String encType, @RequestParam(name = "msg_signature", required = false) String msgSignature, @RequestParam("timestamp") String timestamp, @RequestParam("nonce") String nonce, @PathVariable String appId) { this.logger.info( "\n接收微信請求:[signature=[{}], encType=[{}], msgSignature=[{}]," + " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ", signature, encType, msgSignature, timestamp, nonce, requestBody); final WxMpInMemoryConfigStorage wxConfig = WeixinServiceFactory.getWxConfig(appId,environment); wxService.setWxMpConfigStorage(wxConfig); if (!wxService.checkSignature(timestamp, nonce, signature)) { throw new IllegalArgumentException("非法請求,可能屬於偽造的請求!"); } String out = null; if (encType == null) { // 明文傳輸的訊息 WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody); WxMpXmlOutMessage outMessage = wxService.route(inMessage); if (outMessage == null) { return ""; } out = outMessage.toXml(); } else if ("aes".equals(encType)) { // aes加密的訊息 WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(requestBody, wxService.getWxMpConfigStorage(), timestamp, nonce, msgSignature); this.logger.debug("\n訊息解密後內容為:\n{} ", inMessage.toString()); WxMpXmlOutMessage outMessage = wxService.route(inMessage); if (outMessage == null) { return ""; } out = outMessage.toEncryptedXml(wxService.getWxMpConfigStorage()); } this.logger.debug("\n組裝回覆信息:{}", out); return out; } }
關注事件監聽程式碼:
@Component public class SubscribeHandler extends AbstractHandler { @Autowired private RabbitProducer rabbitProducer; @Autowired private MqMessageLogRepository mqMessageLogRepository; @Autowired private RabbitConfig rabbitConfig; @Autowired private Environment environment; @Override public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException { this.logger.info("關注使用者 OPENID: " + wxMessage.getFromUser()); this.logger.info("關注公眾號 AppId:"+wxMpService.getWxMpConfigStorage().getAppId()); JSONObject jsonObject = new JSONObject(); jsonObject.put("error", 0); String openId = wxMessage.getFromUser(); this.logger.info("新關注使用者 OPENID: " + openId); JSONObject contentObject = (JSONObject) JSONObject.toJSON(wxMessage); String appId = wxMpService.getWxMpConfigStorage().getAppId(); WxMpUser userWxInfo = wxMpService.getUserService().userInfo(openId, null); this.logger.info("新關注使用者詳細資訊: " + userWxInfo); contentObject.put("openId",openId); contentObject.put("unionId",userWxInfo.getUnionId()); contentObject.put("headImgUrl",userWxInfo.getHeadImgUrl()); contentObject.put("userName",userWxInfo.getNickname()); contentObject.put("nickname",userWxInfo.getNickname()); contentObject.put("country",userWxInfo.getCountry()); contentObject.put("province",userWxInfo.getProvince()); contentObject.put("city",userWxInfo.getCity()); contentObject.put("sex",userWxInfo.getSex()); contentObject.put("language",userWxInfo.getLanguage()); contentObject.put("remark",userWxInfo.getRemark()); contentObject.put("subscribeTime",userWxInfo.getSubscribeTime()); contentObject.put("subscribe",userWxInfo.getSubscribe()); SimpleDateFormat nowTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); contentObject.put("nowTime",nowTime.format(System.currentTimeMillis())); String eventKey = wxMessage.getEventKey(); if (StringUtils.isNotBlank(eventKey)) { eventKey = eventKey.replace("qrscene_", ""); contentObject.put("devCode",eventKey); } contentObject.put("type","subscribe"); //獲取微信appId contentObject.put("appId",appId); //userType 1:導購 2:消費者 String userType = environment.getProperty("spring."+appId+".userType"); if("1".equals(userType)){ contentObject.put("appType","org"); }else if("2".equals(userType)){ contentObject.put("appType","customer"); } String content = JSONObject.toJSONString(contentObject); this.logger.info("經訊息佇列傳遞的使用者資訊: " + content); rabbitProducer.sendMsg(content, rabbitConfig.EXCHANGE,rabbitConfig.ROUTINGKEY_SUBSCRIBE); //記錄mq日誌 MqMessageLog mqMessageLog = JSONObject.toJavaObject(contentObject,MqMessageLog.class); mqMessageLogRepository.insert(mqMessageLog); return null; } }
該專案是基於spring cloud構建的微服務,微信公眾號配置資訊是存放在配置服務中,格式如下
spring:
xxxxx1: #該值為第一個微信公眾號appId
#YCC端測試
appId: xxxxx1
appSecret:
token:
aesKey:
xxxxx2: #該值為第二個微信公眾號appId
appId:xxxxx2
appSecret:
token:
aesKey: