Authored by 匡佳华

小程序模板消息改为订阅消息

  1 +package com.yoho.message.dal;
  2 +
  3 +import com.yoho.message.dal.model.MiniSubscribe;
  4 +import org.apache.ibatis.annotations.Param;
  5 +
  6 +public interface IMiniSubscribeDAO {
  7 +
  8 + MiniSubscribe selectAvailableTemplateId(@Param("tableName") String tableName, @Param("uid") Integer uid, @Param("templateId") String templateId);
  9 +
  10 + void updateMiniSubscribe(@Param("tableName") String tableName, @Param("miniSubscribe") MiniSubscribe miniSubscribe);
  11 +
  12 +}
  1 +package com.yoho.message.dal.model;
  2 +
  3 +public class MiniSubscribe {
  4 +
  5 + private Integer id;
  6 +
  7 + private Integer uid;
  8 +
  9 + private String openId;
  10 +
  11 + private String templateId;
  12 +
  13 + private Integer availableTimes;
  14 +
  15 + private Integer miniAppType;
  16 +
  17 + private Integer createTime;
  18 +
  19 + private Integer updateTime;
  20 +
  21 + public String getOpenId() {
  22 + return openId;
  23 + }
  24 +
  25 + public void setOpenId(String openId) {
  26 + this.openId = openId;
  27 + }
  28 +
  29 + public Integer getId() {
  30 + return id;
  31 + }
  32 +
  33 + public void setId(Integer id) {
  34 + this.id = id;
  35 + }
  36 +
  37 + public String getTemplateId() {
  38 + return templateId;
  39 + }
  40 +
  41 + public void setTemplateId(String templateId) {
  42 + this.templateId = templateId;
  43 + }
  44 +
  45 + public Integer getAvailableTimes() {
  46 + return availableTimes;
  47 + }
  48 +
  49 + public void setAvailableTimes(Integer availableTimes) {
  50 + this.availableTimes = availableTimes;
  51 + }
  52 +
  53 + public Integer getMiniAppType() {
  54 + return miniAppType;
  55 + }
  56 +
  57 + public void setMiniAppType(Integer miniAppType) {
  58 + this.miniAppType = miniAppType;
  59 + }
  60 +
  61 + public Integer getUid() {
  62 + return uid;
  63 + }
  64 +
  65 + public void setUid(Integer uid) {
  66 + this.uid = uid;
  67 + }
  68 +
  69 + public Integer getCreateTime() {
  70 + return createTime;
  71 + }
  72 +
  73 + public void setCreateTime(Integer createTime) {
  74 + this.createTime = createTime;
  75 + }
  76 +
  77 + public Integer getUpdateTime() {
  78 + return updateTime;
  79 + }
  80 +
  81 + public void setUpdateTime(Integer updateTime) {
  82 + this.updateTime = updateTime;
  83 + }
  84 +}
  1 +<?xml version="1.0" encoding="UTF-8" ?>
  2 +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
  3 +<mapper namespace="com.yoho.message.dal.IMiniSubscribeDAO" >
  4 +
  5 + <resultMap id="BaseResultMap" type="com.yoho.message.dal.model.MiniSubscribe" >
  6 + <id column="id" property="id" jdbcType="INTEGER" />
  7 + <result column="uid" property="uid" jdbcType="INTEGER" />
  8 + <result column="open_id" property="openId" jdbcType="VARCHAR" />
  9 + <result column="template_id" property="templateId" jdbcType="VARCHAR" />
  10 + <result column="available_time" property="availableTimes" jdbcType="INTEGER" />
  11 + <result column="create_time" property="createTime" jdbcType="INTEGER" />
  12 + <result column="update_time" property="updateTime" jdbcType="INTEGER" />
  13 + </resultMap>
  14 +
  15 + <select id="selectAvailableTemplateId" resultMap="BaseResultMap">
  16 + select uid, open_id, template_id, available_time, create_time, update_time
  17 + from ${tableName}
  18 + where uid = #{uid} and template_id = #{templateId} and available_time > 0
  19 + limit 1
  20 + </select>
  21 +
  22 + <update id="updateMiniSubscribe" parameterType="com.yoho.message.dal.model.MiniSubscribe">
  23 + update ${tableName} set available_time = available_time - 1
  24 + where uid = #{miniSubscribe.uid} and template_id = #{miniSubscribe.templateId}
  25 + </update>
  26 +</mapper>
