千家信息网

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

发表于:2025-01-24 作者:千家信息网编辑
千家信息网最后更新 2025年01月24日,这篇文章主要为大家展示了"如何使用java实现微信公众平台发送模板消息",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"如何使用java实现微信公众平台发送模
千家信息网最后更新 2025年01月24日如何使用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> data; //data数据  public static TreeMap item(String value, String color) {    TreeMap params = new TreeMap();    params.put("value", value);    params.put("color", color);    return params;  }  public TreeMap> getData() {    return data;  }  public void setData(TreeMap> 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> params = new TreeMap>();  //根据具体模板参数组装  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 treeMap = new TreeMap();  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 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 map) {    return HttpDefaultExecute(url, GET_METHOD, map, null);  }  public static String httpPost(String url, Map 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 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 map) {    return HttpsDefaultExecute(url, GET_METHOD, map, null);  }  public static String doPost(String url, Map 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 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 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实现微信公众平台发送模板消息"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

模板 消息 参数 平台 接口 方法 公众 数据 路径 旅行 内容 对象 篇文章 输入 准时 个人 人文 可在 地点 损失 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 商品管理信息数据库设计 ios9 官方验证服务器 手机软件开发公司费用 网络安全隐患情况说明 舆情网络安全方案 中国长沙网络安全制造大会 深圳灵沃软件开发有限公司 黄浦区网络技术开发服务平均价格 香港科技大学论文数据库 我想定制棋牌软件开发 如何使用万方数据库 网络安全的资料和问题 亚洲服务器的刺激战场在哪里下载 dcom配置网络安全策略 ftp服务器怎么退出控制 软件开发糖果公司电话 云南材料基因数据库 数据库连接多个查询条件 网上招聘网络技术人员 求生之路服务器vpk插件 无锡金互联网科技鑫 华为全球软件开发总部落户昆明 把数据库导出到本地 广州邮箱外贸软件开发公司 服务器自建和托管租用有什么区别 松江区网络软件开发厂家批发价 什么是pop3服务器地址 网络安全法 对比 计算机网络技术与信息系统 求生之路服务器vpk插件
0