Official Account -- 03 -- Java微信公众号模板消息

原文链接:Official Account – 03 – Java微信公众号模板消息


相关文章


模板消息仅用于公众号向用户发送重要的服务通知,只能用于符合其要求的服务场景中,如信用卡刷卡通知,商品购买成功通知等

官方文档:模板消息接口


一、公共类

  • WXConstants.java

    /**
     * 获取access_token接口
     * 此处的ACCESS_TOKEN与授权登陆获得的ACCESS_TOKEN不同,有效期为7200s
     */
    public static final String GET_ACCESS_TOKEN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
    
    /**
     * 设置所属行业接口
     */
    public static final String SET_INDUSTRY_URL = "https://api.weixin.qq.com/cgi-bin/template/api_set_industry?access_token=%s";
    
    /**
     * 获得模板ID
     */
    public static final String GET_TEMPLATE_ID = "https://api.weixin.qq.com/cgi-bin/template/api_add_template?access_token=%s";
    
    /**
     * 发送模板消息
     */
    public static final String SEND_TEMPLATE_MSG = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s";
    
  • HttpUtils.java

    @Slf4j
    public class HttpUtils {
    
        public static JSONObject sendGetRequest(String requestUrl) {
            return (JSONObject) sendHttpRequest(requestUrl, "GET", null, null, null, null);
        }
    
        public static JSONObject sendJsonPostRequest(String requestUrl, String data){
            return (JSONObject) sendHttpRequest(requestUrl, "POST", "Content-Type", "application/json; charset=UTF-8", data, null);
        }
    
        public static String sendXmlPostRequest(String requestUrl, String xmlInfo){
            return (String) sendHttpRequest(requestUrl, "POST", "Content-Type", "text/xml;charset=utf-8", null, xmlInfo);
        }
    
        private static Object sendHttpRequest(String requestUrl, String requestMethod,
                                              String requestPropertyKey, String requestPropertyValue,
                                              String data, String xmlInfo) {
            BufferedReader bufferedReader = null;
            try {
                URL url = new URL(requestUrl);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setDoOutput(true);
                conn.setDoInput(true);
                conn.setUseCaches(false);
                conn.setRequestMethod(requestMethod);
                if (StringUtils.isNotBlank(requestPropertyKey) && StringUtils.isNotBlank(requestPropertyValue)) {
                    conn.setRequestProperty(requestPropertyKey, requestPropertyValue);
                }
                OutputStream outputStream = conn.getOutputStream();
                if (StringUtils.isNotBlank(data) && StringUtils.isBlank(xmlInfo)) {
                    // 在输出流中进行转码
                    outputStream.write(data.getBytes(StandardCharsets.UTF_8));
                    outputStream.close();
                }
                if (StringUtils.isNotBlank(xmlInfo) && StringUtils.isBlank(data)) {
                    // 在输出流中进行转码
                    outputStream.write(xmlInfo.getBytes(StandardCharsets.UTF_8));
                    outputStream.close();
                }
                InputStream inputStream = conn.getInputStream();
                InputStreamReader isr = new InputStreamReader(inputStream);
                bufferedReader = new BufferedReader(isr);
                String str;
                StringBuilder builder = new StringBuilder();
                while ((str = bufferedReader.readLine()) != null) {
                    builder.append(str);
                }
                conn.disconnect();
                if (StringUtils.isNotBlank(xmlInfo) && StringUtils.isBlank(data)) {
                    return builder.toString();
                } else {
                    return JSONObject.fromObject(builder.toString());
                }
            } catch (Exception e) {
                log.error("发送http请求,失败", e);
                return null;
            } finally {
                // 释放资源
                try {
                    if(null != bufferedReader) {
                        bufferedReader.close();
                    }
                } catch (IOException e) {
                    log.error("释放资源,失败", e);
                }
            }
        }
    }
    
  • WXUtils.java

    @Slf4j
    public class WXUtils {
    
        private static String appid = "xxxxxxxxxxxx";
        private static String appsecret = "xxxxxxxxxxxx";
    
        public static String getAccessToken() {
            // 使用自己公众号的 AppID、AppSecret
            String url = String.format(WXConstants.GET_ACCESS_TOKEN, appid, appsecret);
            JSONObject jsonObject = HttpUtils.sendGetRequest(url);
            if (jsonObject != null) {
                log.info("获取access_token,成功,返回信息为【{}】", jsonObject);
                return (String) jsonObject.get("access_token");
            }
            return null;
        }
    }
    

