赞
踩
1.先得到公众号的appid和appsecret和token(此程序可有可无)
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
因为调用上面一个接口,需要获取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; } }
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") @ResponseBody public 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; //用户OpenID private String template_id; //模板消息ID private 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 } @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public 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) */ @Override protected 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) */ @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub super.doPost(req, resp); } }
最后我们启动项目,访问localhost:8080/weChat/sendMessage即可给用户发送消息
效果图:
记录成长!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。