看着大家用公众号推消息推得不亦乐乎,心里痒痒吧,那就进来了解一下吧。
一、提前准备:公网服务器、备案域名。
二、先申请微信公众号,如果你申请的是个人订阅号,那么模板消息推送就没法进行了,所以我们需要申请一个微信公众号测试账号。如何操作,请百度之。
三、大概原理:我们拿着账号的appId和appSecret就可以调用微信的接口,获取一个叫做access_token的东西了,然后剩余大部分接口,我们拿着access_token,调取相应的微信接口就好了。
接下来以测试账号为例来说明:
我们可以看到测试号的appId和appSecret:
这两个参数保管好,不要泄露。
四、配置服务器url
在配置之前往先要开发对应的接口,用以接收微信的请求:
@Controller
public class WxController {
Logger logger = LoggerFactory.getLogger(WxController.class);
@Autowired
private WxConfig wxConfig;
@RequestMapping("/wx")
@ResponseBody
public String responseWx(HttpServletRequest request){
Map<String, String[]> parametersMap = request.getParameterMap();
StringBuilder sb = new StringBuilder();
for(Map.Entry<String, String[]> entry:parametersMap.entrySet()){
sb.append(entry.getKey()).append(":").append(String.join(",",entry.getValue())).append(" ,");
}
logger.info("收到微信的消息:"+sb.toString());
String returnStr = null;
if(parametersMap.containsKey("signature")
&¶metersMap.containsKey("timestamp")
&¶metersMap.containsKey("nonce")
&¶metersMap.containsKey("echostr")){// 微信token认证
String signature = parametersMap.get("signature")[0];
String timestamp = parametersMap.get("timestamp")[0];
String nonce = parametersMap.get("nonce")[0];
String echostr = parametersMap.get("echostr")[0];
String[] arr = new String[]{wxConfig.token, timestamp, nonce};
sort(arr);
StringBuilder content = new StringBuilder();
for (int i = 0; i < arr.length; i++) {
content.append(arr[i]);
}
String mySignature = SHA1.encode(content.toString());
if(mySignature.equalsIgnoreCase(signature)){
returnStr = echostr;
}
}
logger.info("返回给微信的消息:"+returnStr);
return returnStr;
}
}
SHA1校验的部分:
public class SHA1 {
/**
* 加密
* @param content
* @return
*/
public static String encode(String content) {
if (content == null) {
return null;
}
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA-1");
// 将三个参数字符串拼接成一个字符串进行sha1加密
byte[] digest = md.digest(content.getBytes());
return byteToStr(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
/**
* 将字节数组转换为十六进制字符串
*
* @param byteArray
* @return
*/
private static String byteToStr ( byte[] byteArray){
String strDigest = "";
for (int i = 0; i < byteArray.length; i++) {
strDigest += byteToHexStr(byteArray[i]);
}
return strDigest;
}
/**
* 将字节转换为十六进制字符串
*
* @param mByte
* @return
*/
private static String byteToHexStr ( byte mByte){
char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
char[] tempArr = new char[2];
tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
tempArr[1] = Digit[mByte & 0X0F];
String s = new String(tempArr);
return s;
}
}
填写服务器的url,用来接收微信的认证消息,其实就是微信给你的服务器发个消息,你做出对应的响应,微信就认为服务器是通的。
配置需要注意的是需要是:如果是http,那么服务的端口必须是80端口,如果是https,则是443端口:
五、配置js接口安全域名
如果模板消息有更多复杂的内容需要展示,我们是无法一次性发送给微信进行展示的,因此点击消息的详情,就会跳入我们的页面。不能谁的页面都跳转,那不安全,所以你要设置一下,才给你跳。
六、获取access_token
/**
* 获取accessToken
*
* @return
* @throws ParseException
* @throws IOException
*/
public static String getAccessToken(String appId,String appSecret) {
if(appId==null||appId.trim().isEmpty()){
throw new RuntimeException("appId为空");
}
if(appSecret==null||appSecret.trim().isEmpty()){
throw new RuntimeException("appSecret为空");
}
try {
//如果是空的,或者超时,刷新access_token
if (StringUtil.isEmpty(WxBean.ACCESS_TOKEN) || System.currentTimeMillis() >= WxBean.TOKEN_TIME_OUT) {
String url = ACCESS_TOKEN_URL.replace("APP_ID", appId).replace("APP_SECRET", appSecret);
// TODO 后期删除该日志 敏感信息
logger.info("获取access_token的发送:"+url);
String result = HttpUtil.doGet(url);
logger.info("获取access_token的接口返回:"+result);
if(result!=null&&!result.trim().isEmpty()){
JSONObject jsonObject = JSONObject.parseObject(result);
WxBean.ACCESS_TOKEN = jsonObject.getString("access_token");
WxBean.TOKEN_TIME_OUT = System.currentTimeMillis() + (ACCESS_TOKEN_TIMEOUT_SECOND * 1000);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return WxBean.ACCESS_TOKEN;
}
/**
* get请求
*
* @param url
* @return
*/
public static String doGet(String url) {
CloseableHttpResponse response = null;
String result = null;
try {
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
response = httpclient.execute(httpGet);
HttpEntity entity = response.getEntity();
if (entity != null) {
result = EntityUtils.toString(entity, "UTF-8");
}
EntityUtils.consume(entity);
}catch (Exception e){
e.printStackTrace();
} finally {
try {
response.close();
}catch (Exception e2){
e2.printStackTrace();
}
}
return result;
}
/**
* POST请求
*
*/
public static String doPost(String url, String msg){
CloseableHttpResponse response = null;
String result = null;
try {
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new StringEntity(msg, "UTF-8"));
response = httpclient.execute(httpPost);
HttpEntity entity = response.getEntity();
result = EntityUtils.toString(response.getEntity(), "UTF-8");
EntityUtils.consume(entity);
}catch (Exception e){
e.printStackTrace();
} finally {
try {
response.close();
}catch (Exception e2){
e2.printStackTrace();
}
}
return result;
}
六、关注测试号
拿起你的手机,扫一扫二维码,我们就关注了该测试号,当然界面很丑,不管了。现在右边就出现了微信号,这个就是你的openId。不用苦苦的使用js-sdk获取,也不用调用用户列表接口,就获取到了openId。当然这是测试号,正式的可能情况有所不同。
七、新建一个模板,发送消息
模板:
标题随便写一个,模板的地方值的注意的是,如果觉得行间距太小,不美观,可以加空行。
建立模板之后,我们就获取到了模板的id。现在万事俱备,我们来发一个模板消息吧:
@RequestMapping("/wxPushMsg")
@ResponseBody
public String wxPushMsg(){
logger.info("推送模板消息");
String accessToken = WxUtil.getAccessToken(wxConfig.appId,wxConfig.appSecret);
logger.info("获取的access_token为:"+accessToken);
String openId = "xxx";
String templateId ="xxxxxxxxx";
String url ="https://www.fantasyworldforyou.com/#/index";
//微信推送
JSONObject jsonObject = new JSONObject();
JSONObject data = new JSONObject();
jsonObject.put("data",data);
JSONObject msg1 = new JSONObject();//内容值
data.put("msg1", msg1);
JSONObject msg2 = new JSONObject();//内容值
data.put("ms2", msg2);
jsonObject.put("touser", openId);
jsonObject.put("topcolor", "#FF0000");
//给楼栋管理员推送统计信息
jsonObject.put("url", url+"?date="+ UuidUtil.getUUID());
jsonObject.put("template_id", templateId);
msg1.put("value", "你好 世界");
msg1.put("color", "#173177");
msg2.put("value", "哈哈哈");
msg2.put("color", "#173177");
String result = WxUtil.sendTemplateMessage(accessToken,jsonObject.toString());
logger.info("返回:"+result);
return result;
}
/**
* 发送微信模板消息
*
* @param message
* @return
* @throws ParseException
* @throws IOException
*/
public static String sendTemplateMessage(String accessToken, String message) {
String result = null;
if(accessToken==null||accessToken.trim().isEmpty()){
throw new RuntimeException("accessToken为空");
}
String url = SEND_TEMPLATE_MESSAGE_URL.replace("ACCESS_TOKEN", accessToken);
try {
logger.info("发送微信模板消息消息体:"+message);
result = HttpUtil.doPost(url, message);
logger.info("发送微信模板消息返回:"+result);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
现在打开手机,你会看到一个推送消息:
点击还可以查看详情,就是我们自己的页面。