软件编程
位置:首页>> 软件编程>> java编程>> Java实现微信公众号发送模版消息

Java实现微信公众号发送模版消息

作者:热水瓶、  发布时间:2021-07-16 17:03:35 

标签:java,微信,公众号

微信公众号发送模版消息 背景:如下图,当用户发布需求的时候,公众号自定推送消息。例如:微信支付的时候,公众号会推送支付成功消息

Java实现微信公众号发送模版消息

前提:发送模版消息,顾名思义,前提就是需要有模版,那么在哪里配置模版呢?
微信公众号平台–>广告与服务–>模版消息–>我的模版
模版消息是已经申请过的模版,如果里面的模版都不符合自己业务的话,可以到模版库里找,然后添加到「我的模版」。也可以按照自己的需求申请新的模版,一般第二个工作日会审核通过。

Java实现微信公众号发送模版消息

在模版详情可以查看模版的格式,下图左边红框是消息最终展示的效果,
右边红框是需要传的参数。

Java实现微信公众号发送模版消息

有了模版之后,模版ID就是我们要放进代码里的,复制出来。

消息模版准备好之后,暂时不要写代码奥,查看微信开发文档,看看发送模版都需要哪些参数。
微信开发文档–>基础消息能力–>模版消息接口–「发送模版消息」

Java实现微信公众号发送模版消息

查看微信开发文档

发送模版消息
http请求方式: POST https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN

Java实现微信公众号发送模版消息

注:url和miniprogram都是非必填字段,若都不传则模板无跳转;若都传,会优先跳转至小程序。开发者可根据实际需要选择其中一种跳转方式即可。当用户的微信客户端版本不支持跳小程序时,将会跳转至url。
返回码说明
在调用模板消息接口后,会返回JSON数据包。
正常时的返回JSON数据包示例:
{
“errcode”:0,
“errmsg”:“ok”,
“msgid”:200228332
}

发送模版所需参数:
模版ID和openId是必须有的,剩下的就是和自己业务有关了。

上面的内容都搞定之后,就可以开始撸代码了

发送模版微信返回Dto

@Data
public class TemplateMsgResultDto extends ResultState {

/**
    * 消息id(发送模板消息)
    */
   private String msgid;

}

发送模版微信返回状态

@Data
public class ResultState implements Serializable {

/**
    * 状态
    */
   private int errcode;

/**
    * 信息
    */
   private String errmsg;

}

微信模版消息请求参数实体类

@Data
public class WxTemplateMsg {
   /**
    * 接收者openId
    */
   private String touser;
   /**
    * 模板ID
    */
   private String template_id;
   /**
    * 模板跳转链接
    */
   private String url;

// "miniprogram":{ 未加入
   // "appid":"xiaochengxuappid12345",
   // "pagepath":"index?foo=bar"
   // },

/**
    * data数据
    */
   private TreeMap<String, TreeMap<String, String>> data;

/**
    * 参数
    *
    * @param value 值
    * @param color 颜色 可不填
    * @return params
    */
   public static TreeMap<String, String> item(String value, String color) {
       TreeMap<String, String> params = new TreeMap<String, String>();
       params.put("value", value);
       params.put("color", color);
       return params;
   }
}

Java封装模版信息代码

public TemplateMsgResultDto noticeTemplate(TemplateMsgVo templateMsgVo) {
       // 模版ID
       String templateId="XXX";
       TreeMap<String, TreeMap<String, String>> params = new TreeMap<>();
       //根据具体模板参数组装
       params.put("first", WxTemplateMsg.item("恭喜!您的需求已发布成功", "#000000"));
       params.put("keyword1", WxTemplateMsg.item(templateMsgVo.getTaskName(), "#000000"));
       params.put("keyword2", WxTemplateMsg.item("需求已发布", "#000000"));
       params.put("remark", WxTemplateMsg.item("请耐心等待审核", "#000000"));
       WxTemplateMsg wxTemplateMsg = new WxTemplateMsg();
       // 模版ID
       wxTemplateMsg.setTemplate_id(templateId);
       // openId
       wxTemplateMsg.setTouser(templateMsgVo.getOpenId());
       // 关键字赋值
       wxTemplateMsg.setData(params);
       String data = JsonUtils.ObjectToString(wxTemplateMsg);
       return handleSendMsgLog(data);
   }

发送模版代码

private TemplateMsgResultDto handleSendMsgLog(String data) {
       TemplateMsgResultDto resultDto = new TemplateMsgResultDto();
       try {
           resultDto = sendTemplateMsg(data);
       } catch (Exception exception) {
           log.error("发送模版失败",  exception);
       }
       // TODO 可以记录一下发送记录的日志
       return resultDto;
   }

