首页 > 编程 > JavaScript > 正文

微信小程序与公众号实现数据互通的方法

2019-11-19 11:08:17
字体:
来源:转载
供稿:网友

公司因小程序项目先上线,公众号后开发,接到上级的安排实现小程序打通任务,看文档后发现:同一开发者账号只要是在微信开放平台绑定小程序与公众号以后,会有一个唯一的unionid,这个unionid腾讯公司下产品共享。这个unionid就是我们进行打通的关键。

先说一下思路:

1.微信小程序与公众号进行绑定后,在小程序调用wx.login()方法后会自动获取unionid,公众号根据官方文档在获取用户基本信息后会拿到相同的unionid,openid,nickname。。。等相关信息;

2.将小程序拿到的unionid进行数据库的更新操作,公众号拿到的unionid等信息,新建数据库表A进行存储;(注:在这一步,因为我们公司的原因,我们的公众号之前就有人关注了,那么在这之前,我通过公众号获取关注用户列表获取openid的列表,进行循环openid列表,在调用公众号获取用户基本信息列表进行储存数据库表A,循环结束后之前关注的人的信息就储存在数据库A,然后在进行,这一步的操作)

3.通过公众号关注/取关的事件相应,来进行数据库表A的增删操作,维护数据的新鲜度;

4.进行关联查询,到这一步我们会发现,通过unionid进行表的关联后我们已经实现数据的互通了 

洋洋洒洒的说了一大堆,其实就是公众号的两个接口至关重要(1.关注/取关的事件相应接口     2.获取用户的基本信息接口)

有关于公众号的安全域名配置,服务器域名配置以及获取token就不在这里说了,百度一下一大堆。

代码实现:

第一步,获取公众号用户的openid列表操作,根据opneid进进行用户的基本信息的查询,存入数据库操作(因为我们公司的公众号关注人数只有1000+,所以我只调用了一次获取关注列表的接口)

//主要代码逻辑//获取token AccessToken accessToken=wxUtils.getAccessToken(); String url="https://api.weixin.qq.com/cgi-bin/user/get?access_token="+accessToken.getAccessToken()+"&next_openid=";//获取所有用户openidJSONObject jsonObject = httpRequest(url, "GET", null);  try { if(jsonObject.getString("errcode")!=null){ } }catch(Exception e) { } WeixinUserList userList = (WeixinUserList)JSONObject.toBean(jsonObject, WeixinUserList.class); if(null==userList) {  return "无用户"; } userList.getTotal();//关注总人数 //用户openId 列表 WxOpenidInfo wxOpenidInfo=userList.getData(); List<String> openIdList=null; if(null!=wxOpenidInfo) { openIdList=wxOpenidInfo.getOpenid();//公众号返回的openid列表数据  if(null!=openIdList && openIdList.size()>0) { for(String opendid:openIdList) {      //获取用户的基本信息(unionid机制)  url="https://api.weixin.qq.com/cgi-bin/user/info?    access_token="+accessToken.getAccessToken()+"&openid="+opendid+"&lang=zh_CN";//通过openid获取用户信息  jsonObject = httpRequest(url, "GET", null);   WeixinUser wxUser=(WeixinUser)JSONObject.toBean(jsonObject, WeixinUser.class);      //进行数据库表A的储存操作   int row = gzhService.addGZHUser(wxUser);  } }}    /** * 用户列表  * @author 一叶知秋plus * */public class WeixinUserList{       private Integer total;//关注该公众账号的总用户数    private Integer count;//拉取的OPENID个数,最大值为10000    private WxOpenidInfo data;//列表数据,OPENID的列表    private String next_openid;//拉取列表的最后一个用户的OPENID    private int errcode;//错误编码    private String errmsg="ok";//错误提示    public Integer getTotal() {     return total;   }    public void setTotal(Integer total) {     this.total = total;   }    public Integer getCount() {     return count;   }    public void setCount(Integer count) {     this.count = count;   }    public String getNext_openid() {     return next_openid;   }    public void setNext_openid(String next_openid) {     this.next_openid = next_openid;   }    public WxOpenidInfo getData() {     return data;   }    public void setData(WxOpenidInfo data) {     this.data = data;   }    public int getErrcode() {     return errcode;   }    public void setErrcode(int errcode) {     this.errcode = errcode;   }    public String getErrmsg() {     return errmsg;   }    public void setErrmsg(String errmsg) {     this.errmsg = errmsg;   }  }  /** * 用户基本信息  * @author 一叶知秋plus * */  public class WeixinUser { private String subscribe;// 用户是否订阅该公众号标识,值为0时,代表此用户没有关注该公众号,拉取不到其余信息。 private String openid;// 用户的标识,对当前公众号唯一 private String nickname;// 用户的昵称 private String sex;// 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知 private String city;// 用户所在城市 private String country;// 用户所在国家 private String province;// 用户所在省份 private String language;// 用户的语言,简体中文为zh_CN private List<String> tagid_list;//用户被打上的标签ID列表 private String unionid; //用户的unionid private String headimgurl;//用户的头像     public String getHeadimgurl() { return headimgurl; } public void setHeadimgurl(String headimgurl) { this.headimgurl = headimgurl; } public String getUnionid() { return unionid; } public void setUnionid(String unionid) { this.unionid = unionid; } public String getSubscribe() { return subscribe; } public void setSubscribe(String subscribe) { this.subscribe = subscribe; } public String getOpenid() { return openid; } public void setOpenid(String openid) { this.openid = openid; } public String getNickname() { return nickname; } public void setNickname(String nickname) { this.nickname = nickname; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } public String getProvince() { return province; } public void setProvince(String province) { this.province = province; } public String getLanguage() { return language; } public void setLanguage(String language) { this.language = language; } public List<String> getTagid_list() { return tagid_list; } public void setTagid_list(List<String> tagid_list) { this.tagid_list = tagid_list; }}  public class WxOpenidInfo { private List<String> openid;   public List<String> getOpenid() {    return openid;  }   public void setOpenid(List<String> openid) {    this.openid = openid;  }}

