Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 40 additions & 37 deletions solon-plugins/wx-java-cp-multi-solon-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,22 @@
- 未实现 WxCpTpService 初始化,需要的小伙伴可以参考多 WxCpService 配置的实现。
- 未实现 WxCpCgService 初始化,需要的小伙伴可以参考多 WxCpService 配置的实现。

## 关于 corp-secret 的说明

企业微信中不同功能模块对应不同的 `corp-secret`,每种 Secret 只对对应模块的接口具有调用权限:

| Secret 类型 | 获取位置 | 可调用的接口 | 是否需要 agent-id |
|---|---|---|---|
| 自建应用 Secret | 应用管理 → 自建应用 → 选择应用 → 查看 Secret | 该应用有权限的接口 | **必填** |
| 通讯录同步 Secret | 管理工具 → 通讯录同步 → 查看 Secret | 部门/成员增删改查等通讯录接口 | **不填** |
| 客户联系 Secret | 客户联系 → API → Secret | 客户联系相关接口 | 不填 |

> **常见问题**:
> - 使用自建应用 Secret + agent-id 可以获取部门列表,但**无法更新部门**(因为写接口需要通讯录同步权限)
> - 使用通讯录同步 Secret 可以同步部门,但**调用某些需要 agent-id 的应用接口会报错**

如需同时使用多种权限范围,可在 `wx.cp.corps` 下配置多个条目,每个条目使用对应权限的 Secret,通过不同的 `tenantId` 区分后使用。

## 快速开始

1. 引入依赖
Expand All @@ -18,25 +34,21 @@
```
2. 添加配置(app.properties)
```properties
# 应用 1 配置
wx.cp.corps.tenantId1.corp-id = @corp-id
wx.cp.corps.tenantId1.corp-secret = @corp-secret
# 自建应用 1 配置(使用自建应用 Secret,需填写 agent-id)
wx.cp.corps.app1.corp-id = @corp-id
wx.cp.corps.app1.corp-secret = @自建应用的Secret(在"应用管理-自建应用"中查看)
wx.cp.corps.app1.agent-id = @自建应用的AgentId
## 选填
wx.cp.corps.tenantId1.agent-id = @agent-id
wx.cp.corps.tenantId1.token = @token
wx.cp.corps.tenantId1.aes-key = @aes-key
wx.cp.corps.tenantId1.msg-audit-priKey = @msg-audit-priKey
wx.cp.corps.tenantId1.msg-audit-lib-path = @msg-audit-lib-path

# 应用 2 配置
wx.cp.corps.tenantId2.corp-id = @corp-id
wx.cp.corps.tenantId2.corp-secret = @corp-secret
## 选填
wx.cp.corps.tenantId2.agent-id = @agent-id
wx.cp.corps.tenantId2.token = @token
wx.cp.corps.tenantId2.aes-key = @aes-key
wx.cp.corps.tenantId2.msg-audit-priKey = @msg-audit-priKey
wx.cp.corps.tenantId2.msg-audit-lib-path = @msg-audit-lib-path
wx.cp.corps.app1.token = @token
wx.cp.corps.app1.aes-key = @aes-key
wx.cp.corps.app1.msg-audit-priKey = @msg-audit-priKey
wx.cp.corps.app1.msg-audit-lib-path = @msg-audit-lib-path

# 通讯录同步配置(使用通讯录同步 Secret,不需要填写 agent-id)
# 此配置用于部门、成员的增删改查等通讯录管理操作
wx.cp.corps.contact.corp-id = @corp-id
wx.cp.corps.contact.corp-secret = @通讯录同步的Secret(在"管理工具-通讯录同步"中查看)
## agent-id 不填,通讯录同步不需要 agentId

# 公共配置
## ConfigStorage 配置(选填)
Expand All @@ -59,6 +71,7 @@

