下发统一消息
用于通过服务号模板消息下发小程序和公众号统一的服务消息,接口文档地址:
https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-message-management/uniform-message/sendUniformMessage.html
开通模板功能:
登录公众号后台,在“新的功能/广告与服务”中开通模板消息。
access_token 获取:
调用 uniform_send
发送消息需要 access_token
,获取 access_token
方法有两种:使用 getAccessToken
或者 authorizer_access_token
,这里使用的是 getAccessToken
方式。
getAccessToken
:有效期目前为 7200 秒,并且是有上限次数的(具体上限次数在公众号后台的接口权限中查看),需做缓存处理,防止超过次数导致失效。
编码
代码语言:javascript复制package com.demo.util;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import java.time.Duration;
import java.time.Instant;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
/**
* @ClassName: WxapiUtil.java
* @ClassPath: com.demo.util.WxapiUtil.java
* @Description: 微信工具
* @Author: tanyp
* @Date: 2023/9/18 10:07
**/
@Slf4j
public class WxapiUtil {
/**
* @MonthName: getToken
* @Description: 获取token
* @Author: tanyp
* @Date: 2023/9/18 11:07
* @Param: [appid, secret]
* @return: java.lang.String
**/
public synchronized static String getToken(String appid, String secret) {
JSONObject obj = accessTokenMap.get(appid);
if (Objects.isNull(obj) || Duration.between((Instant) obj.get("time"), Instant.now()).getSeconds() > 7100) {
String token = getAccessToken(appid, secret);
accessTokenMap.put(appid, JSONObject.of("token", token, "time", Instant.now()));
log.info("========获取 AccessToken======:{}", accessTokenMap.get(appid));
return token;
} else {
log.info("========缓存取 AccessToken======:{}", obj);
return obj.getString("token");
}
}
public static String getAccessToken(String appid, String secret) {
String AccessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" appid "&secret=" secret;
HttpClient client = null;
String accessToken = null;
try {
client = new DefaultHttpClient();
HttpGet httpget = new HttpGet(AccessTokenUrl);
ResponseHandler<String> responseHandler = new BasicResponseHandler();
String response = client.execute(httpget, responseHandler);
JSONObject OpenidJSON = JSONObject.parseObject(response);
accessToken = String.valueOf(OpenidJSON.get("access_token"));
} catch (Exception e) {
log.error("获取token异常:", e);
} finally {
client.getConnectionManager().shutdown();
}
return accessToken;
}
/**
* @MonthName: uniformSend
* @Description: 下发统一消息
* @Author: tanyp
* @Date: 2023/9/18 10:10
* @return: java.lang.String
**/
public static String uniformSend(String appid, String secret, String openId, String pagepath, String mpAppId, String url, String templateId, JSONObject data) {
HttpClient client = null;
try {
client = HttpClients.createDefault();
// 获取 access_token
String token = getToken(appid, secret);
if (Objects.isNull(token) && Objects.equals("", token)) {
log.error("获取AccessToken异常");
return "获取 AccessToken 异常";
}
// 发送消息
String messageUrl = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send?access_token=";
HttpPost httpPost = new HttpPost(messageUrl token);
JSONObject params = new JSONObject();
params.put("touser", openId); // 接收者openid
// 公众号模板消息相关的信息
JSONObject mp_template_msg = new JSONObject();
mp_template_msg.put("appid", mpAppId);
mp_template_msg.put("template_id", templateId);
// 模板跳转链接
mp_template_msg.put("url", url);
// 跳小程序所需数据,不需跳小程序可不用传该数据
JSONObject miniprogram = new JSONObject();
miniprogram.put("appid", appid);
miniprogram.put("pagepath", pagepath);
mp_template_msg.put("miniprogram", miniprogram);
// 模板数据
mp_template_msg.put("data", data);
params.put("mp_template_msg", mp_template_msg);
httpPost.setEntity(new StringEntity(params.toString(), "UTF-8"));
String res = client.execute(httpPost, new BasicResponseHandler());
if (Objects.nonNull(res) && !Objects.equals("", res)) {
JSONObject obj = JSONObject.parseObject(res);
if (Objects.equals("0", obj.getString("errcode"))) {
return "发送消息成功!";
}
return obj.getString("errmsg");
}
} catch (Exception e) {
log.error("发送模板消息异常:{}", e);
} finally {
client.getConnectionManager().shutdown();
}
return "发送消息失败!";
}
}
uniformSend 参数:
- • appid:小程序 appid
- • secret:小程序 secret
- • openId:用户 openid (以是小程序的 openid,也可以是 mp_template_msg.app
- • pagepath:小程序跳转地址,如:pages/home/home
- • mpAppId:公众号 appid,要求与小程序有绑定且同主体
- • url:公众号模板消息所要跳转的url(可以为空)
- • templateId:公众号模板id
- • data:公众号模板消息的数据,如:{"thing1":{"value":"测试"}}
注意事项
1、access_token 是用小程序的 appid 和 secret 获取的。
2、接受用的 openid 为小程序端的。
3、mp_template_msg.appid 为公众号的 appid。
4、mp_template_msg.url 不能为空,那么怕写个 xxx。
5、如果要小程序,则 miniprogram 下填充小程序的 appid 和 page。
6、统一服务消息的发送位置为公众号。
7、公众号的小程序一定要关联以下哦(不需要开放平台关联)。