步骤二:关注/取关的事件响应接口

/** * 请求校验工具类 */public class SignUtil {  // 与接口配置信息中的Token要一致,我的是明文格式  private static String token = "填写你服务器配置时写的token";     public static boolean checkSignature(String signature, String timestamp,      String nonce) {    //从请求中(也就是微信服务器传过来的)拿到的token, timestamp, nonce    String[] arr = new String[] { token, timestamp, nonce };    // 将token、timestamp、nonce三个参数进行字典序排序    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;  }  //将加密后的字节数组变成字符串  private static String byteToStr(byte[] byteArray) {    String strDigest = "";    for (int i = 0; i < byteArray.length; i++) {      strDigest += byteToHexStr(byteArray[i]);    }    return strDigest;  }   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;  }//用于字典排序  public static void sort(String a[]) {    for (int i = 0; i < a.length - 1; i++) {      for (int j = i + 1; j < a.length; j++) {        if (a[j].compareTo(a[i]) < 0) {          String temp = a[i];          a[i] = a[j];          a[j] = temp;        }      }    }  }}  //事件响应的接口@RequestMapping(value="/GZHConcern.do") public void GZHConcern(HttpServletRequest request, HttpServletResponse response) throws IOException { String message = "success"; // 微信加密签名  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);  //在这里相应微信的操作 }   try {  Map<String, String> map = XmlUtil.xmlToMap(request);  String fromUserName = map.get("FromUserName");//消息来源用户标识  String toUserName = map.get("ToUserName");//消息目的用户标识  String msgType = map.get("MsgType");//消息类型  String content = map.get("Content");//消息内容    String eventType = map.get("Event");  WeixinUser weixinUser = new WeixinUser();  if(MessageUtil.MSGTYPE_EVENT.equals(msgType)){//如果为事件类型  if(MessageUtil.MESSAGE_SUBSCIBE.equals(eventType)){//处理订阅事件   //获取token   String token = WXUtil.getGZHToken();   weixinUser = WXUtil.getUnionid(fromUserName, token);   //进行数据库的操作   weixinUser.setNickname(weixinUser.getNickname());   int row = gzhService.addGZHUser(weixinUser);   //通过openid获取用户的数据   message = MessageUtil.subscribeForText(toUserName, fromUserName);  }else if(MessageUtil.MESSAGE_UNSUBSCIBE.equals(eventType)){//处理取消订阅事件   message = MessageUtil.unsubscribe(toUserName, fromUserName);   weixinUser.setOpenid(fromUserName);   //进行数据库的操作   int row = gzhService.deleteGZHUser(weixinUser);  }  } } catch (DocumentException e) {  // TODO Auto-generated catch block  e.printStackTrace(); }finally {  out.close(); } out = null; } /* * 消息处理工具类 */public class MessageUtil { public static final String MSGTYPE_EVENT = "event";//消息类型--事件 public static final String MESSAGE_SUBSCIBE = "subscribe";//消息事件类型--订阅事件 public static final String MESSAGE_UNSUBSCIBE = "unsubscribe";//消息事件类型--取消订阅事件 public static final String MESSAGE_TEXT = "text";//消息类型--文本消息  /* * 组装文本消息 */ public static String textMsg(String toUserName,String fromUserName,String content){ TextMessage text = new TextMessage(); text.setFromUserName(toUserName); text.setToUserName(fromUserName); text.setMsgType(MESSAGE_TEXT); text.setCreateTime(new Date().getTime()); text.setContent(content); return XmlUtil.textMsgToxml(text); }  /* * 响应订阅事件--回复文本消息 */ public static String subscribeForText(String toUserName,String fromUserName){ return textMsg(toUserName, fromUserName, "欢迎关注,精彩内容不容错过!!!"); }  /* * 响应取消订阅事件 */ public static String unsubscribe(String toUserName,String fromUserName){ //TODO 可以进行取关后的其他后续业务处理 System.out.println("用户:"+ fromUserName +"取消关注~"); return ""; }}  /* * xml处理工具类 */public class XmlUtil { /* * xml转map */ public static Map<String, String> xmlToMap(HttpServletRequest request) throws IOException, DocumentException{ HashMap<String, String> map = new HashMap<String,String>(); SAXReader reader = new SAXReader();  InputStream ins = request.getInputStream(); Document doc = reader.read(ins);  Element root = doc.getRootElement(); @SuppressWarnings("unchecked") List<Element> list = (List<Element>)root.elements();  for(Element e:list){  map.put(e.getName(), e.getText()); } ins.close(); return map; } /* * 文本消息对象转xml */ public static String textMsgToxml(TextMessage textMessage){ XStream xstream = new XStream(); xstream.alias("xml", textMessage.getClass()); return xstream.toXML(textMessage); }}

ok,到这一步数据库中有了小程序opneid unionid 公众号opneid  unionid等用户信息,进行关联后就可以进行数据的查询操作,当然小程序也可以发送公众号模板的相应操作了。如果有更好的实现方式,欢迎各位大佬不吝赐教~

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表