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查询用户
查看部门的成员列表