二、设置所属行业

  • 设置行业可在微信公众平台后台完成,每月可修改行业 1 次,帐号仅可使用所属行业中相关的模板

  • 参数说明

    • 调用接口 (https POST 请求)

      https://api.weixin.qq.com/cgi-bin/template/api_set_industry?access_token=ACCESS_TOKEN
      
    • 请求参数

      参数是否必须说明
      access_token接口调用凭证
      industry_id1公众号模板消息所属行业编号
      industry_id2公众号模板消息所属行业编号
    • 行业代码 (其余行业代码详见官方文档)

      主行业副行业代码
      IT科技互联网/电子商务1
      IT科技IT软件与服务2
      IT科技IT硬件与设备3
      IT科技电子技术4
      IT科技通信与运营商5
      IT科技网络游戏6
  • 设置所属行业

    • WXUtils.java

      @Slf4j
      public class WXUtils {
      
          public static void setIndustry() {
              Optional.ofNullable(getAccessToken()).ifPresent(accessToken -> {
                  JSONObject industry = new JSONObject();
                  // IT科技 IT软件与服务
                  industry.put("industry_id1", 2);
                  // IT科技 IT硬件与设备
                  industry.put("industry_id2", 3);
                  String url = String.format(WXConstants.SET_INDUSTRY_URL, accessToken);
                  Optional.ofNullable(HttpUtils.sendJsonPostRequest(url, industry.toString())).ifPresent(jsonObject -> {
                  if ((Integer) jsonObject.get("errcode") == 0) {
                          log.info("设置所属行业,成功,返回信息为【{}】", jsonObject);
                      } else {
                          log.error("设置所属行业,失败,返回信息为【{}】", jsonObject);
                      }
                  });
              });
          }
          
          public static void main(String[] args) {
              setIndustry();
          }
      }
      
    • 测试结果

      // 设置所属行业,成功,返回信息为【{"errcode":0,"errmsg":"ok"}】
      

三、获取模板 ID

  • 从行业模板库选择模板到帐号后台,我们即可获取到对应的模板 ID,这里我们尝试下调用接口来获取模板 ID

    • 路径:功能 --> 模板消息 --> 模板库

    • 注意:每调用一次该接口,就等价于在账号后台将模板从【模板库】添加到【我的模板】,同时会生成一个模板 ID

  • 参数说明

    • 调用接口 (https POST 请求)

      https://api.weixin.qq.com/cgi-bin/template/api_add_template?access_token=ACCESS_TOKEN
      
    • 请求参数

      参数是否必须说明
      access_token接口调用凭证
      template_id_short模板库中模板的编号,有 “TM**” 和 “OPENTMTM**” 等形式
    • 返回参数

      参数说明
      template_id模板 ID
  • 获取模板 ID

    • WXUtils.java

      @Slf4j
      public class WXUtils {
      
          public static String getTemplateID(String templateIdShort) {
              String accessToken = getAccessToken();
              if (StringUtils.isNotBlank(accessToken)) {
                  JSONObject template = new JSONObject();
                  // templateIdShort 为模板库中模板的编号
                  template.put("template_id_short", templateIdShort);
                  String url = String.format(WXConstants.GET_TEMPLATE_ID, accessToken);
                  JSONObject jsonObject = HttpUtils.sendJsonPostRequest(url, template.toString());
                  if (jsonObject != null) {
                      if ((Integer) jsonObject.get("errcode") == 0) {
                          log.info("获取模板ID,成功,返回信息为【{}】", jsonObject);
                          return (String) jsonObject.get("template_id");
                      } else {
                          log.error("获取模板ID,失败,返回信息为【{}】", jsonObject);
                      }
                  }
              }
              return null;
          }
          
          public static void main(String[] args) {
              getTemplateID("TM00201");
          }
      }
      
    • 测试结果

      // 获取模板ID,成功,返回信息为【{"errcode":0,"errmsg":"ok","template_id":"ePgZmrXWAwURCFHbr4p01WTI6GMS594f42YRNjXhcZY"}】
      

