您好,欢迎来到锐游网。
搜索
您的当前位置:首页企微提取用户unionid

企微提取用户unionid

来源:锐游网

前言

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

pom

<!-- 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>

 

工具类

 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.*;

/**
 * 企微员工所绑定用户提取
 * @author zhangle
 * @create 2021-04-21 10:41
 */
@Slf4j
@Service
public class QiWeiTest {

    /**
     * 微信token公共变量
     */
    private  String access_token;
    /**
     * HTTP线程池 这个如果需要代理需要配置 看我博客
     * https:///HezhezhiyuLe/article/details/92395041
     */
    @Autowired
    private RestTemplate bean;
    /**
     * 最终获得用户信息保存接口  自定义 不用删除
     */
    @Autowired
    private WXUserVoMapper wxUserVoMapper;
    /**
     * corpid  corpsecret 填自己的公司
     * 获取token get
     * https://work.weixin.qq.com/api/doc/90000/90135/91039 参考文档
     */
    private final String tokenurl = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=10086&corpsecret=10010";

    /**
     * 获取部门 post  可省略ID 不填默认拉取当前权限下可见部门
     * https://work.weixin.qq.com/api/doc/90000/90135/90208
     */
    private   String depturl = "https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token=";
    /**
     * 批量获取客户详情 post
     * https://work.weixin.qq.com/api/doc/90000/90135/92994
     */
    private  String userurl = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/batch/get_by_user?access_token=";
    /**
     * 企微当前最高权限获取部门所有成员 department_id=1 fetch_child=1 递归 =0当前部门
     * https://work.weixin.qq.com/api/doc/90000/90135/90200
     */
    private  String deptuserurl = "https://qyapi.weixin.qq.com/cgi-bin/user/simplelist?fetch_child=1&department_id=";

    /**
     * 1
     * 获取企微token
     * @return token
     */
    public String getToken() {
        String tokenstr = bean.getForEntity(tokenurl, String.class).getBody();
        log.info("获取token:"+tokenstr);
        JSONObject tokenjson = parseStr(tokenstr);
        access_token=tokenjson.get("access_token").toString();
        return access_token;
    }

    /**
     * 0
     */
    public void start(){
        //获取token
        access_token=getToken();
        //获得父节点
        Set<String> treeDept = findTreeDept();
        if(treeDept==null||treeDept.size()==0){
            log.info("查询部门为空");
            return;
        }
        //迭代父节点
        for (String deptparent : treeDept) {
            //父节点下所有员工 递归
            Set<String> deptUserByDId = findDeptUserByDId(deptparent);
            int unionidByUserId = findUnionidByUserId(deptUserByDId);
            log.info("当前"+deptparent+"部门员工客户人数:"+unionidByUserId);
        }

    }
    /**
     * 2
     * 获取当前企微最高节点部门ID
     * 当自己不是当前公众号最高权限即不可以查看所有部门时使用
     * @return 最高父节点
     */
    public Set<String> findTreeDept() {

        String deptstr = bean.getForEntity(depturl+access_token, String.class).getBody();
        deptstr=iflegal(deptstr);
        if(deptstr==null||"".equals(deptstr)){
            log.info("获取部门失败");
            return null;
        }
        JSONObject jsonObject = parseStr(deptstr);
        //获取所有部门
        String dept = jsonObject.get("department").toString();
        List<JSONObject> departments = JSON.parseArray(dept, JSONObject.class);
        return  recursiondept(departments);
    }

    /**
     * 判断微信接口返回是否合法
     * @param resp
     * @return
     */
    public String iflegal(String resp){
        if(resp.contains("\"errcode\":0")){
            return resp;
        }
        log.info("失敗預警:"+resp);
        if(resp.contains("\"errcode\":40014")||resp.contains(" \"errcode\":42001")){
            getToken();
            log.info("恢复:"+access_token);
        }
        return null;
    }
    /**
     * 转换企微返回数据为json对象
     * @param str
     * @return
     */
    public JSONObject parseStr(String str){
        return JSON.parseObject(str);
    }

    /**
     * 查询部门父ID
     * @param departments 当前企微权限下所有部门 包含父子级
     * @return 最高父节点
     */
    public Set<String> recursiondept(List<JSONObject> departments){
        Set<String> deptid = new HashSet<>();
        Set<String> treedept = new HashSet<>();

        for (JSONObject department : departments) {
            deptid.add(department.getString("id"));
        }
        for (JSONObject department : departments) {
            String parentid = department.getString("parentid");
            //找不到父ID即为最高节点
            if(!deptid.contains(parentid)){
                treedept.add(department.getString("id"));
            }
        }
        return treedept;
    }

