本篇文章讲解了如何向用户发送模板消息,前提是已经搭建了微信开发环境。读完本文后,实现的主要效果如下
向已绑定用户发送模板消息,如我们常见的消费通知、订单通知等业务都可以用该功能实现。理论知识就不反复强调了,实践是检验真理的唯一标准,直接看例子,相信大家就能一目了然了。下面我们来看下要准备哪里步骤:
登录测试公众号/正式公众号(认证后的服务号),测试公众号:模板消息接口->新增测试模板中添加模板,正式公众号:在功能->模板消息中添加模板,模板可以在模板库中选择,如果没有你需要的模板,可以申请添加,一个月可以申请三条。模板添加成功后,有个模板ID(用于接口调用)。
20190602更新:
很多人私信问,代码里面的模板是哪里来的。看上面,是微信后台配置的,模板内容和内容变量,会自动生成模板ID,在程序里面调用;变量要配置,值为程序里面传入的参数。
具体如何配置可以参看官方文档:https://mp.weixin.qq.com/wiki 中消息管理->发送消息-模板消息接口
封装发送模板接口
package com.entry;
import java.util.Map;
/**
* 模板基类
* @author CLiang
*
*/
public class WxTemplate {
private String template_id;//模板ID
private String touser;//目标客户
private String url;//用户点击模板信息的跳转页面
private String topcolor;//字体颜色
private Map data;//模板里的数据
public String getTemplate_id() {
return template_id;
}
public void setTemplate_id(String template_id) {
this.template_id = template_id;
}
public String getTouser() {
return touser;
}
public void setTouser(String touser) {
this.touser = touser;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getTopcolor() {
return topcolor;
}
public void setTopcolor(String topcolor) {
this.topcolor = topcolor;
}
public Map getData() {
return data;
}
public void setData(Map data) {
this.data = data;
}
}
一条模板包含多条数据,模板数据类封装
package com.entry;
/**
* 模板数据
* @author CLiang
*
*/
public class TemplateData {
private String value;//模板显示值
private String color;//模板显示颜色
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
看文档,发送模板信息接口为:https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN,前期模板数据都准备好了,现在缺少ACCESS_TOKEN,缺什么就去获取什么,查看文档可知获取ACCESS_TOKEN接口为:https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET,现在就封装个获取ACCESS_TOKEN的请求接口:
package com.Servlet;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.Common.AccessTokenInfo;
import com.entry.AccessToken;
import com.util.NetWorkHelper;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
/**
* 用于获取accessToken的Servlet
* Created by CLiang on 2018/8/14.
*/
@WebServlet(
name = "AccessTokenServlet",
urlPatterns = {"/AccessTokenServlet"},
loadOnStartup = 1,
initParams = {
@WebInitParam(name = "appId", value = "wx2cf6086315216ab0"),
@WebInitParam(name = "appSecret", value = "a4362add70c148da80e7442100782e4e")
})
public class AccessTokenServlet extends HttpServlet {
@Override
public void init() throws ServletException {
System.out.println("启动WebServlet");
super.init();
final String appId = getInitParameter("appId");
final String appSecret = getInitParameter("appSecret");
//开启一个新的线程
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
//获取accessToken
AccessTokenInfo.accessToken = getAccessToken(appId, appSecret);
//获取成功
if (AccessTokenInfo.accessToken != null) {
//获取到access_token 休眠7000秒,大约2个小时左右
Thread.sleep(7000 * 1000);
//Thread.sleep(10 * 1000);//10秒钟获取一次
} else {
//获取失败
Thread.sleep(1000 * 3); //获取的access_token为空 休眠3秒
}
} catch (Exception e) {
System.out.println("发生异常:" + e.getMessage());
e.printStackTrace();
try {
Thread.sleep(1000 * 10); //发生异常休眠1秒
} catch (Exception e1) {
}
}
}
}
}).start();
}
/**
* 获取access_token
*
* @return AccessToken
*/
private AccessToken getAccessToken(String appId, String appSecret) {
NetWorkHelper netHelper = new NetWorkHelper();
/**
* 接口地址为https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET,其中grant_type固定写为client_credential即可。
*/
String Url = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", appId, appSecret);
//此请求为https的get请求,返回的数据格式为{"access_token":"ACCESS_TOKEN","expires_in":7200}
String result = netHelper.getHttpsResponse(Url, "");
System.out.println("获取到的access_token="+result);
//使用FastJson将Json字符串解析成Json对象
JSONObject json = JSON.parseObject(result);
AccessToken token = new AccessToken();
token.setAccessToken(json.getString("access_token"));
token.setExpiresin(json.getInteger("expires_in"));
return token;
}
}
注意:ACCESS_TOKEN有请求次数限制,而且会在获取后7200秒后自动失效,所以要妥善保存好ACCESS_TOKEN,本实例是放在内存里面,每次获取时,判断是否已经存在,不存在才去请求,而如何保证保存的ACCESS_TOKEN为有效的呢?一般解决方法是定时请求获取最新ACCESS_TOKEN,更新内存里的数据,可使用servlet线程定时请求。
现在ACCESS_TOKEN已经获取,万事俱备,只欠调用了,下面给出发送模板
{{first.DATA}}
订单编号:{{keyword1.DATA}}
订单类型:{{keyword2.DATA}}
商品名称:{{keyword3.DATA}}
{{remark.DATA}}
这里是在测试公众号添加的模板,申请测试号网址http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login
/**
* 发送模板消息调用实例
* @param map 封装了解析结果的Map
* @return 空
*/
private static String buildTempMessage(Map map) {
//发送方帐号
String fromUserName = map.get("FromUserName");
// 开发者微信号
String toUserName = map.get("ToUserName");
WxTemplate template = new WxTemplate();
template.setUrl("www.baidu.com");
template.setTouser(fromUserName);
template.setTopcolor("#000000");
template.setTemplate_id("EjM9IHXD5vD1oEBO0PuAcgLTG2-74d6mRdspS6XRh9o");
Map m = new HashMap();
TemplateData first = new TemplateData();
first.setColor("#000000");
first.setValue("您好,您有一条待确认订单。");
m.put("first", first);
TemplateData keyword1 = new TemplateData();
keyword1.setColor("#328392");
keyword1.setValue("O00001");
m.put("keyword1", keyword1);
TemplateData keyword2 = new TemplateData();
keyword2.setColor("#328392");
keyword2.setValue("预定订单");
m.put("keyword2", keyword2);
TemplateData keyword3 = new TemplateData();
keyword3.setColor("#328392");
keyword3.setValue("可口可乐");
m.put("keyword3", keyword3);
TemplateData remark = new TemplateData();
remark.setColor("#929232");
remark.setValue("请及时确认订单!");
m.put("remark", remark);
sendMessageBefore("",template, m);
return "";
}
上面的代码需要修改测试公众号生成的模板ID。
/**
* 发送模板消息前获取token
* @param template_id_short 模板库中模板的编号
* @param t
* @param m
*/
public static void sendMessageBefore(String template_id_short,WxTemplate t,Map m){
AccessToken token = null;
token = AccessTokenInfo.accessToken;
// if(template_id_short!=null&&!"".equals(template_id_short)){
// WxTemplate template = WeixinUtil.getTemplate(template_id_short,token.getToken());
// t.setTemplate_id(template.getTemplate_id());
// }
t.setData(m);
sendMessage(t,token.getAccessToken());
}
/**
* 发送模板消息
* @param t
* @param accessToken
* @return
*/
public static int sendMessage(WxTemplate t,String accessToken) {
int result = 0;
// 拼装创建菜单的url
String url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN".replace("ACCESS_TOKEN", accessToken);
// 将菜单对象转换成json字符串
String jsonMenu = JSONObject.toJSONString(t);
// 调用接口创建菜单
String response = WeChatApiUtil.httpsRequestToString(url, "POST", jsonMenu);
JSONObject jsonObject = JSON.parseObject(response);
//JSONObject jsonObject = httpRequest(url, "POST", jsonMenu);
if (null != jsonObject) {
if (0 != jsonObject.getIntValue("errcode")) {
result = jsonObject.getIntValue("errcode");
System.out.println("发送模板消息失败 errcode:{"
+jsonObject.getIntValue("errcode")+"} errmsg:{"+jsonObject.getString("errmsg")+"}");
}
}
return result;
}
至此,发送消息流程已全部完成。向测试公众号发送“模板”后,微信返回的模板显示效果如下
所有源代码、请参考 https://download.csdn.net/download/u011752195/10604165
如有不足、不解或者改进之处,欢迎大家在评论区指出,相互交流。
整个下来通过网络资源整理学习,并且完善了一些代码,程序员挺累的
如果觉得不错可以点歌关注吧~
后续将分享更多程序代码~
合作请联系chat 1012638162
有问题可以在下面提出来~
如果本文对您有一丢丢帮助,可以通过下方二维码支持作者哦 后续将分享更多高质量代码~
Alipay WeChat