Java实现微信公众号发送模版消息
作者:热水瓶、 发布时间:2021-07-16 17:03:35
微信公众号发送模版消息 背景:如下图,当用户发布需求的时候,公众号自定推送消息。例如:微信支付的时候,公众号会推送支付成功消息
前提:发送模版消息,顾名思义,前提就是需要有模版,那么在哪里配置模版呢?
微信公众号平台–>广告与服务–>模版消息–>我的模版
模版消息是已经申请过的模版,如果里面的模版都不符合自己业务的话,可以到模版库里找,然后添加到「我的模版」。也可以按照自己的需求申请新的模版,一般第二个工作日会审核通过。
在模版详情可以查看模版的格式,下图左边红框是消息最终展示的效果,
右边红框是需要传的参数。
有了模版之后,模版ID就是我们要放进代码里的,复制出来。
消息模版准备好之后,暂时不要写代码奥,查看微信开发文档,看看发送模版都需要哪些参数。
微信开发文档–>基础消息能力–>模版消息接口–「发送模版消息」
查看微信开发文档
发送模版消息
http请求方式: POST https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN注:url和miniprogram都是非必填字段,若都不传则模板无跳转;若都传,会优先跳转至小程序。开发者可根据实际需要选择其中一种跳转方式即可。当用户的微信客户端版本不支持跳小程序时,将会跳转至url。
返回码说明
在调用模板消息接口后,会返回JSON数据包。
正常时的返回JSON数据包示例:
{
“errcode”:0,
“errmsg”:“ok”,
“msgid”:200228332
}
发送模版所需参数:
模版ID和openId是必须有的,剩下的就是和自己业务有关了。
上面的内容都搞定之后,就可以开始撸代码了
发送模版微信返回Dto
@Data
public class TemplateMsgResultDto extends ResultState {
/**
* 消息id(发送模板消息)
*/
private String msgid;
}
发送模版微信返回状态
@Data
public class ResultState implements Serializable {
/**
* 状态
*/
private int errcode;
/**
* 信息
*/
private String errmsg;
}
微信模版消息请求参数实体类
@Data
public class WxTemplateMsg {
/**
* 接收者openId
*/
private String touser;
/**
* 模板ID
*/
private String template_id;
/**
* 模板跳转链接
*/
private String url;
// "miniprogram":{ 未加入
// "appid":"xiaochengxuappid12345",
// "pagepath":"index?foo=bar"
// },
/**
* data数据
*/
private TreeMap<String, TreeMap<String, String>> data;
/**
* 参数
*
* @param value 值
* @param color 颜色 可不填
* @return params
*/
public static TreeMap<String, String> item(String value, String color) {
TreeMap<String, String> params = new TreeMap<String, String>();
params.put("value", value);
params.put("color", color);
return params;
}
}
Java封装模版信息代码
public TemplateMsgResultDto noticeTemplate(TemplateMsgVo templateMsgVo) {
// 模版ID
String templateId="XXX";
TreeMap<String, TreeMap<String, String>> params = new TreeMap<>();
//根据具体模板参数组装
params.put("first", WxTemplateMsg.item("恭喜!您的需求已发布成功", "#000000"));
params.put("keyword1", WxTemplateMsg.item(templateMsgVo.getTaskName(), "#000000"));
params.put("keyword2", WxTemplateMsg.item("需求已发布", "#000000"));
params.put("remark", WxTemplateMsg.item("请耐心等待审核", "#000000"));
WxTemplateMsg wxTemplateMsg = new WxTemplateMsg();
// 模版ID
wxTemplateMsg.setTemplate_id(templateId);
// openId
wxTemplateMsg.setTouser(templateMsgVo.getOpenId());
// 关键字赋值
wxTemplateMsg.setData(params);
String data = JsonUtils.ObjectToString(wxTemplateMsg);
return handleSendMsgLog(data);
}
发送模版代码
private TemplateMsgResultDto handleSendMsgLog(String data) {
TemplateMsgResultDto resultDto = new TemplateMsgResultDto();
try {
resultDto = sendTemplateMsg(data);
} catch (Exception exception) {
log.error("发送模版失败", exception);
}
// TODO 可以记录一下发送记录的日志
return resultDto;
}
public TemplateMsgResultDto sendTemplateMsg(String data) throws Exception {
// 获取token
String accessToken = getAccessToken();
// 发送消息
HttpResult httpResult = HttpUtils.stringPostJson(ConstantsPath.SEND_MESSAGE_TEMPLATE_URL + accessToken, data);
return IMJsonUtils.getObject(httpResult.getBody(), TemplateMsgResultDto.class);
}
/**
* 获取全局token
*/
public String getAccessToken() {
String key = ConstantsRedisKey.ADV_WX_ACCESS_TOKEN;
// 从redis缓存中获取token
if (redisCacheManager.get(key) != null) {
return (String) redisCacheManager.get(key);
}
// 获取access_token
String url = String.format(ConstantsPath.WX_ACCESS_TOKEN_URL, appid, secret);
ResponseEntity<String> result = restTemplate.getForEntity(url, String.class);
if (result.getStatusCode() == HttpStatus.OK) {
JSONObject jsonObject = JSON.parseObject(result.getBody());
String accessToken = jsonObject.getString("access_token");
// Long expires_in = jsonObject.getLong("expires_in");
redisCacheManager.set(key, accessToken, 1800);
return accessToken;
}
return null;
}
微信地址常量类
public class ConstantsPath {
/**
* 微信公众号获取全局token
*/
public static final String WX_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
/**
* 微信发送模版消息
*/
public static final String SEND_MESSAGE_TEMPLATE_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=";
}
Json工具类
@Slf4j
public class JsonUtils {
private static ObjectMapper json;
static {
json = new ObjectMapper();
json.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
json.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
/**
* 序列化为JSON字符串
*/
public static String ObjectToString(Object object) {
try {
return (json.writeValueAsString(object));
} catch (Exception e) {
log.error("序列化为JSON字符串出错",e);
}
return null;
}
public static <T> T getObject(String jsonString, Class<T> clazz) {
if (StringUtils.isEmpty(jsonString))
return null;
try {
return json.readValue(jsonString, clazz);
} catch (Exception e) {
log.error("将JSON字符串转化为Map出错",e);
return null;
}
}
}
Http工具类
@Component
@Slf4j
public class HttpUtils {
private static String sourcePath;
public static HttpResult stringPostJson(String path, String content) throws Exception{
return stringPost(path, null, content, "utf-8", "utf-8", "application/json");
}
public static HttpResult stringPost(String path, Map<String,String> headerMap, String content, String contentencode, String encode, String contentType) throws Exception{
StringEntity entity = new StringEntity(content, contentencode);
entity.setContentType(contentType);
return post(path, headerMap, entity, encode);
}
private static HttpResult post(String path, Map<String,String> headerMap, HttpEntity entity, String encode){
HttpResult httpResult = new HttpResult();
CloseableHttpClient httpClient = null;
CloseableHttpResponse response = null;
try{
HttpPost httpPost = new HttpPost(getURI(path));
LaxRedirectStrategy redirectStrategy = new LaxRedirectStrategy();
httpClient = HttpClientBuilder.create().setRedirectStrategy(redirectStrategy).build();
RequestConfig requestConfig = RequestConfig.custom()
.setSocketTimeout(120000)
.setConnectTimeout(120000)
.setConnectionRequestTimeout(120000)
.setCircularRedirectsAllowed(true)
.setRedirectsEnabled(true)
.setMaxRedirects(5)
.build();
httpPost.setConfig(requestConfig);
httpPost.setHeader("User-Agent", header);
if(headerMap != null && headerMap.size() > 0){
for(String name:headerMap.keySet()) {
httpPost.addHeader(name, headerMap.get(name));
}
}
httpPost.setEntity(entity);
response = httpClient.execute(httpPost);
httpResult.setStatus(response.getStatusLine().getStatusCode());
if(httpResult.getStatus() == 200){
HttpEntity resEntity = response.getEntity();
httpResult.setBody(EntityUtils.toString(resEntity, encode));
}
}catch(Exception ex){
log.error("post请求出错", ex);
}finally{
try{
if(response != null){
response.close();
}
if(httpClient != null){
httpClient.close();
}
}catch(Exception ex) {
log.error("post请求关闭资源出错", ex);
}
}
return httpResult;
}
}
来源:https://blog.csdn.net/mxs1226/article/details/122731633
猜你喜欢
- 本文实例为大家分享了java图形用户界面实现菜单功能的具体代码,供大家参考,具体内容如下题目:编写一个图形用户界面,实现菜单的功能。有3个一
- 本文实例讲述了Java擦除和转换。分享给大家供大家参考,具体如下:一 点睛在严格的泛型代码里,带泛型声明的类总应该带着类型参数。
- 上篇文章已经对Synchronized关键字做了初步的介绍,从字节码层面介绍了Synchronized关键字,最终字节码层面就是monito
- java模拟银行ATM机操作(基础版),供大家参考,具体内容如下实现的功能需求:修改密码之后,就会自动退出登录,再重新登录,若登录成功才能验
- 一、LinkedHashMap的类继承关系二、源码分析1.自己对LinkedHashMap的理解从继承关系上,我们看到LinkedHashM
- 介绍在 C/C++ 中,程序员负责对象的创建和销毁。通常程序员会忽略无用对象的销毁。由于这种疏忽,在某些时候,为了创建新对象,可能没有足够的
- 首先,查到java里文件重命名的方法为:renameTo();我将180张图片放在d:\\backup下,用下面的程序进行重命名:publi
- 点击此处:官网下载 根据自己的系统 ,下载相应的JDK版本。1. JDK1.8安装1.双击下载的安装包(.exe文件),进行安装。2.点击“
- 一、BIO、NIO、AIO学习Netty需要了解BIO、NIO、AIO,具体可参考Java网络编程IO模型 — BIO、
- 一、实体类转换成XML将实体类转换成XML需要使用XmlSerializer类的Serialize方法,将实体类序列化public stat
- 摘要 &n
- 一、网络爬虫的基本知识网络爬虫通过遍历互联网络,把网络中的相关网页全部抓取过来,这体现了爬的概念。爬虫如何遍历网络呢,互联网可以看做是一张大
- Android四种数据存储的应用方式作为一个完整的应用程序,数据存储操作是必不可少的。因此,Android系统一共提供了四种数据存储方式。分
- SpringBoot多线程进行异步请求的处理近期在协会博客园中,有人发布了博客,系统进行查重的时候由于机器最低配置进行大量计算时需要十秒左右
- Mybatis Log Plugin使用今天发现大部分猿友关于查看执行sql语句的方法,只知道将其输出到控制台。然而还有更简便的方法,就是使
- 实现方案:我们直接参考实例代码:private String pattern = "((http|ftp
- 目录一、自定义认证逻辑二、自定义过滤器总结一、自定义认证逻辑生成验证码工具<dependency> &
- 前言 ChatGPT已经组件放开了,现在都可以基于它写插件了。但是说实话我还真没想到可以用它干嘛,也许
- 1 spring-retry是什么?以往我们在进行网络请求的时候,需要考虑网络异常的情况,本文就介绍了利用spring-retry,是spr
- Java中,只有8种基本类型不是对象,例如:4种整形类型(byte, short, int,long),2种浮点类型(flout, doub