    /**
     * 3
     * 通过部门ID查询当前部门员工 递归获取当前部门所有员工
     * @param deptId 部门ID
     * @return
     */
    public Set<String> findDeptUserByDId(String deptId){
        //获取当前部门下的所有员工 包括子节点
        String deptuserstr = bean.getForEntity(deptuserurl+deptId+"&access_token="+access_token, String.class).getBody();
        deptuserstr=iflegal(deptuserstr);
        if(deptuserstr==null||"".equals(deptuserstr)){
            log.info("获取部门成员失败");
            return null;
        }
        JSONObject jsonObject = parseStr(deptuserstr);
        String dept = jsonObject.get("userlist").toString();

        List<JSONObject> departments = JSON.parseArray(dept, JSONObject.class);
        if(departments==null||departments.size()==0){
            return null;
        }
        //去重
        Set<String> userids = new HashSet<>();
        for (JSONObject department : departments) {
            userids.add(department.getString("userid"));
        }
        log.info("用户ID总数:"+userids.size());
        return userids;
    }

    /**
     * 4
     * 企微员工通过员工ID查找用户unionid
     * @param userids 当前部门所有员工
     * @return
     */
    public int  findUnionidByUserId(Set<String> userids){
        //用户unionid集合 所有用户 包含重复  如果父级部门平行有多个 用户可能会重复 建议把人员再次汇总 我是因为确定父级只有一个有最大权限才这么写
        int count=0;
        int size = userids.size();
        //去重总用户(一个客户加了N个员工) 这个存储值几十万没问题 SQL写对加主键一把就成功
        Set<String> unionids = new HashSet<>();
        int formum=0;
        for (String userid : userids) {
            formum++;
            if(formum%1000==0){
                log.info("循环到:"+formum+"/"+unionids.size()+"/"+size);
            }
            //实时更新token 防止失效
            Set<String> personnelUsers = handleUserByUserId(userid,userurl+access_token);
            unionids.addAll(personnelUsers);
            count+=personnelUsers.size();

        }
        //用户unionid集合有值就保存 可以根据业务需求 自行决定存储 IO SQL
        ArrayList<String> unionidarr = new ArrayList<>();

        for (String unionid : unionids) {
            unionidarr.add(unionid);
            //依据自己数据库能力分批次插入 一次插入几十万容易IO溢出
            if(unionidarr.size()==1000){
                Integer insertnum = wxUserVoMapper.insertQiWei(unionidarr);
                log.info(insertnum+"");
                unionidarr.clear();
            }
        }
        if(unionidarr.size()>0){
            Integer insertnum = wxUserVoMapper.insertQiWei(unionidarr);
            log.info(insertnum+"");
        }
        log.info(" 员工总用户数:"+unionids.size()+"交叉结果集:"+count);

        return unionids.size();
    }

    /**
     * 处理单个用户所拥有的全部客户
     * @param userid 用户ID
     * @param url 实时链接
     * @return
     */
    public Set<String> handleUserByUserId(String userid,String url) {

        Set<String> unionids = new HashSet<>();
        Map<String, Object> params = new HashMap<>();
        params.put("userid",userid);
        //企微最大分页量
        params.put("limit",100);
        String openid = "";
        //封顶值 一个员工10W用户
        for (int i = 0; i < 1000; i++) {
            params.put("cursor",openid);
            String resp = bean.postForEntity(url, params, String.class).getBody();
            resp=iflegal(resp);
            if (resp == null ||"".equals(resp)) {
                log.info("不合法返回:"+userid);
                break;
            }
            if(i==999){
               log.info("员工用户超限:"+userid);
            }
            JSONObject jsonObject = parseStr(resp);
            //员工客户列表
            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) {
                String external_contact = customer.getString("external_contact");
                if(external_contact==null||"".equals(external_contact)){
                    break;
                }
                //用户粗略详情
                JSONObject customercontact = parseStr(external_contact);
                if(customercontact==null){
                    break;
                }
                // 可以拿到 客户微信名 name 头像 avatar 性别 gender 标识 unionid 类型 type更多详情需要换链接
                String unionid = customercontact.getString("unionid");
                if(unionid!=null&&!"".equals(unionid)){
                    unionids.add(unionid);
                }
            }

                String next_cursor = jsonObject.getString("next_cursor");
                if ("".equals(next_cursor)) {
                    break;
                }else {
                    //迭代
                    openid=next_cursor;
                }

        }
        return unionids;
    }

}

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- ryyc.cn 版权所有

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务