• SpringBoot 2.X 发送微信公众平台模板消息


    1、微信模板消息官方文档

      http://mp.weixin.qq.com/debug/cgi-bin/readtmpl?t=tmplmsg/faq_tmpl

    2、申请微信公众平台接口测试账号

           http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login

    关注测试号二维码

    新增测试模板

     3、配置和代码

    ①新建配置类WeChatConfig,和微信支付用了同一个文件

    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.PropertySource;
    import org.springframework.stereotype.Component;
    
    @Component
    @Configuration
    @PropertySource(value = "classpath:wxpay.properties")
    public class WeChatConfig {
        // 获取accessToken的接口
        public static final String GET_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
    
        // 发送消息的接口
        public static final String PUSH_MESSAGE_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s";
    
        @Value("${wechat.appid}")
        private String appId;
    
        @Value("${wechat.appsecret}")
        private String appsecret;
    
        @Value("${wechat.templateId}")
        private String templateId;
    
        @Value("${wechat.forwardUrl}")
        private String forwardUrl;
    
        // 发送消息的接口的访问凭证
        private String accessToken;
    
        public String getAppId() {
            return appId;
        }
    
        public void setAppId(String appId) {
            this.appId = appId;
        }
    
        public String getAppsecret() {
            return appsecret;
        }
    
        public void setAppsecret(String appsecret) {
            this.appsecret = appsecret;
        }
    
        public String getTemplateId() {
            return templateId;
        }
    
        public void setTemplateId(String templateId) {
            this.templateId = templateId;
        }
    
        public String getForwardUrl() {
            return forwardUrl;
        }
    
        public void setForwardUrl(String forwardUrl) {
            this.forwardUrl = forwardUrl;
        }
    
        public String getAccessToken() {
            return accessToken;
        }
    
        public void setAccessToken(String accessToken) {
            this.accessToken = accessToken;
        }
    
    }
    

    ②配置wxpay.properties

    #Wechat发送微信模板消息
    wechat.appid=wxcc6efdba2803335c
    wechat.appsecret=
    #模板消息id
    wechat.templateId=Ef3UeXmHSU8FY9eiHHE7FY559vNZ2zs1gHKfv8EowEE
    #跳转地址
    wechat.forwardUrl=http://www.baidu.com
    

      

    ③注入Http请求对象

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.client.RestTemplate;
    
    
    @Configuration
    public class RestConfig {
    
        @Bean
        public RestTemplate getRestTemplate(){
            return new RestTemplate();
        }
    
    }
    

      

    ④微信接口凭证返回实体类

    import com.fasterxml.jackson.annotation.JsonProperty;
    
    
    
    public class AccessToken {
        @JsonProperty("access_token")
        private String accessToken;
    
        @JsonProperty("expires_in")
        private Long expiresIn;
    
        public String getAccessToken() {
            return accessToken;
        }
    
        public void setAccessToken(String accessToken) {
            this.accessToken = accessToken;
        }
    
        public Long getExpiresIn() {
            return expiresIn;
        }
    
        public void setExpiresIn(Long expiresIn) {
            this.expiresIn = expiresIn;
        }
    
    }
    

      

    ⑤定时获取微信接口凭证的token

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Component;
    import org.springframework.web.client.RestTemplate;
    
    
    @Component
    public class WeChatAccessTokenTask {
        @Autowired
        private RestTemplate restTemplate;
        @Autowired
        private WeChatConfig weChatConfig;
    
        /**
         * initialDelay: 初始化2s后执行第一次
         * fixedDelay:微信默认Token过期时间为7200s,这里定时7100s执行一次定时任务
         */
        @Scheduled(initialDelay = 2000, fixedDelay = 7100 * 1000)
        public void refreshToken() {
            // 请求方式: GET
            // URL:https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
    
            AccessToken accessToken = restTemplate.getForObject(
                    String.format(WeChatConfig.GET_TOKEN_URL, weChatConfig.getAppId(), weChatConfig.getAppsecret()),
                    AccessToken.class);
            // 将获取的accessToken注入wechatConf
            weChatConfig.setAccessToken(accessToken.getAccessToken());
        }
    }
    

      

    ⑥发送模板消息的请求参数封装类

    import java.util.HashMap;
    import java.util.Map;
    import com.fasterxml.jackson.annotation.JsonProperty;
    
    
    public class WeChatTemplate {
        @JsonProperty("touser")
        private String toUser;
    
        @JsonProperty("template_id")
        private String templateId;
    
        private String url;
    
        private Map<String,String> miniprogram;
    
        private Map<String, Map<String, String>> data = new HashMap<>();
    
        public static Map<String, String> initData(String value, String color) {
            HashMap<String, String> data = new HashMap<String, String>();
            data.put("value", value);
            data.put("color", color);
            return data;
        }
    
        public String getToUser() {
            return toUser;
        }
    
        public void setToUser(String toUser) {
            this.toUser = toUser;
        }
    
        public String getTemplateId() {
            return templateId;
        }
    
        public void setTemplateId(String templateId) {
            this.templateId = templateId;
        }
    
        public String getUrl() {
            return url;
        }
    
        public void setUrl(String url) {
            this.url = url;
        }
    
        public Map<String, String> getMiniprogram() {
            return miniprogram;
        }
    
        public void setMiniprogram(Map<String, String> miniprogram) {
            this.miniprogram = miniprogram;
        }
    
        public Map<String, Map<String, String>> getData() {
            return data;
        }
    
        public void setData(Map<String, Map<String, String>> data) {
            this.data = data;
        }
    
    }
    

      

    ⑦发送模板消息的返回参数封装类

    public class WeiXinResponse {
        private Integer errcode;
        private String errmsg;
        private Long msgid;
    
        public Integer getErrcode() {
            return errcode;
        }
    
        public void setErrcode(Integer errcode) {
            this.errcode = errcode;
        }
    
        public String getErrmsg() {
            return errmsg;
        }
    
        public void setErrmsg(String errmsg) {
            this.errmsg = errmsg;
        }
    
        public Long getMsgid() {
            return msgid;
        }
    
        public void setMsgid(Long msgid) {
            this.msgid = msgid;
        }
    
    }
    

      

    ⑧发送微信模板消息接口

    import com.alibaba.fastjson.JSONObject;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.CrossOrigin;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;
    
    import java.time.LocalDate;
    import java.time.LocalDateTime;
    import java.time.format.DateTimeFormatter;
    import java.util.Map;
    import java.util.Objects;
    
    
    @RestController
    @CrossOrigin
    public class WeChatMessage {
        @Autowired
        private RestTemplate restTemplate;
        @Autowired
        private WeChatConfig weChatConfig;
    
        @RequestMapping("/sendWxMessage")
        public Object sendMessage(@RequestBody String json) {
            Map<String, Object> map = JSONObject.parseObject(json, Map.class);
            WeChatTemplate weChatTemplate = new WeChatTemplate();
            // 设置模板id
            weChatTemplate.setTemplateId(weChatConfig.getTemplateId());
            //获取openid
            String openid = map.get("openid").toString();
            // 设置接收用户openId
            weChatTemplate.setToUser(openid);
            //点击详情跳转的地址
            weChatTemplate.setUrl(weChatConfig.getForwardUrl());
            //设置模板dada参数
            LocalDate date = LocalDate.now();
            String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            weChatTemplate.getData().put("date", WeChatTemplate.initData(date.getMonthValue()+"月"+date.getDayOfMonth()+"日"+"
    ",""));
            weChatTemplate.getData().put("topic", WeChatTemplate.initData("店长您好,有一笔新的让利单,需要您的确认。"+"
    ", "#0000EE"));
            weChatTemplate.getData().put("time", WeChatTemplate.initData(time, ""));
            //调用微信接口,发送模板消息
            WeiXinResponse result = restTemplate.postForObject(String.format(WeChatConfig.PUSH_MESSAGE_URL, weChatConfig.getAccessToken()),
                    weChatTemplate, WeiXinResponse.class);
            if (Objects.nonNull(result)){
                return ResultJson.ok();
            }
            return ResultJson.failure(ResultCode.SEND_MESSAGE_FAIL);
        }
    }
    

      

    ⑨后端返回统一格式

    import lombok.Data;
    import java.io.Serializable;
    
    
    @Data
    public class ResultJson<T> implements Serializable{
    
        private static final long serialVersionUID = 783015033603078674L;
        private int code;
        private String msg;
        private T data;
    
        public static ResultJson ok() {
            return ok("");
        }
    
        public static ResultJson ok(Object o) {
            return new ResultJson(ResultCode.SUCCESS, o);
        }
    
        public static ResultJson failure(ResultCode code) {
            return failure(code, "");
        }
    
        public static ResultJson failure(ResultCode code, Object o) {
            return new ResultJson(code, o);
        }
    
        public ResultJson (ResultCode resultCode) {
            setResultCode(resultCode);
        }
    
        public ResultJson (ResultCode resultCode,T data) {
            setResultCode(resultCode);
            this.data = data;
        }
    
        public void setResultCode(ResultCode resultCode) {
            this.code = resultCode.getCode();
            this.msg = resultCode.getMsg();
        }
    
        @Override
        public String toString() {
            return "{" +
                    ""code":" + code +
                    ", "msg":"" + msg + '"' +
                    ", "data":"" + data + '"'+
                    '}';
        }
    }
    

      

    ⑩返回状态码

    public enum ResultCode {
        /*
        请求返回状态码和说明信息
         */
        SUCCESS(200, "成功"),
        SEND_MESSAGE_FAIL(401, "消息发送失败"),
        NOT_FOUND(404, "请求的资源不存在"),
        OPERATE_ERROR(405, "操作失败,请求操作的资源不存在"),
        TIME_OUT(408, "请求超时"),
    
    
        SERVER_ERROR(500, "服务器内部错误"),
    
    ;
        private int code;
        private String msg;
    
        ResultCode(int code, String msg) {
            this.code = code;
            this.msg = msg;
        }
    
        public int getCode() {
            return code;
        }
    
        public String getMsg() {
            return msg;
        }
    
    }
    

      

    4、访问接口进行测试,公众号收到信息

      

  • 相关阅读:
    jni基础
    Rank Scores
    LeetCode:Longest Substring Without Repeating Characters
    LeetCode: Two Sum
    vim配置
    设计模式眨一眨
    分布式时序数据库InfluxDB
    地图坐标转换
    根据两点间的经纬度计算距离
    解密经纬度数据(火星坐标)
  • 原文地址:https://www.cnblogs.com/guduershi/p/13385293.html
Copyright © 2020-2023  润新知