微信公众平台: https://mp.weixin.qq.com
每个公众号都有自己的 开发者ID(AppID) 和 开发者密码(AppSecret) 。可以前往微信公众平台,在开发基本配置中查看。
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
1.登录微信公众平台,找到模板消息,从模板库中找到自己想要的消息模板,进入详情添加即可。
access_token 是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。
access_token 的存储至少要保留512个字符空间。
access_token 的有效期目前为2个小时,重复获取将导致上次获取的access_token失效。
access_token 每日获取上限 100000 次。
建议公众号开发者使用中控服务器统一获取和刷新access_token,其他业务逻辑服务器所使用的access_token均来自于该中控服务器,不应该各自去刷新,否则容易造成冲突,导致access_token覆盖而影响业务
https请求方式: GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
参数 | 是否必须 | 是否必须 |
---|---|---|
grant_type | 是 | 获取access_token填写client_credential |
appid | 是 | 第三方用户唯一凭证 |
secret | 是 | 第三方用户唯一凭证密钥,即appsecret |
{“access_token”:“ACCESS_TOKEN”,“expires_in”:7200}
参数 | 说明 |
---|---|
access_token | 获取到的凭证 |
expires_in | 凭证有效时间,单位:秒 |
{“errcode”:40013,“errmsg”:“invalid appid”}
错误时错误码等信息详情可查看官方文档
http请求方式: POST https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN
POST数据示例如下:
{
"touser":"OPENID",
"template_id":"ngqIpbwh8bUfcSsECmogfXcV14J0tQlEpBO27izEYtY",
"url":"http://weixin.qq.com/download",
"miniprogram":{
"appid":"xiaochengxuappid12345",
"pagepath":"index?foo=bar"
},
"data":{
"first": {
"value":"恭喜你购买成功!",
"color":"#173177"
},
"keyword1":{
"value":"巧克力",
"color":"#173177"
},
"keyword2": {
"value":"39.8元",
"color":"#173177"
},
"keyword3": {
"value":"2014年9月22日",
"color":"#173177"
},
"remark":{
"value":"欢迎再次购买!",
"color":"#173177"
}
}
}
参数 | 是否必填 | 说明 |
---|---|---|
touser | 是 | 接收者openid |
template_id | 是 | 模板ID |
url | 否 | 模板跳转链接(海外帐号没有跳转能力) |
miniprogram | 否 | 跳小程序所需数据,不需跳小程序可不用传该数据 |
appid | 是 | 所需跳转到的小程序appid(该小程序appid必须与发模板消息的公众号是绑定关联关系,暂不支持小游戏) |
pagepath | 否 | 所需跳转到小程序的具体页面路径,支持带参数,(示例index?foo=bar),要求该小程序已发布,暂不支持小游戏 |
data | 是 | 模板数据 |
color | 否 | 模板内容字体颜色,不填默认为黑色 |
其他详细内容可查看官方文档
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yo.project.module.common.utils.character.StringUtils;
import com.yo.project.web.controller.parking.TemplateData;
import com.yo.project.web.controller.parking.WxTemplate;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import java.util.HashMap;
import java.util.Map;
/**
* @Auther: yoult
* @Description: TODO
* @LoginName: ZDGG
* @Date: 2020-12-02 14:27 星期三
*/
public class WxTemplateMessageServlet {
// 开发者密码(AppSecret)
private static String AppSecret;
// 开发者ID(AppID)
private static String AppId;
// 消息模板ID
private static String TemplateId;
// 网页授权接口
private final static String GetAccessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=SECRET";
// 发送模板消息接口
private final static String SendTempMessage = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN";
/**
* 推送模板消息
* @param parkingName 停车场名称
* @param plateNumber 车牌号
* @param enterTime 入场时间
* @param openId 推送用户OpenId (注意,是OpenId)
* @param templateUrl 跳转Url
*/
public void sendEnterTemplateMessage(String parkingName, String plateNumber, String enterTime, String openId, String templateUrl) {
Map<String, Object> result = null;
try {
Map<String, TemplateData> data = new HashMap<>();
TemplateData first = new TemplateData();
TemplateData keyword1 = new TemplateData();
TemplateData keyword2 = new TemplateData();
TemplateData keyword3 = new TemplateData();
TemplateData remark = new TemplateData();
first.setColor("#328392");
first.setValue("欢迎进入" + parkingName);
keyword1.setColor("#328392");
keyword1.setValue(plateNumber);
keyword2.setColor("#328392");
keyword2.setValue(parkingName);
keyword3.setColor("#328392");
keyword3.setValue(enterTime);
remark.setColor("#328392");
// 有模板模板跳转链接,则推送消息可点击
remark.setValue("本车场开通车牌识别,临停车辆请在临出场之前进行缴费,方便您的出行。" + (StringUtils.isBlank(templateUrl) ? "" : "点击可预支付缴费出场。"));
data.put("first", first);
data.put("keyword1", keyword1);
data.put("keyword2", keyword2);
data.put("keyword3", keyword3);
data.put("remark", remark);
WxTemplate template = new WxTemplate();
// 推送用户OpenId
template.setTouser(openId);
// 消息模板ID
template.setTemplate_id(TemplateId);
// 有模板模板跳转链接,则推送消息可点击
if (!StringUtils.isBlank(templateUrl)) template.setUrl(templateUrl);
template.setData(data);
System.out.println("模板消息推送:" + template.toString());
// 获取 AccessToken
String accessToken = null;
try {
accessToken = getAccessToken();
} catch (Exception e) {
e.printStackTrace();
}
template.setAppid(AppId);
String message = sendPostMessage(SendTempMessage.replace("ACCESS_TOKEN", accessToken), template);
result.put("code", 1);
result.put("message", message);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println((String.valueOf(result)));
}
/**
* Post 请求发送数据
* @param url
* @param dataMap
* @return
*/
private static String sendPostMessage(String url, Object dataMap) {
String data = new String();
// 创建HttpClient实例
HttpClient client = HttpClientBuilder.create().build();
// 根据URL创建HttpPost实例
HttpPost post = new HttpPost(url);
try {
// 构造post参数
StringEntity s = new StringEntity(JSON.toJSONString(dataMap), "UTF-8");
s.setContentEncoding("UTF-8");
s.setContentType("application/json");//发送json数据需要设置contentType
post.setEntity(s);
// 发送请求,得到响应体
HttpResponse response = client.execute(post);
// 判断是否正常返回
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
// 解析数据
HttpEntity resEntity = response.getEntity();
data = EntityUtils.toString(resEntity);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
client.getConnectionManager().shutdown();
}
return data;
}
/**
* 获取AccessToken
* @return
* @throws Exception
*/
private static String getAccessToken() throws Exception {
String requestUrl = GetAccessTokenUrl.replace("APPID", AppId).replace("SECRET", AppSecret);
HttpClient client = HttpClientBuilder.create().build();
String accessToken = null;
String errcode = null;
String errmsg = null;
try {
HttpGet httpget = new HttpGet(requestUrl);
ResponseHandler<String> responseHandler = new BasicResponseHandler();
String response = client.execute(httpget, responseHandler);
JSONObject OpenidJSONO = JSONObject.parseObject(response);
errcode = String.valueOf(OpenidJSONO.get("errcode"));
errmsg = String.valueOf(OpenidJSONO.get("errmsg"));
accessToken = String.valueOf(OpenidJSONO.get("access_token"));
} catch (Exception e) {
e.printStackTrace();
} finally {
client.getConnectionManager().shutdown();
}
if (!StringUtils.isBlank(errcode) && !errcode.equals("null"))
throw new Exception(errmsg);
return accessToken;
}
}
import lombok.Data;
/**
* 模板消息
*/
@Data
public class TemplateData {
private String value;//模板显示值
private String color;//模板显示颜色
@Override
public String toString() {
return "TemplateData{" + "value='" + value + '\'' + ", color='" + color + '\'' + '}';
}
}
import lombok.Data;
import java.util.Map;
/**
* 模板基类
*
* @author CLiang
*/
@Data
public class WxTemplate {
private String touser;//目标openId
private String template_id;//模板ID
private String url;//用户点击模板信息的跳转页面
private Map<String, Object> miniprogram;//跳小程序所需数据,不需跳小程序可不用传该数据
private String appid;//所需跳转到的小程序appid(该小程序appid必须与发模板消息的公众号是绑定关联关系,暂不支持小游戏)
private String pagepath;//所需跳转到小程序的具体页面路径,支持带参数,(示例index?foo=bar),要求该小程序已发布,暂不支持小游戏
private String color;//模板内容字体颜色,不填默认为黑色
private Map<String, TemplateData> data;//模板里的数据
@Override
public String toString() {
return "WxTemplate{" + "touser='" + touser + '\'' + ", template_id='" + template_id + '\'' + ", url='" + url + '\'' + ", miniprogram=" + miniprogram + ", appid='" + appid + '\'' + ", pagepath='" + pagepath + '\'' + ", color='" + color + '\'' + ", data=" + data + '}';
}
}