首先,公众号的准备工作(以测试号为主)

1.先得到公众号的appidappsecrettoken(此程序可有可无)

2.然后得到一个推送的用户oppenid
3.消息推送模板准备,点击新增测试模板

我的模板信息(可直接CV)

标题:交易提醒   内容:尊敬的{{User.DATA}} {{k1.DATA}} 您的尾号{{CardNumber.DATA}} 的建设银行储蓄卡最新交易信息 交易时间:{{Date.DATA}} 交易类型:{{Type.DATA}} 交易金额:{{Money.DATA}} {{k2.DATA}} 截止至{{DeadTime.DATA}},您在建设银行储蓄卡账户可用余额为{{Left.DATA}}元

4.微信开发平台又提供推送消息的 文档 ,我们只需要POST请求下面的接口就行了

https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN
后台JAVA程序
1.获取access_token

因为调用上面一个接口,需要获取access_token

1.1创建一个access_token的实体类

package com.example.demo.entity;import java.io.Serializable;/**AccessToken 对象*/
public class AccessToken implements Serializable {//获取到的凭证private String accessToken;//凭证有效时间,单位:秒private int expiresin;public String getAccessToken() {return accessToken;}public void setAccessToken(String accessToken) {this.accessToken = accessToken;}public int getExpiresin() {return expiresin;}public void setExpiresin(int expiresin) {this.expiresin = expiresin;}
}

1.2因为需要在程序中发送http请求,添加一个http请求的工具类

