热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

小程序开发与公众号用户关联推送消息

最近做了一个类似于日程提醒的小程序,需要把用户语音识别出的日程或提醒按照设置的提醒日期通过微信公众号推送给对应的用户进行提醒这样子.这是需求背景.这个项目我已经做完了,但是中间遇到

最近做了一个类似于日程提醒的小程序,需要把用户语音识别出的日程或提醒按照设置的提醒日期通过微信公众号推送给对应的用户进行提醒这样子.这是需求背景.

    这个项目我已经做完了,但是中间遇到很多坑,所以想出篇帖子,让大家不浪费爬坑的时间.后面我会尽量把所有需要的代码什么的,都贴上来,尽量做到拿了就能用的程度.

 

    接下来,就是一个又一个的坑需要爬了.首先我说一下小程序与公众号开发的一个完整流程.与一些细节.

 

1.小程序开发首先需要appid 与secret  也就是账号密码,用来获取用户的unionid与openid.(需要根据js_code来获取)这两个名叫id的东西,都是用户的唯一标识,(以前不同的appid获取到的用户openid都是一样的,现在不一样了) unionid是干什么用的,我一会会说.

2.公众号开发也需要一个appid跟secret,这个跟小程序的不一样,具体怎么拿,跟小程序一样.有了appid与secret我们就可以获取到公众号用户的openid与unionid了(需要根据code来获取),(获取之前还需要先获取assess_token,这是一个微信的接口,用来验证身份,微信设置一个开发者账号每天可以请求200次的限制,每个token有7200s的有效时间...所以这里获取到的话,需要放到redis或者java缓存中去,然后设置一个7200s的过期时间,用的时候从缓存取,缓存里没有再请求.后面我会说怎么获取)这里的openid与小程序的openid是不一样的,但是unionid可以弄成一样的.怎么弄呢,看第三步.

3.这时候应该上微信公众平台把小程序绑定到其下.然后再注册一个微信开放平台,并且获取开发者资质,(一年好像是300).然后把你的小程序与公众号都绑定到开放平台下,这样的话,你的小程序获取到的unionid跟公众号获取到的unionid就是一样的了,这样就可以用它来进行小程序与公众号用户的关联了.

------------------------------------------------------然后进行代码------------------------------------------------------

 

1.根据js_code获取小程序用户的openid与unionid  (js_code 是小程序在调用wx.login的时候获取到的.)  代码如下:

@RequestMapping(value = "/checkUserByOpenid", method = RequestMethod.GET)public @ResponseBody Map checkUserByOpenid(HttpServletRequest request,HttpServletResponse response,@RequestParam("js_code") String js_code) throws Exception {response.setHeader("Access-Control-Allow-Origin", "*");/*星号表示所有的域都可以接受,*/response.setHeader("Access-Control-Allow-Methods", "GET,POST");HashMap jsonMap = new HashMap();
// if(js_code!=null && !"".equals(js_code)){String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appid + "&secret=" + secret + "&js_code=" + js_code + "&grant_type=" + grant_type;String httpsRtn = HttpsPostUtil.doPost(url, "UTF-8");Map json = mapper.readValue(httpsRtn, Map.class);String openid = (String) json.get("openid");//用openid获取unionid等敏感信息------------小程序String unionid = (String) json.get("unionid");//此处开始你的逻辑代码jsonMap.put("message", "success");
// }return jsonMap;}

2.httpsclient工具类  发送请求给微信接口

package com.qs.util;import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.util.EntityUtils;/*** 利用HttpClient进行post请求的工具类** @author Kevin* @ClassName: HttpsClientUtil* @Description: TODO* @date 2017年2月7日 下午1:43:38*/
public class HttpsPostUtil {public static String doPost(String url, String charset) {HttpClient httpClient = null;HttpPost httpPost = null;String result = null;try {httpClient = new SSLClient();httpPost = new HttpPost(url);HttpResponse response = httpClient.execute(httpPost);if (response != null) {HttpEntity resEntity = response.getEntity();if (resEntity != null) {result = EntityUtils.toString(resEntity, charset);}}} catch (Exception ex) {ex.printStackTrace();}return result;}
}

package com.qs.util;import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;/*** 用于进行Https请求的HttpClient** @author Kevin * @ClassName: SSLClient* @Description: TODO* @date 2017年2月7日 下午1:42:07*/
public class SSLClient extends DefaultHttpClient {public SSLClient() throws Exception {super();SSLContext ctx = SSLContext.getInstance("TLS");X509TrustManager tm = new X509TrustManager() {public void checkClientTrusted(X509Certificate[] chain,String authType) throws CertificateException {}public void checkServerTrusted(X509Certificate[] chain,String authType) throws CertificateException {}public X509Certificate[] getAcceptedIssuers() {return null;}};ctx.init(null, new TrustManager[]{tm}, null);SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);ClientConnectionManager ccm = this.getConnectionManager();SchemeRegistry sr = ccm.getSchemeRegistry();sr.register(new Scheme("https", 443, ssf));}
}

 

