如何使用java实现微信公众平台发送模板消息

这篇文章主要为大家展示了“如何使用java实现微信公众平台发送模板消息”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何使用java实现微信公众平台发送模板消息”这篇文章吧。

请求模板消息接口

1)微信网页授权

//前端发请请求 this.axios.get('/wx/get_code_num').then((res) => {  window.location.href = res.data; }).catch((error) => {  console.log(error) }); /**  * 1.用户同意授权,获取code  */  @RequestMapping(value = "/get_code_num", method = RequestMethod.GET)  public String getCode() throws UnsupportedEncodingException {    return "https://open.weixin.qq.com/connect/oauth3/authorize?appid=" + Constants.APPID + "&redirect_uri="        + URLEncoder.encode("http://192.168.0.152:8085/wx/send_wx_msg", "UTF-8") + "&response_type=code&scope="        + Constants.GRANTSCOPE + "&state=STATE#wechat_redirect";  }

2)获取用户openid

/** * 2.通过code换取网页授权access_token及openid */@RequestMapping(value = "/send_wx_msg", method = RequestMethod.GET)public String sendWxMsg(String code) {  String access_token_url = "https://api.weixin.qq.com/sns/oauth3/access_token";  String accessTokenObj = HttpClientUtil.sendGet(access_token_url, "appid=" + Constants.APPID + "&secret="      + Constants.APPSECRET + "&code=" + code + "&grant_type=authorization_code");  JSONObject jsonToken = JSONObject.fromObject(accessTokenObj);  String openId = null;  if (StringUtils.isNotBlank(String.valueOf(jsonToken))) {    openId = jsonToken.getString("openid");  }  logger.info("获取openid,微信平台接口返回{}", openId);  return openId;}

3)组装、发送模板消息

