1. 程式人生 > >微信微服務重構

微信微服務重構

微信微服務

 

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: