1、二维码的生成

image.png
通过rpc 调用base的 eh.qrInfoService 接口

接口在base-api中

image.png
调到了 NgariQrInfoService 类
image.png

需要拼接的数据
image.png
可以看到 QRInfoConstant 表示二维码的类型
image.png
同意存放在 BusQrInfoBean 对象中

  1. String sceneStr = QRInfoConstant.QRTYPE_NGARICHECKLIST + "_" + ngariChecklistInfo;

sceneStr就是传入的 类型 + 参数

  1. QRInfoBean qrInfoBean = createBriefQRInfoFromOpbase(busQrInfoBean, clientConfigDTO);

之后调用 createBriefQRInfoFromOpbase 方法 去获取二维码的参数

  1. @RpcService
  2. public QRInfoBean createBriefQRInfoFromOpbase(BusQrInfoBean busQrInfoBean, ClientConfigDTO clientConfig) {
  3. Integer organId = busQrInfoBean.getOrganId();
  4. String SceneStr=busQrInfoBean.getSceneStr();
  5. Integer qrType=busQrInfoBean.getQrType();
  6. LOGGER.info("生成临时二维码 SceneStr={}," +
  7. "organId={},createWay={},clientConfigId={}",
  8. SceneStr, organId, busQrInfoBean.getCreateWay(),
  9. clientConfig.getId());
  10. if (SceneStr == null || qrType==null) {
  11. LOGGER.info("SceneStr为空或qrType未空,无法获取二维码,clientConfigId={}", clientConfig.getId());
  12. return null;
  13. }
  14. //设置二维码类型和参数
  15. Integer clientConfigId = clientConfig.getId() == null ?
  16. QRInfoConstant.CLIENTCONFIGID_NGARI : clientConfig.getId();
  17. //生成业务相关二维码[永久]
  18. QRInfo qr=null;
  19. //针对营销页面,纳里健康终端生成临时二维码
  20. if (busQrInfoBean.getQrType() == QRInfoConstant.QRTYPE_MARKETINGPAGE && "wx870abf50c6bc6da3".equals(clientConfig.getAppKey())) {
  21. //获取有效时间
  22. if (busQrInfoBean.getExpireSeconds() == null) {
  23. String expireSecondsStr = ParamUtils.getParam(ParameterConstant.KEY_QRCODE_EXPIRE_SECONDS, "2592000");
  24. busQrInfoBean.setExpireSeconds(Long.valueOf(expireSecondsStr));
  25. }
  26. List<QRInfo> infos = qrDao.findBriefQRInfoAndQRCategory(clientConfigId, SceneStr,new Date(), qrType);
  27. if (infos.isEmpty()) {
  28. qr = qrCodeService.createBriefQRInfo(busQrInfoBean, clientConfig);
  29. } else {
  30. qr = infos.get(0);
  31. }
  32. return getBean(qr,QRInfoBean.class);
  33. }
  34. //针对营销页面,除纳里健康终端,生成二维码时依旧生成永久二维码
  35. if (busQrInfoBean.getQrType() == QRInfoConstant.QRTYPE_MARKETINGPAGE){
  36. List<QRInfo> infos = qrDao.findQRInfoByClientConfigId(clientConfigId, SceneStr, qrType);
  37. if (infos.isEmpty()) {
  38. qr = qrCodeService.createPermanentQRInfo(busQrInfoBean, clientConfig);
  39. } else {
  40. qr = infos.get(0);
  41. }
  42. return getBean(qr,QRInfoBean.class);
  43. }
  44. if ("WX".equals(busQrInfoBean.getCreateWay())) {
  45. //只有当是微信端时,采用临时二维码
  46. LOGGER.info("wx client loading qrCode");
  47. //获取有效时间
  48. if (busQrInfoBean.getExpireSeconds() == null) {
  49. String expireSecondsStr = ParamUtils.getParam(ParameterConstant.KEY_QRCODE_EXPIRE_SECONDS, "2592000");
  50. busQrInfoBean.setExpireSeconds(Long.valueOf(expireSecondsStr));
  51. }
  52. //先查询有没有永久二维码,如果有,直接返回,如果没有,则生成临时二维码
  53. List<QRInfo> infos = qrDao.findQRInfoByClientConfigIdAndQRCategory(clientConfigId, SceneStr, qrType);
  54. if (infos.isEmpty()) {
  55. //查询有没有没过期的临时二维码,如果没有,则生成新的二维码
  56. List<QRInfo> briefQRInfo = qrDao.findBriefQRInfoAndQRCategory(clientConfigId, SceneStr, new Date(), qrType);
  57. LOGGER.info("qrCodeCount count={},clientConfigId={},sceneStr={},qrType={}",briefQRInfo.size(),clientConfigId,SceneStr,qrType);
  58. if (briefQRInfo.isEmpty()) {
  59. qr = qrCodeService.createBriefQRInfo(busQrInfoBean, clientConfig);
  60. }else {
  61. qr = briefQRInfo.get(0);
  62. }
  63. } else {
  64. qr = infos.get(0);
  65. }
  66. }else {
  67. LOGGER.info("other client loading qrCode");
  68. List<QRInfo> infos = qrDao.findQRInfoByClientConfigId(clientConfigId, SceneStr, qrType);
  69. if (infos.isEmpty()) {
  70. qr = qrCodeService.createPermanentQRInfo(busQrInfoBean, clientConfig);
  71. } else {
  72. qr = infos.get(0);
  73. }
  74. }
  75. return getBean(qr,QRInfoBean.class);
  76. }

