企业微信开发(通讯录模块)

2023-11-05

1.前言

关于企业微信通讯录同步的开发
先获取企业corpid,通讯录应用的secret
并在通讯录应用开启API编辑通讯录权限

在这里插入图片描述

2. 关于token

token是通过调用微信api接口由corpid和secret获取
由于token是每隔两个小时(时间不确定)失效,
调用企业微信的接口主要业务是自动获取token,拼接url

3.开始编写接口

这篇文章主要写通讯录中的成员类

3.1公共类

3.1.1 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.1</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.cxy</groupId>
    <artifactId>cxy-service-enterprise-wechat</artifactId>
    <version>1.0.0</version>
    <name>cxy-service-enterprise-wechat</name>
    <description>cxy-demo</description>


    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.5</version>
        </dependency>


        <!--gitlub-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.10</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpmime -->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpmime</artifactId>
            <version>4.5.2</version>
        </dependency>


        <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.3</version>
        </dependency>


        <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpcore -->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpcore</artifactId>
            <version>4.4.13</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>28.1-jre</version>
        </dependency>


        <!-- https://mvnrepository.com/artifact/commons-lang/commons-lang -->
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.62</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.3</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
    <dependencyManagement>

    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

application.yml

server:
port: 8080

spring:
datasource:
url: jdbc:mysql://localhost:3306/wechat?serverTimezone=GMT%2B8&characterEncoding=utf8
username: root
password: root

mybatis:
mapper-locations:
- classpath:/mybatis/mapper/*.xml

wechat:
corpid: 企业id
corpsecret:
ContactsSecret (自定义名字): 通讯录secret
ClientSecret(自定义名字): 客户secret

公共响应结果BusinessResponse

public class BusinessResponse<T> {
    public static final int RESPONSE_NO_RIGHT = 403000;
    public static final int RESPONSE_OK = 0;
    public static final int RESPONSE_ERROR = 500000;
    public static final int RESPONSE_PARA_ERROR = 400000;
    public static final int RESPONSE_NO_DATA = 204000;

    private int rt_code = 500000;
    private String rt_msg = null;
    private T data = null;

    public BusinessResponse() {
        this.rt_code = 0;
        this.rt_msg = "";
    }

    public boolean success() {
        return this.rt_code == 0;
    }

    public static BusinessResponse ok(Object data) {
        BusinessResponse<Object> response = new BusinessResponse();
        response.setData(data);
        response.setRt_code(0);
        response.setRt_msg("success");
        return response;
    }

    public static BusinessResponse fail(int code, String msg) {
        BusinessResponse response = new BusinessResponse();
        response.setRt_code(code);
        response.setRt_msg(msg);
        return response;
    }

    public static BusinessResponse fail(String msg) {
        BusinessResponse response = new BusinessResponse();
        response.setRt_code(500000);
        response.setRt_msg(msg);
        return response;
    }

    public int getRt_code() {
        return rt_code;
    }

    public BusinessResponse setRt_code(int rt_code) {
        this.rt_code = rt_code;
        return this;
    }

    public String getRt_msg() {
        return this.rt_msg;
    }

    public BusinessResponse setRt_msg(String rt_msg) {
        this.rt_msg = rt_msg;
        return this;
    }

    public T getData() {
        return this.data;
    }

    public BusinessResponse setData(T data) {
        this.data = data;
        return this;
    }

    public String toString() {
        return "BusinessResponse [rt_code=" + this.rt_code + ", rt_msg=" + this.rt_msg + ", data=" + this.data + "]";
    }

}







BaseObject

public class BaseObject implements Serializable {
private static final long serialVersionUID = -5824534192273817261L;

public BaseObject() {
}

public int hashCode() {
    return HashCodeBuilder.reflectionHashCode(this, new String[0]);
}

public boolean equals(Object obj) {
    return EqualsBuilder.reflectionEquals(this, obj, new String[0]);
}

public String toString() {
    return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
}

BaseVO

public class BaseVO extends BaseObject {

private static final long serialVersionUID = -785293771287573538L;
private final transient Logger log = LogUtils.getLogger();

public BaseVO() {
}

public boolean isBlank(String value, String key) {
    if (StringUtils.isBlank(value)) {
        this.log.info("Param is null:[{}]", key);
        return true;
    } else {
        return false;
    }
}

BaseEntity

public class BaseEntity extends BaseObject {
    private static final long serialVersionUID = 4926246431415506174L;
    private String id;
    private String createdBy;
    private Date createdDate;
    private String updatedBy;
    private Date updatedDate;

    public BaseEntity() {
    }

    public String getId() {
        return this.id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getCreatedBy() {
        return this.createdBy;
    }

    public void setCreatedBy(String createdBy) {
        this.createdBy = createdBy;
    }

    public Date getCreatedDate() {
        return this.createdDate;
    }

    public void setCreatedDate(Date createdDate) {
        this.createdDate = createdDate;
    }

    public String getUpdatedBy() {
        return this.updatedBy;
    }

    public void setUpdatedBy(String updatedBy) {
        this.updatedBy = updatedBy;
    }

    public Date getUpdatedDate() {
        return this.updatedDate;
    }

    public void setUpdatedDate(Date updatedDate) {
        this.updatedDate = updatedDate;
    }
}

3.2 常量

controller层 url常量

public class UrlConstant {

    /**
     * 成员模块请求的url
     */
    public static final String USER = "/user";

    public static final String USER_SELECT = "/get";

    public static final String USER_ADD = "/create";

    public static final String USER_DELETE = "/delete";

    public static final String USER_UPDATE = "/update";

    public static final String USER_SELECT_USER_LIST = "/listUserByDeptId";

    /**
     * 邀请成员
     */
    public static final String INVITE_USER_BATCH ="/inviteUserBatch";

    /**
     * 获取加入企业二维码
     */
    public static final String GET_JOIN_QRCODE= "/getJoinQrcode";




    /**
     * 部门模块的请求url
     */
    public static final String Dept = "/dept";

    public static final String Dept_ADD = "/create";

    public static final String Dept_DELETE = "/delete";

    public static final String Dept_UPDATE = "/update";

    public static final String GET_DEPT_LIST = "/listDeptByDeptId";





}

微信相关常量WechatConstant

package com.cxy.enterprise.wechat.common;


public class WechatConstant {

    //企业微信 api 网关地址
    public static final String  API_GATEWAY_QY="https://qyapi.weixin.qq.com";

    //企业微信接口限流必传参数state
    public static final String  KEY_STATE="state";

    //微信接口相关键
    public static final String KEY_ACCESS_TOKEN="access_token";

    public static final String GET_ACCESS_TOKEN_URL= "/cgi-bin/gettoken?corpid=";

    public static final String KEY_TICKET="ticket";

    public final static String KEY_USER_ID="UserId";

    /**
     * 企业微信成员模块api调用接口
     */

    /** 1.创建成员 */
    public static final String CREATE_USER_URL= WechatConstant.API_GATEWAY_QY+"/cgi-bin/user/create?access_token=";

    /** 2.删除成员 */
    public static final String DELETE_USER_URL= WechatConstant.API_GATEWAY_QY+"/cgi-bin/user/delete?access_token=";

