diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpCorpGroupService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpCorpGroupService.java new file mode 100644 index 0000000000..10665f7cdf --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpCorpGroupService.java @@ -0,0 +1,18 @@ +package me.chanjar.weixin.cp.api; + +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.bean.corpgroup.*; + +import java.util.List; + +/** + * @Project: WxJava + * @Package: me.chanjar.weixin.cp.api + * @Description: 企业互联相关接口 + * @Author: libo + * @Email: 422423229@qq.com + * @Date: 27/2/2023 9:57 PM + */ +public interface WxCpCorpGroupService { + List listAppShareInfo(Integer agentId,Integer businessType,String corpId,Integer limit,String cursor) throws WxErrorException; +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java index 2c38f6fc52..07400af53c 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java @@ -12,6 +12,7 @@ import me.chanjar.weixin.cp.bean.WxCpMaJsCode2SessionResult; import me.chanjar.weixin.cp.bean.WxCpProviderToken; import me.chanjar.weixin.cp.config.WxCpConfigStorage; +import me.chanjar.weixin.cp.corpgroup.service.WxCpLinkedCorpService; /** * 微信API的Service. @@ -569,4 +570,11 @@ public interface WxCpService extends WxService { * @return the meeting service */ WxCpMeetingService getMeetingService(); + + /** + * 企业互联的服务类对象 + * + * @return + */ + WxCpCorpGroupService getCorpGroupService(); } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/BaseWxCpServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/BaseWxCpServiceImpl.java index 752360003f..0d43145488 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/BaseWxCpServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/BaseWxCpServiceImpl.java @@ -24,6 +24,8 @@ import me.chanjar.weixin.cp.bean.WxCpMaJsCode2SessionResult; import me.chanjar.weixin.cp.bean.WxCpProviderToken; import me.chanjar.weixin.cp.config.WxCpConfigStorage; +import me.chanjar.weixin.cp.corpgroup.service.WxCpLinkedCorpService; +import me.chanjar.weixin.cp.corpgroup.service.impl.WxCpLinkedCorpServiceImpl; import org.apache.commons.lang3.StringUtils; import java.io.File; @@ -71,6 +73,7 @@ public abstract class BaseWxCpServiceImpl implements WxCpService, RequestH private WxCpExportService exportService = new WxCpExportServiceImpl(this); private final WxCpMeetingService meetingService = new WxCpMeetingServiceImpl(this); + private final WxCpCorpGroupService corpGroupService = new WxCpCorpGroupServiceImpl(this); /** * 全局的是否正在刷新access token的锁. @@ -672,4 +675,9 @@ public void setExportService(WxCpExportService exportService) { public WxCpMeetingService getMeetingService() { return meetingService; } + + @Override + public WxCpCorpGroupService getCorpGroupService() { + return corpGroupService; + } } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpCorpGroupServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpCorpGroupServiceImpl.java new file mode 100644 index 0000000000..bdc7724c7a --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpCorpGroupServiceImpl.java @@ -0,0 +1,48 @@ +package me.chanjar.weixin.cp.api.impl; + +import com.google.gson.JsonObject; +import com.google.gson.reflect.TypeToken; +import lombok.RequiredArgsConstructor; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.json.GsonParser; +import me.chanjar.weixin.cp.api.WxCpCorpGroupService; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.corpgroup.*; +import me.chanjar.weixin.cp.constant.WxCpApiPathConsts; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.util.List; + +import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.CorpGroup.*; +import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.LinkedCorp.GET_PERM_LIST; + +/** + * @Project: WxJava + * @Package: me.chanjar.weixin.cp.api.impl + * @Description: 企业互联相关接口实现类 + * @Author: libo + * @Email: 422423229@qq.com + * @Date: 27/2/2023 10:02 PM + */ +@RequiredArgsConstructor +public class WxCpCorpGroupServiceImpl implements WxCpCorpGroupService { + private final WxCpService cpService; + + @Override + public List listAppShareInfo(Integer agentId, Integer businessType, String corpId, Integer limit, String cursor) throws WxErrorException { + final String url = this.cpService.getWxCpConfigStorage().getApiUrl(LIST_SHARE_APP_INFO); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("agentid", agentId); + jsonObject.addProperty("corpid", corpId); + jsonObject.addProperty("business_type", businessType); + jsonObject.addProperty("limit", limit); + jsonObject.addProperty("cursor", cursor); + String responseContent = this.cpService.post(url, jsonObject); + JsonObject tmpJson = GsonParser.parse(responseContent); + + return WxCpGsonBuilder.create().fromJson(tmpJson.get("corp_list"), + new TypeToken>() { + }.getType() + ); + } +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/corpgroup/WxCpCorpGroupCorp.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/corpgroup/WxCpCorpGroupCorp.java new file mode 100644 index 0000000000..60ac1baeb2 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/corpgroup/WxCpCorpGroupCorp.java @@ -0,0 +1,43 @@ +package me.chanjar.weixin.cp.bean.corpgroup; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * @Project: WxJava + * @Package: me.chanjar.weixin.cp.bean.corpgroup + * @Description: 应用类 + * @Author: libo + * @Email: 422423229@qq.com + * @Date: 27/2/2023 9:50 PM + */ +@NoArgsConstructor +@Data +public class WxCpCorpGroupCorp implements Serializable { + + private static final long serialVersionUID = 6842919838272832415L; + @SerializedName("corpid") + private String corpid; + @SerializedName("corp_name") + private String corpName; + @SerializedName("agentid") + private Integer agentid; + + public static WxCpCorpGroupCorp fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpCorpGroupCorp.class); + } + + /** + * To json string. + * + * @return the string + */ + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/corpgroup/WxCpCorpGroupCorpGetTokenReq.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/corpgroup/WxCpCorpGroupCorpGetTokenReq.java new file mode 100644 index 0000000000..7ec97dd07d --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/corpgroup/WxCpCorpGroupCorpGetTokenReq.java @@ -0,0 +1,25 @@ +package me.chanjar.weixin.cp.bean.corpgroup; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; + +import java.io.Serializable; + +/** + * @Project: WxJava + * @Package: me.chanjar.weixin.cp.bean.corpgroup + * @Description: 获取下级/下游企业的access_token + * @Author: libo + * @Email: 422423229@qq.com + * @Date: 27/2/2023 9:07 PM + */ +@Data +public class WxCpCorpGroupCorpGetTokenReq implements Serializable { + private static final long serialVersionUID = -1876754768932436524L; + @SerializedName("corpid") + private String corpId; + @SerializedName("business_type") + private int businessType; + @SerializedName("agentid") + private int agentId; +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/corpgroup/WxCpCorpGroupCorpListAppShareInfoResp.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/corpgroup/WxCpCorpGroupCorpListAppShareInfoResp.java new file mode 100644 index 0000000000..eca424a8b6 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/corpgroup/WxCpCorpGroupCorpListAppShareInfoResp.java @@ -0,0 +1,27 @@ +package me.chanjar.weixin.cp.bean.corpgroup; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; + +import java.io.Serializable; +import java.util.List; + +/** + * @Project: WxJava + * @Package: me.chanjar.weixin.cp.bean.corpgroup + * @Description: 获取应用共享信息返回类 + * @Author: libo + * @Email: 422423229@qq.com + * @Date: 27/2/2023 9:02 PM + */ +@Data +public class WxCpCorpGroupCorpListAppShareInfoResp implements Serializable { + private static final long serialVersionUID = 7165788382879237583L; + @SerializedName("ending") + private int ending; + @SerializedName("corp_list") + private List corpList; + @SerializedName("next_cursor") + private String nextCursor; +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/corpgroup/WxCpCorpGroupCorpToken.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/corpgroup/WxCpCorpGroupCorpToken.java new file mode 100644 index 0000000000..86ec214005 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/corpgroup/WxCpCorpGroupCorpToken.java @@ -0,0 +1,38 @@ +package me.chanjar.weixin.cp.bean.corpgroup; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * @Project: WxJava + * @Package: me.chanjar.weixin.cp.bean.corpgroup + * @Description: 获取下级/下游企业的access_token返回类 + * @Author: libo + * @Email: 422423229@qq.com + * @Date: 27/2/2023 9:07 PM + */ +@Data +public class WxCpCorpGroupCorpToken implements Serializable { + private static final long serialVersionUID = -8139617060677460515L; + @SerializedName("access_token") + private String accessToken; + @SerializedName("expires_in") + private int expiresIn; + + public static WxCpCorpGroupCorpToken fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpCorpGroupCorpToken.class); + } + + /** + * To json string. + * + * @return the string + */ + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/corpgroup/WxCpMaTransferSession.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/corpgroup/WxCpMaTransferSession.java new file mode 100644 index 0000000000..91e42210d0 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/corpgroup/WxCpMaTransferSession.java @@ -0,0 +1,47 @@ +package me.chanjar.weixin.cp.bean.corpgroup; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.cp.bean.WxCpAgent; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * @Project: WxJava + * @Package: me.chanjar.weixin.cp.bean.corpgroup + * @Description: 获取下级/下游企业小程序session返回类 + * @Author: libo + * @Email: 422423229@qq.com + * @Date: 27/2/2023 9:10 PM + */ +@Data +public class WxCpMaTransferSession implements Serializable { + + private static final long serialVersionUID = 4189407986285166516L; + @SerializedName("userid") + private String userId; + @SerializedName("session_key") + private String sessionKey; + + + /** + * From json WxCpMaTransferSession. + * + * @param json the json + * @return the WxCpMaTransferSession + */ + public static WxCpMaTransferSession fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpMaTransferSession.class); + } + + /** + * To json string. + * + * @return the string + */ + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/linkedcorp/WxCpLinkedCorpAgentPerm.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/linkedcorp/WxCpLinkedCorpAgentPerm.java new file mode 100644 index 0000000000..87b9e8d945 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/linkedcorp/WxCpLinkedCorpAgentPerm.java @@ -0,0 +1,23 @@ +package me.chanjar.weixin.cp.bean.linkedcorp; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; + +import java.io.Serializable; + +/** + * @Project: WxJava + * @Package: me.chanjar.weixin.cp.bean.linkedcorp + * @Description: 获取应用可见范围请求类 + * @Author: libo + * @Email: 422423229@qq.com + * @Date: 28/2/2023 6:16 PM + */ +@Data +public class WxCpLinkedCorpAgentPerm implements Serializable { + private static final long serialVersionUID = 6794613362541093845L; + @SerializedName("userids") + private String[] userIdList; + @SerializedName("department_ids") + private String[] departmentIdList; +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/linkedcorp/WxCpLinkedCorpDepartment.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/linkedcorp/WxCpLinkedCorpDepartment.java new file mode 100644 index 0000000000..ca5a28d2ec --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/linkedcorp/WxCpLinkedCorpDepartment.java @@ -0,0 +1,33 @@ +package me.chanjar.weixin.cp.bean.linkedcorp; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * @Project: WxJava + * @Package: me.chanjar.weixin.cp.bean.linkedcorp + * @Description: 获取互联企业部门列表 + * @Author: libo + * @Email: 422423229@qq.com + * @Date: 28/2/2023 6:16 PM + */ +@Data +public class WxCpLinkedCorpDepartment implements Serializable { + private static final long serialVersionUID = -210249269343292440L; + @SerializedName("department_id") + private String departmentId; + @SerializedName("department_name") + private String departmentName; + @SerializedName("parentid") + private String parentId; + @SerializedName("order") + private Integer order; +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/linkedcorp/WxCpLinkedCorpUser.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/linkedcorp/WxCpLinkedCorpUser.java new file mode 100644 index 0000000000..c1948e557e --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/linkedcorp/WxCpLinkedCorpUser.java @@ -0,0 +1,64 @@ +package me.chanjar.weixin.cp.bean.linkedcorp; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.bean.WxCpUser; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * @Project: WxJava + * @Package: me.chanjar.weixin.cp.bean.linkedcorp + * @Description: 获取互联企业成员详细信息 + * @Author: libo + * @Email: 422423229@qq.com + * @Date: 28/2/2023 6:16 PM + */ +@Data +public class WxCpLinkedCorpUser implements Serializable { + private static final long serialVersionUID = -5197865724556226531L; + @SerializedName("userid") + private String userId; + @SerializedName("name") + private String name; + @SerializedName("department") + private String[] department; + @SerializedName("mobile") + private String mobile; + @SerializedName("email") + private String email; + @SerializedName("position") + private String position; + @SerializedName("corpid") + private String corpId; + private final List extAttrs = new ArrayList<>(); + + /** + * The type Attr. + */ + @Data + @Accessors(chain = true) + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class Attr implements Serializable { + private static final long serialVersionUID = -5696099236344075582L; + + /** + * 属性类型: 0-文本 1-网页 + */ + private Integer type; + private String name; + private String textValue; + private String webUrl; + private String webTitle; + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpCorpGroupConfigStorage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpCorpGroupConfigStorage.java new file mode 100644 index 0000000000..5fa87500e5 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpCorpGroupConfigStorage.java @@ -0,0 +1,148 @@ +package me.chanjar.weixin.cp.config; + +import me.chanjar.weixin.common.bean.WxAccessToken; +import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; +import me.chanjar.weixin.cp.bean.WxCpProviderToken; + +import java.io.File; +import java.util.concurrent.locks.Lock; + +/** + * @Project: WxJava + * @Package: me.chanjar.weixin.cp.config + * @Description: 微信客户端(企业互联)配置 + * @or: libo + * @Email: 422423229@qq.com + * @Date: 1/3/2023 9:56 AM + */ +public interface WxCpCorpGroupConfigStorage { + /** + * 设置企业微信服务器 baseUrl. + * 默认值是 https://qyapi.weixin.qq.com , 如果使用默认值,则不需要调用 setBaseApiUrl + * + * @param baseUrl 企业微信服务器 Url + */ + void setBaseApiUrl(String baseUrl); + + /** + * 读取企业微信 API Url. + * 支持私有化企业微信服务器. + * + * @param path the path + * @return the api url + */ + String getApiUrl(String path); + + /** + * Update corp access token. + * + * @param corpId + * @param agentId + * @param corpAccessToken the corp access token + * @param expiresInSeconds the expires in seconds + */ + void updateCorpAccessToken(String corpId, Integer agentId, String corpAccessToken, int expiresInSeconds); + + /** + * 授权企业的access token相关 + * + * @param corpId the corp id + * @param agentId + * @return the access token + */ + String getCorpAccessToken(String corpId, Integer agentId); + + /** + * Gets access token entity. + * + * @param corpId the corp id + * @param agentId + * @return the access token entity + */ + WxAccessToken getCorpAccessTokenEntity(String corpId, Integer agentId); + + /** + * Is access token expired boolean. + * + * @param corpId the corp id + * @param agentId + * @return the boolean + */ + boolean isCorpAccessTokenExpired(String corpId, Integer agentId); + + /** + * Expire access token. + * + * @param corpId the corp id + * @param agentId + */ + void expireCorpAccessToken(String corpId, Integer agentId); + + /** + * 网络代理相关 + * + * @return the http proxy host + */ + String getHttpProxyHost(); + + /** + * Gets http proxy port. + * + * @return the http proxy port + */ + int getHttpProxyPort(); + + /** + * Gets http proxy username. + * + * @return the http proxy username + */ + String getHttpProxyUsername(); + + /** + * Gets http proxy password. + * + * @return the http proxy password + */ + String getHttpProxyPassword(); + + /** + * Gets apache http client builder. + * + * @return the apache http client builder + */ + ApacheHttpClientBuilder getApacheHttpClientBuilder(); + + /** + * Auto refresh token boolean. + * + * @return the boolean + */ + boolean autoRefreshToken(); + + /** + * Gets access token lock. + * + * @param corpId the corp id + * @return the access token lock + */ + Lock getCorpAccessTokenLock(String corpId, Integer agentId); + + void setCorpId(String corpId); + + void setAgentId(Integer agentId); + + /** + * Gets corp id. + * + * @return the corp id + */ + String getCorpId(); + + /** + * Gets agent id. + * + * @return the agent id + */ + Integer getAgentId(); +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/WxCpCorpGroupDefaultConfigImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/WxCpCorpGroupDefaultConfigImpl.java new file mode 100644 index 0000000000..056f911bd9 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/WxCpCorpGroupDefaultConfigImpl.java @@ -0,0 +1,203 @@ +package me.chanjar.weixin.cp.config.impl; + +import me.chanjar.weixin.common.bean.WxAccessToken; +import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; +import me.chanjar.weixin.cp.config.WxCpConfigStorage; +import me.chanjar.weixin.cp.config.WxCpCorpGroupConfigStorage; +import org.apache.commons.lang3.StringUtils; + +import java.io.File; +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * @Project: WxJava + * @Package: me.chanjar.weixin.cp.config.impl + * @Description: 基于内存的微信配置provider,在实际生产环境中应该将这些配置持久化. + * @Author: libo + * @Email: 422423229@qq.com + * @Date: 1/3/2023 10:30 AM + */ +public class WxCpCorpGroupDefaultConfigImpl implements WxCpCorpGroupConfigStorage, Serializable { + private final transient Map corpAccessTokenLocker = new ConcurrentHashMap<>(); + + private final Map corpAccessTokenMap = new HashMap<>(); + private final Map corpAccessTokenExpireTimeMap = new HashMap<>(); + + private volatile String httpProxyHost; + private volatile int httpProxyPort; + private volatile String httpProxyUsername; + private volatile String httpProxyPassword; + private volatile ApacheHttpClientBuilder apacheHttpClientBuilder; + private volatile String baseApiUrl; + + /** + * 微信企业号 corpId + */ + private volatile String corpId; + /** + * 微信企业号应用 ID + */ + private volatile Integer agentId; + + @Override + public void setBaseApiUrl(String baseUrl) { + this.baseApiUrl = baseUrl; + } + + @Override + public String getApiUrl(String path) { + if (baseApiUrl == null) { + baseApiUrl = "https://qyapi.weixin.qq.com"; + } + return baseApiUrl + path; + } + + @Override + public String getCorpId() { + return corpId; + } + + @Override + public void setCorpId(String corpId) { + this.corpId = corpId; + } + + @Override + public Integer getAgentId() { + return agentId; + } + + @Override + public void setAgentId(Integer agentId) { + this.agentId = agentId; + } + + @Override + public void updateCorpAccessToken(String corpId, Integer agentId, String corpAccessToken, int expiresInSeconds) { + String key = generateAccessTokenKey(corpId, agentId); + corpAccessTokenMap.put(key, corpAccessToken); + //预留200秒的时间 + corpAccessTokenExpireTimeMap.put(key, System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L); + } + + @Override + public String getCorpAccessToken(String corpId, Integer agentId) { + return this.corpAccessTokenMap.get(generateAccessTokenKey(corpId, agentId)); + } + + @Override + public WxAccessToken getCorpAccessTokenEntity(String corpId, Integer agentId) { + String key = generateAccessTokenKey(corpId, agentId); + String accessToken = corpAccessTokenMap.getOrDefault(key, StringUtils.EMPTY); + Long expire = corpAccessTokenExpireTimeMap.getOrDefault(key, 0L); + WxAccessToken accessTokenEntity = new WxAccessToken(); + accessTokenEntity.setAccessToken(accessToken); + accessTokenEntity.setExpiresIn((int) ((expire - System.currentTimeMillis()) / 1000 + 200)); + return accessTokenEntity; + } + + @Override + public boolean isCorpAccessTokenExpired(String corpId, Integer agentId) { + //不存在或者过期 + String key = generateAccessTokenKey(corpId, agentId); + return corpAccessTokenExpireTimeMap.get(key) == null + || System.currentTimeMillis() > corpAccessTokenExpireTimeMap.get(key); + } + + @Override + public void expireCorpAccessToken(String corpId, Integer agentId) { + String key = generateAccessTokenKey(corpId, agentId); + corpAccessTokenMap.remove(key); + corpAccessTokenExpireTimeMap.remove(key); + } + + @Override + public String getHttpProxyHost() { + return this.httpProxyHost; + } + + /** + * Sets http proxy host. + * + * @param httpProxyHost the http proxy host + */ + public void setHttpProxyHost(String httpProxyHost) { + this.httpProxyHost = httpProxyHost; + } + + @Override + public int getHttpProxyPort() { + return this.httpProxyPort; + } + + /** + * Sets http proxy port. + * + * @param httpProxyPort the http proxy port + */ + public void setHttpProxyPort(int httpProxyPort) { + this.httpProxyPort = httpProxyPort; + } + + @Override + public String getHttpProxyUsername() { + return this.httpProxyUsername; + } + + /** + * Sets http proxy username. + * + * @param httpProxyUsername the http proxy username + */ + public void setHttpProxyUsername(String httpProxyUsername) { + this.httpProxyUsername = httpProxyUsername; + } + + @Override + public String getHttpProxyPassword() { + return this.httpProxyPassword; + } + + /** + * Sets http proxy password. + * + * @param httpProxyPassword the http proxy password + */ + public void setHttpProxyPassword(String httpProxyPassword) { + this.httpProxyPassword = httpProxyPassword; + } + + @Override + public ApacheHttpClientBuilder getApacheHttpClientBuilder() { + return this.apacheHttpClientBuilder; + } + + /** + * Sets apache http client builder. + * + * @param apacheHttpClientBuilder the apache http client builder + */ + public void setApacheHttpClientBuilder(ApacheHttpClientBuilder apacheHttpClientBuilder) { + this.apacheHttpClientBuilder = apacheHttpClientBuilder; + } + + @Override + public boolean autoRefreshToken() { + return true; + } + + @Override + public Lock getCorpAccessTokenLock(String corpId, Integer agentId) { + return this.corpAccessTokenLocker + .computeIfAbsent(generateAccessTokenKey(corpId, agentId), key -> new ReentrantLock()); + } + + private String generateAccessTokenKey(String corpId, Integer agentId) { + return String.join(":", this.corpId, String.valueOf(this.agentId), corpId, String.valueOf(agentId)); + } +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/WxCpCorpGroupRedissonConfigImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/WxCpCorpGroupRedissonConfigImpl.java new file mode 100644 index 0000000000..94111229ef --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/WxCpCorpGroupRedissonConfigImpl.java @@ -0,0 +1,222 @@ +package me.chanjar.weixin.cp.config.impl; + +import lombok.Builder; +import lombok.NonNull; +import lombok.Setter; +import me.chanjar.weixin.common.bean.WxAccessToken; +import me.chanjar.weixin.common.redis.WxRedisOps; +import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; +import me.chanjar.weixin.cp.bean.WxCpProviderToken; +import me.chanjar.weixin.cp.config.WxCpCorpGroupConfigStorage; +import org.apache.commons.lang3.StringUtils; + +import java.io.Serializable; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * @Project: WxJava + * @Package: me.chanjar.weixin.cp.config.impl + * @Description: 企业微信企业互联各种固定、授权配置的Redisson存储实现 + * @Author: libo + * @Email: 422423229@qq.com + * @Date: 1/3/2023 10:48 AM + */ +@Builder +public class WxCpCorpGroupRedissonConfigImpl implements WxCpCorpGroupConfigStorage, Serializable { + private final transient Map corpAccessTokenLocker = new ConcurrentHashMap<>(); + + /** + * The constant LOCK_KEY. + */ + protected static final String LOCK_KEY = "wechat_cg_lock:"; + /** + * The constant LOCKER_CORP_ACCESS_TOKEN. + */ + protected static final String LOCKER_CORP_ACCESS_TOKEN = "corpAccessTokenLock"; + /** + * The constant CG_ACCESS_TOKEN_KEY. + */ + protected static final String CG_ACCESS_TOKEN_KEY = "wechat_cg_access_token_key:"; + @NonNull + private final WxRedisOps wxRedisOps; + /** + * redis里面key的统一前缀 + */ + @Setter + private String keyPrefix = ""; + + private volatile String httpProxyHost; + private volatile int httpProxyPort; + private volatile String httpProxyUsername; + private volatile String httpProxyPassword; + private volatile ApacheHttpClientBuilder apacheHttpClientBuilder; + private volatile String baseApiUrl; + /** + * 微信企业号 corpId + */ + private volatile String corpId; + /** + * 微信企业号应用 ID + */ + private volatile Integer agentId; + + @Override + public void setBaseApiUrl(String baseUrl) { + this.baseApiUrl = baseUrl; + } + + @Override + public String getApiUrl(String path) { + if (baseApiUrl == null) { + baseApiUrl = "https://qyapi.weixin.qq.com"; + } + return baseApiUrl + path; + } + + @Override + public String getCorpId() { + return corpId; + } + + @Override + public void setCorpId(String corpId) { + this.corpId = corpId; + } + + @Override + public Integer getAgentId() { + return agentId; + } + + @Override + public void setAgentId(Integer agentId) { + this.agentId = agentId; + } + + @Override + public void updateCorpAccessToken(String corpId, Integer agentId, String corpAccessToken, int expiresInSeconds) { + wxRedisOps.setValue(generateAccessTokenKey(corpId, agentId), corpAccessToken, expiresInSeconds, TimeUnit.SECONDS); + } + + @Override + public String getCorpAccessToken(String corpId, Integer agentId) { + return wxRedisOps.getValue(generateAccessTokenKey(corpId, agentId)); + } + + @Override + public WxAccessToken getCorpAccessTokenEntity(String corpId, Integer agentId) { + String key = generateAccessTokenKey(corpId, agentId); + String accessToken = wxRedisOps.getValue(key); + Long expire = wxRedisOps.getExpire(key); + if (StringUtils.isBlank(accessToken) || expire == null || expire == 0 || expire == -2) { + return new WxAccessToken(); + } + WxAccessToken accessTokenEntity = new WxAccessToken(); + accessTokenEntity.setAccessToken(accessToken); + accessTokenEntity.setExpiresIn(Math.max(Math.toIntExact(expire), 0)); + return accessTokenEntity; + } + + @Override + public boolean isCorpAccessTokenExpired(String corpId, Integer agentId) { + String key = generateAccessTokenKey(corpId, agentId); + return wxRedisOps.getExpire(key) == 0L || wxRedisOps.getExpire(key) == -2; + } + + @Override + public void expireCorpAccessToken(String corpId, Integer agentId) { + wxRedisOps.expire(generateAccessTokenKey(corpId, agentId), 0, TimeUnit.SECONDS); + } + + @Override + public String getHttpProxyHost() { + return this.httpProxyHost; + } + + /** + * Sets http proxy host. + * + * @param httpProxyHost the http proxy host + */ + public void setHttpProxyHost(String httpProxyHost) { + this.httpProxyHost = httpProxyHost; + } + + @Override + public int getHttpProxyPort() { + return this.httpProxyPort; + } + + /** + * Sets http proxy port. + * + * @param httpProxyPort the http proxy port + */ + public void setHttpProxyPort(int httpProxyPort) { + this.httpProxyPort = httpProxyPort; + } + + @Override + public String getHttpProxyUsername() { + return this.httpProxyUsername; + } + + /** + * Sets http proxy username. + * + * @param httpProxyUsername the http proxy username + */ + public void setHttpProxyUsername(String httpProxyUsername) { + this.httpProxyUsername = httpProxyUsername; + } + + @Override + public String getHttpProxyPassword() { + return this.httpProxyPassword; + } + + /** + * Sets http proxy password. + * + * @param httpProxyPassword the http proxy password + */ + public void setHttpProxyPassword(String httpProxyPassword) { + this.httpProxyPassword = httpProxyPassword; + } + + @Override + public ApacheHttpClientBuilder getApacheHttpClientBuilder() { + return this.apacheHttpClientBuilder; + } + + /** + * Sets apache http client builder. + * + * @param apacheHttpClientBuilder the apache http client builder + */ + public void setApacheHttpClientBuilder(ApacheHttpClientBuilder apacheHttpClientBuilder) { + this.apacheHttpClientBuilder = apacheHttpClientBuilder; + } + + @Override + public boolean autoRefreshToken() { + return true; + } + + @Override + public Lock getCorpAccessTokenLock(String corpId, Integer agentId) { + return this.getLockByKey(String.join(":", corpId, String.valueOf(agentId), LOCKER_CORP_ACCESS_TOKEN)); + } + + private String generateAccessTokenKey(String corpId, Integer agentId) { + return String.join(":", keyPrefix, CG_ACCESS_TOKEN_KEY, corpId, String.valueOf(agentId)); + } + + private Lock getLockByKey(String key) { + return this.wxRedisOps.getLock(String.join(":", keyPrefix, LOCK_KEY, key)); + } +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java index c592682afa..5ffcee7ddb 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java @@ -72,12 +72,6 @@ interface Message { */ String GET_STATISTICS = "/cgi-bin/message/get_statistics"; - /** - * 互联企业发送应用消息 - * https://developer.work.weixin.qq.com/document/path/90250 - */ - String LINKEDCORP_MESSAGE_SEND = "/cgi-bin/linkedcorp/message/send"; - /** * 发送「学校通知」 * https://developer.work.weixin.qq.com/document/path/92321 @@ -90,6 +84,12 @@ interface Message { */ String MESSAGE_RECALL = "/cgi-bin/message/recall"; + /** + * 互联企业发送应用消息 + * https://developer.work.weixin.qq.com/document/path/90250 + */ + String LINKEDCORP_MESSAGE_SEND = "/cgi-bin/linkedcorp/message/send"; + } /** @@ -826,12 +826,12 @@ interface Tp { */ String GET_ADMIN_LIST = "/cgi-bin/service/get_admin_list"; /** - * The constant GET_APP_QRCODE. + * The constant GET_APP_QRCODE. */ String GET_APP_QRCODE = "/cgi-bin/service/get_app_qrcode"; /** - * The constant CORPID_TO_OPENCORPID. + * The constant CORPID_TO_OPENCORPID. */ String CORPID_TO_OPENCORPID = "/cgi-bin/service/corpid_to_opencorpid"; @@ -1400,4 +1400,55 @@ interface Export { */ String GET_RESULT = "/cgi-bin/export/get_result?jobid=%s"; } + + interface CorpGroup { + /** + * 获取应用共享信息 + * https://developer.work.weixin.qq.com/document/path/93403 + */ + String LIST_SHARE_APP_INFO = "/cgi-bin/corpgroup/corp/list_app_share_info"; + /** + * 获取下级/下游企业的access_token + * https://developer.work.weixin.qq.com/document/path/93359 + */ + String CORP_GET_TOKEN = "/cgi-bin/corpgroup/corp/gettoken"; + /** + * 获取下级/下游企业小程序session + * https://developer.work.weixin.qq.com/document/path/93355 + */ + String MA_TRANSFER_SESSION = "/cgi-bin/miniprogram/transfer_session"; + } + + interface LinkedCorp { + /** + * 获取应用的可见范围 + * https://developer.work.weixin.qq.com/document/path/93172 + */ + String GET_PERM_LIST = "/cgi-bin/linkedcorp/agent/get_perm_list"; + /** + * 获取互联企业成员详细信息 + * https://developer.work.weixin.qq.com/document/path/93171 + */ + String GET_USER = "/cgi-bin/linkedcorp/user/get"; + /** + * 获取互联企业部门成员 + * https://developer.work.weixin.qq.com/document/path/93168 + */ + String GET_USER_SIMPLELIST = "/cgi-bin/linkedcorp/user/simplelist"; + /** + * 获取互联企业部门成员详情 + * https://developer.work.weixin.qq.com/document/path/93169 + */ + String GET_USER_LIST = "/cgi-bin/linkedcorp/user/list"; + /** + * 获取互联企业部门列表 + * https://developer.work.weixin.qq.com/document/path/93170 + */ + String GET_DEPARTMENT_LIST = "/cgi-bin/linkedcorp/department/list"; + /** + * 发送应用消息 + * https://developer.work.weixin.qq.com/document/path/90250 + */ + String SENG_MESSAGE="/cgi-bin/linkedcorp/message/send"; + } } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/corpgroup/service/WxCpCgService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/corpgroup/service/WxCpCgService.java new file mode 100644 index 0000000000..c0c058abab --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/corpgroup/service/WxCpCgService.java @@ -0,0 +1,174 @@ +package me.chanjar.weixin.cp.corpgroup.service; + +import me.chanjar.weixin.common.bean.WxAccessToken; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.corpgroup.WxCpCorpGroupCorpGetTokenReq; +import me.chanjar.weixin.cp.bean.corpgroup.WxCpMaTransferSession; +import me.chanjar.weixin.cp.config.WxCpCorpGroupConfigStorage; + +/** + * @Project: WxJava + * @Package: me.chanjar.weixin.cp.corpgroup.service + * @Description: 企业微信企业互联API的Service. + * @Author: libo + * @Email: 422423229@qq.com + * @Date: 1/3/2023 5:37 PM + */ +public interface WxCpCgService { + /** + * Update corp access token. + * + * @param corpId + * @param agentId + * @param corpAccessToken the corp access token + * @param expiresInSeconds the expires in seconds + */ + void updateCorpAccessToken(String corpId, Integer agentId, String corpAccessToken, int expiresInSeconds); + + String getCorpAccessToken(String corpId, Integer agentId, Integer businessType) throws WxErrorException; + + String getCorpAccessToken(String corpId, Integer agentId, Integer businessType, boolean forceRefresh) throws WxErrorException; + + /** + * 授权企业的access token相关 + * + * @param corpId the corp id + * @param agentId + * @param businessType + * @return the access token + */ + WxAccessToken getCorpAccessTokenEntity(String corpId, Integer agentId, Integer businessType) throws WxErrorException; + + /** + * Gets access token entity. + * + * @param corpId the corp id + * @param agentId + * @param businessType + * @return the access token entity + */ + WxAccessToken getCorpAccessTokenEntity(String corpId, Integer agentId, Integer businessType, boolean forceRefresh) throws WxErrorException; + + /** + * Is access token expired boolean. + * + * @param corpId the corp id + * @param agentId + * @return the boolean + */ + boolean isCorpAccessTokenExpired(String corpId, Integer agentId); + + /** + * Expire access token. + * + * @param corpId the corp id + * @param agentId + */ + void expireCorpAccessToken(String corpId, Integer agentId); + + /** + * 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的GET请求. + * + * @param url 接口地址 + * @param queryParam 请求参数 + * @return the string + * @throws WxErrorException the wx error exception + */ + String get(String url, String queryParam, WxCpCorpGroupCorpGetTokenReq req) throws WxErrorException; + + /** + * 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的GET请求. + * + * @param url 接口地址 + * @param queryParam 请求参数 + * @param withoutCorpAccessToken 请求是否忽略CorpAccessToken 默认不忽略-false + * @return the string + * @throws WxErrorException the wx error exception + */ + String get(String url, String queryParam, boolean withoutCorpAccessToken, WxCpCorpGroupCorpGetTokenReq req) throws WxErrorException; + + /** + * 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的POST请求. + * + * @param url 接口地址 + * @param postData 请求body字符串 + * @return the string + * @throws WxErrorException the wx error exception + */ + String post(String url, String postData, WxCpCorpGroupCorpGetTokenReq req) throws WxErrorException; + + /** + *
+   * Service没有实现某个API的时候,可以用这个,
+   * 比{@link #get}和{@link #post}方法更灵活,可以自己构造RequestExecutor用来处理不同的参数和不同的返回类型。
+   * 可以参考,{@link MediaUploadRequestExecutor}的实现方法
+   * 
+ * + * @param 请求值类型 + * @param 返回值类型 + * @param executor 执行器 + * @param uri 请求地址 + * @param data 参数 + * @return the t + * @throws WxErrorException the wx error exception + */ + T execute(RequestExecutor executor, String uri, E data, WxCpCorpGroupCorpGetTokenReq req) throws WxErrorException; + + /** + *
+   * 设置当微信系统响应系统繁忙时,要等待多少 retrySleepMillis(ms) * 2^(重试次数 - 1) 再发起重试.
+   * 默认:1000ms
+   * 
+ * + * @param retrySleepMillis 重试休息时间 + */ + void setRetrySleepMillis(int retrySleepMillis); + + /** + *
+   * 设置当微信系统响应系统繁忙时,最大重试次数.
+   * 默认:5次
+   * 
+ * + * @param maxRetryTimes 最大重试次数 + */ + void setMaxRetryTimes(int maxRetryTimes); + + /** + * 初始化http请求对象 + */ + void initHttp(); + + void setWxCpCorpGroupConfigStorage(WxCpCorpGroupConfigStorage wxCpCorpGroupConfigStorage); + + WxCpCorpGroupConfigStorage getWxCpCorpGroupConfigStorage(); + /** + * http请求对象. + * + * @return the request http + */ + RequestHttp getRequestHttp(); + + void setWxCpService(WxCpService wxCpService); + + /** + * 互联企业的服务类对象 + * + * @return + */ + WxCpLinkedCorpService getLinkedCorpService(); + + /** + * 获取下级/下游企业小程序session + * https://developer.work.weixin.qq.com/document/path/93355 + * @param userId + * @param sessionKey + * @return + * @throws WxErrorException + */ + WxCpMaTransferSession getCorpTransferSession(String userId, String sessionKey,WxCpCorpGroupCorpGetTokenReq req) throws WxErrorException; +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/corpgroup/service/WxCpLinkedCorpService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/corpgroup/service/WxCpLinkedCorpService.java new file mode 100644 index 0000000000..473e2ce923 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/corpgroup/service/WxCpLinkedCorpService.java @@ -0,0 +1,30 @@ +package me.chanjar.weixin.cp.corpgroup.service; + +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.bean.corpgroup.*; +import me.chanjar.weixin.cp.bean.linkedcorp.WxCpLinkedCorpAgentPerm; +import me.chanjar.weixin.cp.bean.linkedcorp.WxCpLinkedCorpDepartment; +import me.chanjar.weixin.cp.bean.linkedcorp.WxCpLinkedCorpUser; + +import java.util.List; + +/** + * @Project: WxJava + * @Package: me.chanjar.weixin.cp.api + * @Description: 互联企业相关接口 + * @Author: libo + * @Email: 422423229@qq.com + * @Date: 27/2/2023 9:57 PM + */ +public interface WxCpLinkedCorpService { + WxCpLinkedCorpAgentPerm getLinkedCorpAgentPerm(WxCpCorpGroupCorpGetTokenReq req) throws WxErrorException; + + WxCpLinkedCorpUser getLinkedCorpUser(String userId,WxCpCorpGroupCorpGetTokenReq req) throws WxErrorException; + + List getLinkedCorpSimpleUserList(String departmentId,WxCpCorpGroupCorpGetTokenReq req) throws WxErrorException; + + List getLinkedCorpUserList(String departmentId,WxCpCorpGroupCorpGetTokenReq req) throws WxErrorException; + + List getLinkedCorpDepartmentList(String departmentId,WxCpCorpGroupCorpGetTokenReq req) throws WxErrorException; + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/corpgroup/service/impl/BaseWxCpCgServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/corpgroup/service/impl/BaseWxCpCgServiceImpl.java new file mode 100644 index 0000000000..c431b7c3d9 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/corpgroup/service/impl/BaseWxCpCgServiceImpl.java @@ -0,0 +1,300 @@ +package me.chanjar.weixin.cp.corpgroup.service.impl; + +import com.google.gson.JsonObject; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.bean.WxAccessToken; +import me.chanjar.weixin.common.enums.WxType; +import me.chanjar.weixin.common.error.WxCpErrorMsgEnum; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.error.WxRuntimeException; +import me.chanjar.weixin.common.util.DataUtils; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; +import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.corpgroup.WxCpCorpGroupCorpGetTokenReq; +import me.chanjar.weixin.cp.bean.corpgroup.WxCpMaTransferSession; +import me.chanjar.weixin.cp.config.WxCpCorpGroupConfigStorage; +import me.chanjar.weixin.cp.config.WxCpTpConfigStorage; +import me.chanjar.weixin.cp.corpgroup.service.WxCpCgService; +import me.chanjar.weixin.cp.corpgroup.service.WxCpLinkedCorpService; + +import java.io.IOException; + +import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.CorpGroup.*; + +/** + * @Project: WxJava + * @Package: me.chanjar.weixin.cp.corpgroup.service.impl + * @Description: + * @Author: libo + * @Email: 422423229@qq.com + * @Date: 1/3/2023 5:45 PM + */ +@Slf4j +public abstract class BaseWxCpCgServiceImpl implements WxCpCgService, RequestHttp { + + WxCpService wxCpService; + /** + * The Config storage. + */ + protected WxCpCorpGroupConfigStorage configStorage; + + private int retrySleepMillis = 1000; + private int maxRetryTimes = 5; + + private final WxCpLinkedCorpService linkedCorpService = new WxCpLinkedCorpServiceImpl(this); + + @Override + public void updateCorpAccessToken(String corpId, Integer agentId, String corpAccessToken, int expiresInSeconds) { + + } + + @Override + public String getCorpAccessToken(String corpId, Integer agentId, Integer businessType) throws WxErrorException { + return getCorpAccessToken(corpId, agentId, businessType, false); + } + + @Override + public String getCorpAccessToken(String corpId, Integer agentId, Integer businessType, boolean forceRefresh) throws WxErrorException { + if (!this.configStorage.isCorpAccessTokenExpired(corpId, agentId) && !forceRefresh) { + return this.configStorage.getCorpAccessToken(corpId, agentId); + } + synchronized (this) { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("corpid", corpId); + jsonObject.addProperty("agentid", agentId); + jsonObject.addProperty("business_type", businessType); + final String url = this.wxCpService.getWxCpConfigStorage().getApiUrl(CORP_GET_TOKEN); + String responseContent = this.wxCpService.post(url, jsonObject); + WxAccessToken corpToken = WxAccessToken.fromJson(responseContent); + this.configStorage.updateCorpAccessToken(corpId, agentId, corpToken.getAccessToken(), corpToken.getExpiresIn()); + } + return this.configStorage.getCorpAccessToken(corpId, agentId); + } + + @Override + public WxAccessToken getCorpAccessTokenEntity(String corpId, Integer agentId, Integer businessType) throws WxErrorException { + return this.getCorpAccessTokenEntity(corpId, agentId, businessType, false); + } + + + @Override + public WxAccessToken getCorpAccessTokenEntity(String corpId, Integer agentId, Integer businessType, boolean forceRefresh) throws WxErrorException { + return this.configStorage.getCorpAccessTokenEntity(corpId, agentId); + } + + @Override + public boolean isCorpAccessTokenExpired(String corpId, Integer agentId) { + return this.configStorage.isCorpAccessTokenExpired(corpId, agentId); + } + + @Override + public void expireCorpAccessToken(String corpId, Integer agentId) { + this.configStorage.expireCorpAccessToken(corpId, agentId); + } + + @Override + public String get(String url, String queryParam, WxCpCorpGroupCorpGetTokenReq req) throws WxErrorException { + return execute(SimpleGetRequestExecutor.create(this), url, queryParam, req); + } + + @Override + public String get(String url, String queryParam, boolean withoutCorpAccessToken, WxCpCorpGroupCorpGetTokenReq req) throws WxErrorException { + return execute(SimpleGetRequestExecutor.create(this), url, queryParam, withoutCorpAccessToken, req); + } + + @Override + public String post(String url, String postData, WxCpCorpGroupCorpGetTokenReq req) throws WxErrorException { + return execute(SimplePostRequestExecutor.create(this), url, postData, false, req); + } + + /** + * Post string. + * + * @param url the url + * @param postData the post data + * @param withoutCorpAccessToken the without Corp access token + * @return the string + * @throws WxErrorException the wx error exception + */ + public String post(String url, String postData, boolean withoutCorpAccessToken, WxCpCorpGroupCorpGetTokenReq req) throws WxErrorException { + return execute(SimplePostRequestExecutor.create(this), url, postData, withoutCorpAccessToken, req); + } + + /** + * 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求. + */ + @Override + public T execute(RequestExecutor executor, String uri, E data, WxCpCorpGroupCorpGetTokenReq req) throws WxErrorException { + return execute(executor, uri, data, false, req); + } + + /** + * Execute t. + * + * @param the type parameter + * @param the type parameter + * @param executor the executor + * @param uri the uri + * @param data the data + * @param withoutCorpAccessToken the without Corp access token + * @return the t + * @throws WxErrorException the wx error exception + */ + public T execute(RequestExecutor executor, String uri, E data, boolean withoutCorpAccessToken, WxCpCorpGroupCorpGetTokenReq req) throws WxErrorException { + int retryTimes = 0; + do { + try { + return this.executeInternal(executor, uri, data, withoutCorpAccessToken, req); + } catch (WxErrorException e) { + if (retryTimes + 1 > this.maxRetryTimes) { + log.warn("重试达到最大次数【{}】", this.maxRetryTimes); + //最后一次重试失败后,直接抛出异常,不再等待 + throw new WxRuntimeException("微信服务端异常,超出重试次数"); + } + + WxError error = e.getError(); + /* + * -1 系统繁忙, 1000ms后重试 + */ + if (error.getErrorCode() == -1) { + int sleepMillis = this.retrySleepMillis * (1 << retryTimes); + try { + log.debug("微信系统繁忙,{} ms 后重试(第{}次)", sleepMillis, retryTimes + 1); + Thread.sleep(sleepMillis); + } catch (InterruptedException e1) { + Thread.currentThread().interrupt(); + } + } else { + throw e; + } + } + } while (retryTimes++ < this.maxRetryTimes); + + log.warn("重试达到最大次数【{}】", this.maxRetryTimes); + throw new WxRuntimeException("微信服务端异常,超出重试次数"); + } + + /** + * Execute internal t. + * + * @param the type parameter + * @param the type parameter + * @param executor the executor + * @param uri the uri + * @param data the data + * @return the t + * @throws WxErrorException the wx error exception + */ + protected T executeInternal(RequestExecutor executor, String uri, E data, WxCpCorpGroupCorpGetTokenReq req) throws WxErrorException { + return executeInternal(executor, uri, data, false, req); + } + + /** + * Execute internal t. + * + * @param the type parameter + * @param the type parameter + * @param executor the executor + * @param uri the uri + * @param data the data + * @param withoutCorpAccessToken the without Corp access token + * @return the t + * @throws WxErrorException the wx error exception + */ + protected T executeInternal(RequestExecutor executor, String uri, E data, + boolean withoutCorpAccessToken, WxCpCorpGroupCorpGetTokenReq req) throws WxErrorException { + E dataForLog = DataUtils.handleDataWithSecret(data); + + if (uri.contains("access_token=")) { + throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); + } + String uriWithAccessToken; + if (!withoutCorpAccessToken) { + String corpAccessToken = getCorpAccessToken(req.getCorpId(), req.getAgentId(), req.getBusinessType()); + uriWithAccessToken = uri + (uri.contains("?") ? "&" : "?") + "access_token=" + corpAccessToken; + } else { + uriWithAccessToken = uri; + } + + + try { + T result = executor.execute(uriWithAccessToken, data, WxType.CP); + log.debug("\n【请求地址】: {}\n【请求参数】:{}\n【响应数据】:{}", uriWithAccessToken, dataForLog, result); + return result; + } catch (WxErrorException e) { + WxError error = e.getError(); + /* + * 发生以下情况时尝试刷新Corp_access_token + * 42009 Corp_access_token已过期 + */ + if (error.getErrorCode() == WxCpErrorMsgEnum.CODE_42009.getCode()) { + // 强制设置wxCpCorpGroupConfigStorage它的corp access token过期了,这样在下一次请求里就会刷新corp access token + this.configStorage.expireCorpAccessToken(req.getCorpId(), req.getAgentId()); + if (this.getWxCpCorpGroupConfigStorage().autoRefreshToken()) { + log.warn("即将重新获取新的access_token,错误代码:{},错误信息:{}", error.getErrorCode(), error.getErrorMsg()); + return this.execute(executor, uri, data, req); + } + } + + if (error.getErrorCode() != 0) { + log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uriWithAccessToken, dataForLog, error); + throw new WxErrorException(error, e); + } + return null; + } catch (IOException e) { + log.error("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, dataForLog, e.getMessage()); + throw new WxRuntimeException(e); + } + } + + @Override + public void setWxCpCorpGroupConfigStorage(WxCpCorpGroupConfigStorage wxCpCorpGroupConfigStorage) { + this.configStorage = wxCpCorpGroupConfigStorage; + this.initHttp(); + } + + @Override + public WxCpCorpGroupConfigStorage getWxCpCorpGroupConfigStorage() { + return configStorage; + } + + @Override + public void setRetrySleepMillis(int retrySleepMillis) { + this.retrySleepMillis = retrySleepMillis; + } + + + @Override + public void setMaxRetryTimes(int maxRetryTimes) { + this.maxRetryTimes = maxRetryTimes; + } + + @Override + public RequestHttp getRequestHttp() { + return this; + } + + @Override + public void setWxCpService(WxCpService wxCpService) { + this.wxCpService = wxCpService; + } + + @Override + public WxCpLinkedCorpService getLinkedCorpService() { + return linkedCorpService; + } + + @Override + public WxCpMaTransferSession getCorpTransferSession(String userId, String sessionKey, WxCpCorpGroupCorpGetTokenReq req) throws WxErrorException { + final String url = this.wxCpService.getWxCpConfigStorage().getApiUrl(MA_TRANSFER_SESSION); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("userid", userId); + jsonObject.addProperty("session_key", sessionKey); + String result = this.post(url, jsonObject.toString(), req); + return WxCpMaTransferSession.fromJson(result); + } +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/corpgroup/service/impl/WxCpCgServiceApacheHttpClientImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/corpgroup/service/impl/WxCpCgServiceApacheHttpClientImpl.java new file mode 100644 index 0000000000..d135be0dde --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/corpgroup/service/impl/WxCpCgServiceApacheHttpClientImpl.java @@ -0,0 +1,57 @@ +package me.chanjar.weixin.cp.corpgroup.service.impl; + +import com.fasterxml.jackson.databind.ser.Serializers; +import me.chanjar.weixin.common.util.http.HttpType; +import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; +import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; +import org.apache.http.HttpHost; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.CloseableHttpClient; + +/** + * @Project: WxJava + * @Package: me.chanjar.weixin.cp.corpgroup.service.impl + * @Description: + * @Author: libo + * @Email: 422423229@qq.com + * @Date: 1/3/2023 6:16 PM + */ +public class WxCpCgServiceApacheHttpClientImpl extends BaseWxCpCgServiceImpl { + private CloseableHttpClient httpClient; + private HttpHost httpProxy; + + @Override + public CloseableHttpClient getRequestHttpClient() { + return httpClient; + } + + @Override + public HttpHost getRequestHttpProxy() { + return httpProxy; + } + + @Override + public HttpType getRequestType() { + return HttpType.APACHE_HTTP; + } + + @Override + public void initHttp() { + ApacheHttpClientBuilder apacheHttpClientBuilder = this.configStorage.getApacheHttpClientBuilder(); + if (null == apacheHttpClientBuilder) { + apacheHttpClientBuilder = DefaultApacheHttpClientBuilder.get(); + } + + apacheHttpClientBuilder.httpProxyHost(this.configStorage.getHttpProxyHost()) + .httpProxyPort(this.configStorage.getHttpProxyPort()) + .httpProxyUsername(this.configStorage.getHttpProxyUsername()) + .httpProxyPassword(this.configStorage.getHttpProxyPassword()); + + if (this.configStorage.getHttpProxyHost() != null && this.configStorage.getHttpProxyPort() > 0) { + this.httpProxy = new HttpHost(this.configStorage.getHttpProxyHost(), this.configStorage.getHttpProxyPort()); + } + + this.httpClient = apacheHttpClientBuilder.build(); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/corpgroup/service/impl/WxCpLinkedCorpServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/corpgroup/service/impl/WxCpLinkedCorpServiceImpl.java new file mode 100644 index 0000000000..fca053d265 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/corpgroup/service/impl/WxCpLinkedCorpServiceImpl.java @@ -0,0 +1,96 @@ +package me.chanjar.weixin.cp.corpgroup.service.impl; + +import com.google.gson.JsonObject; +import com.google.gson.reflect.TypeToken; +import lombok.RequiredArgsConstructor; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.json.GsonParser; +import me.chanjar.weixin.cp.bean.corpgroup.WxCpCorpGroupCorpGetTokenReq; +import me.chanjar.weixin.cp.corpgroup.service.WxCpCgService; +import me.chanjar.weixin.cp.corpgroup.service.WxCpLinkedCorpService; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.linkedcorp.WxCpLinkedCorpAgentPerm; +import me.chanjar.weixin.cp.bean.linkedcorp.WxCpLinkedCorpDepartment; +import me.chanjar.weixin.cp.bean.linkedcorp.WxCpLinkedCorpUser; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.util.List; + +import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.LinkedCorp.*; + +/** + * @Project: WxJava + * @Package: me.chanjar.weixin.cp.api.impl + * @Description: 互联企业相关接口实现类 + * @Author: libo + * @Email: 422423229@qq.com + * @Date: 27/2/2023 10:02 PM + */ +@RequiredArgsConstructor +public class WxCpLinkedCorpServiceImpl implements WxCpLinkedCorpService { + private final WxCpCgService cpCgService; + + @Override + public WxCpLinkedCorpAgentPerm getLinkedCorpAgentPerm(WxCpCorpGroupCorpGetTokenReq req) throws WxErrorException { + final String url = this.cpCgService.getWxCpCorpGroupConfigStorage().getApiUrl(GET_PERM_LIST); + JsonObject jsonObject = new JsonObject(); + String responseContent = this.cpCgService.post(url, jsonObject.toString(), req); + return WxCpGsonBuilder.create().fromJson(responseContent, WxCpLinkedCorpAgentPerm.class); + } + + @Override + public WxCpLinkedCorpUser getLinkedCorpUser(String userId, WxCpCorpGroupCorpGetTokenReq req) throws WxErrorException { + final String url = this.cpCgService.getWxCpCorpGroupConfigStorage().getApiUrl(GET_USER); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("userid", userId); + String responseContent = this.cpCgService.post(url, jsonObject.toString(), req); + JsonObject tmpJson = GsonParser.parse(responseContent); + + return WxCpGsonBuilder.create().fromJson(tmpJson.get("user_info"), + new TypeToken() { + }.getType() + ); + } + + @Override + public List getLinkedCorpSimpleUserList(String departmentId, WxCpCorpGroupCorpGetTokenReq req) throws WxErrorException { + final String url = this.cpCgService.getWxCpCorpGroupConfigStorage().getApiUrl(GET_USER_SIMPLELIST); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("department_id", departmentId); + String responseContent = this.cpCgService.post(url, jsonObject.toString(),req); + JsonObject tmpJson = GsonParser.parse(responseContent); + + return WxCpGsonBuilder.create().fromJson(tmpJson.get("userlist"), + new TypeToken>() { + }.getType() + ); + } + + @Override + public List getLinkedCorpUserList(String departmentId, WxCpCorpGroupCorpGetTokenReq req) throws WxErrorException { + final String url = this.cpCgService.getWxCpCorpGroupConfigStorage().getApiUrl(GET_USER_LIST); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("department_id", departmentId); + String responseContent = this.cpCgService.post(url, jsonObject.toString(),req); + JsonObject tmpJson = GsonParser.parse(responseContent); + + return WxCpGsonBuilder.create().fromJson(tmpJson.get("userlist"), + new TypeToken>() { + }.getType() + ); + } + + @Override + public List getLinkedCorpDepartmentList(String departmentId, WxCpCorpGroupCorpGetTokenReq req) throws WxErrorException { + final String url = this.cpCgService.getWxCpCorpGroupConfigStorage().getApiUrl(GET_DEPARTMENT_LIST); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("department_id", departmentId); + String responseContent = this.cpCgService.post(url, jsonObject.toString(),req); + JsonObject tmpJson = GsonParser.parse(responseContent); + + return WxCpGsonBuilder.create().fromJson(tmpJson.get("department_list"), + new TypeToken>() { + }.getType() + ); + } +} diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpCorpGroupServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpCorpGroupServiceImplTest.java new file mode 100644 index 0000000000..db2d0c9535 --- /dev/null +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpCorpGroupServiceImplTest.java @@ -0,0 +1,43 @@ +package me.chanjar.weixin.cp.api.impl; + +import com.google.gson.JsonObject; +import com.google.inject.Inject; +import me.chanjar.weixin.common.bean.WxAccessToken; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.api.ApiTestModule; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.corpgroup.*; +import me.chanjar.weixin.cp.corpgroup.service.WxCpCgService; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import java.util.List; + +import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.CorpGroup.CORP_GET_TOKEN; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; + +/** + * @Project: WxJava + * @Package: me.chanjar.weixin.cp.api.impl + * @Description: + * @Author: libo + * @Email: 422423229@qq.com + * @Date: 28/2/2023 7:06 PM + */ +@Guice(modules = ApiTestModule.class) +public class WxCpCorpGroupServiceImplTest { + @Inject + private WxCpService wxService; + + @Test + public void testListAppShareInfo() throws WxErrorException { + Integer agentId = wxService.getWxCpConfigStorage().getAgentId(); + Integer businessType = 0; + String corpId = null; + Integer limit = null; + String cursor = null; + List resp = wxService.getCorpGroupService().listAppShareInfo(agentId, businessType, corpId, limit, cursor); + assertNotNull(resp); + } +} diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpMeetingServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpMeetingServiceImplTest.java index 55ca45fc56..b178e01fad 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpMeetingServiceImplTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpMeetingServiceImplTest.java @@ -79,7 +79,7 @@ public void testAdd() throws WxErrorException { wxCpMeeting.setTitle("修改会议"); wxCpMeeting.setDescription("修改会议描述"); WxCpMeetingUpdateResult wxCpMeetingUpdateResult = wxCpMeetingService.update(wxCpMeeting); - assertEquals(wxCpMeetingUpdateResult.getErrcode(), 0L); + assertEquals(wxCpMeetingUpdateResult.getErrcode().longValue(), 0L); /* 测试 获取会议详情 */ diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/corpgroup/service/impl/WxCpCgServiceApacheHttpClientImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/corpgroup/service/impl/WxCpCgServiceApacheHttpClientImplTest.java new file mode 100644 index 0000000000..1437727568 --- /dev/null +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/corpgroup/service/impl/WxCpCgServiceApacheHttpClientImplTest.java @@ -0,0 +1,114 @@ +package me.chanjar.weixin.cp.corpgroup.service.impl; + +import com.google.gson.JsonObject; +import com.google.inject.Inject; +import me.chanjar.weixin.common.bean.WxAccessToken; +import me.chanjar.weixin.cp.api.ApiTestModule; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.api.impl.WxCpServiceApacheHttpClientImpl; +import me.chanjar.weixin.cp.bean.WxCpAgent; +import me.chanjar.weixin.cp.bean.WxCpUser; +import me.chanjar.weixin.cp.bean.corpgroup.WxCpCorpGroupCorpGetTokenReq; +import me.chanjar.weixin.cp.bean.corpgroup.WxCpMaTransferSession; +import me.chanjar.weixin.cp.config.WxCpCorpGroupConfigStorage; +import me.chanjar.weixin.cp.config.impl.WxCpCorpGroupDefaultConfigImpl; +import me.chanjar.weixin.cp.config.impl.WxCpCorpGroupRedissonConfigImpl; +import me.chanjar.weixin.cp.constant.WxCpApiPathConsts; +import me.chanjar.weixin.cp.corpgroup.service.WxCpCgService; + +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; +import org.mockito.Mockito; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.CorpGroup.MA_TRANSFER_SESSION; +import static org.testng.Assert.assertNotNull; + +/** + * @Project: WxJava + * @Package: me.chanjar.weixin.cp.corpgroup.service.impl + * @Description: + * @Author: libo + * @Email: 422423229@qq.com + * @Date: 2/3/2023 4:00 PM + */ +@Guice(modules = ApiTestModule.class) +public class WxCpCgServiceApacheHttpClientImplTest { + private final WxCpCgService cgService = Mockito.spy(new WxCpCgServiceApacheHttpClientImpl()); + WxCpCorpGroupConfigStorage wxCpCorpGroupConfigStorage; + @Inject + WxCpService wxCpService; + + //下游企业的corpId + String corpId = ""; + //下游企业的agentId + int agentId = 0; + int businessType = 0; + String userId = ""; + WxCpCorpGroupCorpGetTokenReq wxCpCorpGroupCorpGetTokenReq; + + @BeforeMethod + public void setUp() { + cgService.setWxCpCorpGroupConfigStorage(wxCpCorpGroupConfigStorage()); + cgService.setWxCpService(wxCpService); + + wxCpCorpGroupCorpGetTokenReq = new WxCpCorpGroupCorpGetTokenReq(); + wxCpCorpGroupCorpGetTokenReq.setCorpId(corpId); + wxCpCorpGroupCorpGetTokenReq.setAgentId(agentId); + wxCpCorpGroupCorpGetTokenReq.setBusinessType(businessType); + } + + public WxCpCorpGroupConfigStorage wxCpCorpGroupConfigStorage() { + wxCpCorpGroupConfigStorage = new WxCpCorpGroupDefaultConfigImpl(); + wxCpCorpGroupConfigStorage.setCorpId(wxCpService.getWxCpConfigStorage().getCorpId()); + wxCpCorpGroupConfigStorage.setAgentId(wxCpService.getWxCpConfigStorage().getAgentId()); + return wxCpCorpGroupConfigStorage; + } + + @Test + public void testGetCorpAccessToken() throws Exception { + String corpAccessToken = cgService.getCorpAccessToken(corpId, agentId, businessType); + assertNotNull(corpAccessToken); + } + + /** + * 通讯录-读取成员 + * + * @throws Exception + */ + @Test + public void testGetCorpUser() throws Exception { + String result = cgService.get(wxCpService.getWxCpConfigStorage().getApiUrl(WxCpApiPathConsts.User.USER_GET + userId), null, wxCpCorpGroupCorpGetTokenReq); + assertNotNull(result); + WxCpUser wxCpUser = WxCpUser.fromJson(result); + assertNotNull(wxCpUser.getUserId()); + } + + /** + * 应用管理-获取指定的应用详情 + * + * @throws Exception + */ + @Test + public void testGetAgent() throws Exception { + + String result = cgService.get(wxCpService.getWxCpConfigStorage().getApiUrl(String.format(WxCpApiPathConsts.Agent.AGENT_GET, agentId)), null, wxCpCorpGroupCorpGetTokenReq); + assertNotNull(result); + WxCpAgent wxCpAgent = WxCpAgent.fromJson(result); + assertNotNull(wxCpAgent.getAgentId()); + } + + /** + * 获取下级/下游企业小程序session + * + * @throws Exception + */ + @Test + public void testGetTransferSession() throws Exception { + String sessionKey = ""; + + WxCpMaTransferSession wxCpMaTransferSession = cgService.getCorpTransferSession(userId, sessionKey, wxCpCorpGroupCorpGetTokenReq); + assertNotNull(wxCpMaTransferSession); + } +} diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/corpgroup/service/impl/WxCpLinkedCorpServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/corpgroup/service/impl/WxCpLinkedCorpServiceImplTest.java new file mode 100644 index 0000000000..8ca2a98d51 --- /dev/null +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/corpgroup/service/impl/WxCpLinkedCorpServiceImplTest.java @@ -0,0 +1,98 @@ +package me.chanjar.weixin.cp.corpgroup.service.impl; + +import com.google.inject.Inject; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.api.ApiTestModule; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.corpgroup.WxCpCorpGroupCorpGetTokenReq; +import me.chanjar.weixin.cp.bean.linkedcorp.WxCpLinkedCorpAgentPerm; +import me.chanjar.weixin.cp.bean.linkedcorp.WxCpLinkedCorpDepartment; +import me.chanjar.weixin.cp.bean.linkedcorp.WxCpLinkedCorpUser; +import me.chanjar.weixin.cp.config.WxCpCorpGroupConfigStorage; +import me.chanjar.weixin.cp.config.impl.WxCpCorpGroupDefaultConfigImpl; +import me.chanjar.weixin.cp.corpgroup.service.WxCpCgService; +import org.mockito.Mockito; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import java.util.List; + +import static org.testng.Assert.assertNotNull; + +/** + * @Project: WxJava + * @Package: me.chanjar.weixin.cp.api.impl + * @Description: + * @Author: libo + * @Email: 422423229@qq.com + * @Date: 28/2/2023 7:06 PM + */ +@Guice(modules = ApiTestModule.class) +public class WxCpLinkedCorpServiceImplTest { + WxCpCorpGroupConfigStorage wxCpCorpGroupConfigStorage; + @Inject + WxCpService wxCpService; + + WxCpCgService cgService; + + //下游企业的corpId + String corpId = ""; + //下游企业的agentId + int agentId = 0; + int businessType = 0; + //CorpID/UserID + String corpUserId = ""; + String departmentId = ""; + WxCpCorpGroupCorpGetTokenReq wxCpCorpGroupCorpGetTokenReq; + + @BeforeMethod + public void setUp() { + cgService = new WxCpCgServiceApacheHttpClientImpl(); + cgService.setWxCpCorpGroupConfigStorage(wxCpCorpGroupConfigStorage()); + cgService.setWxCpService(wxCpService); + + wxCpCorpGroupCorpGetTokenReq = new WxCpCorpGroupCorpGetTokenReq(); + wxCpCorpGroupCorpGetTokenReq.setCorpId(corpId); + wxCpCorpGroupCorpGetTokenReq.setAgentId(agentId); + wxCpCorpGroupCorpGetTokenReq.setBusinessType(businessType); + } + + public WxCpCorpGroupConfigStorage wxCpCorpGroupConfigStorage() { + wxCpCorpGroupConfigStorage = new WxCpCorpGroupDefaultConfigImpl(); + wxCpCorpGroupConfigStorage.setCorpId(wxCpService.getWxCpConfigStorage().getCorpId()); + wxCpCorpGroupConfigStorage.setAgentId(wxCpService.getWxCpConfigStorage().getAgentId()); + return wxCpCorpGroupConfigStorage; + } + + @Test + public void testGetLinkedCorpAgentPerm() throws WxErrorException { + WxCpLinkedCorpAgentPerm resp = cgService.getLinkedCorpService().getLinkedCorpAgentPerm(wxCpCorpGroupCorpGetTokenReq); + assertNotNull(resp); + } + + @Test + public void testGetLinkedCorpUser() throws WxErrorException { + WxCpLinkedCorpUser resp = cgService.getLinkedCorpService().getLinkedCorpUser(corpUserId, wxCpCorpGroupCorpGetTokenReq); + assertNotNull(resp); + } + + @Test + public void testGetLinkedCorpSimpleUserList() throws WxErrorException { + List resp = cgService.getLinkedCorpService().getLinkedCorpSimpleUserList(departmentId, wxCpCorpGroupCorpGetTokenReq); + assertNotNull(resp); + } + + @Test + public void testGetLinkedCorpUserList() throws WxErrorException { + List resp = cgService.getLinkedCorpService().getLinkedCorpUserList(departmentId, wxCpCorpGroupCorpGetTokenReq); + assertNotNull(resp); + } + + @Test + public void testGetLinkedCorpDepartmentList() throws WxErrorException { + List resp = cgService.getLinkedCorpService().getLinkedCorpDepartmentList(departmentId, wxCpCorpGroupCorpGetTokenReq); + assertNotNull(resp); + } + +} diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/tp/service/impl/BaseWxCpTpServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/tp/service/impl/BaseWxCpTpServiceImplTest.java index 8235e48f93..6f2639c890 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/tp/service/impl/BaseWxCpTpServiceImplTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/tp/service/impl/BaseWxCpTpServiceImplTest.java @@ -8,11 +8,9 @@ import me.chanjar.weixin.cp.bean.WxCpTpPermanentCodeInfo; import me.chanjar.weixin.cp.bean.WxTpCustomizedAuthUrl; import me.chanjar.weixin.cp.config.WxCpTpConfigStorage; -import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl; import me.chanjar.weixin.cp.config.impl.WxCpTpDefaultConfigImpl; import me.chanjar.weixin.cp.config.impl.WxCpTpRedissonConfigImpl; import me.chanjar.weixin.cp.tp.service.WxCpTpService; -import org.apache.http.util.Asserts; import org.mockito.Mockito; import org.redisson.Redisson; import org.redisson.api.RedissonClient; @@ -22,7 +20,6 @@ import org.testng.annotations.Test; import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.Objects;