1. 程式人生 > 實用技巧 >SpringBoot 2.X 傳送微信公眾平臺模板訊息

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()+"日"+"\n",""));
        weChatTemplate.getData().put("topic", WeChatTemplate.initData("店長您好,有一筆新的讓利單,需要您的確認。"+"\n", "#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、訪問介面進行測試,公眾號收到資訊