昨天写了微信小程序授权登录的教程 https://mp.csdn.net/postedit/84993265 其中关于一些名词的解释可以参考这个
1:一个可以测试的微信小程序
2:此微信小程序的APPID和APPscret
3:模板id(创建模板就会生成)
4:接收者的openid
推送模板消息的场景在开发时用的特别多,此项目是类似一个购物网站,所以在买家购买了商品后需要给买家发送模板消息告知它。发送模板消息的流程大体分为步两步。
1.获取用户的formid
在微信小程序中,我们不能像微信公众号那样大量给用户发送模板消息,每次发送模板消息都需要一个凭证,那就是formid。用户每次提交表单或者进行一次支付操作会产生一个formid(获取formid的详细说明请查看官方文档),这个fromid有效期为7天,而且用这个formid发送的模板消息只能发送给它本人(没错,每一个openid产生的formid在发送模板消息只能发送给相应的openid)。所以如果我们想要随时随地发消息的话就只能把用户日常的操作改为表单操作,然后通过SpringMVC拦截器收集用户上传的formid,放到一个队列中,需要给他发送消息时就从队列中获取它的formid使用即可。
首先建立一个formid管理器
public class FormidCollection {
private static HashMap> userFormidMap = new HashMap>();
//添加一个formid
public static synchronized void AddFormid(String openid, String formid) {
LinkedBlockingQueue formidlist = userFormidMap.get(openid);
//如果不存在formid队列,创建一个
if(formidlist == null) {
formidlist = new LinkedBlockingQueue(50);
}
//如果队列满了,就把对头的一个元素去掉
if(formidlist.size() == 50) {
formidlist.poll();
}
//添加formid
formidlist.offer(new Formid(formid,new Date().getTime()/1000));
//更新收集器
userFormidMap.put(openid, formidlist);
}
public static synchronized String getFormid(String openid) {
if (openid == null) {
return null;
}
LinkedBlockingQueue queue = userFormidMap.get(openid);
if(queue == null) {
return null;
}
//返回对头的
long nowtime = new Date().getTime() / 1000;
Formid formid = null;
//如果超过7天就重新获取一个
do {
formid = queue.poll();
//如果队列空了就返回null
if(formid == null) {
return null;
}
}while(nowtime - formid.getDate() > 604740);
return formid.getFormid();
}
public static void clearLoginflag() {
userFormidMap.clear();
}
}
在SpringMVC拦截器中捕获formid,并与之openid对应起来,以便之后使用。
2.发送模板消息
现在我们拥有了用户的openid和formid就可以对他进行模板消息推送了。发送的方式就是对微信后台的一个接口进行一次post请求,在请求的参数中添加我们要发送模板消息的各种信息即可
接口url:
https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=ACCESS_TOKEN
url中的ACCESS_TOKEN是调用微信小程序后台的凭证,要通过我们自己的小程序的appid和appsecret获取然后替换,access_token2小时刷新一次,可以用一个定时器去定时刷新然后存到缓存。
请求的参数
openid:用户对应小程序的唯一标识,此处传入要发送的对象的openid
templateid:模板id
formid:专属于接收者openid的formid,不相符则不能发送成功
page:点击模板消息跳转小程序的页面的具体路径
data:模板消息的内容,可以做成一个map然后转为json
官方模板消息参数图
org.apache.httpcomponents
httpclient
4.5.2
public static void WXuserinfo(String openid, String templateid, String formid, String accesstoken, String page, Map data) {
StringBuilder url = new StringBuilder("https://api.weixin.qq.com/cgibin/message/wxopen/template/send?access_token=");
url.append(accesstoken);//设置accesstoken
JSONObject json = new JSONObject();
json.put("touser", openid);//设置openid
json.put("template_id", templateid);//设置模板id
json.put("form_id", formid);//设置formid
json.put("data", data);//设置模板消息内容
json.put("page", page);//跳转微信小程序页面路径(非必须)
Map map = null;
try {
HttpClient client =HttpClientBuilder.create().build();//构建一个Client
HttpPost post = new HttpPost(url.toString());//构建一个POST请求
StringEntity s = new StringEntity(json.toString(), "UTF-8");
s.setContentEncoding("UTF-8");
s.setContentType("application/json; charset=UTF-8");
post.setEntity(s);//设置编码,不然模板内容会乱码
HttpResponse response = client.execute(post);//提交POST请求
HttpEntity result = response.getEntity();//拿到返回的HttpResponse的"实体"
String content = EntityUtils.toString(result);
System.out.println(content);//打印返回的消息
JSONObject res = JSONObject.fromObject(content);//转为json格式
//把信息封装到map
map = MdzwUtils.parseJSON2Map(res);
if(map != null && "ok".equals(map.get("errmsg"))) {
System.out.println("模版消息发送成功");
}else {
//封装一个异常
StringBuilder sb = new StringBuilder("模版消息发送失败\n");
sb.append(map.toString());
throw new Exception(sb.toString());
}
} catch (Exception e) {
e.printStackTrace();
}
}
发送模板消息时就从formid管理器中获取该用户对应的formid,如果能获取到就发送模板消息。其中要注意的时formid有效期为7天,要注意保存的时长。还有模板消息内容的填写,一定要把键的名称写对了(键的名称在模板详情界面就可以看到)。page路径可以带参数,具体形式与一般的get请求方式相同。
https://developers.weixin.qq.com/miniprogram/dev/api/sendTemplateMessage.html
微信官方文档有详细的教程,写的很好。
本文只是笔者多次爬坑之后的笔记,如果有不懂得可以在下方留言。要是我写的地方有出错的地方,也请大家指出,谢谢#抱拳