    /** 3.更新成员 */
    public static final String UPDATE_USER_URL= WechatConstant.API_GATEWAY_QY+"/cgi-bin/user/update?access_token=";

    /** 4.获取成员信息 */
    public static final String GET_USER_BY_ID_URL= WechatConstant.API_GATEWAY_QY+"/cgi-bin/user/get?access_token=";

    /** 5.根据code 获取用户信息:网页授权时**/
    public static final String GET_USER_BY_CODE_URL= WechatConstant.API_GATEWAY_QY+"/cgi-bin/user/getuserinfo?access_token=";

    /** 6.获取部门成员详情**/
    public static final String LIST_USER_BY_DEPARTMENT_ID_URL= WechatConstant.API_GATEWAY_QY+"/cgi-bin/user/list?access_token=";

    /** 7.邀请成员(批量)**/
    public static final String INVITE_USER_BATCH = WechatConstant.API_GATEWAY_QY+"/cgi-bin/batch/invite?access_token=";

    /** 8.获取加入企业二维码**/
    public static final String GET_JOIN_QRCODE= WechatConstant.API_GATEWAY_QY+"/cgi-bin/corp/get_join_qrcode?access_token=";


    /**
     * 企业微信部门模块api调用接口
     */

    /**
     * 1.创建部门
     */
    public static final String CREATE_DEPT_URL = WechatConstant.API_GATEWAY_QY + "/cgi-bin/department/create?access_token=";

    /**
     * 2.更新部门
     */
    public static final String UPDATE_DEPT_URL = WechatConstant.API_GATEWAY_QY + "/cgi-bin/department/update?access_token=";

    /**
     * 3.删除部门
     */
    public static final String DELETE_DEPT_URL = WechatConstant.API_GATEWAY_QY + "/cgi-bin/department/delete?access_token=";

    /**
     * 4.获取部门列表
     */
    public static final String LIST_DEPT_BY_DEPT_ID_URL = WechatConstant.API_GATEWAY_QY + "/cgi-bin/department/list?access_token=";


    /**
     * 微信api返回错误码
     */
    public static final String ERR_CODE = "errcode";

    /**
     * 微信api返回错误信息
     */
    public static final String ERR_MSG = "errmsg";

    /**
     * 返回的二维码链接
     */
    public static final String JOIN_QRCODE ="join_qrcode";

    /**
     * 成员url相关常量
     */

    public static final String USER_ID = "&userid=";

    public static final String DEPARTMENT_ID = "&department_id=";

    public static final String SIZE_TYPE= "&size_type=";

    /**
     * 是否递归获取子部门的成员
     */
    public static final String FETCH_CHILD = "&fetchChild=";




    /**
     * 部门相关常量
     */

    /**
     * 拼接url的部门id
     */
    public static final String DEPT_ID = "&id=";

    /**
     * 返回值中的department
     */
    public static final String RESPONSE_DEPARTMENT = "department";



}

3.2 相关工具类

LogUtils

public final class LogUtils {
    private static final Logger normal = LoggerFactory.getLogger("normal");
    private static final Logger threshold = LoggerFactory.getLogger("threshold");
    private static final Logger trace = LoggerFactory.getLogger("trace");

    public LogUtils() {
    }

    public static Logger getLogger() {
        return normal;
    }

    public static Logger getLogger(String logName) {
        return LoggerFactory.getLogger(logName);
    }

    public static Logger getThresholdLogger() {
        return threshold;
    }

    public static Logger getTraceLogger() {
        return trace;
    }


}

JSONUtil

package com.cxy.enterprise.wechat.util;

import com.alibaba.fastjson.JSON;


public class JSONUtil {

    public JSONUtil() {
    }

    public static <T> T fromObject(String json, Class<T> clazz) {
        return JSON.parseObject(json, clazz);
    }

    public static String toJson(Object obj) {
        return JSON.toJSONString(obj);
    }


}

HttpHelper

package com.cxy.enterprise.wechat.util;

import com.alibaba.fastjson.JSONObject;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

public class HttpHelper {

    @Resource

    RestTemplate restTemplate;

    public HttpHelper(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    public JSONObject get(String url){
        //将url转成JSONObject格式
        ResponseEntity<JSONObject> respString = restTemplate.getForEntity(url, JSONObject.class);
        return isHttpSuccess(respString);
    }

    public  JSONObject post( String url, Object data){
        ResponseEntity<JSONObject> respString = restTemplate.postForEntity(url, data, JSONObject.class);
        return isHttpSuccess(respString);
    }

    private JSONObject isHttpSuccess(ResponseEntity<JSONObject> respString) {

        JSONObject strBody = respString.getBody();


        return strBody;

    }
}

3.2 pojo

WeiXinQYAuthConfigDTO

package com.cxy.enterprise.wechat.pojo.dto;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.List;


@Component
@ConfigurationProperties(prefix = "wechat")
public class WeiXinQYAuthConfigDTO {

    private String corpId;

    private String ContactsSecret;

    private List<AgentAuthConfigDTO> agent;

    public String getCorpId() {
        return corpId;
    }

    public void setCorpId(String corpId) {
        this.corpId = corpId;
    }

    public String getContactsSecret() {
        return ContactsSecret;
    }

    public void setContactsSecret(String contactsSecret) {
        ContactsSecret = contactsSecret;
    }

    public List<AgentAuthConfigDTO> getAgent() {
        return agent;
    }

    public void setAgent(List<AgentAuthConfigDTO> agent) {
        this.agent = agent;
    }
}

AgentAuthConfigDTO

@Component
public class AgentAuthConfigDTO {

    private int agentId;

    private String agentSecret;

    private String token;

    private String encodingAesKey;

    //网页授权登录校验
    private String state;

    public int getAgentId() {
        return agentId;
    }

    public void setAgentId(int agentId) {
        this.agentId = agentId;
    }

    public String getAgentSecret() {
        return agentSecret;
    }

    public void setAgentSecret(String agentSecret) {
        this.agentSecret = agentSecret;
    }

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }

    public String getEncodingAesKey() {
        return encodingAesKey;
    }

    public void setEncodingAesKey(String encodingAesKey) {
        this.encodingAesKey = encodingAesKey;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }
}

UserVO

package com.cxy.enterprise.wechat.pojo.vo.request;

import org.apache.commons.lang.StringUtils;

import java.util.List;


public class UserVO {

    private String userid;
    private String name;
    /**
     * 别名;第三方仅通讯录应用可获取
     */
    private String alias;
    private String mobile;
    private Long[] department;
    private Integer[] order;
    private String position;
    private String gender;
    private String email;
    /**
     * is_leader_in_dept.
     * 个数必须和department一致,表示在所在的部门内是否为上级。1表示为上级,0表示非上级。在审批等应用里可以用来标识上级审批人
     */
    private Integer[] is_leader_in_dept;
    private Integer enable;
    private String avatar_mediaid;
    private String telephone;
    /**
     * 地址。长度最大128个字符
     */
    private String address;
    private String main_department;
    private Extattr extattr;
    private Boolean to_invite;
    private String external_position;
    private ExternalPorfile external_profile;

