职贝云数AI新零售门户

标题: 企微提取用户unionid [打印本页]

作者: jQGCPeAbH    时间: 2022-12-30 14:58
标题: 企微提取用户unionid
前言

业务需求 需求根据提取企业微信一切员工所拥有客户 也就是提取unionid 特此写个一站式工具类 一次性生成

pom
  1. <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.73</version></dependency><!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.12</version><scope>provided</scope></dependency>
复制代码
工具类
  1. package ins.platfrom.test;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import ins.platfrom.dao.WXUserVoMapper;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.web.client.RestTemplate;import java.util.*;/**
  2. * 企微员工所绑定用户提取
  3. * @author zhangle
  4. * @create 2021-04-21 10:41
  5. */@Slf4j@ServicepublicclassQiWeiTest{/**
  6.      * 微信token公共变量
  7.      */private  String access_token;/**
  8.      * HTTP线程池 这个假如需求代理需求配置 看我博客
  9.      * https://blog.csdn.net/HezhezhiyuLe/article/details/92395041
  10.      */@Autowiredprivate RestTemplate bean;/**
  11.      * 最终获得用户信息保存接口  自定义 不用删除
  12.      */@Autowiredprivate WXUserVoMapper wxUserVoMapper;/**
  13.      * corpid  corpsecret 填本人的公司
  14.      * 获取token get
  15.      * https://work.weixin.qq.com/api/doc/90000/90135/91039 参考文档
  16.      */privatefinal String tokenurl ="https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=10086&corpsecret=10010";/**
  17.      * 获取部门 post  可省略ID 不填默许拉取当前权限下可见部门
  18.      * https://work.weixin.qq.com/api/doc/90000/90135/90208
  19.      */private   String depturl ="https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token=";/**
  20.      * 批量获取客户概况 post
  21.      * https://work.weixin.qq.com/api/doc/90000/90135/92994
  22.      */private  String userurl ="https://qyapi.weixin.qq.com/cgi-bin/externalcontact/batch/get_by_user?access_token=";/**
  23.      * 企微当前最高权限获取部门一切成员 department_id=1 fetch_child=1 递归 =0当前部门
  24.      * https://work.weixin.qq.com/api/doc/90000/90135/90200
  25.      */private  String deptuserurl ="https://qyapi.weixin.qq.com/cgi-bin/user/simplelist?fetch_child=1&department_id=";/**
  26.      * 1
  27.      * 获取企微token
  28.      * @return token
  29.      */public String getToken(){
  30.         String tokenstr = bean.getForEntity(tokenurl, String.class).getBody();
  31.         log.info("获取token:"+tokenstr);
  32.         JSONObject tokenjson =parseStr(tokenstr);
  33.         access_token=tokenjson.get("access_token").toString();return access_token;}/**
  34.      * 0
  35.      */publicvoidstart(){//获取token
  36.         access_token=getToken();//获得父节点
  37.         Set<String> treeDept =findTreeDept();if(treeDept==null||treeDept.size()==0){
  38.             log.info("查询部门为空");return;}//迭代父节点for(String deptparent : treeDept){//父节点下一切员工 递归
  39.             Set<String> deptUserByDId =findDeptUserByDId(deptparent);int unionidByUserId =findUnionidByUserId(deptUserByDId);
  40.             log.info("当前"+deptparent+"部门员工客户人数:"+unionidByUserId);}}/**
  41.      * 2
  42.      * 获取当前企微最高节点部门ID
  43.      * 当本人不是当前公众号最高权限即不可以查看一切部门时运用
  44.      * @return 最高父节点
  45.      */public Set<String>findTreeDept(){
  46.         String deptstr = bean.getForEntity(depturl+access_token, String.class).getBody();
  47.         deptstr=iflegal(deptstr);if(deptstr==null||"".equals(deptstr)){
  48.             log.info("获取部门失败");return null;}
  49.         JSONObject jsonObject =parseStr(deptstr);//获取一切部门
  50.         String dept = jsonObject.get("department").toString();
  51.         List<JSONObject> departments = JSON.parseArray(dept, JSONObject.class);returnrecursiondept(departments);}/**
  52.      * 判别微信接口前往能否合法
  53.      * @param resp
  54.      * @return
  55.      */public String iflegal(String resp){if(resp.contains(""errcode":0")){return resp;}
  56.         log.info("失敗預警:"+resp);if(resp.contains(""errcode":40014")||resp.contains(" "errcode":42001")){getToken();
  57.             log.info("恢复:"+access_token);}return null;}/**
  58.      * 转换企微前往数据为json对象
  59.      * @param str
  60.      * @return
  61.      */public JSONObject parseStr(String str){return JSON.parseObject(str);}/**
  62.      * 查询部门父ID
  63.      * @param departments 当前企微权限下一切部门 包含父子级
  64.      * @return 最高父节点
  65.      */public Set<String>recursiondept(List<JSONObject> departments){
  66.         Set<String> deptid =newHashSet<>();
  67.         Set<String> treedept =newHashSet<>();for(JSONObject department : departments){
  68.             deptid.add(department.getString("id"));}for(JSONObject department : departments){
  69.             String parentid = department.getString("parentid");//找不到父ID即为最高节点if(!deptid.contains(parentid)){
  70.                 treedept.add(department.getString("id"));}}return treedept;}/**
  71.      * 3
  72.      * 经过部门ID查询当前部门员工 递归获取当前部门一切员工
  73.      * @param deptId 部门ID
  74.      * @return
  75.      */public Set<String>findDeptUserByDId(String deptId){//获取当前部门下的一切员工 包括子节点
  76.         String deptuserstr = bean.getForEntity(deptuserurl+deptId+"&access_token="+access_token, String.class).getBody();
  77.         deptuserstr=iflegal(deptuserstr);if(deptuserstr==null||"".equals(deptuserstr)){
  78.             log.info("获取部门成员失败");return null;}
  79.         JSONObject jsonObject =parseStr(deptuserstr);
  80.         String dept = jsonObject.get("userlist").toString();
  81.         List<JSONObject> departments = JSON.parseArray(dept, JSONObject.class);if(departments==null||departments.size()==0){return null;}//去重
  82.         Set<String> userids =newHashSet<>();for(JSONObject department : departments){
  83.             userids.add(department.getString("userid"));}
  84.         log.info("用户ID总数:"+userids.size());return userids;}/**
  85.      * 4
  86.      * 企微员工经过员工ID查找用户unionid
  87.      * @param userids 当前部门一切员工
  88.      * @return
  89.      */publicintfindUnionidByUserId(Set<String> userids){//用户unionid集合 一切用户 包含反复  假如父级部门平行有多个 用户能够会反复 建议把人员再次汇总 我是由于确定父级只要一个有最大权限才这么写int count=0;int size = userids.size();//去重总用户(一个客户加了N个员工) 这个存储值几十万没成绩 SQL写对加主键一把就成功
  90.         Set<String> unionids =newHashSet<>();int formum=0;for(String userid : userids){
  91.             formum++;if(formum%1000==0){
  92.                 log.info("循环到:"+formum+"/"+unionids.size()+"/"+size);}//实时更新token 防止失效
  93.             Set<String> personnelUsers =handleUserByUserId(userid,userurl+access_token);
  94.             unionids.addAll(personnelUsers);
  95.             count+=personnelUsers.size();}//用户unionid集合有值就保存 可以根据业务需求 自行决议存储 IO SQL
  96.         ArrayList<String> unionidarr =newArrayList<>();for(String unionid : unionids){
  97.             unionidarr.add(unionid);//根据本人数据库才能分批次插入 一次插入几十万容易IO溢出if(unionidarr.size()==1000){
  98.                 Integer insertnum = wxUserVoMapper.insertQiWei(unionidarr);
  99.                 log.info(insertnum+"");
  100.                 unionidarr.clear();}}if(unionidarr.size()>0){
  101.             Integer insertnum = wxUserVoMapper.insertQiWei(unionidarr);
  102.             log.info(insertnum+"");}
  103.         log.info(" 员工总用户数:"+unionids.size()+"交叉结果集:"+count);return unionids.size();}/**
  104.      * 处理单个用户所拥有的全部客户
  105.      * @param userid 用户ID
  106.      * @param url 实时链接
  107.      * @return
  108.      */public Set<String>handleUserByUserId(String userid,String url){
  109.         Set<String> unionids =newHashSet<>();
  110.         Map<String, Object> params =newHashMap<>();
  111.         params.put("userid",userid);//企微最大分页量
  112.         params.put("limit",100);
  113.         String openid ="";//封顶值 一个员工10W用户for(int i =0; i <1000; i++){
  114.             params.put("cursor",openid);
  115.             String resp = bean.postForEntity(url, params, String.class).getBody();
  116.             resp=iflegal(resp);if(resp == null ||"".equals(resp)){
  117.                 log.info("不合法前往:"+userid);break;}if(i==999){
  118.                log.info("员工用户超限:"+userid);}
  119.             JSONObject jsonObject =parseStr(resp);//员工客户列表
  120.             List<JSONObject> external_contact_list = JSON.parseArray(jsonObject.get("external_contact_list").toString(), JSONObject.class);if(external_contact_list==null||external_contact_list.size()==0){break;}for(JSONObject customer : external_contact_list){
  121.                 String external_contact = customer.getString("external_contact");if(external_contact==null||"".equals(external_contact)){break;}//用户粗略概况
  122.                 JSONObject customercontact =parseStr(external_contact);if(customercontact==null){break;}// 可以拿到 客户微信名 name 头像 avatar 性别 gender 标识 unionid 类型 type更多概况需求换链接
  123.                 String unionid = customercontact.getString("unionid");if(unionid!=null&&!"".equals(unionid)){
  124.                     unionids.add(unionid);}}
  125.                 String next_cursor = jsonObject.getString("next_cursor");if("".equals(next_cursor)){break;}else{//迭代
  126.                     openid=next_cursor;}}return unionids;}}
复制代码





欢迎光临 职贝云数AI新零售门户 (https://www.taojin168.com/cloud/) Powered by Discuz! X3.5