springboot 实现微信公众号的模板消息推送

一、微信公众号测试平台

地址: http://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index

需要数据1

在这里插入图片描述
需要数据2
在这里插入图片描述

发送消息模板可不配置公众号对接相关功能,直接使用openId 发送模板信息功能即可,openId 可让用户关注公众号录入系统,
或者在公众号添加h5 表单,绑定系统账号, 微信打开的h5 页面可获取当前用户的openId

二、实现代码

结构
在这里插入图片描述

1、yml 配置

## 微信公众号 相关配置信息
wx:
  mp:
    configs:
      - appId: wxa997b110821cbfd6    # 第一个公众号的appid
        secret: a5cee82a40995afc5bc14d17058908c1   # 公众号的appsecret
        token: 123456789     # 接口配置里的Token值
        aesKey: 123456789    # 接口配置里的EncodingAESKey值

2、yml 配置对应参数类

package com.ws.ldy.others.wechat.wxbase.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

import java.util.List;

/**
 * 微信公众配置信息
 */
@Data
@ConfigurationProperties(prefix = "wx.mp")
public class WxMpProperties {

    /**
     * 多个公众号配置信息
     */
    private List<MpConfig> configs;

    @Data
    public static class MpConfig {
        /**
         * 设置微信公众号的appid
         */
        private String appId;

        /**
         * 设置微信公众号的app secret
         */
        private String secret;

        /**
         * 设置微信公众号的token
         */
        private String token;

        /**
         * 设置微信公众号的EncodingAESKey
         */
        private String aesKey;
    }
}

3、微信url 封装类

public interface WxChatConstant {

    /**
     * 微信公众号相关操作的链接
     */
    interface Url {

        /**
         * 1、获取 accessToken 的请求地址
         * 参数1: APPID
         * 参数2: APPSECRET
         */
        String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";

        /**
         * 2、发送模版信息的url
         * 参数1: ACCESS_TOKEN
         */
        String SEND_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN";
    }
}

4、微信缓存类( 缓存AccessToken )

public class WxChatCache {

    /**
     * 微信 accessToken缓存
     */
    public static class AccessToken {
        public static String token = null;   // accessToken
        public static Long expiration = 0L;  // accessToken 过期时间(获取的token 默认有效期2小时)
    }

5、微信通用service 类,避免重复依赖注入

/**
 * 微信通用service层
 */
public class BaseWeChatServiceImpl {

    // rpc
    @Autowired
    protected RestTemplate restTemplate;


    // 获取token
    @Autowired
    protected WeChetAccessToken weChetAccessToken;

}

6、获取token的工具类

/**
 * 获取微信token工具类
 */
@Component
public class WeChetAccessToken {

    //微信配置
    @Autowired
    private WxMpProperties wxMpProperties;
    //rpc
    @Autowired
    private RestTemplate restTemplate;

    /**
     * 获取 accessToken (token有效期为2小时, 设置缓存, 过期并重新获取 accessToken)
     * <p>
     * 微信请求正确返回 {\"access_token\":\"37_B7bSN7N0VoqOVhf5rOk7NOHY6aMoxvE15VxNIcnD3f2kXvZkc0HOU-9rhfGZyWAoYkVfLrPzxTMhdcf86kgQeabfWSV-DH0hUYD8YMBF9vcbASzwRlEE3zJbKW2PuHJIl5Nu4BLouY4rUSFwTCBbAHAIRQ\",\"expires_in\":7200}
     * 微信请求错误返回 {"errcode":40013,"errmsg":"invalid appid"}
     * </p>
     * <P>
     *     流程:
     *     1、 判断token是否过期
     *     2、 获取 url 并拼接参数 APPID + APPSECRET
     *     3、 发起请求
     *     4、 判断请求是否成功
     *     5、 缓存accessToken + accessToken过期时间到jvm 内存中
     * </P>
     * @author wangsong
     * @date 2019年6月19日 下午5:55:11
     * @return
     */
    public String getToken() {
        if (WxChatCache.AccessToken.expiration <= System.currentTimeMillis()) {
            String url = WxChatConstant.Url.ACCESS_TOKEN_URL
                    .replace("APPID", wxMpProperties.getConfigs().get(0).getAppId())
                    .replace("APPSECRET", wxMpProperties.getConfigs().get(0).getSecret());
            //http
            ResponseEntity<String> forEntity = restTemplate.getForEntity(url, String.class);
            JSONObject jsonObject = JSON.parseObject(forEntity.getBody());
            Object errcode = jsonObject.get("errcode");
            if (errcode != null && "40013".equals(errcode.toString())) {
                throw new ErrorException(RType.WX_GET_ACCESS_TOKEN_ERROR);
            }
            // 设置为1小时59分钟有效期,防止空指针异常
            WxChatCache.AccessToken.token = jsonObject.get("access_token").toString();
            WxChatCache.AccessToken.expiration = ((Integer.parseInt(jsonObject.get("expires_in").toString()) - 1) * 1000) + System.currentTimeMillis();
        }
        return WxChatCache.AccessToken.token;
    }
}

7、消息推送接口

public interface WxChatService {

