微信推广带id二维码生成详细解读

来源:互联网 发布:fa503细纱机工艺算法 编辑:程序博客网 时间:2024/05/21 17:31

需求:登录用户产生一个二维码,下一个人扫描这个二维码之后关注公众号,登录之后自动成为第一个用户的粉丝

吐槽一把,这个需求很操蛋。。。。但是,操不操蛋那是你程序猿说的不?微信开发本来就相当操蛋了。。。都懂得,文档又少,限制又多,傻逼的很。。。。 

首先看下微信官方的文档,我们先了解下需要哪些东西


当然毫不犹豫的点开。。。 然后发现这个。。 



却发现,并没有神马卵用 。。。。。。。。  生成二维码需要token ,我们就按照他提供的方法来搞一搞了。。。 就按照他提供的方法搞一搞了。。 

二维码的几种生成方式,在这里就不解释了。。 

不够简单粗暴,我直接上java代码了。。。。。 


import java.io.BufferedReader;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.net.HttpURLConnection;import java.net.URL;import net.sf.json.JSONObject;public class Test {static String wechatAppID = "";static String wechatAppSecret = "";static String wechatAccessTokenUrl = "";public static String getWechatAccessToken() {try {URL object = new URL(wechatAccessTokenUrl + "&appid=" + wechatAppID + "&secret=" + wechatAppSecret);HttpURLConnection con = (HttpURLConnection) object.openConnection();con.setDoOutput(true);con.setDoInput(true);con.setRequestProperty("Content-Type", "application/json");con.setRequestProperty("Accept", "application/json");con.setRequestMethod("GET");OutputStreamWriter wr = new OutputStreamWriter(con.getOutputStream(), "utf-8");wr.flush();// 显示 POST 请求返回的内容StringBuilder sb = new StringBuilder();int HttpResult = con.getResponseCode();if (HttpResult == HttpURLConnection.HTTP_OK) {BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "utf-8"));String line = null;while ((line = br.readLine()) != null) {sb.append(line + "\n");}br.close();System.out.println("" + sb.toString());} else {System.out.println(con.getResponseMessage());}return sb.toString();} catch (Exception e) {e.printStackTrace();}return "";}public static String getUserQRCode(Integer userId) {JSONObject jsonObject = JSONObject.fromObject(getWechatAccessToken());String access_token = jsonObject.getString("access_token");try {URL object = new URL("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" + access_token);HttpURLConnection con = (HttpURLConnection) object.openConnection();con.setDoOutput(true);con.setDoInput(true);con.setRequestProperty("Content-Type", "application/json");con.setRequestProperty("Accept", "application/json");con.setRequestMethod("POST");JSONObject data = new JSONObject();data.put("action_name", "QR_LIMIT_SCENE");JSONObject dojb = new JSONObject();dojb.put("scene_id", userId);JSONObject cojb = new JSONObject();cojb.put("scene", dojb);data.put("action_info", cojb);OutputStreamWriter wr = new OutputStreamWriter(con.getOutputStream(), "utf-8");wr.write(data.toString());wr.flush();// 显示 POST 请求返回的内容StringBuilder sb = new StringBuilder();int HttpResult = con.getResponseCode();if (HttpResult == HttpURLConnection.HTTP_OK) {BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "utf-8"));String line = null;while ((line = br.readLine()) != null) {sb.append(line + "\n");}br.close();JSONObject jsonObj = JSONObject.fromObject(sb.toString());String ticket = jsonObj.getString("ticket");//// 生成二维码return "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=" + ticket;} else {System.out.println(con.getResponseMessage());}} catch (Exception e) {e.printStackTrace();}return "";}}


运行这两段代码之后,我们发现我们的二维码居然生成了 ,第二个方法返回一个字符串就是二维码图片的绝对路径。。。。 生成的二维码我在这里就不解释了 。。 截出来也没有神马卵用。。。  我们回头看看方法。。。



我们发现我们用的是scene_id ,而没有使用字符串,为啥子????????  这个问题很关键二维码是生成了,但是怎么把二维码里面的id和下一个用户关联起来了?下一个用户关注上一个用户的二维码,我擦,我怎么知道啥时候关注了了 ???? 如果把上下级用户关联起来了 ?  重重问题 。。。 各种蛋疼。。。 

首先,当用户点击微信公众号关注的时候,后台是如何知道哪个用户点击了关注了 ? 那么就有这么一个问题,那就是通信的问题,当用户点击关注,微信公众号如何跟我们自己的后台通信了 ???? 这个很关键

你需要在微信公众号的后台做一些配置,打开后台




IP白名单,就是哪些IP有权限调用这些接口,一般配置你服务器的IP和你开发电脑的公网IP(不是192.168.0.111),好吧,来张图吧。。 



然后启动这东西 。。。 



然后填写以下配置。。。 



URL:其实就是一个外网可以访问的接口,注意:必须是80或443端口,做过后台都懂得。。。 这个接口的作用是,被微信调用,然后产生回调。。。。。也就是微信通过这个接口你的服务器发送消息。这个很重要

Token:自己定义的一个字符串,加密的要是,你写jinsanpang都可以;可以参考我的另外一篇文章了解token(http://blog.csdn.net/chmod_r_755/article/details/75554735)

EncodeKey:随机生成,干啥子用的,不知道,问微信

模式:明文模式,你想怎样? 加密? 搞得跟真的似的 ,有意思吗?金融机构自己看着办 。。。。 

到这里,我们就明白了,用户关注微信我们的后台是怎么知道的。。。原来是有通信的 。。。这块我们就必须搞一个接口了,让微信回调。。。。。。 

说太抽象了 。。。。  我们首先来张图 。。 



当我扫码关注的时候, 微信会回调这个接口,注意我这边日志是json格式的,但是网上有xml版本的



这种格式的,因为我把xml转json了,xml看着都蛋疼 ,来段代码压压惊


@RequestMapping(value = "/wx.do")public void get(@RequestBody(required = false) String body, HttpServletRequest request,HttpServletResponse response) throws Exception {org.json.JSONObject jsonObject = JSONML.toJSONObject(body);logger.info("请求进来了..." + jsonObject);org.json.JSONArray jsonArray = jsonObject.getJSONArray("childNodes");org.json.JSONObject fromUser = null;org.json.JSONObject event = null;org.json.JSONObject eventKey = null;for (int i = 0; i < jsonArray.length(); i++) {org.json.JSONObject obj = jsonArray.getJSONObject(i);String tagName = obj.getString("tagName");if ("FromUserName".equals(tagName)) {fromUser = obj;} else if ("Event".equals(tagName)) {event = obj;} else if ("EventKey".equals(tagName)) {eventKey = obj;}}logger.info("请求进来了...fromUser=" + fromUser.toString() + "    event=" + event.toString() + "    eventKey="+ eventKey.toString());if (event != null && eventKey != null && fromUser != null) {org.json.JSONArray eventArray = event.getJSONArray("childNodes");org.json.JSONArray eventKeyArray = eventKey.getJSONArray("childNodes");org.json.JSONArray fromUserNameArray = fromUser.getJSONArray("childNodes");logger.info("请求进来了...eventArray=" + eventArray.toString() + "    eventKeyArray=" + eventKeyArray.toString()+ "    fromUserNameArray=" + fromUserNameArray.toString());if (eventArray.length() > 0 && fromUserNameArray.length() > 0 && eventKeyArray.length() > 0) {String subscribeString = eventArray.getString(0); // 动作String fromUserString = fromUserNameArray.getString(0); // openIdString eventKeyString = eventKeyArray.getString(0); // 带入的信息logger.info("请求进来了...subscribeString=" + subscribeString + "    fromUserString=" + fromUserString+ "    eventKeyString=" + eventKeyString);if ("subscribe".equals(subscribeString)) {// 点击关注, 保存上级的id 且保存openId// 点击取消关注,删除这条记录// 如果 eventKeyString 为空字符串 ,表示关注官方二维码关注的/// 包含上级Id ,则保存到数据库中if (eventKeyString.contains("qrscene_")) {String userIdString = eventKeyString.replaceAll("qrscene_", "");Integer userId = Integer.parseInt(userIdString);WechatKey wechatKey = new WechatKey();wechatKey.setOpenId(fromUserString);wechatKey.setUserId(userId);wechatKeyManager.saveWechatkey(wechatKey);}} else if ("unsubscribe".equals(subscribeString)) {WechatKey wechatKey = wechatKeyManager.getWechatKeyByOpenId(fromUserString);if (wechatKey != null) {wechatKeyManager.deleteByOpenId(fromUserString);}}}}Enumeration pNames = request.getParameterNames();while (pNames.hasMoreElements()) {String name = (String) pNames.nextElement();String value = request.getParameter(name);// out.print(name + "=" + value);String log = "name =" + name + "     value =" + value;logger.error(log);}String signature = request.getParameter("signature");/// 微信加密签名String timestamp = request.getParameter("timestamp");/// 时间戳String nonce = request.getParameter("nonce"); /// 随机数String echostr = request.getParameter("echostr"); // 随机字符串PrintWriter out = response.getWriter();if (CheckUtil.checkSignature(signature, timestamp, nonce)) {out.print(echostr);}out.close();out = null;}


关注的时候微信会给服务器推送一条消息


subscribe:表示开始关注

fromUser:表示哪个用户关注的,这里返回的是当前用户的openId ,唯一的 

EventKey:qrscene_20 前面的qrscene_是固定的,后面的20 也就是上个用户的id

那么到了这一步, 上个用户和下一个用户就联系在一起了。。。。。。如果扫的码是系统生成的。。。EventKey:就为空字符串了。。

扯到这里了 。。。。  其他的不解释,自己理解。。。。 







阅读全文
0 0
原创粉丝点击