3.然后再根据code获取公众号下用户的openid与uninonid等个人信息了,这里要多说一下,这个code在小程序里面是无法直接获取的,我是在小程序wx.login后调用了web view网页弹出  来引导用户进行授权的,这里大家可以参考一下微信的官方说明文档,需要配置一个服务器域名  或  测试用机的IP地址白名单,还要配置一个授权成功后回调的接口地址,也就是你自己写的接口,这个接口中就可以获取到code,code是从你的授权网页传递过来的,在网页上写一个onload默认加载,把页面地址栏里接收到的微信传来的code参数拿出来,传到自己的接口中去..下面我把接口中根据code获取微信公众平台用户的个人信息代码贴上

 

@RequestMapping(value = "/callBack", method = RequestMethod.GET)public @ResponseBody void callBack(HttpServletRequest request,HttpServletResponse response) throws Exception {response.setHeader("Access-Control-Allow-Origin", "*");/*星号表示所有的域都可以接受,*/response.setHeader("Access-Control-Allow-Methods", "GET,POST");//使用code获取公众号用户的openid------------String urls = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="+appId+"&secret="+appSecret+"&code="+code+"&grant_type=authorization_code";JSONObject result = WX_HttpsUtil.httpsRequest(urls, "GET");JSONObject resultJson = new JSONObject(result);String GZHopenid = (String) resultJson.get("openid");String errmsg = (String) resultJson.get("errmsg");//如果code失效 则不添加用户if(errmsg==null){//使用openid获取unionidString access_token = WX_TokenUtil.getWXToken().getAccessToken();String url2 = "https://api.weixin.qq.com/cgi-bin/user/info?access_token="+access_token+"&openid="+GZHopenid+"&lang=zh_CN";JSONObject result2 = WX_HttpsUtil.httpsRequest(url2, "GET");JSONObject resultJson2 = new JSONObject(result2);String GZHunionid = (String) resultJson.get("unionid");}}

 

 

---------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------

到这里为止,你的公众号与小程序的用户的个人信息就全部获取到了,可以通过unionid关联起来了...

 

 

下面开始通过微信公众平台来给用户推送消息.

ps:这里需要登录微信公众平台先设置一个自己需要推送的消息模板,可以从微信提供的模板库中选取,如果没有合适的,就自己申请一个模板,然后把模板ID复制粘贴到代码中.

如下几个都是需要的工具类 

package weixin.util.wxservlet;import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
/*** 请求校验工具类* @author m**/
public class SignUtil {// 与接口配置信息中的Token要一致 private static String token = "weixin"; /** * 验证签名 * * @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 >> 4) & 0X0F]; tempArr[1] = Digit[mByte & 0X0F]; String s = new String(tempArr); return s; }
}

package weixin.util.wxservlet;import java.io.IOException;
import java.io.PrintWriter;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;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);}}

 

