微信微服务重构

微信微服务

 

1. 背景

 

2. 业务逻辑

 

3. 设计方案

 

1. 背景

 

  现有业务和微信openId关联,目前,消费者测存在多个公众号时需要修改为:业务和unionid关联。
  此设计包含如下设计内容

 

2.业务逻辑

 微信微服务逻辑设计

             

微信微服务重构_第1张图片

用户:浏览器,手机客户端

消费者服务:业务系统

微信微服务:所有和微信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 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: 

 

你可能感兴趣的:(微信公众号开发)