微信发送模板消息

2023-11-05 11:34:05 浏览数 (1)

模板消息

由于微信自 2023 年 9 月 20 日起,下发统一消息接口将被收回,无法下发小程序模板消息与公众号模板消息。

如业务需下发模板消息,只能通过公众号模板消息或者小程序订阅模板消息能力满足需求:公众号模板消息小程序订阅模板消息

获取 ACCESS_TOKEN

获取公众号、小程序全局唯一后台接口调用凭据,token 有效期为 7200s,简单做缓存存储(资质不同获取次数是有限的)。

接口地址:

代码语言:javascript复制
GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=&secret=
代码语言:javascript复制
@Slf4j
public class WxapiUtil {

    private static ConcurrentHashMap<String, JSONObject> accessTokenMap = new ConcurrentHashMap();

    /**
     * @MonthName: getToken
     * @Description: 获取token
     * @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);
            if (Objects.nonNull(token) && token.length() > 10) {
                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);
            log.info("获取AccessToken返回值:{}", response);
            JSONObject json = JSONObject.parseObject(response);
            accessToken = String.valueOf(json.get("access_token"));
        } catch (Exception e) {
            log.error("获取token异常:", e);
        } finally {
            client.getConnectionManager().shutdown();
        }
        return accessToken;
    }

}

公众号模板消息

模板消息仅用于公众号向用户发送重要的服务通知,只能用于符合其要求的服务场景中,如信用卡刷卡通知,商品购买成功通知等。不支持广告等营销类消息以及其它所有可能对用户造成骚扰的消息。

当前每个账号的模板消息的日调用上限为 10万 次,单个模板没有特殊限制。 当账号粉丝数超过 10W/100W/1000W 时,模板消息的日调用上限会相应提升,以公众号MP后台开发者中心页面中标明的数字为准。

发送模板消息

该接口用于发送订阅消息

文档地址:https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Template_Message_Interface.html

接口地址:

代码语言:javascript复制
POST https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN

模板申请

登录 微信公众平台广告与服务-模板消息 中开通模板消息。

模板消息 中选择符合自己业务需求的模板开通,如没有自己业务需求的模板,可申请符合自己需求的模板。

服务端消息发送

代码语言:javascript复制
/**
 * @MonthName: sendTemplateMessage
 * @Description: 公众号模板消息
 * @Param:
 *  appid:公众号 appid,
 *  secret:公众号 secret,
 *  mappId: 小程序 appid,
 *  openId:用户 openid (公众号授权的 openid),
 *  pagepath:小程序跳转地址,如:pages/home/home,
 *  url:公众号模板消息所要跳转的url(可以为空),
 *  templateId:公众号模板id,
 *  data:公众号模板消息的数据,如:{"thing1":{"value":"测试"}}
 * @return: java.lang.String
 **/
public static String sendTemplateMessage(String appid, String secret, String mappId, String openId, String pagepath, 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/template/send?access_token=";
        HttpPost httpPost = new HttpPost(messageUrl   token);
        JSONObject params = new JSONObject();
        params.put("touser", openId); // 接收者openid
        params.put("template_id", templateId); // 模板ID
        params.put("url", url); // 模板跳转链接
        params.put("data", data); // 模板数据

        // 跳小程序所需数据,不需跳小程序可不用传该数据
        JSONObject miniprogram = new JSONObject();
        miniprogram.put("appid", mappId);
        miniprogram.put("pagepath", pagepath);
        params.put("miniprogram", miniprogram);

        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 "发送消息失败!";
}

注意:url 和 miniprogram 都是非必填字段,若都不传则模板无跳转;若都传,会优先跳转至小程序。开发者可根据实际需要选择其中一种跳转方式即可。当用户的微信客户端版本不支持跳小程序时,将会跳转至url。

小程序模板消息

发送模板消息

该接口用于发送模板消息

接口名称:sendMessage

文档地址:https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-message-management/subscribe-message/sendMessage.html

接口地址:

代码语言:javascript复制
POST https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=ACCESS_TOKEN

模板申请

登录 微信公众平台功能-订阅消息 中开通订阅消息。

订阅消息 中选择符合自己业务需求的模板开通,模板分为 一次性订阅长期订阅

  • • 一次性订阅:用户授权一次,即可发送一次模板消息,无法再次发送;
  • • 长期订阅:用户授权一次,可发送多次模板消息。

长期订阅模板:

  • • 长期订阅消息目前只对 政务民生医疗交通金融教育 等部分二级行业类目进行开放,长期订阅模板库有模板可以进行调用,没有模板说明暂时不支持;
  • • 长期订阅模板目前没有提供线上申请方式。

如不满足以上条件如何开通长期订阅模板,可以在小程序类目中添加 工具-设备管理, 在 功能-硬件设备-设备消息 即可使用设备相关的长期订阅模板(无奈之举)。

小程序调起订阅授权

调起客户端小程序订阅消息界面,返回用户订阅消息的操作结果。当用户勾选了订阅面板中的“总是保持以上选择,不再询问”时,模板消息会被添加到用户的小程序设置页,通过 wx.getSetting 接口可获取用户对相关模板消息的订阅状态。

订阅消息:wx.requestSubscribeMessage(Object object)

代码语言:javascript复制
wx.requestSubscribeMessage({
  tmplIds: [''], // 需要订阅的消息模板的id的集合,一次调用最多可订阅3条消息
  success (res) { }
})

注意:一次性模板 id 和永久模板 id 不可同时使用。

官方文档:https://developers.weixin.qq.com/miniprogram/dev/api/open-api/subscribe-message/wx.requestSubscribeMessage.html

服务端消息发送

发送小程序订阅信息 Java 工具方法封装。

代码语言:javascript复制
/**
 * @MonthName: sendMessage
 * @Description: 发送小程序订阅信息
 * @Param: 
 *  appid:小程序 appid
 *  secret:小程序 secret
 *  openid:用户 openid (对应的小程序的 openid)
 *  templateId:小程序订阅的模板id
 *  page:点击模板卡片后的跳转页面
 *  data:模板消息的数据,如:{"thing1":{"value":"测试"}}
 * @return: java.lang.String
 **/
public static String sendMessage(String appid, String secret, String openId, String templateId, String page, Map<String, Object> 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/subscribe/send?access_token=";
        HttpPost httpPost = new HttpPost(messageUrl   token);
        JSONObject params = new JSONObject();
        params.put("touser", openId); // 接收者 openid
        params.put("template_id", templateId); // 模板ID
        params.put("page", page); // 点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)
        params.put("lang", "zh_CN"); // 进入小程序查看”的语言类型,支持zh_CN(简体中文)、en_US(英文)、zh_HK(繁体中文)、zh_TW(繁体中文),默认为zh_CN
        params.put("miniprogram_state", "formal"); // 跳转小程序类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版
        params.put("data", data); // 数据

        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 "发送消息失败!";
}

0 人点赞