package weixin.util;import java.io.Serializable;
/*
*AccessToken 对象
*/
public class AccessToken implements Serializable {//获取到的凭证private String accessToken;//凭证有效时间,单位:秒private int expiresin; /*** @return the accessToken*/public String getAccessToken() {return accessToken;}/*** @param accessToken the accessToken to set*/public void setAccessToken(String accessToken) {this.accessToken = accessToken;}/*** @return the expiresin*/public int getExpiresin() {return expiresin;}/*** @param expiresin the expiresin to set*/public void setExpiresin(int expiresin) {this.expiresin = expiresin;}public AccessToken() {// TODO Auto-generated constructor stub}}

package weixin.util;import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;import javax.net.ssl.X509TrustManager;
/*** 微信请求 - 信任管理器*/public class MyX509TrustManager implements X509TrustManager{public MyX509TrustManager() {// TODO Auto-generated constructor stub}public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}public X509Certificate[] getAcceptedIssuers() {// return new X509Certificate[0];return null;}}

 

package weixin.util;
/*** 模板详细信息 * 根据需求自己更改*/
public class TemplateData {private String value;private String color;public TemplateData(String value,String color){this.value = value;this.color = color;}/*** @return the value*/public String getValue() {return value;}/*** @param value the value to set*/public void setValue(String value) {this.value = value;}/*** @return the color*/public String getColor() {return color;}/*** @param color the color to set*/public void setColor(String color) {this.color = color;}}

 

package weixin.util;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 templateData; //模板详细信息public static TemplateMessage New() {return new TemplateMessage();}/*** @return the touser*/public String getTouser() {return touser;}/*** @param touser the touser to set*/public void setTouser(String touser) {this.touser = touser;}/*** @return the template_id*/public String getTemplate_id() {return template_id;}/*** @param template_id the template_id to set*/public void setTemplate_id(String template_id) {this.template_id = template_id;}/*** @return the url*/public String getUrl() {return url;}/*** @param url the url to set*/public void setUrl(String url) {this.url = url;}/*** @return the topcolor*/public String getTopcolor() {return topcolor;}/*** @param topcolor the topcolor to set*/public void setTopcolor(String topcolor) {this.topcolor = topcolor;}/*** @return the templateData*/public Map getTemplateData() {return templateData;}/*** @param templateData the templateData to set*/public void setTemplateData(Map templateData) {this.templateData = templateData;}}

package weixin.util;import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSONObject;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;}}

 

package weixin.util;import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSONObject;public class WX_TemplateMsgUtil {private static Logger log = LoggerFactory.getLogger(WX_TemplateMsgUtil.class);/*** 封装模板详细信息* @return*/public static JSONObject packJsonmsg(Map param) {JSONObject json = new JSONObject();for (Map.Entry 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";}
// finally {
// if(templatId!=null) {
// //删除新增的 微信模板
// deleteWXTemplateMsgById(templatId);
// }
// }return "success";}}

 

package weixin.util;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;public class WX_TokenUtil {private static Logger log = LoggerFactory.getLogger(WX_TokenUtil.class);/*** 获得微信 AccessToken* access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。* 开发者需要access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取* 的access_token失效。 * (此处我是把token存在java缓存里面了)此代码token没有加入缓存,后面附了缓存的工具类,根据需求自己添加*/public static AccessToken getWXToken() {String appId="****************";String appSecret="****************";String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+ appId+"&secret="+ 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 weixin.util;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);log.error("获取用户是否订阅 errcode:{} errmsg:{}", resultJson.getInteger("errcode"), resultJson.getString("errmsg"));String errmsg = (String) resultJson.get("errmsg");System.out.println(errmsg);if(errmsg==null){//用户是否订阅该公众号标识(0代表此用户没有关注该公众号 1表示关注了该公众号)。Integer subscribe = (Integer) resultJson.get("subscribe");return subscribe;}return 0;}public static JSONObject getUserInfo(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);log.error("获取用户是否订阅 errcode:{} errmsg:{}", resultJson.getInteger("errcode"), resultJson.getString("errmsg"));String errmsg = (String) resultJson.get("errmsg");return resultJson;}
}

 

package cache.util;import java.util.Calendar;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
/** * 简单内存缓存管理器 * 可设置过期时间,单位毫秒 * 使用Timer定时清理过期数据,每分钟清理一次,可修改清理周期 * @author Kevin* @datetime 2018年4月16日 下午5:18:50 */
public class CacheManager { &#64;SuppressWarnings("rawtypes") private static Map cache &#61; new ConcurrentHashMap(); /** * 启动定时任务清理过期缓存&#xff0c;避免内存溢出 */ static { Timer t &#61; new Timer(); t.schedule(new ClearTimerTask(cache), 0, 7000 * 1000); } /** * 设置缓存&#xff0c;不过期 * &#64;param key * &#64;param t */ public static void set(String key, T t) { cache.put(key, new CacheData(t, 0)); } /** * 设置缓存&#xff0c;指定过期时间expire(单位毫秒) * &#64;param key * &#64;param t * &#64;param expire 过期时间 */ public static void set(String key, T t, long expire) { cache.put(key, new CacheData(t, expire)); } /** * 根据key获取指定缓存 * &#64;param key * &#64;return */ &#64;SuppressWarnings("unchecked") public static T get(String key) { CacheData data &#61; cache.get(key); if(null &#61;&#61; data) { return null; } if(data.isExpire()) { remove(key); return null; } return data.getData(); } /** * 移除指定key缓存 * &#64;param key */ public static void remove(String key) { cache.remove(key); } /** * 移除所有缓存 */ public static void removeAll() { cache.clear(); } private static class CacheData { // 缓存数据 private T data; // 过期时间(单位&#xff0c;毫秒) private long expireTime; public CacheData(T t, long expire) { this.data &#61; t; if(expire <&#61; 0) { this.expireTime &#61; 0L; } else { this.expireTime &#61; Calendar.getInstance().getTimeInMillis() &#43; expire; } } /** * 判断缓存数据是否过期 * &#64;return true表示过期&#xff0c;false表示未过期 */ public boolean isExpire() { if(expireTime <&#61; 0) { return false; } if(expireTime > Calendar.getInstance().getTimeInMillis()) { return false; } return true; } public T getData() { return data; } } /** * 清理过期数据定时任务 * &#64;author zsc * &#64;datetime 2018年2月9日 上午10:41:18 */ private static class ClearTimerTask extends TimerTask { &#64;SuppressWarnings("rawtypes") Map cache; &#64;SuppressWarnings("rawtypes") public ClearTimerTask(Map cache) { this.cache &#61; cache; } &#64;Override public void run() { Set keys &#61; cache.keySet(); for(String key : keys) { CacheData data &#61; cache.get(key); if(data.expireTime <&#61; 0) { continue; } if(data.expireTime > Calendar.getInstance().getTimeInMillis()) { continue; } cache.remove(key); } } }
}


最后进行测试发送推送消息

 

package weixin.util;import java.util.HashMap;
import java.util.Map;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;public class TestWX {public static void main(String[] args) {//新增用户成功 - 推送微信消息senMsg("openid 以及几个需要的模板消息参数,这个根据自己需求来修改");}public static void senMsg(String openId,String name,String event,String times,String remark){//用户是否订阅该公众号标识 (0代表此用户没有关注该公众号 1表示关注了该公众号)Integer state&#61; WX_UserUtil.subscribeState(openId);System.out.println("state:"&#43;state);// 绑定了微信并且关注了服务号的用户 , 注册成功-推送注册短信if(state&#61;&#61;1){Map param &#61; new HashMap();param.put("first",new TemplateData("您好,亲爱的"&#43;name&#43;"!","#EE0000"));param.put("keyword1",new TemplateData(event,"#EE0000"));param.put("keyword2",new TemplateData(times,"#EE0000"));param.put("remark",new TemplateData(remark,"#EE0000"));//注册的微信-模板Id
// String regTempId &#61; WX_TemplateMsgUtil.getWXTemplateMsgId("TM00464");JSON.toJSONString(param);JSONObject jsonObject &#61; JSONObject.parseObject(JSON.toJSONString(param));//调用发送微信消息给用户的接口 ********这里写自己在微信公众平台拿到的模板IDWX_TemplateMsgUtil.sendWechatMsgToUser(openId, ***********************************, "", "#000000", jsonObject);//获取公众号的自动回复规则String urlinfo&#61;"https://api.weixin.qq.com/cgi-bin/get_current_autoreply_info?access_token&#61;"&#43;WX_TokenUtil.getWXToken().getAccessToken();JSONObject joinfo &#61; WX_HttpsUtil.httpsRequest(urlinfo, "GET", null);Object o&#61;joinfo.get("is_add_friend_reply_open");// System.out.println("o:"&#43;joinfo);String getTokenUrl &#61; "https://api.weixin.qq.com/cgi-bin/token?grant_type&#61;client_credential&appid&#61;{0}&secret&#61;{1}";JSONObject Token &#61; WX_HttpsUtil.httpsRequest(getTokenUrl, "GET", null);System.out.println("Token:"&#43;Token);}}}

此时你应该可以成功推送消息了.如上代码我确保都是经过测试的,完全可以使用没有问题

帖子写的匆忙,如果任何疑问,请搜索公众号"老秦的快乐生活"获取我的联系方式,需要https工具的请直接公众号发送"https"获取代码

 

 

 

 

 


推荐阅读
  • 本文探讨了如何使用Scrapy框架构建高效的数据采集系统,以及如何通过异步处理技术提升数据存储的效率。同时,文章还介绍了针对不同网站采用的不同采集策略。 ... [详细]
  • 如何高效学习鸿蒙操作系统:开发者指南
    本文探讨了开发者如何更有效地学习鸿蒙操作系统,提供了来自行业专家的建议,包括系统化学习方法、职业规划建议以及具体的开发技巧。 ... [详细]
  • ArcBlock 发布 ABT 节点 1.0.31 版本更新
    2020年11月9日,ArcBlock 区块链基础平台发布了 ABT 节点开发平台的1.0.31版本更新,此次更新带来了多项功能增强与性能优化。 ... [详细]
  • 本文探讨为何Request对象的外观设计被认为是精妙的,重点在于其如何利用门面模式确保数据安全,同时保持系统的高效交互。 ... [详细]
  • Java多线程售票案例分析
    本文通过一个售票系统的实例,深入探讨了Java中的多线程技术及其在资源共享和并发控制中的应用。售票过程涉及查询、收款、找零和出票等多个步骤,其中对总票数的管理尤为关键。 ... [详细]
  • 本文详细介绍如何在SSM(Spring + Spring MVC + MyBatis)框架中实现分页功能。包括分页的基本概念、数据准备、前端分页栏的设计与实现、后端分页逻辑的编写以及最终的测试步骤。 ... [详细]
  • Java虚拟机及其发展历程
    Java虚拟机(JVM)是每个Java开发者日常工作中不可或缺的一部分,但其背后的运作机制却往往显得神秘莫测。本文将探讨Java及其虚拟机的发展历程,帮助读者深入了解这一关键技术。 ... [详细]
  • H5技术实现经典游戏《贪吃蛇》
    本文将分享一个使用HTML5技术实现的经典小游戏——《贪吃蛇》。通过H5技术,我们将探讨如何构建这款游戏的两种主要玩法:积分闯关和无尽模式。 ... [详细]
  • 本文探讨了如何通过优化 DOM 操作来提升 JavaScript 的性能,包括使用 `createElement` 函数、动画元素、理解重绘事件及处理鼠标滚动事件等关键主题。 ... [详细]
  • 如何将955万数据表的17秒SQL查询优化至300毫秒
    本文详细介绍了通过优化SQL查询策略,成功将一张包含955万条记录的财务流水表的查询时间从17秒缩短至300毫秒的方法。文章不仅提供了具体的SQL优化技巧,还深入探讨了背后的数据库原理。 ... [详细]
  • 入门指南:使用FastRPC技术连接Qualcomm Hexagon DSP
    本文旨在为初学者提供关于如何使用FastRPC技术连接Qualcomm Hexagon DSP的基础知识。FastRPC技术允许开发者在本地客户端实现远程调用,从而简化Hexagon DSP的开发和调试过程。 ... [详细]
  • 本文详细介绍了如何在Java Swing中使用`JButton.registerKeyboardAction()`方法来为按钮设置键盘快捷键,并提供了多个实用的代码示例。 ... [详细]
  • Java连接MySQL数据库的方法及测试示例
    本文详细介绍了如何安装MySQL数据库,并通过Java编程语言实现与MySQL数据库的连接,包括环境搭建、数据库创建以及简单的查询操作。 ... [详细]
  • 本文探讨了如何利用 Android 的 Movie 类来展示 GIF 动画,并详细介绍了调整 GIF 尺寸以适应不同布局的方法。同时,提供了相关的代码示例和注意事项。 ... [详细]
  • 从理想主义者的内心深处萌发的技术信仰,推动了云原生技术在全球范围内的快速发展。本文将带你深入了解阿里巴巴在开源领域的贡献与成就。 ... [详细]
author-avatar
情调
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有