@@ -26,4 +26,14 @@ datasources: @@ -26,4 +26,14 @@ datasources:
26 - com.yoho.message.dal.IUserProfileDao 26 - com.yoho.message.dal.IUserProfileDao
27 - com.yoho.message.dal.IWechatTemplateDao 27 - com.yoho.message.dal.IWechatTemplateDao
28 28
  29 + yh_wechat:
  30 + servers:
  31 + - 192.168.102.219:3306
  32 + - 192.168.102.219:3306
  33 + username: yh_test
  34 + password: 9nm0icOwt6bMHjMusIfMLw==
  35 + maxConnections: 50
  36 + daos:
  37 + - com.yoho.message.dal.IMiniSubscribeDAO
  38 +
29 readOnlyInSlave: true 39 readOnlyInSlave: true
1 consumer: 1 consumer:
2 - - address: 172.16.6.54:5672 2 + - address: 192.168.102.211:5672
3 username: yoho 3 username: yoho
4 password: yoho 4 password: yoho
5 consumers: 5 consumers:
@@ -23,7 +23,7 @@ consumer: @@ -23,7 +23,7 @@ consumer:
23 23
24 24
25 producer: 25 producer:
26 - - address: 172.16.6.54:5672 26 + - address: 192.168.102.211:5672
27 username: yoho 27 username: yoho
28 password: yoho 28 password: yoho
29 producers: 29 producers:
@@ -26,4 +26,14 @@ datasources: @@ -26,4 +26,14 @@ datasources:
26 - com.yoho.message.dal.IUserProfileDao 26 - com.yoho.message.dal.IUserProfileDao
27 - com.yoho.message.dal.IWechatTemplateDao 27 - com.yoho.message.dal.IWechatTemplateDao
28 28
  29 + yh_wechat:
  30 + username: ${jdbc.mysql.cobar.username}
  31 + password: ${jdbc.mysql.cobar.password}
  32 + cobar: true
  33 + maxConnections: 80
  34 + minIdle: 20
  35 + maxIdle: 40
  36 + daos:
  37 + - com.yoho.message.dal.IMiniSubscribeDAO
  38 +
29 readOnlyInSlave: ${readOnlyInSlave} 39 readOnlyInSlave: ${readOnlyInSlave}
  1 +package com.yoho.yhmessage.wechat.service;
  2 +
  3 +import com.alibaba.fastjson.JSON;
  4 +import com.alibaba.fastjson.JSONObject;
  5 +import com.yoho.service.model.msgcenter.wechat.MiniappMsgReqBO;
  6 +import com.yoho.service.model.resource.response.CommonRspBO;
  7 +import org.springframework.beans.factory.annotation.Autowired;
  8 +import org.springframework.web.bind.annotation.RequestBody;
  9 +import org.springframework.web.bind.annotation.RequestMapping;
  10 +import org.springframework.web.bind.annotation.RestController;
  11 +
  12 +@RestController
  13 +@RequestMapping("/sendMiniMsgController")
  14 +public class SendMiniMsgController {
  15 +
  16 + @Autowired
  17 + IMiniAppService miniAppService;
  18 +
  19 + @RequestMapping("/testSendMiniMsg")
  20 + public CommonRspBO collectFormId(@RequestBody MiniappMsgReqBO reqBO){
  21 + String data = "{\"keyword1\": { \"value\": \"订单未支付\" }, \"keyword2\": { \"value\": \"${orderCode}\" },\"keyword3\": { \"value\": \"${productName}\" }, \"keyword4\": { \"value\": \"${orderAmount}\" },\"keyword5\": { \"value\":\"您有订单尚未支付!时间所剩不多啦,快来支付吧,更多潮品尽在Yoho!Buy有货\" } }";
  22 + JSONObject dataJson = JSON.parseObject(data);
  23 + reqBO.setData(dataJson);
  24 + miniAppService.sendMiniappMsg(reqBO);
  25 + return new CommonRspBO();
  26 + }
  27 +}
@@ -6,7 +6,9 @@ import com.yoho.core.common.utils.DateUtil; @@ -6,7 +6,9 @@ import com.yoho.core.common.utils.DateUtil;
6 import com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder; 6 import com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder;
7 import com.yoho.error.ServiceError; 7 import com.yoho.error.ServiceError;
8 import com.yoho.error.exception.ServiceException; 8 import com.yoho.error.exception.ServiceException;
  9 +import com.yoho.message.dal.IMiniSubscribeDAO;