    public String getUserid() {
        return userid;
    }

    public void setUserid(String userid) {
        this.userid = userid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAlias() {
        return alias;
    }

    public void setAlias(String alias) {
        this.alias = alias;
    }

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public Long[] getDepartment() {
        return department;
    }

    public void setDepartment(Long[] department) {
        this.department = department;
    }

    public Integer[] getOrder() {
        return order;
    }

    public void setOrder(Integer[] order) {
        this.order = order;
    }

    public String getPosition() {
        return position;
    }

    public void setPosition(String position) {
        this.position = position;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Integer[] getIs_leader_in_dept() {
        return is_leader_in_dept;
    }

    public void setIs_leader_in_dept(Integer[] is_leader_in_dept) {
        this.is_leader_in_dept = is_leader_in_dept;
    }

    public Integer getEnable() {
        return enable;
    }

    public void setEnable(Integer enable) {
        this.enable = enable;
    }

    public String getAvatar_mediaid() {
        return avatar_mediaid;
    }

    public void setAvatar_mediaid(String avatar_mediaid) {
        this.avatar_mediaid = avatar_mediaid;
    }

    public String getTelephone() {
        return telephone;
    }

    public void setTelephone(String telephone) {
        this.telephone = telephone;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getMain_department() {
        return main_department;
    }

    public void setMain_department(String main_department) {
        this.main_department = main_department;
    }

    public Extattr getExtattr() {
        return extattr;
    }

    public void setExtattr(Extattr extattr) {
        this.extattr = extattr;
    }

    public Boolean getTo_invite() {
        return to_invite;
    }

    public void setTo_invite(Boolean to_invite) {
        this.to_invite = to_invite;
    }

    public String getExternal_position() {
        return external_position;
    }

    public void setExternal_position(String external_position) {
        this.external_position = external_position;
    }

    public ExternalPorfile getExternal_profile() {
        return external_profile;
    }

    public void setExternal_profile(ExternalPorfile external_profile) {
        this.external_profile = external_profile;
    }

    public static class Extattr {
       private List<Attr> attrs;

        public List<Attr> getAttrs() {
            return attrs;
        }

        public void setAttrs(List<Attr> attrs) {
            this.attrs = attrs;
        }
    }

    public static class ExternalPorfile {
       private String  external_corp_name;
        /**
         * 成员对外信息.
         */
        private List<ExternalAttrs> external_attr;

        public String getExternal_corp_name() {
            return external_corp_name;
        }

        public void setExternal_corp_name(String external_corp_name) {
            this.external_corp_name = external_corp_name;
        }

        public List<ExternalAttrs> getExternal_attr() {
            return external_attr;
        }

        public void setExternal_attr(List<ExternalAttrs> external_attr) {
            this.external_attr = external_attr;
        }
    }

    public boolean isMustFillEmpty(){
        return !(StringUtils.isNotEmpty(userid)&&StringUtils.isNotEmpty(name)&&null!=department&&department.length>0);
    }


    public static class Attr {
        /**
         * 属性类型: 0-文本 1-网页
         */
        private Integer type;
        private String name;
        private Text text;
        private Web web;

        public Integer getType() {
            return type;
        }

        public void setType(Integer type) {
            this.type = type;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Text getText() {
            return text;
        }

        public void setText(Text text) {
            this.text = text;
        }

        public Web getWeb() {
            return web;
        }

        public void setWeb(Web web) {
            this.web = web;
        }


    }


    public static class ExternalAttrs {
        /**
         * 属性类型: 0-本文 1-网页 2-小程序.
         */
        private Integer type;
        /**
         * 属性名称: 需要先确保在管理端有创建改属性,否则会忽略.
         */
        private String name;

        private Text text;

        private Web web;

        private Miniprogram miniprogram;

        public Integer getType() {
            return type;
        }

        public void setType(Integer type) {
            this.type = type;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Text getText() {
            return text;
        }

        public void setText(Text text) {
            this.text = text;
        }

        public Web getWeb() {
            return web;
        }

        public void setWeb(Web web) {
            this.web = web;
        }

        public Miniprogram getMiniprogram() {
            return miniprogram;
        }

        public void setMiniprogram(Miniprogram miniprogram) {
            this.miniprogram = miniprogram;
        }
    }

    public static class Text {
        private String value;

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }
    }

    public static class Web {
        private String url;

        private String title;

        public String getUrl() {
            return url;
        }

        public void setUrl(String url) {
            this.url = url;
        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }
    }

    public static class Miniprogram {

        private String appid;

        private String pagepath;

        private String title;

        public String getAppid() {
            return appid;
        }

        public void setAppid(String appid) {
            this.appid = appid;
        }

        public String getPagepath() {
            return pagepath;
        }

        public void setPagepath(String pagepath) {
            this.pagepath = pagepath;
        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }
    }
}

UserPO

package com.cxy.enterprise.wechat.pojo.po;


/**
 * 通讯录成员信息
 */
public class UserPO extends BaseEntity {

    private String userId;
    private String name;
    private String alias;
    private String mobile;
    private String departIds;
    private String orders;
    private String positions;
    private String gender;
    private String email;
    private String isLeaderInDept;
    private Integer enable;
    private String avatarMediaId;
    private String telephone;
    private String address;
    private String mainDepartment;
    private String extAttrs;
    private String toInvite;//布尔
    private String externalPosition;
    private String externalProfile;

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAlias() {
        return alias;
    }

    public void setAlias(String alias) {
        this.alias = alias;
    }

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public String getDepartIds() {
        return departIds;
    }

    public void setDepartIds(String departIds) {
        this.departIds = departIds;
    }

    public String getOrders() {
        return orders;
    }

    public void setOrders(String orders) {
        this.orders = orders;
    }

    public String getPositions() {
        return positions;
    }

    public void setPositions(String positions) {
        this.positions = positions;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getIsLeaderInDept() {
        return isLeaderInDept;
    }

    public void setIsLeaderInDept(String isLeaderInDept) {
        this.isLeaderInDept = isLeaderInDept;
    }

    public Integer getEnable() {
        return enable;
    }

    public void setEnable(Integer enable) {
        this.enable = enable;
    }

    public String getAvatarMediaId() {
        return avatarMediaId;
    }

    public void setAvatarMediaId(String avatarMediaId) {
        this.avatarMediaId = avatarMediaId;
    }

    public String getTelephone() {
        return telephone;
    }

    public void setTelephone(String telephone) {
        this.telephone = telephone;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getMainDepartment() {
        return mainDepartment;
    }

    public void setMainDepartment(String mainDepartment) {
        this.mainDepartment = mainDepartment;
    }

    public String getExtAttrs() {
        return extAttrs;
    }

    public void setExtAttrs(String extAttrs) {
        this.extAttrs = extAttrs;
    }

    public String getToInvite() {
        return toInvite;
    }

    public void setToInvite(String toInvite) {
        this.toInvite = toInvite;
    }

    public String getExternalPosition() {
        return externalPosition;
    }

    public void setExternalPosition(String externalPosition) {
        this.externalPosition = externalPosition;
    }

    public String getExternalProfile() {
        return externalProfile;
    }

    public void setExternalProfile(String externalProfile) {
        this.externalProfile = externalProfile;
    }
}

3.3 获取token的方法,封装到服务层sao

package com.cxy.enterprise.wechat.sao;

import com.alibaba.fastjson.JSONObject;
import com.cxy.enterprise.wechat.common.WechatConstant;
import com.cxy.enterprise.wechat.pojo.dto.WeiXinQYAuthConfigDTO;
import com.cxy.enterprise.wechat.util.HttpHelper;
import com.cxy.enterprise.wechat.util.LogUtils;
import org.slf4j.Logger;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;


@Service
public class GetTokenSao {

    public static final Logger logger = LogUtils.getLogger();

    @Resource
    private HttpHelper httpHelper;

    @Resource
    private WeiXinQYAuthConfigDTO weiXinAuthConfig;

    public String getToken(){
        String token = null;
        try {
            logger.info("request wx api for get token");
             token = getContactsAccessToken();
        }catch (Exception e){
            logger.warn("request wx api for get token error.{}",e.toString());
        }

        return token;
    }

    public String getContactsAccessToken(){
        String contactsAccessToken = doGetContactsAccessToken().getString(WechatConstant.KEY_ACCESS_TOKEN);
        return contactsAccessToken;
    }

    public JSONObject doGetContactsAccessToken(){
        String url = WechatConstant.API_GATEWAY_QY + WechatConstant.GET_ACCESS_TOKEN_URL + weiXinAuthConfig.getCorpId() + "&corpsecret=" + weiXinAuthConfig.getContactsSecret();
        return httpHelper.get(url);
    }


}

3.4 DAO

public interface UserDao {

    /**
     * 创建成员
     */
    void createUser(UserPO userPO);

    /**
     * 删除成员
     */
    void deleteUser(String userId);

    /**
     * 更新成员
     */
    void updateUser(UserPO userPO);


    UserPO findUserById(String userId);

}

mapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cxy.enterprise.wechat.dao.UserDao">
    <resultMap id="BaseResultMap" type="com.cxy.enterprise.wechat.pojo.po.UserPO">
        <id column="id" jdbcType="VARCHAR" javaType="String" property="id" />
        <result column="user_id" jdbcType="VARCHAR" property="userId"/>
        <result column="name" jdbcType="VARCHAR" property="name"/>
        <result column="alias" jdbcType="VARCHAR" property="departIds"/>
        <result column="mobile" jdbcType="VARCHAR" property="orders"/>
        <result column="depart_ids" jdbcType="VARCHAR" property="positions"/>
        <result column="orders" jdbcType="VARCHAR" property="mobile"/>
        <result column="positions" jdbcType="VARCHAR" property="gender"/>
        <result column="gender" jdbcType="VARCHAR" property="gender"/>
        <result column="email" jdbcType="VARCHAR" property="email"/>
        <result column="is_leader_in_dept" jdbcType="VARCHAR" property="isLeaderInDept"/>
        <result column="enable" jdbcType="VARCHAR" property="enable"/>
        <result column="avatar_mediaId" jdbcType="VARCHAR" property="avatarMediaId"/>
        <result column="telephone" jdbcType="VARCHAR" property="telephone"/>
        <result column="address" jdbcType="VARCHAR" property="address"/>
        <result column="main_department" jdbcType="VARCHAR" property="mainDepartment"/>
        <result column="ext_attrs" jdbcType="VARCHAR" property="extAttrs"/>
        <result column="to_invite" jdbcType="VARCHAR" property="toInvite"/>
        <result column="external_position" jdbcType="VARCHAR" property="externalPosition"/>
        <result column="external_profile" jdbcType="VARCHAR" property="externalProfile"/>
        <result column="created_by" jdbcType="VARCHAR" property="createdBy"/>
        <result column="created_date" jdbcType="TIMESTAMP" property="createdDate"/>
        <result column="updated_by" jdbcType="VARCHAR" property="updatedBy"/>
        <result column="updated_date" jdbcType="TIMESTAMP" property="updatedDate"/>
    </resultMap>

    <insert id="createUser" parameterType="com.cxy.enterprise.wechat.pojo.po.UserPO" useGeneratedKeys="true"
            keyProperty="id">
        insert into wx_user_info
        (id,user_id, name, alias, mobile, depart_ids, orders, gender, email, is_leader_in_dept,enable,avatar_mediaId,telephone,address,
         main_department,ext_attrs,to_invite,external_position,external_profile, created_by,created_date,updated_by, updated_date)
        values (replace(uuid(),"-",""),#{userId,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{alias, jdbcType=VARCHAR},
                #{mobile,jdbcType=VARCHAR},#{departIds,jdbcType=VARCHAR},#{orders,jdbcType=VARCHAR},
                #{gender,jdbcType=VARCHAR},#{email,jdbcType=VARCHAR},#{isLeaderInDept,jdbcType=VARCHAR},
                #{enable,jdbcType=VARCHAR},#{avatarMediaId,jdbcType=VARCHAR},#{telephone,jdbcType=VARCHAR},
                #{address,jdbcType=VARCHAR},#{mainDepartment,jdbcType=VARCHAR},#{extAttrs,jdbcType=VARCHAR},#{toInvite,jdbcType=VARCHAR},
                #{externalPosition,jdbcType=VARCHAR},#{externalProfile,jdbcType=VARCHAR},
               'admin',now(), 'admin', now())
    </insert>

    <delete id="deleteUser">
        delete from wx_user_info
        where user_id = #{userId}
    </delete>

    <update id="updateUser"  parameterType="com.cxy.enterprise.wechat.pojo.po.UserPO">
        update wx_user_info
        set name = #{name, jdbcType=VARCHAR},
         alias = #{alias,jdbcType=VARCHAR},
         mobile = #{mobile, jdbcType=VARCHAR},
         depart_ids = #{departIds , jdbcType=VARCHAR},
         orders = #{orders, jdbcType=VARCHAR},
         gender = #{gender, jdbcType=VARCHAR},
         email = #{email, jdbcType=VARCHAR},
         is_leader_in_dept = #{isLeaderInDept, jdbcType=VARCHAR},
         enable = #{enable, jdbcType=VARCHAR},
         avatar_mediaId = #{avatarMediaId, jdbcType=VARCHAR},
         telephone = #{telephone, jdbcType=VARCHAR},
         address = #{address, jdbcType=VARCHAR},
         main_department = #{mainDepartment, jdbcType=VARCHAR},
         ext_attrs = #{extAttrs, jdbcType=VARCHAR},
         to_invite = #{toInvite, jdbcType=VARCHAR},
         external_position = #{externalPosition, jdbcType=VARCHAR},
         external_profile = #{externalProfile, jdbcType=VARCHAR},
         created_by = #{name, jdbcType=VARCHAR},
         created_date = #{createdBy, jdbcType=TIMESTAMP},
         updated_by = #{createdDate, jdbcType=VARCHAR},
         updated_date = #{updatedBy, jdbcType=TIMESTAMP},
        where user_id = #{updatedDate,jdbcType=VARCHAR}
    </update>
</mapper>

3.5 返回错误码的枚举类型

public enum ResultEnums {

    FAILED(507001, "service fail", "请求失败"),
    PARAMETERS_EMPTY(507002,"illegal params","参数传入有误"),
    GET_TOKEN_ERROR(507003, "get token error ", "获取token失败,请检查通行证等配置信息"),
    WX_ERROR(507004,"request wx api error","调用微信接口失败!请查看官方错误码表"),
    DB_ERROR(507005,"request db error", "对数据库进行写操作时出错!");

    private int code;
    private String msg;
    private String desc;

    ResultEnums(int code, String desc, String msg) {
        this.code = code;
        this.desc = desc;
        this.msg = msg;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }
    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }


}

业务实现类

package com.cxy.enterprise.wechat.service.impl;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cxy.enterprise.wechat.common.BusinessResponse;
import com.cxy.enterprise.wechat.common.WechatConstant;
import com.cxy.enterprise.wechat.dao.UserDao;
import com.cxy.enterprise.wechat.enums.ResultEnums;
import com.cxy.enterprise.wechat.pojo.po.UserPO;
import com.cxy.enterprise.wechat.pojo.vo.request.InviteUserVO;
import com.cxy.enterprise.wechat.pojo.vo.request.UserVO;
import com.cxy.enterprise.wechat.sao.GetTokenSao;
import com.cxy.enterprise.wechat.service.UserService;
import com.cxy.enterprise.wechat.util.HttpHelper;
import com.cxy.enterprise.wechat.util.LogUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;


@Service
public class UserServiceImpl implements UserService {

    public static final Logger logger = LogUtils.getLogger();

    @Resource
    private UserDao userDao;

    @Resource
    private HttpHelper httpHelper;

    @Resource
    private GetTokenSao getTokenSao;

    /**
     * 创建成员
     *
     * @param userVO
     * @return
     */
    @Transactional
    @Override
    public BusinessResponse createUser(UserVO userVO) throws Exception {

        //1.校验参数
        if (userVO.isMustFillEmpty()) {
            logger.warn("userVO cannot be blank:{}", userVO);
            return BusinessResponse.fail(ResultEnums.PARAMETERS_EMPTY.getCode(), ResultEnums.PARAMETERS_EMPTY.getMsg());
        }

        //2. 调用dao层在数据库创建用户
        UserPO userPO = new UserPO();
        userPO.setUserId(userVO.getUserid());
        userPO.setName(userVO.getName());
        userPO.setAlias(userVO.getAlias());
        userPO.setMobile(userVO.getMobile());
        userPO.setDepartIds(JSONArray.toJSONString(userVO.getDepartment()));
        userPO.setOrders(JSONArray.toJSONString(userVO.getOrder()));
        userPO.setGender(userVO.getGender());
        userPO.setEmail(userVO.getEmail());
        userPO.setIsLeaderInDept(JSONArray.toJSONString(userVO.getIs_leader_in_dept()));
        userPO.setEnable(userVO.getEnable());
        userPO.setAvatarMediaId(userVO.getAvatar_mediaid());
        userPO.setTelephone(userVO.getTelephone());
        userPO.setAddress(userVO.getAddress());
        userPO.setMainDepartment(userVO.getMain_department());
        userPO.setExtAttrs(JSONArray.toJSONString(userVO.getExtattr()));
        userPO.setToInvite(Boolean.toString(userVO.getTo_invite()));
        userPO.setExternalPosition(userVO.getExternal_position());
        userPO.setExternalProfile(JSONArray.toJSONString(userVO.getExternal_profile()));

        try {
            logger.info("insert db user.{}", userPO);
            userDao.createUser(userPO);
        } catch (Exception e) {
            logger.warn("insert db user error.{}", e.toString());
            return BusinessResponse.fail(ResultEnums.DB_ERROR.getCode(), ResultEnums.DB_ERROR.getMsg());
        }
        //2.获取token
        String accessToken = getTokenSao.getToken();
        //3. 封装url
        String url = WechatConstant.CREATE_USER_URL + accessToken;

        try {
            JSONObject jsonObject = httpHelper.post(url, userVO);
            if (jsonObject.getInteger(WechatConstant.ERR_CODE) == 0) {
                return BusinessResponse.ok(jsonObject.getString(WechatConstant.ERR_MSG));
            }else {
                logger.warn("request wx api error.{}",jsonObject.getString(WechatConstant.ERR_MSG));
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return BusinessResponse.fail(ResultEnums.WX_ERROR.getCode(), jsonObject.toString());
            }
        }catch (Exception e){
            logger.warn("http request error:{}", e.toString());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return BusinessResponse.fail(ResultEnums.FAILED.getCode(), ResultEnums.FAILED.getMsg());
        }
    }



    /**
     * 删除成员
     *
     * @param userId
     * @return
     */
    @Transactional
    @Override
    public BusinessResponse deleteUser(String userId) {
        //1. 调用dao层在数据库创建用户
        try {
            logger.info(userId);
            userDao.deleteUser(userId);
        }catch (Exception e){
            logger.warn("delete user in db error.{}",e.toString());
            return BusinessResponse.fail(ResultEnums.DB_ERROR.getCode(), ResultEnums.DB_ERROR.getDesc());
        }
        //2. 获取accessToken
        String accessToken = getTokenSao.getToken();
        //3. 封装url
        String url = WechatConstant.DELETE_USER_URL + accessToken + WechatConstant.USER_ID + userId;
        //4. 发送url请求
        try {
            logger.info("request url:{}", url);
            JSONObject jsonObject = httpHelper.get(url);
            //5. 判断调用微信接口时是否报错, 没有出错则返回响应信息
            if (jsonObject.getInteger(WechatConstant.ERR_CODE) == 0) {
                return BusinessResponse.ok(jsonObject.getString(WechatConstant.ERR_MSG));
            } else {
                logger.warn("request wx api error.{}",jsonObject.getString(WechatConstant.ERR_MSG));
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return BusinessResponse.fail(ResultEnums.WX_ERROR.getCode(), jsonObject.toString());
            }
        } catch (Exception e) {
            logger.warn("http request error:{}", e.toString());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return BusinessResponse.fail(ResultEnums.FAILED.getCode(), ResultEnums.FAILED.getMsg());
        }
    }

    /**
     * 更新成员
     *
     * @param userVO
     * @return
     */
    @Override
    public BusinessResponse updateUser(UserVO userVO) {
        //1.校验参数
        if (null == userVO) {
            logger.warn("userVO cannot be blank:{}", userVO);
            return BusinessResponse.fail(ResultEnums.PARAMETERS_EMPTY.getCode(), ResultEnums.PARAMETERS_EMPTY.getMsg());
        }
        //1. 调用dao层在数据库更新用户  (试试有哪些字段不能改)
        UserPO userPO = userDao.findUserById(userVO.getUserid());
        userPO.setName(userVO.getName());
        userPO.setAlias(userVO.getAlias());
        userPO.setMobile(userVO.getMobile());
        userPO.setDepartIds(JSONArray.toJSONString(userVO.getDepartment()));
        userPO.setOrders(JSONArray.toJSONString(userVO.getOrder()));
        userPO.setGender(userVO.getGender());
        userPO.setEmail(userVO.getEmail());
        userPO.setIsLeaderInDept(JSONArray.toJSONString(userVO.getIs_leader_in_dept()));
        userPO.setEnable(userVO.getEnable());
        userPO.setAvatarMediaId(userVO.getAvatar_mediaid());
        userPO.setTelephone(userVO.getTelephone());
        userPO.setAddress(userVO.getAddress());
        userPO.setMainDepartment(userVO.getMain_department());
        userPO.setExtAttrs(JSONArray.toJSONString(userVO.getExtattr()));
        userPO.setToInvite(Boolean.toString(userVO.getTo_invite()));
        userPO.setExternalPosition(userVO.getExternal_position());
        userPO.setExternalProfile(JSONArray.toJSONString(userVO.getExternal_profile()));
        try {
            userDao.updateUser(userPO);
        }catch (Exception e){
            return  BusinessResponse.fail(ResultEnums.DB_ERROR.getCode(), ResultEnums.DB_ERROR.getDesc());
        }
        //2. 获取accessToken
        String accessToken = getTokenSao.getToken();
        //3. 封装url
        String url = WechatConstant.UPDATE_USER_URL + accessToken;
        //4. 发送url请求
        try {
            logger.info("request url:{}", url);
            JSONObject jsonObject = httpHelper.post(url, userVO);
            //5. 判断调用微信接口时是否报错, 没有出错则返回响应信息
            if (jsonObject.getInteger(WechatConstant.ERR_CODE) == 0) {
                return BusinessResponse.ok(jsonObject.getString(WechatConstant.ERR_MSG));
            } else {
                logger.warn("request wx api error.{}",jsonObject.getString(WechatConstant.ERR_MSG));
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return BusinessResponse.fail(ResultEnums.WX_ERROR.getCode(), jsonObject.toString());
            }
        } catch (Exception e) {
            logger.warn("http request error:{}", e.toString());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return BusinessResponse.fail(ResultEnums.FAILED.getCode(), ResultEnums.FAILED.getMsg());
        }
    }

    /**
     * 根据id获取成员
     *
     * @param userId
     * @return
     */
    @Override
    public BusinessResponse getUserById(String userId) {
        //1.校验参数
        if (StringUtils.isBlank(userId)) {
            logger.warn("request parameter cannot be blank:{}", userId);
            return BusinessResponse.fail(ResultEnums.PARAMETERS_EMPTY.getCode(), ResultEnums.PARAMETERS_EMPTY.getMsg());
        }
        //2.获取token
        String accessToken = getTokenSao.getToken();

        //3.拼接url
        String url = WechatConstant.GET_USER_BY_ID_URL + accessToken + WechatConstant.USER_ID + userId;

        //4.发送url请求
        try {
            logger.info("request url:{}", url);
            JSONObject jsonObject = httpHelper.get(url);
            //5. 判断调用微信接口时是否报错, 没有出错则返回响应信息
            if (jsonObject.getInteger(WechatConstant.ERR_CODE) == 0) {
                return BusinessResponse.ok(jsonObject);
            } else {
                logger.warn("request wx api error.{}",jsonObject.getString(WechatConstant.ERR_MSG));
                return BusinessResponse.fail(ResultEnums.WX_ERROR.getCode(), jsonObject.toString());
            }
        } catch (Exception e) {
            logger.warn("http request error:{}", e.toString());
            return BusinessResponse.fail(ResultEnums.FAILED.getCode(), ResultEnums.FAILED.getMsg());
        }

        //1. 根据userid 获取 Json格式的user返回值结果(应该重新定义一个响应的UserRequestVO)
    }


    /**
     * 获取部门成员(一般情况下的精简信息)
     */


    /**
     * 获取部门成员详情
     *
     * @param deptId
     * @param fetchChild
     * @return
     */
    @Override
    public BusinessResponse listUserByDeptId(Long deptId, Long fetchChild) {
        //1.校验参数
        if (null == deptId) {
            logger.warn("request parameter cannot be blank:{}", deptId);
            return BusinessResponse.fail(ResultEnums.PARAMETERS_EMPTY.getCode(), ResultEnums.PARAMETERS_EMPTY.getMsg());
        }
        //2.获取token并拼接url
        String accessToken = getTokenSao.getToken();
        String url = WechatConstant.LIST_USER_BY_DEPARTMENT_ID_URL + accessToken + WechatConstant.DEPARTMENT_ID + deptId;

        //3.判断参数fetchChild是否为空来决定是否递归获取子部门的成员: 1.递归获取(不为空)  0.只获取本部门 (经测试为大于0的整数都可以递归获取成功)
        if (null != fetchChild && fetchChild != 0) {
            url = url + WechatConstant.FETCH_CHILD + fetchChild;
        }

        //4.发送url请求
        try {
            logger.info("request url: {}",url);
            JSONObject jsonObject = httpHelper.get(url);
            if (jsonObject.getInteger(WechatConstant.ERR_CODE) == 0) {
//                List<UserVO> userVOList = new ArrayList<>();
//                JSONArray userJSONArray = jsonObject.getJSONArray("userlist");

//                for (int i = 0; i < userJSONArray.size(); i++) {
//                    UserVO userVO = userJSONArray.getObject(i, UserVO.class);
//
//                    userVOList.add(userVO);
//                }
                //返回结果的data中只有用户列表
                return BusinessResponse.ok(jsonObject);
            } else {
                logger.warn("request wx api error.{}",jsonObject.getString(WechatConstant.ERR_MSG));
                return BusinessResponse.fail(ResultEnums.WX_ERROR.getCode(), jsonObject.toString());
            }

        } catch (Exception e) {
            logger.warn("http request error:{}", e.toString());
            return BusinessResponse.fail(ResultEnums.FAILED.getCode(), ResultEnums.FAILED.getMsg());
        }

    }

    @Override
    public BusinessResponse inviteUserBatch(InviteUserVO inviteUserVO) {
        //1.校验参数(貌似都可以为空,是发送给全体吗)

        //2.获取token
        String accessToken = getTokenSao.getToken();

        //3.拼接url
        String url = WechatConstant.INVITE_USER_BATCH + accessToken;

        //4.发送http请求
        try {
            logger.info("request wx api url: {}",url);
            JSONObject jsonObject = httpHelper.post(url,inviteUserVO);
            if (jsonObject.getInteger(WechatConstant.ERR_CODE) == 0) {
                return BusinessResponse.ok(jsonObject);
            } else {
                logger.warn("request wx api error.{}",jsonObject.getString(WechatConstant.ERR_MSG));
                return BusinessResponse.fail(ResultEnums.WX_ERROR.getCode(), jsonObject.toString());
            }
        }catch (Exception e){
            logger.warn("http request error:{}", e.toString());
            return BusinessResponse.fail(ResultEnums.FAILED.getCode(), ResultEnums.FAILED.getMsg());
        }
        //5.处理响应结果

        //7.考虑要不要把返回的信息保存到数据库(InviteResultVO)

    }

    @Override
    public BusinessResponse getJoinQrcode(String sizeType) {
        //2.获取token
        String accessToken = getTokenSao.getToken();

        //3.拼接url
        String url = WechatConstant.GET_JOIN_QRCODE + accessToken;
        if (null != sizeType){
            url = url + WechatConstant.SIZE_TYPE +sizeType;
        }

        //4.发送http请求
        try {
            logger.info("request wx api url: {}",url);
            JSONObject jsonObject = httpHelper.get(url);
            if (jsonObject.getInteger(WechatConstant.ERR_CODE) == 0) {
                return BusinessResponse.ok(jsonObject.getString(WechatConstant.JOIN_QRCODE));
            } else {
                logger.warn("request wx api error.{}",jsonObject.getString(WechatConstant.ERR_MSG));
                return BusinessResponse.fail(ResultEnums.WX_ERROR.getCode(), jsonObject.toString());
            }
        }catch (Exception e){
            logger.warn("http request error:{}", e.toString());
            return BusinessResponse.fail(ResultEnums.FAILED.getCode(), ResultEnums.FAILED.getMsg());
        }

    }


    //获取token
}

启动

package com.cxy.enterprise.wechat;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan(basePackages = "com.cxy.enterprise.wechat.dao")
public class SrvEnterpriseWechatApplication {

    public static void main(String[] args) {
        SpringApplication.run(SrvEnterpriseWechatApplication.class,args);
    }

}

测试

根据id查询用户
在这里插入图片描述

查看部门的成员列表
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

企业微信开发(通讯录模块) 的相关文章

  • Adobe illustrator2022(Ai2022)新增功能

    使用 Adobe Substa nce 材质添加纹理 使用 Substance 材质为图稿添加纹理 并创建逼真的 3D 图形 您可以添加自己的材质 也可以从数以千计的 Sub stance 材质资源中进行选择 无缝激活缺失字体 现在 您可以
  • md5 通用工具类

    目录 Java版本 js版本 简介 MD5加密工具类 效果展示 Java版本 import java security MessageDigest title java MD5工具类 author wanglei21 since 2023
  • 从零到一搭建Kconfig配置系统

    从零到一搭建Kconfig配置系统 背景说明 最早接触到Kconfig是在zephyr项目中 之后陆续知道linux和RT Thread等项目都是用Kconfig来管理编译的 而自己也陆续有大型项目开发需要 了解过后对其使用愈发感兴趣起来
  • 什么是计算卸载

    简言 为了应对终端设备处理能力不足 资源有限等问题 业界在移动边缘计算 MEC 中引入了计算卸载概念 边缘计算卸载即用户终端 UE 将计算任务卸载到MEC网络中 主要解决设备在资源存储 计算性能以及能效等方面的不足 0 1 背景 随着科技的
  • 中兴Blade V2021 5G 刷机root教程 ZTE 8012N root 线刷包下载TWRP 刷入

    中兴Blade V2021 5G 刷机root教程 ZTE 8012N root 线刷包下载TWRP 刷入 中兴 ZTE V2021 5G深空灰 6GB 128GB 全网通4800万高 手机 gt 中兴 gt 中兴Blade V2021 6
  • 【pta打印选课学生(python版) 基于python3.0】

    pta打印选课学生 python版 题目介绍 假设全校有最多40000名学生和最多2500门课程 现给出每个学生的选课清单 要求输出每门课的选课学生名单 输入格式 输入的第一行是两个正整数 N 40000 为全校学生总数 K 2500 为总
  • vditor编辑器上传视频方法详解

    此文章主要讲编辑器上传视频的方法 若想了解vditor更多更详细的使用方法可以参考vue中使用vditor 发布 编辑 详情回显 上传图片 粘贴图片回显问题 表情的处理 1 html div div 2 demo toolbar hotke
  • LINUX:开发中用得较多的一些操作

    目录文件相关 cd命令用来切换工作目录至dirname 其中dirName表示法可为绝对路径或相对路径 若目录名称省略 则变换至使用者的home directory 也就是刚login时所在的目录 另外 也表示为home directory
  • [记录]centos java mysql链接错误

    项目场景 CentOS 7 3 JDK openjdk version 1 8 0 302 Mysql 5 7 35 问题描述 数据库链接错误 Communications link failure Caused by javax net
  • Google Filament 源码学习(五):Material System (四) - 材质系统 API

    目录 Shader public APIs Introduction Types Math Matrices Frame constants Vertex only Fragment only Handling colors Linear
  • android开发图片分辨率

    一直受到android开发图片分辨率问题困扰 drawable xdpi hdpi mdpi ldpi nodpi 这几个文件夹到底怎么放图片呢 dpi是什么呢 dpi是 dot per inch 的缩写 每英寸像素数 四种密度分类 ldp
  • OpenCV人脸检测及识别(深度学习)

    简介 最近做了一个人脸检测以及识别的程序 很多的文章都有比较详细的叙述 可以自行查找 但是个人觉得大部分文章都太细致了以至于初学者无法快速领会主干 不是否认质量 是侧重点问题 所以结合我遇到了一些问题 现在做个总结 本文主要叙述实现的思路
  • Batch Processing

    在学习HOG SVM实现手写识别算法的过程中 看到对图片库文件夹提取文件名及标签的操作 即生成一个文本文件 按照文件名 标签的格式依次存储 为换行的意思 zaza Ji轻度强迫症 捣饬了半天才写出了个一行的批处理代码 我也是醉了 仅此留个纪
  • 如何实现apex的安装工作?

    1 具体的apex安装步骤 swav luanhaijing gpu02 extract swav feature git clone https github com ptrblck apex git Cloning into apex
  • VSCODE CMAKE C++ 工程调试, C++不以科学计数法输出并控制小数位数

    1 VSCODE调试CMAKE工程配置 1 1 修改CMakeLists txt文件 1 2 程序中 1 3 launch json配置 1 4 开始调试 1 5 注意 2 C 设置输出浮点数且保留位数固定 1 VSCODE调试CMAKE工
  • 通过 rqt_plot 完成ATI F/T 力和力矩传感器六轴数据可视化

    基于该篇博客https blog csdn net qq 34935373 article details 103481401 实现了通过ROS节点的方式启动ATI sensor 完成配置归零和设置软件矢量偏移 并且获取六轴数据 实时的打印
  • Linux:运行存在的可执行文件提示 No such file or directory

    1 前言 限于作者能力水平 本文可能存在谬误 因此而给读者带来的损失 作者不做任何承诺 2 背景 本文分析基于 linux 4 14 132 上游代码 运行环境为 Ubuntu 16 04 4 LTS QEMU Arm vexpress a
  • HTTP参数污染攻击

    服务器两层架构 服务器端有两个部分 第一部分为tomcat为引擎的jsp型服务器 第二部分为apache为引擎的php服务器 真正提供web服务器的是php服务器 工作流程为 client访问服务器能直接访问到tomcat服务器 然后tom
  • SQL注入系列之ASP+ACCESS手动注入(一)----数字型

    一 access数据库 1 简介 Microsoft Office Access是由微软发布的关系数据库管理系统 它结合了 MicrosoftJet Database Engine 和 图形用户界面两项特点 是 Microsoft Offi
  • 分类模块丨前端uniapp微信小程序项目

    小兔鲜儿 分类模块 用户点击左菜单的一级分类 切换右侧对应的二级分类和商品 准备工作 参考效果 商品分类页中的广告位 可复用之前定义的轮播图组件 XtxSwiper 静态结构 商品分类页静态结构 src pages category cat

随机推荐

  • 拷贝构造(深拷贝、浅拷贝)

    一 概念介绍 拷贝构造 拷贝构造函数 又称构造函数 是一种特殊的构造函数 它由编译器调用来完成一些基于同一类的其他对象的构造及初始化 其唯一的形参必须是引用 但并不限制为const 一般普遍的会加上const限制 在类中如果没有显式给出拷贝
  • avalon.js 转义html,avalon模块的内建适配器

    text bindings 第一个传参将强制转换为字符串 假值为 然后变成目标节点的innerText 今天的天气为 require ready more avalon function var viewModel myMessage ob
  • OpenLayer和JSTS空间相交应用

    getAreaData DrawGeometry level const that this 多边形绘制结束后获取空间几何数据传递 获取边界 const drawExtent DrawGeometry getExtent 实例化jsts c
  • [230517] TPO71

    7102 Minoan Palaces 目录 7102 Minoan Palaces 正文 题目 Paragraph 1 问题 1 Paragraph 2 问题 2 Paragraph 3 问题 3 4 Paragraph 4 问题 5 6
  • 极速搭建Hexo博客【 CentOS7 + Node.js + Hexo + Github Pages】

    Hexo是一款流行的博客框架 基于Node js 支持Markdown语法 这篇文章记录我如何完成搭建并部署到Github Pages上 创建虚拟环境 养成隔离项目环境的好习惯 python3 m venv venv blog 创建虚拟环境
  • 三相三线与三相四线计算公式

    三相三线与三相四线计算公式 项目 计算公式 备注 视在功率 S UI 有功功率 P 3UxIxcos 3ULILcos Ux 相电压 无功功率 Q 3UxIxsin 3ULILsin UL 线电压 功率因数 cos P S P UI 总视在
  • Linux系统开发

    一 实验目的 设计一款携带多种功能的聊天软件 不仅可以聊天 也能修改字体 计时 绘画等等 二 实验内容 1 ui设计 满分15分 2 画图 timer 多线程 满分20分 3 数据库操作 满分15分 4 TCP网络通信 满分40分 客户端1
  • 红队靶场搭建

    这篇博客主要是讲解一下vulstack红队评估的靶场 从信息收集到控制DMZ区域的WEB服务器 接着联合MSF和CS控制内网机器 随后通过搭建隧道 配置代理 攻击内网机器并且控制域控 主要讲解红队的攻击的全部流程 首先主要讲解一下靶场环境的
  • 几个汇编代码

    文章目录 输入输出 输出2 16进制 冒泡排序 判断正数负数零 以有符号数输出 输入输出 DATAS SEGMENT arr dw 20 dup num db 0 string1 db input the number of interge
  • 【Debug】关于Could not get lock /var/lib/dpkg/lock-frontend解决办法

    作者 柒号华仔 个人主页 欢迎访问我的主页 个人信条 星光不问赶路人 岁月不负有心人 个人方向 专注于5G领域 同时兼顾其他网络协议 编解码协议 C C linux等 感兴趣的小伙伴可以关注我 一起交流 目录 现象 原因 解决办法 现象 在
  • 前端js通过ajax请求下载Blob类型文件(XMLHttpRequest)

    方式一 必须通过原生ajax实现 jquery封装的ajax会有问题 function exportDevice params let xhr new XMLHttpRequest xhr open post http localhost
  • LORA项目源码解读

    大模型fineturn技术中类似于核武器的LORA 简单而又高效 其理论基础为 在将通用大模型迁移到具体专业领域时 仅需要对其高维参数的低秩子空间进行更新 基于该朴素的逻辑 LORA降低大模型的fineturn门槛 模型训练时不需要保存原始
  • 地球坐标,火星坐标,百度坐标转换

    标准地球坐标即GPS设备获得的坐标 该坐标需要经过国家测绘局进行加密后形成火星坐标 WGS 84 我们用的google坐标和高德地图坐标也就是火星坐标 百度地图 在火星坐标的基础上再进行一次加密 形成了百度地图上的坐标 因此 直接将标准地球
  • 电脑出现您的计算机配置似乎正确的,Win10提示你的计算机配置似乎是正确的怎么解决?...

    电脑使用久了总是会出现一些问题 最常见的就是系统提示了 相信不少用户都遇到过win10提示你的计算机配置似乎是正确的 但是又不知道怎么办 为此小编赶紧整理了以下教程帮助大家 大家赶紧来看看吧 访问 解决方法 1 首先进入桌面 按下 win
  • echarts自定义仪表盘实现特殊功能:轴线渐变(半透明) + 刻度颜色变化 + 仪表盘轴线宽度自适应

    如图是我画的两个仪表盘 第一个仪表盘 实现了 轴线渐变 半透明 刻度颜色变化 仪表盘轴线宽度自适应 第二个仪表盘 实现了 仪表盘轴线宽度自适应 关于轴线的渐变 本来打算使用img 但是由于此轴线是透明度渐变 不同位置透明度不一样 所以无法使
  • vue定时器无法停止。

    vue模板里面的定时器问题 文章目录 前言 一 定时器是什么 二 使用步骤 1 使用过程 2 读入数据 总结 前言 有些时候我们在使用vue模板时 不免会使用定时器来定时请求后台获取数据 但是在获取数据的时候 定时器就像踩不住刹车的小车 飘
  • Nuxt.js实现SSR的应用

    seo 即 搜索引擎优化 Search Engine Optimization 它是指通过站内优化 如 网站结构调整 网站内容建设 网站代码优化以及站外优化等方法 来进行搜索引擎优化 简单说 通过各种技术 手段 来确保 你的Web内容被搜素
  • 股海心法60条

    看不懂 看不准 没把握时坚决不进场 先学会做空 再学会做多 君子问凶不问吉 高手看盘先看跌 贪婪与恐惧 投资之大忌 侥幸是加大风险的罪魁 犹豫则是错失良机的祸首 心态第一 策略第二 技术只有屈居第三 任何时候不要轻易满仓 这样做 有利于保持
  • MySQL的多表关联查询

    一 多表关联查询 多表关联查询是使用一条SQL语句 将关联的多张表的数据查询出来 1 1 交叉查询 交叉查询就是将多张表的数据没有条件地连接在一起进行展示 1 1 1 语法 使用交叉查询类别和商品 目标 查询所有分类 以及每个分类下的所有商
  • 企业微信开发(通讯录模块)

    1 前言 关于企业微信通讯录同步的开发 先获取企业corpid 通讯录应用的secret 并在通讯录应用开启API编辑通讯录权限 2 关于token token是通过调用微信api接口由corpid和secret获取 由于token是每隔两