2、二维码的解析

二维码的解析 大部分是在wxservice 和 base项目

在WXCallbackListenerImpl 类中进行微信扫码后的回调
image.png
进入onEvent 方法中

String msgType = arg0.getMsgType();
String event = arg0.getEvent();
String openId = arg0.getFromUser();
String appId = arg0.getAppid();
String content = arg0.getEventKey();
if (!msgType.equals(getAppEvent().getKey())) {
    return msgType;
}
if (getAppEvent().getSubscribe().equals(event) || getAppEvent().getScan().equals(event)) {//临时二维码执行web登录
    try {
        if (arg0.getTicket() != null) {
            IWebLoginInfoService webLoginInfoService = AppContextHolder.getBean("eh.webLoginInfoService", IWebLoginInfoService.class);
            String hashCode = Integer.toHexString(arg0.getTicket().hashCode());
            webLoginInfoService.putLoginInfo(hashCode, openId);
        }
    }

}
WXService wxService = AppContextHolder.getBean("wx.wxService", WXService.class);

//未关注公众号时
if (getAppEvent().getSubscribe().equals(event)) {
    // 关注自动回复消息
    replyOnSubscribe(appId, openId);
    // 更新关注标记
    subscribePubPlatform(appId, openId, event);
    //保存或更新
    this.subscribeUserInfo(openId,appId);
    // 扫描医生二维码关注时
    String subscribeStr = StringUtils.substringAfter(arg0.getEventKey(), "qrscene_");
    log.info("没关注公众号的情况扫码:" + JSONUtils.toString(subscribeStr));
    IConfigurationCenterUtilsService configurationCenterUtilsService = AppContextHolder.getBean("eh.configurationCenterUtils",IConfigurationCenterUtilsService.class);
    Boolean ngariQrcode = (Boolean) configurationCenterUtilsService.getPropertyByAppKey(appId,"ngariQrcode");
    //ngariQrcode为true只支持有ngari_qrcode_前缀的 false 支持有ngari_qrcode_前缀和纯数字
    if (ngariQrcode && subscribeStr.matches(reg)){
        log.info("ngariQrcode为true只支持有ngari_qrcode_前缀:" + JSONUtils.toString(subscribeStr));
        return null;
    }
    if (subscribeStr.startsWith(QRInfoConstant.QRCODE_PREFIX)){
        subscribeStr = StringUtils.substringAfter(arg0.getEventKey(), QRInfoConstant.QRCODE_PREFIX);
    }
    if (subscribeStr.matches(reg) && !StringUtils.equals(subscribeStr, "0")) {
        saveWxSubscribeAndSendMsg(appId, openId, subscribeStr);
    }
    if (!subscribeStr.matches(reg) ){
        sendMessage(appId, openId, subscribeStr);
    }
    wxService.saveQRRecords(appId, subscribeStr, openId, false,ClientConfigConstant.APP_CLIENTTYPE_WX);
} else if (getAppEvent().getUnsubscribe().equals(event)) {
    //取消关注公众号时
    subscribePubPlatform(appId, openId, event);

    //更新扫码关注记录
    wxService.updateQRRecords(appId, openId, ClientConfigConstant.APP_CLIENTTYPE_WX);
    //更新关注表
    this.unSubscribeUserInfo(openId);
} else if (getAppEvent().getClick().equals(event)) {
    //点击公众号菜单时
    String eventKey = arg0.getEventKey();
    if("CALL_NUMBER_MESSAGE".equals(eventKey)){
        ICallNumberServiceInterface callNumberService = AppContextHolder.getBean("eh.callNumberService", ICallNumberServiceInterface.class);
        String callNumberReplyMsg = callNumberService.getCallInfoString(appId, openId, "CALLMSG");
        log.info("click event[{}] with response[{}]", eventKey, callNumberReplyMsg);
        sendCustomerMessage(appId, openId, callNumberReplyMsg);
    } else {
        WxMenuMsgInterface menuMsgInterface = AppContextHolder.getBean("eh.wxMsgConfigService", WxMenuMsgInterface.class);
        List<WXMsgConfig> menuMsgList = menuMsgInterface.findWXMsgConfigByAppId(appId, 1);//1:未过期消息
        for (WXMsgConfig wxMsgConfig : menuMsgList) {
            if (StringUtils.equals(wxMsgConfig.getMsgKey(), eventKey)) {
                //处理带参数的事件,替换参数
                WxEventUtils.packageEventMsg(new WxEventParam(openId), wxMsgConfig);
                sendCustomerMessage(appId, openId, wxMsgConfig.getMsg());
            }
        }
    }
} else if (getAppEvent().getLocation().equals(event)) {
    //获取地理位置时
    WXLocationEvent wxLocationEvent = (WXLocationEvent) arg0;
    Double latitude = wxLocationEvent.getLatitude();
    Double longitude = wxLocationEvent.getLongitude();
    String id = new StringBuilder().append(openId).append("@").append(appId).toString();
    String location = "location";
    Map map = ClientStore.instance().get(id);
    if (!map.containsKey(location)) {
        String result = LocationRevertUtils.parse(latitude.toString(), longitude.toString());
        JSONObject object = JSONObject.parseObject(result);
        JSONObject locationObject = object.getJSONObject("result");
        Map ad_info = locationObject.getJSONObject("ad_info");
        map.put(location, ad_info);
        ClientStore.instance().put(id, map);
        //将地理位置放在静态常量里面,由于解绑返回到注册页面需要试用,因此不进行判断是否已关注
        OAuthWeixinMPDAO dao = DAOFactory.getDAO(OAuthWeixinMPDAO.class);
        OAuthWeixinMP oAuthWeixinMP = dao.getByAppIdAndOpenId(appId, openId);
        if (oAuthWeixinMP != null) {
            updateUserCache(oAuthWeixinMP.getUserId(), ad_info);
        }
        log.info("id[{}], location[{}]", id, ad_info);
    }
} else if (getAppEvent().getScan().equals(event)) {
    //已关注公众号时
    String subscribeStr = arg0.getEventKey();
    log.info("已关注公众号的情况扫码:" + JSONUtils.toString(subscribeStr));
    IConfigurationCenterUtilsService configurationCenterUtilsService = AppContextHolder.getBean("eh.configurationCenterUtils",IConfigurationCenterUtilsService.class);
    Boolean ngariQrcode = (Boolean) configurationCenterUtilsService.getPropertyByAppKey(appId,"ngariQrcode");
    //ngariQrcode为true只支持有ngari_qrcode_前缀的 false 支持有ngari_qrcode_前缀和纯数字
    if (ngariQrcode && subscribeStr.matches(reg)){
        log.info("ngariQrcode为true只支持有ngari_qrcode_前缀:" + JSONUtils.toString(subscribeStr));
        return null;
    }
    if (subscribeStr.startsWith(QRInfoConstant.QRCODE_PREFIX)){
        subscribeStr = StringUtils.substringAfter(arg0.getEventKey(), QRInfoConstant.QRCODE_PREFIX);
    }
    if (subscribeStr.matches(reg) && !StringUtils.equals(subscribeStr, "0")) {
        saveWxSubscribeAndSendMsg(appId, openId, subscribeStr);
    }
    if (!subscribeStr.matches(reg)){
        if(subscribeStr.contains("jobNumber")){
            //如果包含医生工号信息,则为出院小结推送
            sendHospitalSummaryMessage(appId, openId, subscribeStr);
        }else {
            sendMessage(appId, openId, subscribeStr);
        }
    }
    wxService.saveQRRecords(appId, subscribeStr, openId, true,ClientConfigConstant.APP_CLIENTTYPE_WX);

进入 sendMessage(appId, openId, subscribeStr); 方法中
image.png

进入sendMessage