package com.example.demo.utils;import com.alibaba.fastjson.JSONObject;
import com.example.demo.entity.MyX509TrustManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;public class WX_HttpsUtil {private static Logger log = LoggerFactory.getLogger(WX_HttpsUtil.class);/*** 发送https请求* @param requestUrl 请求地址* @param requestMethod 请求方式(GET、POST)* @param outputStr 提交的数据* @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)*/public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {JSONObject jsonObject = null;try {// 创建SSLContext对象,并使用我们指定的信任管理器初始化TrustManager[] tm = { new MyX509TrustManager() };SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");sslContext.init(null, tm, new java.security.SecureRandom());// 从上述SSLContext对象中得到SSLSocketFactory对象SSLSocketFactory ssf = sslContext.getSocketFactory();URL url = new URL(requestUrl);HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();conn.setSSLSocketFactory(ssf);conn.setDoOutput(true);conn.setDoInput(true);conn.setUseCaches(false);// 设置请求方式(GET/POST)conn.setRequestMethod(requestMethod);// 当outputStr不为null时向输出流写数据if (null != outputStr) {OutputStream outputStream = conn.getOutputStream();// 注意编码格式outputStream.write(outputStr.getBytes("UTF-8"));outputStream.close();}// 从输入流读取返回内容InputStream inputStream = conn.getInputStream();InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");BufferedReader bufferedReader = new BufferedReader(inputStreamReader);String str = null;StringBuffer buffer = new StringBuffer();while ((str = bufferedReader.readLine()) != null) {buffer.append(str);}// 释放资源bufferedReader.close();inputStreamReader.close();inputStream.close();inputStream = null;conn.disconnect();jsonObject = JSONObject.parseObject(buffer.toString());} catch (ConnectException ce) {log.error("连接超时:{}", ce);} catch (Exception e) {log.error("https请求异常:{}", e);}return jsonObject;}}

1.3获取access_token

package com.example.demo.utils;import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.example.demo.entity.AccessToken;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class WX_TokenUtil {private static Logger log = LoggerFactory.getLogger(WX_TokenUtil.class);/***  获得微信 AccessToken* access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。* 开发者需要access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取* 的access_token失效。* (此处我是把token存在Redis里面了)*/public static AccessToken getWXToken() {String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+ GlobalConfiguration.APPID+"&secret="+ GlobalConfiguration.APPSECRET;JSONObject jsonObject = WX_HttpsUtil.httpsRequest(tokenUrl, "GET", null);System.out.println("jsonObject:"+jsonObject);AccessToken access_token = new AccessToken();if (null != jsonObject) {try {access_token.setAccessToken(jsonObject.getString("access_token"));access_token.setExpiresin(jsonObject.getInteger("expires_in"));} catch (JSONException e) {access_token = null;// 获取token失败log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInteger("errcode"), jsonObject.getString("errmsg"));}}return access_token;}}
2.推送消息给指定的用户
package com.example.demo.controller;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.demo.entity.TemplateData;
import com.example.demo.utils.WX_HttpsUtil;
import com.example.demo.utils.WX_TemplateMsgUtil;
import com.example.demo.utils.WX_TokenUtil;
import com.example.demo.utils.WX_UserUtil;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import sun.reflect.generics.tree.VoidDescriptor;import java.util.HashMap;
import java.util.Map;@Controller
@RequestMapping("/weChat")
public class TestWX {/*public static void main(String[] args) {//新增用户成功 - 推送微信消息senMsg("oTQdNwz-gUeDfLgAQSiRhLZzj1O4");}*/@RequestMapping("/sendMessage")@ResponseBodypublic String sendMessage(){senMsg("oTQdNwz-gUeDfLgAQSiRhLZzj1O4");return "success";}static void senMsg(String openId){//用户是否订阅该公众号标识 (0代表此用户没有关注该公众号 1表示关注了该公众号)Integer  state= WX_UserUtil.subscribeState(openId);System.out.println("state:"+state);// 绑定了微信并且关注了服务号的用户 , 注册成功-推送注册短信if(state==1){Map<String, TemplateData> param = new HashMap<>();param.put("User",new TemplateData("杨先生","#173177"));param.put("Date",new TemplateData("07月18日 19时24分","#173177"));param.put("CardNumber",new TemplateData("0426","#173177"));param.put("Type",new TemplateData("兰州拉面","#173177"));param.put("Money",new TemplateData("人民币5,000,000.00元","#173177"));param.put("DeadTime",new TemplateData("06月08日19时24分","#173177"));param.put("Left",new TemplateData("31872134.09","#173177"));JSON.toJSONString(param);JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(param));//调用发送微信消息给用户的接口WX_TemplateMsgUtil.sendWechatMsgToUser(openId,"lsCnZkSUOIeB4q8ZuHRli3onuciVZPS0GvCh2i06TB4", "http://www.baidu.com","#FFFFFF", jsonObject);//获取公众号的自动回复规则String urlinfo="https://api.weixin.qq.com/cgi-bin/get_current_autoreply_info?access_token="+ WX_TokenUtil.getWXToken().getAccessToken();JSONObject joinfo = WX_HttpsUtil.httpsRequest(urlinfo, "GET", null);Object o=joinfo.get("is_add_friend_reply_open");// System.out.println("o:"+joinfo);String getTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx395cb56f846049fc&secret=b8285bb7fb16553fd11feafb52c332f7";JSONObject Token = WX_HttpsUtil.httpsRequest(getTokenUrl, "GET", null);//System.out.println("Token:"+Token);}}}
package com.example.demo.entity;/*** 模板详细信息* 根据需求自己更改*/
public class TemplateData {private String value;private String color;public TemplateData(String value,String color){this.value = value;this.color = color;}public TemplateData(){}public String getValue() {return value;}public void setValue(String value) {this.value = value;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}
}
package com.example.demo.entity;import java.util.Map;
/*** 注册成功,通知模板消息实体类*/public class TemplateMessage {private String touser; //用户OpenIDprivate String template_id; //模板消息IDprivate String url; //URL置空,在发送后,点模板消息进入一个空白页面(ios),或无法点击(android)。private String topcolor; //标题颜色private Map<String, TemplateData> templateData; //模板详细信息public static TemplateMessage New() {return new TemplateMessage();}public TemplateMessage(){}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;}public String getTopcolor() {return topcolor;}public void setTopcolor(String topcolor) {this.topcolor = topcolor;}public Map<String, TemplateData> getTemplateData() {return templateData;}public void setTemplateData(Map<String, TemplateData> templateData) {this.templateData = templateData;}
}
package com.example.demo.entity;
import javax.net.ssl.X509TrustManager;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
/*** 微信请求 - 信任管理器*/public class MyX509TrustManager implements X509TrustManager{public MyX509TrustManager() {// TODO Auto-generated constructor stub}@Overridepublic void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}@Overridepublic void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}@Overridepublic X509Certificate[] getAcceptedIssuers() {//        return new X509Certificate[0];return  null;}}
package com.example.demo.utils;import java.io.Serializable;/*** 全局公众号配置信息*/
public class GlobalConfiguration implements Serializable {public static final String APPID = "wx395cb56f846049fc";public static final String APPSECRET = "b8285bb7fb16553fd11feafb52c332f7";public static final String TOKEN = "boteWeChat";
}
package com.example.demo.utils;import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;/*** 请求校验工具类* @author m**/
public class SignUtil {// 与接口配置信息中的Token要一致private static String token = "boteWeChat";/*** 验证签名** @param signature* @param timestamp* @param nonce* @return*/public static boolean checkSignature(String signature, String timestamp, String nonce) {String[] arr = new String[] { token, timestamp, nonce };// 将token、timestamp、nonce三个参数进行字典序排序Arrays.sort(arr);StringBuilder content = new StringBuilder();for (int i = 0; i < arr.length; i++) {content.append(arr[i]);}MessageDigest md = null;String tmpStr = null;try {md = MessageDigest.getInstance("SHA-1");// 将三个参数字符串拼接成一个字符串进行sha1加密byte[] digest = md.digest(content.toString().getBytes());tmpStr = byteToStr(digest);} catch (NoSuchAlgorithmException e) {e.printStackTrace();}content = null;// 将sha1加密后的字符串可与signature对比,标识该请求来源于微信return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;}/*** 将字节数组转换为十六进制字符串** @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;}
}
package com.example.demo.utils;import com.alibaba.fastjson.JSONObject;
import com.example.demo.entity.TemplateData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.util.Map;public class WX_TemplateMsgUtil {private static Logger log = LoggerFactory.getLogger(WX_TemplateMsgUtil.class);/*** 封装模板详细信息* @return*/public static JSONObject packJsonmsg(Map<String, TemplateData> param) {JSONObject json = new JSONObject();for (Map.Entry<String,TemplateData> entry : param.entrySet()) {JSONObject keyJson = new JSONObject();TemplateData  dta=  entry.getValue();keyJson.put("value",dta.getValue());keyJson.put("color", dta.getColor());json.put(entry.getKey(), keyJson);}return json;}/*** 根据模板的编号 新增并获取模板ID* @param templateSerialNumber 模板库中模板的 "编号"* @return 模板ID*/public static String getWXTemplateMsgId(String templateSerialNumber){String tmpurl = "https://api.weixin.qq.com/cgi-bin/template/api_add_template?access_token="+ WX_TokenUtil.getWXToken().getAccessToken();JSONObject json = new JSONObject();json.put("template_id_short", templateSerialNumber);JSONObject result = WX_HttpsUtil.httpsRequest(tmpurl, "POST", json.toString());JSONObject resultJson = new JSONObject(result);String errmsg = (String) resultJson.get("errmsg");log.info("获取模板编号返回信息:" + errmsg);if(!"ok".equals(errmsg)){return "error";}String templateId = (String) resultJson.get("template_id");return templateId;}/*** 根据模板ID 删除模板消息* @param templateId 模板ID* @return*/public static String deleteWXTemplateMsgById(String templateId){String tmpurl = "https://api.weixin.qq.com/cgi-bin/template/del_private_template?access_token="+ WX_TokenUtil.getWXToken().getAccessToken();JSONObject json = new JSONObject();json.put("template_id", templateId);try{JSONObject result = WX_HttpsUtil.httpsRequest(tmpurl, "POST", json.toString());JSONObject resultJson = new JSONObject(result);log.info("删除"+templateId+"模板消息,返回CODE:"+ resultJson.get("errcode"));String errmsg = (String) resultJson.get("errmsg");if(!"ok".equals(errmsg)){return "error";}}catch(Exception e){e.printStackTrace();}return "success";}/*** 发送微信消息(模板消息)* @param touser 用户 OpenID* @param templatId 模板消息ID* @param clickurl URL置空,则在发送后,点击模板消息会进入一个空白页面(ios),或无法点击(android)。* @param topcolor 标题颜色* @param data 详细内容* @return*/public static String sendWechatMsgToUser(String touser, String templatId, String clickurl, String topcolor, JSONObject data) {String tmpurl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token="+ WX_TokenUtil.getWXToken().getAccessToken();JSONObject json = new JSONObject();json.put("touser", touser);json.put("template_id", templatId);json.put("url", clickurl);json.put("topcolor", topcolor);json.put("data", data);try{JSONObject result = WX_HttpsUtil.httpsRequest(tmpurl, "POST", json.toString());JSONObject resultJson = new JSONObject(result);log.info("发送微信消息返回信息:" + resultJson.get("errcode"));String errmsg = (String) resultJson.get("errmsg");if(!"ok".equals(errmsg)){  //如果为errmsg为ok,则代表发送成功,公众号推送信息给用户了。return "error";}}catch(Exception e){e.printStackTrace();return "error";}return "success";}}
package com.example.demo.utils;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import com.alibaba.fastjson.JSONObject;public class WX_UserUtil {private static Logger log = LoggerFactory.getLogger(WX_UserUtil.class);/*** 根据微信openId 获取用户是否订阅* @param openId 微信openId* @return 是否订阅该公众号标识*/public static Integer subscribeState(String openId){String tmpurl = "https://api.weixin.qq.com/cgi-bin/user/info?access_token="+WX_TokenUtil.getWXToken().getAccessToken() +"&openid="+ openId;JSONObject result = WX_HttpsUtil.httpsRequest(tmpurl, "GET",null);JSONObject resultJson = new JSONObject(result);String errmsg = (String) resultJson.get("errmsg");if(errmsg==null){//用户是否订阅该公众号标识(0代表此用户没有关注该公众号 1表示关注了该公众号)。Integer subscribe = (Integer) resultJson.get("subscribe");return subscribe;}return -1;}
}
package com.example.demo.utils;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;public class WxServlet extends HttpServlet{public WxServlet() {// TODO Auto-generated constructor stub}/* (non-Javadoc)* @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)*/@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 微信加密签名String signature = request.getParameter("signature");// 时间戳String timestamp = request.getParameter("timestamp");// 随机数String nonce = request.getParameter("nonce");// 随机字符串String echostr = request.getParameter("echostr");PrintWriter out = response.getWriter();// 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败if (SignUtil.checkSignature(signature, timestamp, nonce)) {out.print(echostr);}out.close();out = null;}/* (non-Javadoc)* @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)*/@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// TODO Auto-generated method stubsuper.doPost(req, resp);}}

最后我们启动项目,访问localhost:8080/weChat/sendMessage即可给用户发送消息

效果图:

记录成长!

Java微信消息推送(二)相关推荐

  1. java发送qq消息_Java点餐系统和点餐小程序新加微信消息推送功能

    其实想给点餐系统加推送很久了,之前也有单门写过Java版的微信消息推送和云开发版的微信消息推送.之所以一直没有加,也是考虑到大家的学习接受度,因为做订阅消息推送是一个综合性的开发工作. 需要你既要会小 ...

  2. Java后台微信点餐小程序开发最新版笔记,Springboot+Mysql+Freemarker+Bootstrap+微信小程序实现扫码点餐小程序,包含语音提示,微信消息推送,网页管理后台

    由于之前的Java后台微信点餐小程序有些知识点过时了,所以今天重新出一版,把里面过时的知识点更新下 前五章是部署笔记,后面是知识点的详细讲解,大家可以先看部署笔记,部署起来后,再跟着详细知识学习. 第 ...

  3. 微信消息推送配置详解 JAVA后端版本

    最近公司做小程序需要用到消息推送,笔者在一路采坑做完后几个笔记,希望能帮到大家少采坑. 如果你连小程序都没有注册也没有做,那就不要继续看了....... 微信官方文档:  微信消息推送      微信 ...

  4. Django实现微信消息推送

    一 所需准备条件 微信公众号的分类 微信消息推送 公众号 已认证公众号 服务号 已认证服务号 企业号 基于:微信认证服务号 主动推送微信消息. 前提:关注服务号 环境:沙箱环境 沙箱环境地址: htt ...

  5. 微信消息推送神器【一封传话】介绍,让消息推送更简单

    背景 对于很多个人开发和企业级别的软件开发来说,经常会遇到一些消息推送的场景.如设备报警消息推送.每日天气预报和大盘资讯简报推送等,例如微信公众号消息推送.钉钉消息推送等. 这里以微信消息推送举例,原 ...

  6. 抖音微信消息推送情侣告白浪漫(简易版)

    抖音微信消息推送情侣告白浪漫(简易版) 一.首先去微信公众平台用微信扫码登录 登录后会自动生成属于自己的appId,appSecret 二.在上述登录后页面中下拉,用一个手机扫码会生成user_id( ...

  7. python 全栈开发,Day103(微信消息推送,结算中心业务流程)

    python 全栈开发,Day103(微信消息推送,结算中心业务流程) 昨日内容回顾 第一部分:考试题(Python基础)第二部分:路飞相关 1. 是否遇到bug?难解决的技术点?印象深刻的事?- o ...

  8. Spring Boot 实现企业微信消息推送

    1 Maven依赖 <!-- 阿里JSON解析器 --><dependency><groupId>com.alibaba</groupId><ar ...

  9. 【一封传话】一行代码实现微信消息推送

    一行代码实现微信消息推送 介绍 通过调用一个简单的接口,将要推送的消息提交后,您将在微信收到推送的消息,简单快捷 可以应用的场景设备上下线,量化交易,网站公告,服务器异常信息推送,网页更新提醒等各种可 ...

  10. 微信消息推送神器pushplus介绍,让消息推送更简单

    很早之前曾经做过微信公众号消息推送,实现了一些有意思的小功能.如设备报警消息推送.每日天气预报和大盘资讯简报推送等,使用的是微信官方的api.后台使用golang做了个简单的服务,操作使用上是有点儿麻 ...

最新文章

  1. 某程序员吐槽:组里新来一位美女同事,男同事们冲上去大献殷勤,过几天又一哄而散!...
  2. python怎么学最快-python怎么快速自学?
  3. android java设置颜色_java – 设置背景颜色:Android
  4. VTK修炼之道21:图像基本操作_彩色图像生成灰度图像
  5. Salesforce中所有常用类型字段的取值与赋值
  6. Android 2D Graphic Architecture
  7. mysql日期条件如何应用_MySQL如何使用时间作为判断条件
  8. Django的简单介绍及虚拟环境的搭建、创建项目,数据库(Windows版超级详细)--Python web应用程序开发(Python实战)
  9. Atata——C# Web测试自动化框架
  10. Servlet JSP和Spring MVC初学指南 PDF
  11. datagrid设置单元格边框_更改 DataGridView 控件中的边框和网格线样式 - Windows Forms .NET Framework | Microsoft Docs...
  12. CentOS 7 忘记root密码的解决之道
  13. 计算机二级-C语言-程序设计题-190118记录-通过数组和指针两种方式对字符串进行处理。...
  14. 安鸾_soap协议注入
  15. 各种文件的mime类型
  16. 数据库学习笔记【MySQL】
  17. java 弹出软键盘_android软键盘弹出定位
  18. python提取某一列数据,Python numpy 提取矩阵的某一行或某一列的实例
  19. 移动apn接入点哪个快_电信和联通以及移动物联卡哪个较好
  20. PlatformIO IDE搭建统一的物联网嵌入式开发环境

热门文章

  1. linux字符串处理命令,linux 命令之 字符串处理命令——paste
  2. mongodb 扩展 libmongoc ssl_扩展面板
  3. C#:导出json数据到Excel表格
  4. 数据结构_满二叉树、完全二叉树、二叉排序树、平衡二叉树
  5. SLAM基础_什么是ORB特征,怎么计算的?
  6. 双系统下卸载linux系统
  7. java类的引用使用即String类的toUpperCase的使用
  8. SVN“Previous operation has not finished; run 'cleanup' if it was interrupted”错误修复方法
  9. non-local Means(非局部均值)降噪算法及快速算法原理与实现
  10. Python Bug: TypeError: a bytes-like object is required, not ‘str