Java 微信公众号推送消息
身为初级开发工程师,首次接触java微信公众号业务。
查阅许多相关大佬的文献,简单实现相关功能。
(若与大佬代码雷同,那都是我CV的 狗头.jpg ,文章看太多,找不到CV 的原文章的链接了)
获取微信公众号appId 和 secret
- appId:开发者ID,微信公众号唯一标识
- secret:开发者密码,操作公众号的验证
注:公众号调用接口并不是无限制的。为了防止公众号的程序错误而引发微信服务器负载异常,默认情况下,每个公众号调用接口都不能超过一定限制,当超过一定限制时,调用对应接口会收到如下错误返回码:
{"errcode":45009,"errmsg":"api freq out of limit"}
获取accesToken
access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。
官方接口:
http请求方式: GET
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
代码示例:
public String getAccessToken()throws Exception{
String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="
+ weChatOfficialAppId
+"&secret="
+ weChatOfficialSecret;
JSONObject jsonObject = getResponse(url);
String accessToken = jsonObject.getString("access_token");
return accessToken;
}
注:如若获取token报错,提示错误码 40125
因:appId与secret不对应。注册新账号后再申请测试账号,修改接口配置会改变secret,需刷新。
消息模板ID
页面创建模板后会生成模板Id
获取用户openId
OpenID:微信用户在当前公众号的唯一标识
为了识别用户,每个用户针对每个公众号会产生一个安全的OpenID,如果需要在多公众号、移动应用之间做用户共通,则需前往微信开放平台,将这些公众号和应用绑定到一个开放平台账号下,绑定后,一个用户虽然对多个公众号和应用有多个不同的OpenID,但他对所有这些同一开放平台账号下的公众号和应用,只有一个UnionID
获取用户openID有两种方式:
- 在微信端,用户点击关注公众号时前端会触发回调函数获取code,将code传给后端解析出openID
- 获取公众号下的所有关注者用户列表(这里我采用 2方式)
代码示例:
public Set<String> getUserOpenId(String accessToken)throws Exception{
String usersGetUrl="https://api.weixin.qq.com/cgi-bin/user/get?access_token="
+accessToken;
JSONObject jsonObject = getResponse(usersGetUrl);
Set<String> openIds=new HashSet<String>();
Integer total=0,count=0;
try {
//关注该公众账号的总用户数
total=(Integer) jsonObject.get("total");
//拉取的 OPENID 个数,最大值为10000
count=(Integer) jsonObject.get("count");
if (count<total){
//总关注用户数超过 默认数10000
//需要 next_openid 参数 分批次 多次拉取
openIds.addAll(getUsers(openIds,usersGetUrl, accessToken, (String)jsonObject.get("next_openid")));
}else {
//有关注者
if (count>0){
//列表数据,OPENID的列表
JSONObject openIdDdta = (JSONObject)jsonObject.get("data");
JSONArray openIdArray= (JSONArray) openIdDdta.get("openid");
for (Object objects:openIdArray) {
openIds.add(objects.toString());
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
return openIds;
}
private Set<String> getUsers(Set<String>openIds,String url,String accessToken,String nextOpenId) {
JSONObject data=getResponse(url);
try {
Integer count=(Integer) data.get("count");
if(count>0){
JSONObject openIdData=(JSONObject) data.get("data");
JSONArray openIdArray= (JSONArray) openIdData.get("openid");
for (Object objects:openIdArray) {
openIds.add(objects.toString());
}
}
if(StringUtils.isNotBlank(nextOpenId)){
return getUsers(openIds,url, accessToken, nextOpenId);
}
} catch (JSONException e) {
e.printStackTrace();
}
return openIds;
}
public JSONObject getResponse(String url){
String res = HttpUtil.get(url);
return JSONObject.parseObject(res);
}
发送模板消息
public void sendMessage(String userOpenId,String projectName,String taskName)throws Exception{
//获取token
String accessToken = getAccessToken();
String[] arrDevice = userOpenId.split(",");
RestTemplate restTemplate = new RestTemplate();
//发布接口
String usersGetUrl="https://api.weixin.qq.com/cgi-bin/message/template/send?access_token="+accessToken;
// 模板参数
Map<String, WechatMsgTemplate> sendMag = new HashMap<String, WechatMsgTemplate>();
sendMag.put("projectName", new WechatMsgTemplate(projectName));
sendMag.put("taskName", new WechatMsgTemplate(taskName));
Map<String, Object> sendBody = new HashMap<>();
//批量多人 发送消息
for (String user:arrDevice
) {
//拼接base参数
sendBody=new HashMap<>();
sendBody.put("touser", user); // openId
//TODO 点击模板信息跳转地址
// sendBody.put("url", "www.baidu.com"); // 点击模板信息跳转地址
sendBody.put("topcolor", "#FF0000"); // 顶色
sendBody.put("data", sendMag); // 模板参数
sendBody.put("template_id", weChatOfficialTemplateId); // 模板Id
//调用post发送接口
ResponseEntity<String> stringResponseEntity = restTemplate.postForEntity(usersGetUrl, sendBody, String.class);
if (stringResponseEntity.getStatusCode() != HttpStatus.OK){
log.error("推送服务消息异常:" + user);
}
}
}
public class WechatMsgTemplate {
/**
* 消息
*/
private String value;
/**
* 消息颜色
*/
private String color;
public WechatMsgTemplate(String value) {
this.value = value;
this.color = "#173177";
}
public WechatMsgTemplate(String value, String color) {
this.value = value;
this.color = color;
}
}