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

 更新时间:2022年01月29日 09:31:33   作者:热水瓶、  
大家好,本篇文章主要讲的是Java实现微信公众号发送模版消息,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下

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

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述

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

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

在这里插入图片描述

查看微信开发文档

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

这里是引用

注: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;
    }
}

到此这篇关于Java实现微信公众号发送模版消息的文章就介绍到这了,更多相关Java微信公众号发消息内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java for循环内执行多线程问题

    java for循环内执行多线程问题

    这篇文章主要介绍了java for循环内执行多线程问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • SpringMVC学习之JSON和全局异常处理详解

    SpringMVC学习之JSON和全局异常处理详解

    在项目上线之后,往往会出现一些不可预料的异常信息,对于逻辑性或设计性问题,开发人员或者维护人员需要通过日志,查看异常信息并排除异常,这篇文章主要给大家介绍了关于SpringMVC学习之JSON和全局异常处理的相关资料,需要的朋友可以参考下
    2022-10-10
  • 利用Java实现网站聚合工具

    利用Java实现网站聚合工具

    互联网上有数以万亿计的网站,每个网站大都具有一定的功能。搜索引擎虽然对互联网上的部分网站建立了索引,但是其作为一个大而全的搜索系统,无法很好的定位到一些特殊的需求。因此本文将介绍一个用java实现的网站数据聚合工具,需要的可以参考一下
    2022-01-01
  • JAVA MyBatis入门学习过程记录

    JAVA MyBatis入门学习过程记录

    MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架。这篇文章主要介绍了mybatis框架入门学习教程,需要的朋友可以参考下,希望能帮助到你
    2021-06-06
  • Java基础教程之接口的继承与抽象类

    Java基础教程之接口的继承与抽象类

    这篇文章主要介绍了Java基础教程之接口的继承与抽象类,本文介绍了接口继承、接口的多重继承以及抽象类的知识,需要的朋友可以参考下
    2014-09-09
  • Spring中的@PathVariable注解详细解析

    Spring中的@PathVariable注解详细解析

    这篇文章主要介绍了Spring中的@PathVariable注解详细解析,@PathVariable 是 Spring 框架中的一个注解,用于将 URL 中的变量绑定到方法的参数上,它通常用于处理 RESTful 风格的请求,从 URL 中提取参数值,并将其传递给方法进行处理,需要的朋友可以参考下
    2024-01-01
  • Java String类的理解及字符串常量池介绍

    Java String类的理解及字符串常量池介绍

    这篇文章主要介绍了Java String类的理解及字符串常量池介绍,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-09-09
  • RocketMQ Namesrv架构工作原理详解

    RocketMQ Namesrv架构工作原理详解

    这篇文章主要为大家介绍了RocketMQ Namesrv架构工作原理详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • Java集合框架Collections原理及用法实例

    Java集合框架Collections原理及用法实例

    这篇文章主要介绍了Java集合框架Collections原理及用法实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08
  • 如何查找YUM安装的JAVA_HOME环境变量详解

    如何查找YUM安装的JAVA_HOME环境变量详解

    这篇文章主要给大家介绍了关于如何查找YUM安装的JAVA_HOME环境变量的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2017-10-10

最新评论