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

公司因小程序项目先上线,公众号后开发,接到上级的安排实现小程序打通任务,看文档后发现:同一开发者账号只要是在微信开放平台绑定小程序与公众号以后,会有一个唯一的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=";//获取所有用户openid
JSONObject 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等用户信息,进行关联后就可以进行数据的查询操作,当然小程序也可以发送公众号模板的相应操作了。如果有更好的实现方式,欢迎各位大佬不吝赐教~

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

(0)

相关推荐

  • 微信小程序如何访问公众号文章

    前言 随着小程序不断的发展,现在个人的小程序也开放了很多功能了,个人小程序直接打开公众号链接.在群里看到的一款小程序,点击可以直接阅读文章了,所以琢磨了一下,写了一些源码. 主要代码: <web-view src="https://mp.weixin.qq.com/s?__biz=MzI2ODUxMzg4Nw==&mid=2247485016&idx=1&sn=e5f60600ea30f669264ddcf5db4fb080&chksm=eaef2168dd

  • 微信公众号菜单配置微信小程序实例详解

    先提条件是你的公众号版定了小程序 第一种:直接配置     第二张:代码配置 1.进入在线接口调试工具        2.选择自定义菜单 菜单body为json格式: { "button": [ { "type": "miniprogram", "name": "合作", "url": "http://form.mikecrm.com/2xb9aT", "a

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

    公司因小程序项目先上线,公众号后开发,接到上级的安排实现小程序打通任务,看文档后发现:同一开发者账号只要是在微信开放平台绑定小程序与公众号以后,会有一个唯一的unionid,这个unionid腾讯公司下产品共享.这个unionid就是我们进行打通的关键. 先说一下思路: 1.微信小程序与公众号进行绑定后,在小程序调用wx.login()方法后会自动获取unionid,公众号根据官方文档在获取用户基本信息后会拿到相同的unionid,openid,nickname...等相关信息: 2.将小程序拿

  • 微信小程序与公众号卡券/会员打通的问题

    微信小程序与公众号卡券/会员打通 卡券开发:带你走出小程序的坑 tips:由于笔者也是一位前端菜鸟,所以尽量用简单直白的语言为大家讲解,如有说的不到位的地方,还望多多指教 - 作为小程序的研发人员已经默默在小程序深耕了有8个月了,可以说是陪小程序一起成长起来,经历了小程序内测-小程序API开发趋于稳定 好了,进入正题吧, 批量添加卡券 wx.addCard(OBJECT) 基础库 1.1.0 开始支持,低版本需做兼容处理 查看微信卡包中的卡券 wx.openCard(OBJECT) 基础库 1.

  • 微信小程序和公众号实现签到页面

    本文实例为大家分享了微信小程序和公众号实现签到页面的具体代码,供大家参考,具体内容如下 微信小程序 之前做了一个酒庄的小程序签到,微信小程序和公众号一起的. wxml: <!--pages/Calendar/Calendar.wxml--> <!-- 打卡日历页面 --> <view class='all'>  <view class="bar">   <!-- 上一个月 -->   <view class="

  • 微信小程序获取公众号文章列表及显示文章的示例代码

    微信小程序中如何打开公众号中的文章,步骤相对来说不麻烦. 1.公众号设置 小程序若要获取公众号的素材,公众号需要做一些设置. 1.1 绑定小程序 公众号需要绑定目标小程序,否则无法打开公众号的文章. 在公众号管理界面,点击小程序管理 --> 关联小程序 输入小程序的AppID搜索,绑定即可. 1.2 公众号开发者功能配置 (1) 在公众号管理界面,点击开发模块中的基本配置选项. (2) 开启开发者秘密(AppSecret),注意保存改秘密. (3) 设置ip白名单,这个就是发起请求的机器的外网i

  • mpvue实现微信小程序快递单号查询代码

    mpvue是什么? mpvue 是一套定位于开发小程序的前端开发框架,其核心目标是提高开发效率,增强开发体验.使用该框架,开发者只需初步了解小程序开发规范.熟悉 Vue.js 基本语法即可上手.框架提供了完整的 Vue.js 开发体验,开发者编写 Vue.js 代码,mpvue 将其解析转换为小程序并确保其正确运行.此外,框架还通过 vue-cli 工具向开发者提供 quick start 示例代码,开发者只需执行一条简单命令,即可获得可运行的项目. mpvue简介点击查看:http://mpv

  • 微信小程序 Tab页切换更新数据

    微信小程序 Tab页切换更新数据 微信小程序还处于内测阶段,最不方便的莫过于官方在不停的更新,前几天写的功能隔个几天忽然发现不能用了_(:зゝ∠)_ 功能需求如下: 我在首页点击"5万以上"他会把跳转到买车页然后同时把"5万以上"这个筛选条件带到买车页. 之前navigator导航是可以跳转并携带数据的,但这一次官方更新加了个新东西-----switchTab,专门用来实现tab页的跳转,但禁止携带数据 那么如果还想要实现我们的效果只能用别的方法了 想了一下有两种思

  • 微信小程序 页面跳转和数据传递实例详解

    微信小程序 页面跳转和数据传递 1.先导 在Android中,我们Activity和Fragment都有栈的概念在里面,微信小程序页面也有栈的概念在里面.微信小程序页面跳转有四种方式: 1.wx.navigateTo(OBJECT): 2.wx.redirectTo(OBJECT): 3.wx.switchTab(OBJECT): 4.wx.navigateBack(OBJECT) 5.使用实现对应的跳转功能: 分析: 其中navigateTo是将原来的页面保存在页面栈中,在跳入到下一个页面的时

  • 微信小程序 获取javascript 里的数据

    微信小程序 获取javascript 里的数据 wxml如何获取js里的数据 例: wxml里: <text id="twl">{{txt}}</text> 通过上面的{{txt}}可以对应获取js里data下定义的txt的值 js里: data: { txt:{} } 首先在data里定义一个"容器"txt:{},{}内为空代表是从别的地方传值进去,当然{}里也可以直接写数据,如txt:{'123'},上面的wxml获取了就相当于 <

  • 微信小程序 页面跳转及数据传递详解

    微信小程序 页面跳转及数据传递详解 类似 Android 的 Intent 传值,微信小程序也一样可以传值: 例如:wxml 中写了一个函数跳转: <view class="itemWeight" catchtap="jumpToOverMissionList"> <view class="textStatus">已完成任务</view> <view class="containVertical

  • 微信小程序wx.request实现后台数据交互功能分析

    本文实例讲述了微信小程序wx.request实现后台数据交互功能.分享给大家供大家参考,具体如下: 记录微信小程序wx.request这个api在跟后台交互时遇上的问题. 1.根据资料,完成第一步,请求发送,代码如下: wx.request({ url: 'https://localhost:8443/xiaochengxu/addBill.do', data: e.detail.value, method: 'POST', success:function(res) { console.log

随机推荐