    /**
     * 向一个用户推送消息(测试)
     * @param openId
     * @param
     */
    void sendTest(String openId,String content);

}

8、消息封装实体类 (模板参数)

/**
 * 推送的微信公众信息的每一个 {
   
   {}} 值的内容和颜色封装
 */
@Data
@ToString
public class WeChatTemplateMsg {
    /**
     * 消息
     */
    private String value;
    /**
     * 消息颜色
     */
    private String color;


    public WeChatTemplateMsg(String value) {
        this.value = value;
        this.color = "#173177";
    }

    public WeChatTemplateMsg(String value, String color) {
        this.value = value;
        this.color = color;
    }
}

9、消息推送接口实现


/**
 * 向微信公众号推送消息
 * @author wangsong
 * @mail [email protected]
 * @date 2020/9/9 0009 13:44
 * @version 1.0.0
 */
@Service
public class WxChatServiceImpl extends BaseWeChatServiceImpl implements WxChatService {


    /**
     * 1、发送模版消息-拼接数据(测试信息)
     * @param openId 微信用户的openId
     * @param content 发送的内容
     */
    @Override
    public void sendTest(String openId, String content) {
        // 模板Id
        String templateId = "P6llNez3CAcxEYzhQ_MDdFJGUifXfey15ZIX7MKiB3k";
        // 模板参数
        Map<String, WeChatTemplateMsg> sendMag = new HashMap<String, WeChatTemplateMsg>();
        sendMag.put("MSG", new WeChatTemplateMsg(content));
        //sendMag.put("MSG", new WeChatTemplateMsg(content,"#173177"));
        // 发送
        this.send(openId, templateId, sendMag);
    }


    /**
     * 2、发送模版消息
     * openId     用户Id
     * templateId 模板Id   测试: "ngqIpbwh8bUfcSsECmogfXcV14J0tQlEpBO27izEYtY"
     * data       模板参数
     * @param data
     */
    private String send(String openId, String templateId, Map<String, WeChatTemplateMsg> data) {
        String accessToken = weChetAccessToken.getToken();
        String url = WxChatConstant.Url.SEND_URL.replace("ACCESS_TOKEN", accessToken);
        //拼接base参数
        Map<String, Object> sendBody = new HashMap<>();
        sendBody.put("touser", openId);               // openId
        sendBody.put("url", "www.baidu.com");         // 点击模板信息跳转地址
        sendBody.put("topcolor", "#FF0000");          // 顶色
        sendBody.put("data", data);                   // 模板参数
        sendBody.put("template_id", templateId);      // 模板Id
        ResponseEntity<String> forEntity = restTemplate.postForEntity(url, sendBody, String.class);
        return forEntity.getBody();
    }
}

10、通过测试接口

/**
 * 微信公众号测试接口
 * @author wangsong
 * @mail [email protected]
 * @date 2020/9/9 0009 14:41 
 * @version 1.0.0
 */
@RestController
@RequestMapping("/wechat/template/msg")
@Api(value = "WxChatController", tags = "WeChat --> 微信模板消息推送")
public class WxChatController {

    @Autowired
    private WxChatService wxChatService;

    /**
     * 我的openId:  o8nrg503tfKwepDE4zKeP2g9PujU
     * @return
     */
    @RequestMapping(value = "/sendTest", method = RequestMethod.GET)
    @ApiOperation("推送测试信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "openId", value = "微信openId", required = true, paramType = "query", example = "o8nrg503tfKwepDE4zKeP2g9PujU"),
            @ApiImplicitParam(name = "content", value = "发送内容", required = true, paramType = "query", example = "")
    })
    public R<Boolean> sendTest(String openId, String content) {
        wxChatService.sendTest(openId, content);
        return R.success(true);
    }
}

在这里插入图片描述

11、微信公众号收到消息

在这里插入图片描述

  • 个人开源项目(通用后台管理系统)–> https://gitee.com/wslxm/spring-boot-plus2 , 喜欢的可以看看

  • 本文到此结束,如果觉得有用,动动小手点赞或关注一下呗,将不定时持续更新更多的内容…,感谢大家的观看!

猜你喜欢

转载自blog.csdn.net/qq_41463655/article/details/108561519