import java.util.TreeMap;public class WechatTemplate {  private String touser;//用戶openid  private String template_id;//模板ID  private String url;//URL置空,则在发送后,点击模板消息会进入一个空白页面(ios),或无法点击(android)  private TreeMap<String, TreeMap<String, String>> data; //data数据  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;  }  public TreeMap<String, TreeMap<String, String>> getData() {    return data;  }  public void setData(TreeMap<String, TreeMap<String, String>> data) {    this.data = data;  }  public String getTouser() {    return touser;  }  public void setTouser(String touser) {    this.touser = touser;  }  public String getTemplate_id() {    return template_id;  }  public void setTemplate_id(String template_id) {    this.template_id = template_id;  }  public String getUrl() {    return url;  }  public void setUrl(String url) {    this.url = url;  }  @Override  public String toString() {    return "WechatTemplate{" +        "touser='" + touser + '\'' +        ", template_id='" + template_id + '\'' +        ", url='" + url + '\'' +        ", data=" + data +        '}';  }}
//微信模板接口private final String SEND_TEMPLATE_MESSAGE_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send";//模板消息详情跳转URLprivate static String url = "https://www.baidu.com/";@RequestMapping(value = "/send_wx_msg", method = RequestMethod.GET)public String sendWxMsg(String code) {  String access_token_url = "https://api.weixin.qq.com/sns/oauth3/access_token";  String accessTokenObj = HttpClientUtil.sendGet(access_token_url, "appid=" + Constants.APPID + "&secret="      + Constants.APPSECRET + "&code=" + code + "&grant_type=authorization_code");  JSONObject jsonToken = JSONObject.fromObject(accessTokenObj);  String openId = null;  if (StringUtils.isNotBlank(String.valueOf(jsonToken))) {    openId = jsonToken.getString("openid");  }  logger.info("获取openid,微信平台接口返回{}", openId);  String urlToken = "https://api.weixin.qq.com/cgi-bin/token";  String tokenObj = HttpClientUtil.sendGet(urlToken, "grant_type=client_credential" + "&secret=" + Constants.APPSECRET + "&appid=" + Constants.APPID);  JSONObject retToken = JSONObject.fromObject(tokenObj);  String accessToken = String.valueOf(retToken.get("access_token"));  logger.info("获取access_token,微信平台接口返回{}", accessToken);  TreeMap<String, TreeMap<String, String>> params = new TreeMap<String, TreeMap<String, String>>();  //根据具体模板参数组装  params.put("first", WechatTemplate.item("您的户外旅行活动订单已经支付完成,可在我的个人中心中查看", "#000000"));  params.put("keyword1", WechatTemplate.item("发现尼泊尔—人文与自然的旅行圣地", "#000000"));  params.put("keyword2", WechatTemplate.item("5000元", "#000000"));  params.put("keyword3", WechatTemplate.item("2019.09.04", "#000000"));  params.put("keyword4", WechatTemplate.item("5", "#000000"));  params.put("remark", WechatTemplate.item("请届时携带好身份证件准时到达集合地点,若临时退改将产生相应损失,敬请谅解,谢谢!", "#000000"));  WechatTemplate wechatTemplate = new WechatTemplate();  wechatTemplate.setTemplate_id(Constants.TEMPLATEID);  wechatTemplate.setTouser(openId);  wechatTemplate.setUrl(url);  wechatTemplate.setData(params);  JSONObject json = JSONObject.fromObject(wechatTemplate);//将java对象转换为json对象  String sendData = json.toString();//将json对象转换为字符串  logger.info("板参数组装{}", sendData);  TreeMap<String, String> treeMap = new TreeMap<String, String>();  treeMap.put("access_token", accessToken);  String retInfo = HttpUtil.doPost(SEND_TEMPLATE_MESSAGE_URL, treeMap, sendData);  logger.info("消息模板返回{}", retInfo);  return retInfo;}

请求的数据格式

{  "data": {    "first": {      "color": "#000000",      "value": "您的户外旅行活动订单已经支付完成,可在我的个人中心中查看"    },    "keyword1": {      "color": "#000000",      "value": "发现尼泊尔—人文与自然的旅行圣地"    },    "keyword2": {      "color": "#000000",      "value": "5000元"    },    "keyword3": {      "color": "#000000",      "value": "2019.09.04"    },    "keyword4": {      "color": "#000000",      "value": "5"    },    "remark": {      "color": "#000000",      "value": "请届时携带好身份证件准时到达集合地点,若临时退改将产生相应损失,敬请谅解,谢谢!"    }  },  "template_id": "ZUMTnYtG0O4vZSv4bPTtWTOFZ2zirOjaM50GYywRRnA",  "touser": "olv_asx8nmggCQEmAFNbQstx3xd0",  "url": "https://www.baidu.com/"}

微信公众号通知消息

工具类:

import org.apache.commons.collections.MapUtils;import org.apache.commons.io.IOUtils;import org.apache.commons.lang3.StringUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.net.ssl.*;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.HttpURLConnection;import java.net.URL;import java.net.URLEncoder;import java.nio.charset.StandardCharsets;import java.security.SecureRandom;import java.security.cert.CertificateException;import java.security.cert.X509Certificate;import java.util.Map;public class HttpUtil {  private static Logger logger = LoggerFactory.getLogger(HttpUtil.class);  protected static final String POST_METHOD = "POST";  private static final String GET_METHOD = "GET";  static {    TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {      @Override      public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {        logger.debug("ClientTrusted");      }      @Override      public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {        logger.debug("ServerTrusted");      }      @Override      public X509Certificate[] getAcceptedIssuers() {        return new X509Certificate[]{};      }    }};    HostnameVerifier doNotVerify = (s, sslSession) -> true;    try {      SSLContext sc = SSLContext.getInstance("SSL", "SunJSSE");      sc.init(null, trustAllCerts, new SecureRandom());      HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());      HttpsURLConnection.setDefaultHostnameVerifier(doNotVerify);    } catch (Exception e) {      logger.error("Initialization https impl occur exception : {}", e);    }  }  /**   * 默认的http请求执行方法   *   * @param url  url 路径   * @param method 请求的方法 POST/GET   * @param map  请求参数集合   * @param data  输入的数据 允许为空   * @return result   */  private static String HttpDefaultExecute(String url, String method, Map<String, String> map, String data) {    String result = "";    try {      url = setParmas(url, map, null);      result = defaultConnection(url, method, data);    } catch (Exception e) {      logger.error("出错参数 {}", map);    }    return result;  }  public static String httpGet(String url, Map<String, String> map) {    return HttpDefaultExecute(url, GET_METHOD, map, null);  }  public static String httpPost(String url, Map<String, String> map, String data) {    return HttpDefaultExecute(url, POST_METHOD, map, data);  }  /**   * 默认的https执行方法,返回   *   * @param url  url 路径   * @param method 请求的方法 POST/GET   * @param map  请求参数集合   * @param data  输入的数据 允许为空   * @return result   */  private static String HttpsDefaultExecute(String url, String method, Map<String, String> map, String data) {    try {      url = setParmas(url, map, null);      logger.info(data);      return defaultConnection(url, method, data);    } catch (Exception e) {      logger.error("出错参数 {}", map);    }    return "";  }  public static String doGet(String url, Map<String, String> map) {    return HttpsDefaultExecute(url, GET_METHOD, map, null);  }  public static String doPost(String url, Map<String, String> map, String data) {    return HttpsDefaultExecute(url, POST_METHOD, map, data);  }  /**   * @param path  请求路径   * @param method 方法   * @param data  输入的数据 允许为空   * @return   * @throws Exception   */  private static String defaultConnection(String path, String method, String data) throws Exception {    if (StringUtils.isBlank(path)) {      throw new IOException("url can not be null");    }    String result = null;    URL url = new URL(path);    HttpURLConnection conn = getConnection(url, method);    if (StringUtils.isNotEmpty(data)) {      OutputStream output = conn.getOutputStream();      output.write(data.getBytes(StandardCharsets.UTF_8));      output.flush();      output.close();    }    if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {      InputStream input = conn.getInputStream();      result = IOUtils.toString(input, StandardCharsets.UTF_8);      input.close();      conn.disconnect();    }//    log.info(result);    return result;  }  /**   * 根据url的协议选择对应的请求方式   *   * @param url  请求路径   * @param method 方法   * @return conn   * @throws IOException 异常   */  //待改进  protected static HttpURLConnection getConnection(URL url, String method) throws IOException {    HttpURLConnection conn;    if (StringUtils.equals("https", url.getProtocol())) {      conn = (HttpsURLConnection) url.openConnection();    } else {      conn = (HttpURLConnection) url.openConnection();    }    if (conn == null) {      throw new IOException("connection can not be null");    }    conn.setRequestProperty("Pragma", "no-cache");// 设置不适用缓存    conn.setRequestProperty("Cache-Control", "no-cache");    conn.setRequestProperty("Connection", "Close");// 不支持Keep-Alive    conn.setUseCaches(false);    conn.setDoOutput(true);    conn.setDoInput(true);    conn.setInstanceFollowRedirects(true);    conn.setRequestMethod(method);    conn.setConnectTimeout(8000);    conn.setReadTimeout(8000);    return conn;  }  /**   * 根据url   *   * @param url 请求路径   * @return isFile   * @throws IOException 异常   */  //待改进  protected static HttpURLConnection getConnection(URL url, boolean isFile) throws IOException {    HttpURLConnection conn = (HttpURLConnection) url.openConnection();    if (conn == null) {      throw new IOException("connection can not be null");    }    //设置从httpUrlConnection读入    conn.setDoInput(true);    conn.setDoOutput(true);    conn.setUseCaches(false);    //如果是上传文件,则设为POST    if (isFile) {      conn.setRequestMethod(POST_METHOD); //GET和 POST都可以 文件略大改成POST    }    // 设置请求头信息    conn.setRequestProperty("Connection", "Keep-Alive");    conn.setRequestProperty("Charset", String.valueOf(StandardCharsets.UTF_8));    conn.setConnectTimeout(8000);    conn.setReadTimeout(8000);    return conn;  }  /**   * 拼接参数   *   * @param url   需要拼接参数的url   * @param map   参数   * @param charset 编码格式   * @return 拼接完成后的url   */  public static String setParmas(String url, Map<String, String> map, String charset) throws Exception {    String result = StringUtils.EMPTY;    boolean hasParams = false;    if (StringUtils.isNotEmpty(url) && MapUtils.isNotEmpty(map)) {      StringBuilder builder = new StringBuilder();      for (Map.Entry<String, String> entry : map.entrySet()) {        String key = entry.getKey().trim();        String value = entry.getValue().trim();        if (hasParams) {          builder.append("&");        } else {          hasParams = true;        }        if (StringUtils.isNotEmpty(charset)) {          builder.append(key).append("=").append(URLEncoder.encode(value, charset));        } else {          builder.append(key).append("=").append(value);        }      }      result = builder.toString();    }    URL u = new URL(url);    if (StringUtils.isEmpty(u.getQuery())) {      if (url.endsWith("?")) {        url += result;      } else {        url = url + "?" + result;      }    } else {      if (url.endsWith("&")) {        url += result;      } else {        url = url + "&" + result;      }    }    logger.debug("request url is {}", url);    return url;  }}

遇到的问题

1)"errcode":40001,"errmsg":"invalid credential, access_token is invalid or not latest hint: [Ua2IXa0080sz47!]"获取的access_token不对,这边的token不是授权的token,是公众号调用各接口时使用的access_token

以上是“如何使用java实现微信公众平台发送模板消息”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!