微信公众号发送模板消息其实很简单,调用下面的这个工具类即可(这个工具类是我在网上找的。。。)。工具类主要用于调用微信发送模板消息的接口。
首先会获取ACCESS_TOKEN,若之前获取的没过期则用之前的,若过期了则从新获取。然后用一个http工具类调用发送模板消息的接口即可。
发送模板消息工具类:
package org.guangyu.utils;
import java.io.IOException;
import java.util.Date;
import java.util.Properties;
import net.sf.json.JSONObject;
public class WeChatUtil {
// // URL验证时使用的token
// public static final String TOKEN = "qq";
// appid
public static String APPID = "";
// secret
public static String SECRET = "";
// 创建菜单接口地址
// public static final String CREATE_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
// 发送模板消息的接口
public static final String SEND_TEMPLATE_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN";
// 获取access_token的接口地址
public static final String GET_ACCESSTOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
// 缓存的access_token
private static String accessToken;
// access_token的失效时间
private static long expiresTime;
private static Properties properties = new Properties();
static{
try {
properties.load(WeChatUtil.class.getClassLoader().getResourceAsStream("weixin.properties"));
APPID = properties.getProperty("APPID");
SECRET = properties.getProperty("SECRET");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取accessToken
*
* @return
* @throws IOException
*/
public static String getAccessToken() throws IOException {
// 判断accessToken是否已经过期,如果过期需要重新获取
if (accessToken == null || expiresTime < new Date().getTime()) {
// 发起请求获取accessToken
String result = HttpUtil.get(GET_ACCESSTOKEN_URL.replace("APPID",
APPID).replace("APPSECRET", SECRET));
System.out.println(APPID + "/////" + SECRET);
// 把json字符串转换为json对象
JSONObject json = JSONObject.fromObject(result);
// 缓存accessToken
accessToken = json.getString("access_token");
// 设置accessToken的失效时间
long expires_in = json.getLong("expires_in");
// 失效时间 = 当前时间 + 有效期(提前一分钟)
expiresTime = new Date().getTime() + (expires_in - 60) * 1000;
}
return accessToken;
}
/**
* 发送模板
*
* @return 结果集({"errcode":0,"errmsg":"ok","msgid":528986890112614400})、
* ({"errcode":40003,"errmsg":"invalid openid hint: [tv6YMa03463946]"})
* @throws IOException
*/
public static String sendTemplate(String data) throws IOException {
// 通过调用HttpUtil工具类发送post请求
// 调用微信发送模板消息的接口
String result = HttpUtil.post(SEND_TEMPLATE_URL.replace("ACCESS_TOKEN",
getAccessToken()), data);
System.out.println(result);
return result;
}
}
weixin.properties是配置文件。用于动态获取APPID和APPSECRET。
APPID=xxxxxxxx
SECRET=xxxxxxxxxxxxxxxxxxxxxx
至于HttpUtil是一个http工具类,网上有很多。
package org.guangyu.utils;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
/**
*
* @project baidamei
* @author cevencheng <[email protected]>
* @create 2012-11-17 ����2:35:38
*/
public class HttpUtil {
/**
* Send a get request
*
* @param url
* @return response
* @throws IOException
*/
static public String get(String url) throws IOException {
return get(url, null);
}
/**
* Send a get request
*
* @param url
* Url as string
* @param headers
* Optional map with headers
* @return response Response as string
* @throws IOException
*/
static public String get(String url, Map<String, String> headers)
throws IOException {
return fetch("GET", url, null, headers);
}
/**
* Send a post request
*
* @param url
* Url as string
* @param body
* Request body as string
* @param headers
* Optional map with headers
* @return response Response as string
* @throws IOException
*/
static public String post(String url, String body,
Map<String, String> headers) throws IOException {
return fetch("POST", url, body, headers);
}
/**
* Send a post request
*
* @param url
* Url as string
* @param body
* Request body as string
* @return response Response as string
* @throws IOException
*/
static public String post(String url, String body) throws IOException {
return post(url, body, null);
}
/**
* Post a form with parameters
*
* @param url
* Url as string
* @param params
* map with parameters/values
* @return response Response as string
* @throws IOException
*/
static public String postForm(String url, Map<String, String> params)
throws IOException {
return postForm(url, params, null);
}
/**
* Post a form with parameters
*
* @param url
* Url as string
* @param params
* Map with parameters/values
* @param headers
* Optional map with headers
* @return response Response as string
* @throws IOException
*/
static public String postForm(String url, Map<String, String> params,
Map<String, String> headers) throws IOException {
// set content type
if (headers == null) {
headers = new HashMap<String, String>();
}
headers.put("Content-Type", "application/x-www-form-urlencoded");
// parse parameters
String body = "";
if (params != null) {
boolean first = true;
for (String param : params.keySet()) {
if (first) {
first = false;
} else {
body += "&";
}
String value = params.get(param);
body += URLEncoder.encode(param, "UTF-8") + "=";
body += URLEncoder.encode(value, "UTF-8");
}
}
return post(url, body, headers);
}
/**
* Send a put request
*
* @param url
* Url as string
* @param body
* Request body as string
* @param headers
* Optional map with headers
* @return response Response as string
* @throws IOException
*/
static public String put(String url, String body,
Map<String, String> headers) throws IOException {
return fetch("PUT", url, body, headers);
}
/**
* Send a put request
*
* @param url
* Url as string
* @return response Response as string
* @throws IOException
*/
static public String put(String url, String body) throws IOException {
return put(url, body, null);
}
/**
* Send a delete request
*
* @param url
* Url as string
* @param headers
* Optional map with headers
* @return response Response as string
* @throws IOException
*/
static public String delete(String url, Map<String, String> headers)
throws IOException {
return fetch("DELETE", url, null, headers);
}
/**
* Send a delete request
*
* @param url
* Url as string
* @return response Response as string
* @throws IOException
*/
static public String delete(String url) throws IOException {
return delete(url, null);
}
/**
* Append query parameters to given url
*
* @param url
* Url as string
* @param params
* Map with query parameters
* @return url Url with query parameters appended
* @throws IOException
*/
static public String appendQueryParams(String url,
Map<String, String> params) throws IOException {
String fullUrl = new String(url);
if (params != null) {
boolean first = (fullUrl.indexOf('?') == -1);
for (String param : params.keySet()) {
if (first) {
fullUrl += '?';
first = false;
} else {
fullUrl += '&';
}
String value = params.get(param);
fullUrl += URLEncoder.encode(param, "GBK") + '=';
fullUrl += URLEncoder.encode(value, "GBK");
}
}
return fullUrl;
}
/**
* Retrieve the query parameters from given url
*
* @param url
* Url containing query parameters
* @return params Map with query parameters
* @throws IOException
*/
static public Map<String, String> getQueryParams(String url)
throws IOException {
Map<String, String> params = new HashMap<String, String>();
int start = url.indexOf('?');
while (start != -1) {
// read parameter name
int equals = url.indexOf('=', start);
String param = "";
if (equals != -1) {
param = url.substring(start + 1, equals);
} else {
param = url.substring(start + 1);
}
// read parameter value
String value = "";
if (equals != -1) {
start = url.indexOf('&', equals);
if (start != -1) {
value = url.substring(equals + 1, start);
} else {
value = url.substring(equals + 1);
}
}
params.put(URLDecoder.decode(param, "GBK"), URLDecoder.decode(
value, "GBK"));
}
return params;
}
/**
* Returns the url without query parameters
*
* @param url
* Url containing query parameters
* @return url Url without query parameters
* @throws IOException
*/
static public String removeQueryParams(String url) throws IOException {
int q = url.indexOf('?');
if (q != -1) {
return url.substring(0, q);
} else {
return url;
}
}
/**
* Send a request
*
* @param method
* HTTP method, for example "GET" or "POST"
* @param url
* Url as string
* @param body
* Request body as string
* @param headers
* Optional map with headers
* @return response Response as string
* @throws IOException
*/
static public String fetch(String method, String url, String body,
Map<String, String> headers) throws IOException {
// connection
URL u = new URL(url);
HttpURLConnection conn = (HttpURLConnection) u.openConnection();
conn.setConnectTimeout(90000);
conn.setReadTimeout(90000);
// method
if (method != null) {
conn.setRequestMethod(method);
}
// headers
if (headers != null) {
for (String key : headers.keySet()) {
conn.addRequestProperty(key, headers.get(key));
}
}
// body
if (body != null) {
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
os.write(body.getBytes("UTF-8"));
os.flush();
os.close();
}
// response
InputStream is = conn.getInputStream();
String response = streamToString(is);
is.close();
// handle redirects
if (conn.getResponseCode() == 301) {
String location = conn.getHeaderField("Location");
return fetch(method, location, body, headers);
}
return response;
}
/**
* Read an input stream into a string
*
* @param in
* @return
* @throws IOException
*/
static public String streamToString(InputStream in) throws IOException {
StringBuffer out = new StringBuffer();
byte[] b = new byte[4096];
for (int n; (n = in.read(b)) != -1;) {
out.append(new String(b, 0, n));
}
return out.toString();
}
}
做完以上准备,接下来就开始来正式的了。
这是官网上说的一些参数。
接下来编写一个实体类用于存放这些参数。
package org.guangyu.orm.model;
import java.util.TreeMap;
public class TemplateMessage {
private String touser; // 接收者openid
private String template_id; // 模板ID
private String url; // 模板跳转链接
private TreeMap<String, TreeMap<String, String>> data; // data数据
//get、set已省略
/**
* 参数
*
* @param value
* @param color
* 可不填
* @return
*/
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 void sendTemplateMessage() throws IOException {
System.out.println("开始封装模板消息。。。。。。。。。。");
// 将信息内容封装到实体类
TemplateMessage temp = new TemplateMessage();
// 设置接收方的openid user.getOpenid()是从数据库中得到的对应的openid
temp.setTouser(user.getOpenid());
// 设置模板id(从页面上复制)
temp.setTemplate_id("VMFMaNyr67yn8dMk1UJPwS1yTLgPUDHZbBj9D608O0c");
// 设置回调地址(点击模板消息所跳转的地址,设置为空即无跳转)
temp.setUrl("");
// 设置模板消息内容和对应的字体颜色
TreeMap<String, TreeMap<String, String>> params = new TreeMap<String, TreeMap<String, String>>();
params.put("first", TemplateMessage.item("新的学习任务已发布,请登录APP尽快完成,完成任务得红包!", "#173177"));
//date为当前时间,new出来的在这里省略
params.put("keyword1", TemplateMessage.item(date, "#173177"));
params.put("keyword2", TemplateMessage.item("尚未完成!", "#173177"));
params.put("keyword3", TemplateMessage.item("-", "#173177"));
params.put("remark", TemplateMessage.item("", "#173177"));
// 将实体类转为jsonObject
JSONObject data = JSONObject.fromObject(temp);
System.out.println(data + "");
// 通过工具类调用微信接口发送模板消息
String result = WeChatUtil.sendTemplate(data + "");
System.out.println("返回结果集:" + result);
}
结果如下图所示:
没设置url即为不可点击,设置了则点击即可跳转到设定的url。