9 import com.yoho.message.dal.IMiniappMsgFormDAO; 10 import com.yoho.message.dal.IMiniappMsgFormDAO;
  11 +import com.yoho.message.dal.model.MiniSubscribe;
10 import com.yoho.message.dal.model.MiniappMsgForm; 12 import com.yoho.message.dal.model.MiniappMsgForm;
11 import com.yoho.service.model.msgcenter.wechat.MiniappMsgReqBO; 13 import com.yoho.service.model.msgcenter.wechat.MiniappMsgReqBO;
12 import com.yoho.yhmessage.constants.RedisCacheKeyConstant; 14 import com.yoho.yhmessage.constants.RedisCacheKeyConstant;
@@ -42,6 +44,8 @@ public class MiniServiceAppImpl implements IMiniAppService { @@ -42,6 +44,8 @@ public class MiniServiceAppImpl implements IMiniAppService {
42 @Value("${miniapp.send.tempalte:/cgi-bin/message/wxopen/template/send?}") 44 @Value("${miniapp.send.tempalte:/cgi-bin/message/wxopen/template/send?}")
43 private String sendMsgTemplate; 45 private String sendMsgTemplate;
44 46
  47 + private static final String sendSubscribeMsg = "/cgi-bin/message/subscribe/send?";
  48 +
45 @Autowired 49 @Autowired
46 private IMiniappMsgFormDAO miniappMsgFormDAO; 50 private IMiniappMsgFormDAO miniappMsgFormDAO;
47 51
@@ -49,7 +53,7 @@ public class MiniServiceAppImpl implements IMiniAppService { @@ -49,7 +53,7 @@ public class MiniServiceAppImpl implements IMiniAppService {
49 private IMiniAppAccessTokenService miniAppAccessTokenService; 53 private IMiniAppAccessTokenService miniAppAccessTokenService;
50 54
51 public String getMsgSendUrl(){ 55 public String getMsgSendUrl(){
52 - return wechatHost + sendMsgTemplate; 56 + return wechatHost + sendSubscribeMsg;
53 } 57 }
54 58
55 @Autowired 59 @Autowired
@@ -64,6 +68,9 @@ public class MiniServiceAppImpl implements IMiniAppService { @@ -64,6 +68,9 @@ public class MiniServiceAppImpl implements IMiniAppService {
64 @Autowired 68 @Autowired
65 private IFilterSensitiveWordService filterSensitiveWordService; 69 private IFilterSensitiveWordService filterSensitiveWordService;
66 70
  71 + @Autowired
  72 + private IMiniSubscribeDAO miniSubscribeDAO;
  73 +
67 /** 74 /**
68 * 发送小程序模板消息 75 * 发送小程序模板消息
69 * @param reqBO 76 * @param reqBO
@@ -78,10 +85,7 @@ public class MiniServiceAppImpl implements IMiniAppService { @@ -78,10 +85,7 @@ public class MiniServiceAppImpl implements IMiniAppService {
78 } 85 }
79 86
80 //过滤敏感词目前只过滤了‘测试’相关字眼,以后若要加敏感词,则改为该方法过滤 将敏感词维护在 q_msg_system.message_sensitive_words 表中 87 //过滤敏感词目前只过滤了‘测试’相关字眼,以后若要加敏感词,则改为该方法过滤 将敏感词维护在 q_msg_system.message_sensitive_words 表中
81 - /*if(filterSensitiveWordService.isContainSensitiveWord(reqBO.getData().toJSONString())){  
82 - logger.warn("sendMiniappMsg with sensitiveWord exist,reqBO is {}",reqBO);  
83 - return new JSONObject();  
84 - }*/ 88 +
85 if(filterSensitiveWordService.checkTestWord(reqBO.getData().toJSONString())){ 89 if(filterSensitiveWordService.checkTestWord(reqBO.getData().toJSONString())){
86 logger.warn("sendMiniappMsg with sensitiveWord exist,uid is {},reqBO is {}",reqBO.getUid(),reqBO); 90 logger.warn("sendMiniappMsg with sensitiveWord exist,uid is {},reqBO is {}",reqBO.getUid(),reqBO);
87 return new JSONObject(); 91 return new JSONObject();
@@ -92,33 +96,40 @@ public class MiniServiceAppImpl implements IMiniAppService { @@ -92,33 +96,40 @@ public class MiniServiceAppImpl implements IMiniAppService {
92 throw new ServiceException(ServiceError.WECHAT_PARAM_ISNULL); 96 throw new ServiceException(ServiceError.WECHAT_PARAM_ISNULL);
93 } 97 }
94 98
95 - // 获取有效的formid 99 + //判断该模板用户是否已经订阅
  100 + MiniSubscribe miniSubscribe = miniSubscribeDAO.selectAvailableTemplateId("mini_subscribe_"+reqBO.getMiniappType(), Integer.valueOf(reqBO.getUid()), reqBO.getTemplateId());
  101 + if(miniSubscribe == null){
  102 + return new JSONObject();
  103 + }
  104 + /*// 获取有效的formid
96 MiniappMsgForm miniappMsgForm = miniappMsgFormDAO.selectLastedAvailabByUid(reqBO.getUid(), reqBO.getMiniappType()); 105 MiniappMsgForm miniappMsgForm = miniappMsgFormDAO.selectLastedAvailabByUid(reqBO.getUid(), reqBO.getMiniappType());
97 if (miniappMsgForm == null) { 106 if (miniappMsgForm == null) {
98 logger.warn("validate form not exist, uid is {},reqBO is {}",reqBO.getUid(),reqBO); 107 logger.warn("validate form not exist, uid is {},reqBO is {}",reqBO.getUid(),reqBO);
99 return new JSONObject(); 108 return new JSONObject();
100 - } 109 + }*/
101 110
102 - // 新获取的formid 111 + /* // 新获取的formid
103 if (!reqBO.getFormId().equals(miniappMsgForm.getFormId())){ 112 if (!reqBO.getFormId().equals(miniappMsgForm.getFormId())){
104 logger.info("reset form id, uid is {},old formid is {}, new formid is {}", reqBO.getUid(),reqBO.getFormId(), miniappMsgForm.getFormId()); 113 logger.info("reset form id, uid is {},old formid is {}, new formid is {}", reqBO.getUid(),reqBO.getFormId(), miniappMsgForm.getFormId());
105 reqBO.setFormId(miniappMsgForm.getFormId()); 114 reqBO.setFormId(miniappMsgForm.getFormId());
106 - } 115 + }*/
107 116
108 // 发送消息 117 // 发送消息
109 - JSONObject result = sendMsgUpdateDB(reqBO, miniappMsgForm); 118 + JSONObject result = sendMsgUpdateDB(reqBO, miniSubscribe);
110 119
111 // token过期重新获取 120 // token过期重新获取
112 - if (result == null || result.getInteger("errcode") == 40001){  
113 - logger.warn("retry send msg because error is {}, uid is {},reqBO is {}", result != null ? result.toJSONString() : null, reqBO.getUid(), reqBO); 121 + if (result == null || (Integer)result.get("errcode") == 40001){
  122 + logger.warn("retry send msg because error is {}, uid is {},reqBO is {}", result != null ? result.toString() : null, reqBO.getUid(), reqBO);
114 miniAppAccessTokenService.deletAccessToken(reqBO.getMiniappType()); 123 miniAppAccessTokenService.deletAccessToken(reqBO.getMiniappType());
115 - return sendMsgUpdateDB(reqBO, miniappMsgForm); 124 + return sendMsgUpdateDB(reqBO, miniSubscribe);
116 } 125 }
117 - // 过期的formId 和 不合法的formid  
118 - else if(result.getInteger("errcode") == 41028 || result.getInteger("errcode")== 41029){  
119 - logger.info("retry send msg because error is {}, uid is {},reqBO is {}", result.toJSONString(),reqBO.getUid(),reqBO);  
120 - miniappMsgForm.setAvailableTimes(0);  
121 - miniappMsgFormDAO.updateByPrimaryKey(miniappMsgForm); 126 +
  127 + // TODO用户拒绝订阅需清空订阅次数
  128 + /*// 过期的formId 和 不合法的formid
  129 + else if((Integer)result.get("errcode") == 41028 || (Integer)result.get("errcode")== 41029){
  130 + logger.info("retry send msg because error is {}, uid is {},reqBO is {}", result.toString(),reqBO.getUid(),reqBO);
  131 + miniSubscribe.setAvailableTimes(0);
  132 + miniappMsgFormDAO.updateByPrimaryKey(miniSubscribe);
122 133
123 MiniappMsgForm miniappMsgFormNew = miniappMsgFormDAO.selectLastedAvailabByUid(reqBO.getUid(), reqBO.getMiniappType()); 134 MiniappMsgForm miniappMsgFormNew = miniappMsgFormDAO.selectLastedAvailabByUid(reqBO.getUid(), reqBO.getMiniappType());
124 135
@@ -130,19 +141,20 @@ public class MiniServiceAppImpl implements IMiniAppService { @@ -130,19 +141,20 @@ public class MiniServiceAppImpl implements IMiniAppService {
130 } 141 }
131 142
132 return sendMsgUpdateDB(reqBO, miniappMsgFormNew); 143 return sendMsgUpdateDB(reqBO, miniappMsgFormNew);
133 - } 144 + }*/
134 145
135 return result; 146 return result;
136 147
137 } 148 }
138 149
139 150
140 - private JSONObject sendMsgUpdateDB(MiniappMsgReqBO reqBO, MiniappMsgForm miniappMsgForm) { 151 + private JSONObject sendMsgUpdateDB(MiniappMsgReqBO reqBO, MiniSubscribe miniSubscribe) {
  152 + reqBO.setTouser(miniSubscribe.getOpenId());
141 JSONObject result = sendTemplateMsg(reqBO); 153 JSONObject result = sendTemplateMsg(reqBO);
142 -  
143 - if (result != null && result.getInteger("errcode") == 0){  
144 - miniappMsgForm.setAvailableTimes(miniappMsgForm.getAvailableTimes()-1);  
145 - miniappMsgFormDAO.updateByPrimaryKey(miniappMsgForm); 154 + if (result != null && (Integer)result.get("errcode") == 0){
  155 + miniSubscribe.setAvailableTimes(miniSubscribe.getAvailableTimes()-1);
  156 + miniSubscribeDAO.updateMiniSubscribe("mini_subscribe_" + reqBO.getMiniappType(), miniSubscribe);
  157 + //miniappMsgFormDAO.updateByPrimaryKey(miniappMsgForm);
146 //发送成功,记入发送数至 redis 158 //发送成功,记入发送数至 redis
147 saveSendRedis(reqBO.getPage()); 159 saveSendRedis(reqBO.getPage());
148 } 160 }
@@ -163,6 +175,7 @@ public class MiniServiceAppImpl implements IMiniAppService { @@ -163,6 +175,7 @@ public class MiniServiceAppImpl implements IMiniAppService {
163 String msgId = page.substring(index + MSG_ID_INDEX); 175 String msgId = page.substring(index + MSG_ID_INDEX);
164 //组装key:日期,value部分为 以场景id为key的hash结构 设置超时时间2天 176 //组装key:日期,value部分为 以场景id为key的hash结构 设置超时时间2天
165 RedisKeyBuilder redisKey = RedisKeyBuilder.newInstance().appendFixed(RedisCacheKeyConstant.MINI_SEND_NUM_KEY).appendVar(DateUtil.getToday("yyyyMMdd")); 177 RedisKeyBuilder redisKey = RedisKeyBuilder.newInstance().appendFixed(RedisCacheKeyConstant.MINI_SEND_NUM_KEY).appendVar(DateUtil.getToday("yyyyMMdd"));
  178 + //todo 若是
166 long result = pushRedisService.hashIncrement(redisKey,msgId,1,TWO_DAYS_HOURS); 179 long result = pushRedisService.hashIncrement(redisKey,msgId,1,TWO_DAYS_HOURS);
167 logger.info("saveSendRedis end with msgId is {},result is {}",msgId,result); 180 logger.info("saveSendRedis end with msgId is {},result is {}",msgId,result);
168 }catch (Exception e){ 181 }catch (Exception e){
@@ -196,7 +209,6 @@ public class MiniServiceAppImpl implements IMiniAppService { @@ -196,7 +209,6 @@ public class MiniServiceAppImpl implements IMiniAppService {
196 bodyParam.put("touser", reqBO.getTouser()); 209 bodyParam.put("touser", reqBO.getTouser());
197 bodyParam.put("template_id", reqBO.getTemplateId()); 210 bodyParam.put("template_id", reqBO.getTemplateId());
198 bodyParam.put("page", reqBO.getPage()); 211 bodyParam.put("page", reqBO.getPage());
199 - bodyParam.put("form_id", reqBO.getFormId());  
200 bodyParam.put("data", reqBO.getData()); 212 bodyParam.put("data", reqBO.getData());
201 213
202 if (StringUtils.isNotBlank(reqBO.getEmphasisKeyword())){ 214 if (StringUtils.isNotBlank(reqBO.getEmphasisKeyword())){