```java
import com.binarywang.solon.wxjava.cp_multi.service.WxCpMultiServices;
import me.chanjar.weixin.cp.api.WxCpDepartmentService;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.api.WxCpUserService;
import org.noear.solon.annotation.Component;
Expand All @@ -70,27 +83,17 @@ public class DemoService {
private WxCpMultiServices wxCpMultiServices;

public void test() {
// 应用 1 的 WxCpService
WxCpService wxCpService1 = wxCpMultiServices.getWxCpService("tenantId1");
WxCpUserService userService1 = wxCpService1.getUserService();
userService1.getUserId("xxx");
// todo ...

// 应用 2 的 WxCpService
WxCpService wxCpService2 = wxCpMultiServices.getWxCpService("tenantId2");
WxCpUserService userService2 = wxCpService2.getUserService();
userService2.getUserId("xxx");
// 使用自建应用的 WxCpService(对应 corp-secret 为自建应用 Secret)
WxCpService appService = wxCpMultiServices.getWxCpService("app1");
WxCpUserService userService = appService.getUserService();
userService.getUserId("xxx");
// todo ...

// 应用 3 的 WxCpService
WxCpService wxCpService3 = wxCpMultiServices.getWxCpService("tenantId3");
// 判断是否为空
if (wxCpService3 == null) {
// todo wxCpService3 为空,请先配置 tenantId3 企业微信应用参数
return;
}
WxCpUserService userService3 = wxCpService3.getUserService();
userService3.getUserId("xxx");
// 使用通讯录同步的 WxCpService(对应 corp-secret 为通讯录同步 Secret)
// 通讯录同步 Secret 具有部门/成员增删改查等权限
WxCpService contactService = wxCpMultiServices.getWxCpService("contact");
WxCpDepartmentService departmentService = contactService.getDepartmentService();
departmentService.update(department);
// todo ...
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ protected WxCpMultiServices wxCpMultiServices(WxCpMultiProperties wxCpMultiPrope
/**
* 校验同一个企业下,agentId 是否唯一,避免使用 redis 缓存 token、ticket 时错乱。
*
* <p>同一企业(corpId 相同)下可配置多个条目以使用不同的权限 Secret,例如:
* <ul>
* <li>自建应用条目:填写应用对应的 corpSecret 和 agentId</li>
* <li>通讯录同步条目:填写通讯录同步 Secret,agentId 可不填(null)</li>
* </ul>
* 但同一 corpId 下不允许出现重复的 agentId(包括多个 null)。
* </p>
*
* 查看 {@link me.chanjar.weixin.cp.config.impl.AbstractWxCpInRedisConfigImpl#setAgentId(Integer)}
*/
Collection<WxCpSingleProperties> corpList = corps.values();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@
/**
* 企业微信企业相关配置属性
*
* <p>企业微信中不同的 corpSecret 对应不同的权限范围,常见的有:</p>
* <ul>
* <li>自建应用 Secret:在"应用管理 - 自建应用"中查看,只能调用该应用有权限的接口</li>
* <li>通讯录同步 Secret:在"管理工具 - 通讯录同步"中查看,用于管理部门和成员(增删改查)</li>
* <li>客户联系 Secret:在"客户联系"中查看,用于客户联系相关接口</li>
* </ul>
* <p>如需同时使用多种权限范围(例如:既要操作通讯录,又要调用自建应用接口),
* 可在 {@code wx.cp.corps} 下配置多个条目,每个条目使用对应权限的 {@code corpSecret},
* 其中通讯录同步的条目无需填写 {@code agentId}。</p>
*
* @author yl
* created on 2023/10/16
*/
Expand All @@ -20,15 +30,27 @@ public class WxCpSingleProperties implements Serializable {
*/
private String corpId;
/**
* 微信企业号 corpSecret
* 微信企业号 corpSecret(权限密钥)
*
* <p>企业微信针对不同的功能模块提供了不同的 Secret,每种 Secret 只对对应模块的接口有调用权限:</p>
* <ul>
* <li>自建应用 Secret:在"应用管理 - 自建应用"中找到对应应用,查看其 Secret,
* 使用时需同时配置对应的 {@code agentId}</li>
* <li>通讯录同步 Secret:在"管理工具 - 通讯录同步"中查看,
* 使用此 Secret 可管理部门、成员,无需配置 {@code agentId}</li>
* <li>其他 Secret(客户联系等):根据需要在企业微信后台查看对应 Secret</li>
* </ul>
*/
private String corpSecret;
/**
* 微信企业号应用 token
*/
private String token;
/**
* 微信企业号应用 ID
* 微信企业号应用 ID(AgentId)
*
* <p>使用自建应用 Secret 时,需要填写对应应用的 AgentId。</p>
* <p>使用通讯录同步 Secret 时,无需填写此字段。</p>
*/
private Integer agentId;
/**
Expand Down
77 changes: 40 additions & 37 deletions spring-boot-starters/wx-java-cp-multi-spring-boot-starter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,22 @@
- 未实现 WxCpTpService 初始化,需要的小伙伴可以参考多 WxCpService 配置的实现。
- 未实现 WxCpCgService 初始化,需要的小伙伴可以参考多 WxCpService 配置的实现。

## 关于 corp-secret 的说明

企业微信中不同功能模块对应不同的 `corp-secret`,每种 Secret 只对对应模块的接口具有调用权限:

| Secret 类型 | 获取位置 | 可调用的接口 | 是否需要 agent-id |
|---|---|---|---|
| 自建应用 Secret | 应用管理 → 自建应用 → 选择应用 → 查看 Secret | 该应用有权限的接口 | **必填** |
| 通讯录同步 Secret | 管理工具 → 通讯录同步 → 查看 Secret | 部门/成员增删改查等通讯录接口 | **不填** |
| 客户联系 Secret | 客户联系 → API → Secret | 客户联系相关接口 | 不填 |

> **常见问题**:
> - 使用自建应用 Secret + agent-id 可以获取部门列表,但**无法更新部门**(因为写接口需要通讯录同步权限)
> - 使用通讯录同步 Secret 可以同步部门,但**调用某些需要 agent-id 的应用接口会报错**

如需同时使用多种权限范围,可在 `wx.cp.corps` 下配置多个条目,每个条目使用对应权限的 Secret,通过不同的 `tenantId` 区分后使用。

## 快速开始

1. 引入依赖
Expand All @@ -18,25 +34,21 @@
```
2. 添加配置(application.properties)
```properties
# 应用 1 配置
wx.cp.corps.tenantId1.corp-id = @corp-id
wx.cp.corps.tenantId1.corp-secret = @corp-secret
# 自建应用 1 配置(使用自建应用 Secret,需填写 agent-id)
wx.cp.corps.app1.corp-id = @corp-id
wx.cp.corps.app1.corp-secret = @自建应用的Secret(在"应用管理-自建应用"中查看)
wx.cp.corps.app1.agent-id = @自建应用的AgentId
## 选填
wx.cp.corps.tenantId1.agent-id = @agent-id
wx.cp.corps.tenantId1.token = @token
wx.cp.corps.tenantId1.aes-key = @aes-key
wx.cp.corps.tenantId1.msg-audit-priKey = @msg-audit-priKey
wx.cp.corps.tenantId1.msg-audit-lib-path = @msg-audit-lib-path

# 应用 2 配置
wx.cp.corps.tenantId2.corp-id = @corp-id
wx.cp.corps.tenantId2.corp-secret = @corp-secret
## 选填
wx.cp.corps.tenantId2.agent-id = @agent-id
wx.cp.corps.tenantId2.token = @token
wx.cp.corps.tenantId2.aes-key = @aes-key
wx.cp.corps.tenantId2.msg-audit-priKey = @msg-audit-priKey
wx.cp.corps.tenantId2.msg-audit-lib-path = @msg-audit-lib-path
wx.cp.corps.app1.token = @token
wx.cp.corps.app1.aes-key = @aes-key
wx.cp.corps.app1.msg-audit-priKey = @msg-audit-priKey
wx.cp.corps.app1.msg-audit-lib-path = @msg-audit-lib-path

# 通讯录同步配置(使用通讯录同步 Secret,不需要填写 agent-id)
# 此配置用于部门、成员的增删改查等通讯录管理操作
wx.cp.corps.contact.corp-id = @corp-id
wx.cp.corps.contact.corp-secret = @通讯录同步的Secret(在"管理工具-通讯录同步"中查看)
## agent-id 不填,通讯录同步不需要 agentId

# 公共配置
## ConfigStorage 配置(选填)
Expand All @@ -59,6 +71,7 @@

```java
import com.binarywang.spring.starter.wxjava.cp.service.WxCpMultiServices;
import me.chanjar.weixin.cp.api.WxCpDepartmentService;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.api.WxCpUserService;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -70,27 +83,17 @@ public class DemoService {
private WxCpMultiServices wxCpMultiServices;

public void test() {
// 应用 1 的 WxCpService
WxCpService wxCpService1 = wxCpMultiServices.getWxCpService("tenantId1");
WxCpUserService userService1 = wxCpService1.getUserService();
userService1.getUserId("xxx");
// todo ...

// 应用 2 的 WxCpService
WxCpService wxCpService2 = wxCpMultiServices.getWxCpService("tenantId2");
WxCpUserService userService2 = wxCpService2.getUserService();
userService2.getUserId("xxx");
// 使用自建应用的 WxCpService(对应 corp-secret 为自建应用 Secret)
WxCpService appService = wxCpMultiServices.getWxCpService("app1");
WxCpUserService userService = appService.getUserService();
userService.getUserId("xxx");
// todo ...

// 应用 3 的 WxCpService
WxCpService wxCpService3 = wxCpMultiServices.getWxCpService("tenantId3");
// 判断是否为空
if (wxCpService3 == null) {
// todo wxCpService3 为空,请先配置 tenantId3 企业微信应用参数
return;
}
WxCpUserService userService3 = wxCpService3.getUserService();
userService3.getUserId("xxx");
// 使用通讯录同步的 WxCpService(对应 corp-secret 为通讯录同步 Secret)
// 通讯录同步 Secret 具有部门/成员增删改查等权限
WxCpService contactService = wxCpMultiServices.getWxCpService("contact");
WxCpDepartmentService departmentService = contactService.getDepartmentService();
departmentService.update(department);
// todo ...
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ protected WxCpMultiServices wxCpMultiServices(WxCpMultiProperties wxCpMultiPrope
/**
* 校验同一个企业下,agentId 是否唯一,避免使用 redis 缓存 token、ticket 时错乱。
*
* <p>同一企业(corpId 相同)下可配置多个条目以使用不同的权限 Secret,例如:
* <ul>
* <li>自建应用条目:填写应用对应的 corpSecret 和 agentId</li>
* <li>通讯录同步条目:填写通讯录同步 Secret,agentId 可不填(null)</li>
* </ul>
* 但同一 corpId 下不允许出现重复的 agentId(包括多个 null)。
* </p>
*
* 查看 {@link me.chanjar.weixin.cp.config.impl.AbstractWxCpInRedisConfigImpl#setAgentId(Integer)}
*/
Collection<WxCpSingleProperties> corpList = corps.values();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@
/**
* 企业微信企业相关配置属性
*
* <p>企业微信中不同的 corpSecret 对应不同的权限范围,常见的有:</p>
* <ul>
* <li>自建应用 Secret:在"应用管理 - 自建应用"中查看,只能调用该应用有权限的接口</li>
* <li>通讯录同步 Secret:在"管理工具 - 通讯录同步"中查看,用于管理部门和成员(增删改查)</li>
* <li>客户联系 Secret:在"客户联系"中查看,用于客户联系相关接口</li>
* </ul>
* <p>如需同时使用多种权限范围(例如:既要操作通讯录,又要调用自建应用接口),
* 可在 {@code wx.cp.corps} 下配置多个条目,每个条目使用对应权限的 {@code corpSecret},
* 其中通讯录同步的条目无需填写 {@code agentId}。</p>
*
* @author yl
* created on 2023/10/16
*/
Expand All @@ -20,15 +30,27 @@ public class WxCpSingleProperties implements Serializable {
*/
private String corpId;
/**
* 微信企业号 corpSecret
* 微信企业号 corpSecret(权限密钥)
*
* <p>企业微信针对不同的功能模块提供了不同的 Secret,每种 Secret 只对对应模块的接口有调用权限:</p>
* <ul>
* <li>自建应用 Secret:在"应用管理 - 自建应用"中找到对应应用,查看其 Secret,
* 使用时需同时配置对应的 {@code agentId}</li>
* <li>通讯录同步 Secret:在"管理工具 - 通讯录同步"中查看,
* 使用此 Secret 可管理部门、成员,无需配置 {@code agentId}</li>
* <li>其他 Secret(客户联系等):根据需要在企业微信后台查看对应 Secret</li>
* </ul>
*/
private String corpSecret;
/**
* 微信企业号应用 token
*/
private String token;
/**
* 微信企业号应用 ID
* 微信企业号应用 ID(AgentId)
*
* <p>使用自建应用 Secret 时,需要填写对应应用的 AgentId。</p>
* <p>使用通讯录同步 Secret 时,无需填写此字段。</p>
*/
private Integer agentId;
/**
Expand Down