微信模板消息
扫码关注公众号
模板消息配置数据库表设计
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for kl_b_template_msg
-- ----------------------------
DROP TABLE IF EXISTS `kl_b_template_msg`;
CREATE TABLE `kl_b_template_msg` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`title` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '模板标题',
`scene_type` int(6) NULL DEFAULT NULL COMMENT '场景类型:1-注册成功通知;2-实名认证通知;3-收款结果通知',
`template_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '模板ID',
`first` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '模板开头',
`remark` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '模板结尾',
`font_color` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '字体颜色',
`keyword` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '主题词; 关键词,关键字:多个用英文逗号分割',
`jump_url` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '跳转地址',
`use_num` int(13) NULL DEFAULT NULL COMMENT '使用/发送次数',
`is_usable` int(1) NULL DEFAULT NULL COMMENT '是否可用:1-可用;0-停用',
`extend` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '扩展字段',
`create_time` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '创建时间',
`update_time` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
选择模板微信公众平台,找到适合自己的模板,模板ID 自定义参数进行数据库配置
根据自己业务所需选择适合自己的消息模板进行配置
代码封装service、impl
package com.kalo.yepay.domain.service;
import com.kalo.yepay.domain.pojo.TemplateMsg;
import java.util.List;
public interface TemplateMsgService {
/**
* @MethodName: getTemplateMsg
* @Param: [sceneType]
* @Author: Calo_Pangu
* @Date: 2020-1-9 19:34
* @Description: TODO 根据场景类型获取模板配置
*/
TemplateMsg getTemplateMsg(Integer sceneType);
/**
* @MethodName: useNum
* @Param: [templateMsg]
* @Author: Calo_Pangu
* @Date: 2020-1-9 19:38
* @Description: TODO 统计模板发送次数
*/
void useNum(TemplateMsg templateMsg);
/**
* @MethodName: sendTemplateMsg
* @Param: [sceneType 模板场景类型, touser 接收者openid, values 模板内容]
* @Author: Calo_Pangu
* @Date: 2020-1-9 19:52
* @Description: TODO 发送模板消息
*/
void sendTemplateMsg(Integer sceneType,String userinfoid,List<String> values);
}
package com.kalo.yepay.domain.service.impl;
import com.alibaba.fastjson.JSON;
import com.kalo.yepay.common.service.RedisToolService;
import com.kalo.yepay.domain.mapper.TemplateMsgMapper;
import com.kalo.yepay.domain.pojo.TemplateMsg;
import com.kalo.yepay.domain.pojo.UserAuths;
import com.kalo.yepay.domain.service.TemplateMsgService;
import com.kalo.yepay.domain.service.UserAuthsService;
import com.kalo.yepay.sdk.tempmsg.request.TemplateMsgSend;
import com.kalo.yepay.sdk.tempmsg.util.HttpUtil;
import com.kalo.yepay.utils.DateUtils;
import com.kalo.yepay.utils.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;
import java.util.Arrays;
import java.util.List;
import java.util.TreeMap;
/**
* @ClassName TemplateMsgServiceImpl
* @Description: TODO :
* @Author Calo-Pangu
* @Date 2020-1-9 19:33
* @Version V1.0
**/
@Slf4j
@Service
public class TemplateMsgServiceImpl implements TemplateMsgService {
@Value("${你的application.properties或yml配置}")
private String requestURL;
@Value("${你的application.properties或yml配置 这里我是存放redis的 redis存储的key}")
private String accessTokenKey;
@Autowired
private TemplateMsgMapper templateMsgMapper;
@Autowired
private RedisToolService redisToolService;
@Autowired
private UserAuthsService userAuthsService;
/**
* @MethodName: getTemplateMsg
* @Param: [sceneType]
* @Author: Calo_Pangu
* @Date: 2020-1-9 19:34
* @Description: TODO 根据场景类型获取模板配置
*/
@Override
public TemplateMsg getTemplateMsg(Integer sceneType) {
log.warn("--------------------------------------- 根据模板场景类型获取模板配置 ---------------------------------------");
Example example = new Example(TemplateMsg.class);
Example.Criteria criteria = example.createCriteria();
criteria.andEqualTo("sceneType", sceneType);
criteria.andEqualTo("isUsable", 1);
return templateMsgMapper.selectOneByExample(example);
}
/**
* @MethodName: useNum
* @Param: [templateMsg]
* @Author: Calo_Pangu
* @Date: 2020-1-9 19:38
* @Description: TODO 统计模板发送次数
*/
@Override
public void useNum(TemplateMsg templateMsg) {
log.warn("--------------------------------------- 统计模板发送次数 ---------------------------------------");
Integer useNum = templateMsg.getUseNum();//使用前次数
templateMsg.setUseNum(useNum + 1);
templateMsg.setUpdateTime(DateUtils.getDateTime());
templateMsgMapper.updateByPrimaryKeySelective(templateMsg);
}
/**
* @MethodName: sendTemplateMsg
* @Param: [sceneType 模板场景类型, touser 接收者openid, values 模板内容]
* @Author: Calo_Pangu
* @Date: 2020-1-9 19:52
* @Description: TODO 发送模板消息
*/
@Override
public void sendTemplateMsg(Integer sceneType,String userinfoid, List<String> values) {
List<UserAuths> userAuths = userAuthsService.userAuthsList(userinfoid);
if (values.size() > 0 && userAuths.size() > 0) {
UserAuths userAuth = userAuths.get(0);
//1. 拿到模板配置信息
TemplateMsg templateMsg = getTemplateMsg(sceneType);
//2. ACCESS_TOKEN 从 Redis 获取 拼接URL
String sendURL = requestURL.replace("ACCESS_TOKEN", redisToolService.get(accessTokenKey));
//3. 数据库模板keywords 拿到keyword
List<String> keywords = Arrays.asList(templateMsg.getKeyword().split(","));
//4. 构建请求参数
TemplateMsgSend templateMsgSend = new TemplateMsgSend();
templateMsgSend.setTouser(userAuth.getOpenid());
templateMsgSend.setTemplate_id(templateMsg.getTemplateId());
templateMsgSend.setUrl(templateMsg.getJumpUrl());
TreeMap<String, TreeMap<String, String>> data = new TreeMap<>();
String first = templateMsg.getFirst().replace("USER",userAuth.getNick_name());
data.put("first", templateMsgSend.item(first, templateMsg.getFontColor()));
for (int i = 0; i < keywords.size(); i++) {
data.put(keywords.get(i), templateMsgSend.item(values.get(i), templateMsg.getFontColor()));
}
data.put("remark", templateMsgSend.item(templateMsg.getRemark(), templateMsg.getFontColor()));
templateMsgSend.setData(data);
//5. 发送模板消息
String request = JSON.toJSONString(templateMsgSend);
log.warn("发送模板消息请求参数:{}", request);
JSONObject result = HttpUtil.sendPost(sendURL, request);
log.warn("发送模板消息返回信息:{}", result);
//6. 发送成功后统计发送次数
String errcode = JSONUtil.getValNetsf(result, "errcode");
String errmsg = JSONUtil.getValNetsf(result, "errmsg");
//7. 更新模板发送次数
if ("0".equalsIgnoreCase(errcode) && "ok".equalsIgnoreCase(errmsg)){
useNum(templateMsg);
}
}
}
}
HttpUtil 工具类
package com.kalo.yepay.sdk.tempmsg.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
@Slf4j
public class HttpUtil {
private static final String charset = "UTF-8";
private static final String requestMode = "POST";
private static final String NoSuchAlgorithm = "No Such Algorithm Exception [无此算法异常]:{}";
private static final String KeyManagement = "Key Management Exception [密钥管理异常]:{}";
@SuppressWarnings("static-access")
public static JSONObject sendPost(String urls, String data) {
JSONObject result = new JSONObject();
StringBuffer sb = new StringBuffer();
OutputStreamWriter outputStreamWriter = null;
BufferedReader bufferedReader = null;
try {
URL url = new URL(urls);
trustAllHttpsCertificates();
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
HttpsURLConnection httpsConn = (HttpsURLConnection) url.openConnection();
httpsConn.setUseCaches(false);
httpsConn.setDoOutput(true);
httpsConn.setDoInput(true);
httpsConn.setFollowRedirects(true);
httpsConn.setInstanceFollowRedirects(true);
httpsConn.setRequestMethod(requestMode);
outputStreamWriter = new OutputStreamWriter(httpsConn.getOutputStream(), charset);
outputStreamWriter.write(data);
outputStreamWriter.flush();
bufferedReader = new BufferedReader(new InputStreamReader(httpsConn.getInputStream(), charset));
String inputLine;
while ((inputLine = bufferedReader.readLine()) != null) {
sb.append(inputLine);
}
log.info("HttpClientPost Response Info:[{}]",result.fromObject(sb.toString()));
return result.fromObject(sb.toString());
} catch (Exception e) {
log.error("Key Management Exception [密钥管理异常]", e.getMessage());
} finally {
try {
outputStreamWriter.close();
bufferedReader.close();
} catch (IOException e) {
log.error("IOException [关闭请求流异常]", e.getMessage());
}
}
return result;
}
private static void trustAllHttpsCertificates() {
try {
javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
javax.net.ssl.TrustManager tm = new MiTM();
trustAllCerts[0] = tm;
javax.net.ssl.SSLContext sc;
sc = javax.net.ssl.SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (NoSuchAlgorithmException e) {
log.error(NoSuchAlgorithm, e.getMessage());
} catch (KeyManagementException e) {
log.error(KeyManagement, e.getMessage());
}
}
static class MiTM implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public boolean isServerTrusted(java.security.cert.X509Certificate[] certs) {
return true;
}
public boolean isClientTrusted(java.security.cert.X509Certificate[] certs) {
return true;
}
public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
throws java.security.cert.CertificateException {
return;
}
public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
throws java.security.cert.CertificateException {
return;
}
}
static HostnameVerifier hostnameVerifier = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
}
调用方式
效果展示