Java 微信公众号推送消息

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有两种方式:

  1. 在微信端,用户点击关注公众号时前端会触发回调函数获取code,将code传给后端解析出openID
  2. 获取公众号下的所有关注者用户列表(这里我采用 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;
    }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值