java实现微信公众平台发送模板消息的示例代码

网友投稿 325 2022-12-28


java实现微信公众平台发送模板消息的示例代码

获取template_id(注意:仅微信开放平台同事可获取)

通过向微信公众平台申请模板,来获取模板id,模板消息调用时主要需要模板ID和模板中各参数的赋值内容。请注意:

1.模板中参数内容必须以".DATA"结尾,否则视为保留字;

2.模板保留符号"{{ }}"

请求模板消息接口

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/oauth2/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/oauth2/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";

//模板消息详情跳转URL

private static String url = "https://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/oauth2/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://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) {

sPbtGCZ 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 stasPbtGCZtic 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.sPbtGCZHTTP_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!]"


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:微信接口测试工具下载(微信开发者工具测试)
下一篇:Java多线程 BlockingQueue实现生产者消费者模型详解
相关文章

 发表评论

暂时没有评论,来抢沙发吧~