public TemplateMsgResultDto sendTemplateMsg(String data) throws Exception {
       // 获取token
       String accessToken = getAccessToken();
       // 发送消息
       HttpResult httpResult = HttpUtils.stringPostJson(ConstantsPath.SEND_MESSAGE_TEMPLATE_URL + accessToken, data);
       return IMJsonUtils.getObject(httpResult.getBody(), TemplateMsgResultDto.class);
   }

/**
    * 获取全局token
    */
   public String getAccessToken() {
       String key = ConstantsRedisKey.ADV_WX_ACCESS_TOKEN;
       // 从redis缓存中获取token
       if (redisCacheManager.get(key) != null) {
           return (String) redisCacheManager.get(key);
       }
       // 获取access_token
       String url = String.format(ConstantsPath.WX_ACCESS_TOKEN_URL, appid, secret);
       ResponseEntity<String> result = restTemplate.getForEntity(url, String.class);
       if (result.getStatusCode() == HttpStatus.OK) {
           JSONObject jsonObject = JSON.parseObject(result.getBody());
           String accessToken = jsonObject.getString("access_token");
           // Long expires_in = jsonObject.getLong("expires_in");
           redisCacheManager.set(key, accessToken, 1800);
           return accessToken;
       }
       return null;
   }

微信地址常量类

public class ConstantsPath {
   /**
    * 微信公众号获取全局token
    */
   public static final String WX_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";

/**
    * 微信发送模版消息
    */
   public static final String SEND_MESSAGE_TEMPLATE_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=";

}

Json工具类

@Slf4j
public class JsonUtils {
   private static ObjectMapper json;
   static {
       json = new ObjectMapper();
       json.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
       json.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
   }

/**
    * 序列化为JSON字符串
    */
   public static String ObjectToString(Object object) {
       try {
           return (json.writeValueAsString(object));
       } catch (Exception e) {
           log.error("序列化为JSON字符串出错",e);
       }
       return null;
   }

public static <T> T getObject(String jsonString, Class<T> clazz) {
       if (StringUtils.isEmpty(jsonString))
           return null;
       try {
           return json.readValue(jsonString, clazz);
       } catch (Exception e) {
           log.error("将JSON字符串转化为Map出错",e);
           return null;
       }
   }

}

Http工具类

@Component
@Slf4j
public class HttpUtils {
   private static String sourcePath;

public static HttpResult stringPostJson(String path, String content) throws Exception{
       return stringPost(path, null, content, "utf-8", "utf-8", "application/json");
   }

public static HttpResult stringPost(String path, Map<String,String> headerMap, String content, String contentencode, String encode, String contentType) throws Exception{
       StringEntity entity = new StringEntity(content, contentencode);
       entity.setContentType(contentType);
       return post(path, headerMap, entity, encode);
   }

private static HttpResult post(String path, Map<String,String> headerMap, HttpEntity entity, String encode){
       HttpResult httpResult = new HttpResult();
       CloseableHttpClient httpClient = null;
       CloseableHttpResponse response = null;
       try{
           HttpPost httpPost = new HttpPost(getURI(path));
           LaxRedirectStrategy redirectStrategy = new LaxRedirectStrategy();
           httpClient = HttpClientBuilder.create().setRedirectStrategy(redirectStrategy).build();
           RequestConfig requestConfig = RequestConfig.custom()
                   .setSocketTimeout(120000)
                   .setConnectTimeout(120000)
                   .setConnectionRequestTimeout(120000)
                   .setCircularRedirectsAllowed(true)
                   .setRedirectsEnabled(true)
                   .setMaxRedirects(5)
                   .build();
           httpPost.setConfig(requestConfig);

httpPost.setHeader("User-Agent", header);

if(headerMap != null && headerMap.size() > 0){
               for(String name:headerMap.keySet()) {
                   httpPost.addHeader(name, headerMap.get(name));
               }
           }
           httpPost.setEntity(entity);
           response = httpClient.execute(httpPost);
           httpResult.setStatus(response.getStatusLine().getStatusCode());
           if(httpResult.getStatus() == 200){
               HttpEntity resEntity = response.getEntity();
               httpResult.setBody(EntityUtils.toString(resEntity, encode));
           }
       }catch(Exception ex){
           log.error("post请求出错", ex);
       }finally{
           try{
               if(response != null){
                   response.close();
               }
               if(httpClient != null){
                   httpClient.close();
               }
           }catch(Exception ex) {
               log.error("post请求关闭资源出错", ex);
           }
       }
       return httpResult;
   }
}

来源:https://blog.csdn.net/mxs1226/article/details/122731633

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com