四、发送模板消息

  • 参数说明

    • 调用接口 (https POST 请求)

      https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN
      
    • 请求参数

      参数是否必须说明
      touser接收者 openid
      template_id模板 ID
      url模板跳转链接 (海外帐号没有跳转能力)
      miniprogram跳小程序所需数据,不需跳小程序可不用传该数据
      appid所需跳转到的小程序 appid
      (该小程序 appid 必须与发模板消息的公众号是绑定关联关系,暂不支持小游戏)
      pagepath所需跳转到小程序的具体页面路径,支持带参数,
      (示例 index?foo=bar),要求该小程序已发布,暂不支持小游戏
      data模板数据
      color模板内容字体颜色,不填默认为黑色
    • 返回参数

      参数说明
      msgid消息 ID
  • 发送模板消息

    • 消息模板

      在这里插入图片描述

    • SendTemplateMsgData.java

      @Data
      public class SendTemplateMsgData {
      
          /**
           * 接收者openid
           */
          private String touser;
          /**
           * 模板ID
           */
          private String template_id;
          /**
           * 模板数据
           */
          private TemplateMsgData data;
      
          @Data
          public class TemplateMsgData {
              private First first;
              private Keyword1 keyword1;
              private Keyword2 keyword2;
              private Keyword3 keyword3;
              private Remark remark;
          }
      
          @Data
          public class First {
              private String value;
      
              public First(String value) {
                  this.value = value;
              }
          }
      
          @Data
          public class Keyword1 {
              private String value;
      
              public Keyword1(String value) {
                  this.value = value;
              }
          }
      
          @Data
          public class Keyword2 {
              private String value;
      
              public Keyword2(String value) {
                  this.value = value;
              }
          }
      
          @Data
          public class Keyword3 {
              private String value;
      
              public Keyword3(String value) {
                  this.value = value;
              }
          }
      
          @Data
          public class Remark {
              private String value;
      
              public Remark(String value) {
                  this.value = value;
              }
          }
      }
      
    • WXUtils.java

      @Slf4j
      public class WXUtils {
      
          private static String openid = "xxxxxxxxxxxx";
          private static String first = "尊敬的用户,你好";
          private static String keyword1 = "1号公寓1001房间";
          private static String keyword2 = "电费剩余低于10度,请尽快缴费";
          private static String keyword3 = "2018年8月6日 12:12";
          private static String remark = "如有疑问,请联系管理员 电话:010-11111111";
      
          public static void sendTemplateMsg(String templateId) {
              Optional.ofNullable(getAccessToken()).ifPresent(accessToken -> {
                  SendTemplateMsgData sendTemplateMsgData = new SendTemplateMsgData();
                  sendTemplateMsgData.setTouser(openid);
                  sendTemplateMsgData.setTemplate_id(templateId);
                  SendTemplateMsgData.TemplateMsgData data = new SendTemplateMsgData().new TemplateMsgData();
                  data.setFirst(new SendTemplateMsgData().new First(first));
                  data.setKeyword1(new SendTemplateMsgData().new Keyword1(keyword1));
                  data.setKeyword2(new SendTemplateMsgData().new Keyword2(keyword2));
                  data.setKeyword3(new SendTemplateMsgData().new Keyword3(keyword3));
                  data.setRemark(new SendTemplateMsgData().new Remark(remark));
                  sendTemplateMsgData.setData(data);
                  String url = String.format(WXConstants.SEND_TEMPLATE_MSG, accessToken);
                  Optional.ofNullable(HttpUtils.sendJsonPostRequest(url, JSONObject
                      .fromObject(sendTemplateMsgData).toString())).ifPresent(jsonObject -> {
                      if ((Integer) jsonObject.get("errcode") == 0) {
                          log.info("发送模板消息,成功,返回信息为【{}】", jsonObject);
                      } else {
                          log.error("发送模板消息,失败,返回信息为【{}】", jsonObject);
                      }
                  });
              });
          }
          
          public static void main(String[] args) {
              sendTemplateMsg("tXXutFOKEAI2sQVnXGK82ZR0KJiU868fEu6EBcQz2hQ");
          }
      }
      
    • 测试结果

      在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值