-
-
Notifications
You must be signed in to change notification settings - Fork 9.1k
文档:明确说明 wx-java-cp-multi-spring-boot-starter 中 corp-secret 的配置方式 #3957
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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. 引入依赖 | ||
|
|
@@ -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 配置(选填) | ||
|
|
@@ -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; | ||
|
|
@@ -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); | ||
|
Comment on lines
+92
to
+96
|
||
| // todo ... | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -37,6 +37,14 @@ protected WxCpMultiServices wxCpMultiServices(WxCpMultiProperties wxCpMultiPrope | |||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||
| * 校验同一个企业下,agentId 是否唯一,避免使用 redis 缓存 token、ticket 时错乱。 | ||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||
| * <p>同一企业(corpId 相同)下可配置多个条目以使用不同的权限 Secret,例如: | ||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Severity: low Other Locations
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage. |
||||||||||||||||||||||||||||
| * <ul> | ||||||||||||||||||||||||||||
| * <li>自建应用条目:填写应用对应的 corpSecret 和 agentId</li> | ||||||||||||||||||||||||||||
| * <li>通讯录同步条目:填写通讯录同步 Secret,agentId 可不填(null)</li> | ||||||||||||||||||||||||||||
| * </ul> | ||||||||||||||||||||||||||||
| * 但同一 corpId 下不允许出现重复的 agentId(包括多个 null)。 | ||||||||||||||||||||||||||||
| * </p> | ||||||||||||||||||||||||||||
|
Comment on lines
+40
to
+46
|
||||||||||||||||||||||||||||
| * <p>同一企业(corpId 相同)下可配置多个条目以使用不同的权限 Secret,例如: | |
| * <ul> | |
| * <li>自建应用条目:填写应用对应的 corpSecret 和 agentId</li> | |
| * <li>通讯录同步条目:填写通讯录同步 Secret,agentId 可不填(null)</li> | |
| * </ul> | |
| * 但同一 corpId 下不允许出现重复的 agentId(包括多个 null)。 | |
| * </p> | |
| * <p>同一企业(corpId 相同)下可配置多个条目以使用不同的权限 Secret,例如:</p> | |
| * <ul> | |
| * <li>自建应用条目:填写应用对应的 corpSecret 和 agentId</li> | |
| * <li>通讯录同步条目:填写通讯录同步 Secret,agentId 可不填(null)</li> | |
| * </ul> | |
| * <p>但同一 corpId 下不允许出现重复的 agentId(包括多个 null)。</p> |
Copilot
AI
Apr 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
注释里说明“重复的 agentId(包括多个 null)”是对的,但当前唯一性校验实现用 null -> 0 做分组键,会把合法的 agentId=0 与 null 视为同一组并误判重复。建议改为对 null 使用不会与任何合法 agentId 冲突的哨兵值(例如 Integer.MIN_VALUE)或改为按 Objects.toString(agentId, "null") 分组。
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -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` 区分后使用。 | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Severity: medium Other Locations
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage. |
||||||||||||||||||
|
|
||||||||||||||||||
|
||||||||||||||||||
| > **配置限制说明**: | |
| > - 当前 starter/插件实现会校验:同一 `corp-id` 下,`agent-id` **必须唯一** | |
| > - 同一 `corp-id` 下,**只能有一个条目不填 `agent-id`** | |
| > - 否则会因为 token/ticket 缓存 key 冲突而在启动时直接抛异常 | |
| > | |
| > 因此,像“通讯录同步 Secret”“客户联系 Secret”这类通常不填写 `agent-id` 的配置,**不能**在同一个 `corp-id` 下同时配置多个都为空 `agent-id` 的条目;如确有多个条目,请确保其中最多只有一个未填写 `agent-id`` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
spring-boot-starters/wx-java-cp-multi-spring-boot-starter/README.md:96 这里示例调用 departmentService.update(department) 但 department 变量/类型在示例中未声明,读者直接复制会卡住。可以考虑补充部门对象的创建与其对应类型说明。
Severity: low
Other Locations
solon-plugins/wx-java-cp-multi-solon-plugin/README.md:96
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
Copilot
AI
Apr 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
此处示例代码里 departmentService.update(department); 的 department 变量未定义,示例无法直接编译/运行。建议补充 WxCpDepart 的构造/赋值示例(至少包含要更新的部门 id 与字段),或改成更明确的伪代码占位。
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -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> | ||||||||||||||||||||||||||||
|
Comment on lines
+43
to
+49
|
||||||||||||||||||||||||||||
| * <p>同一企业(corpId 相同)下可配置多个条目以使用不同的权限 Secret,例如: | |
| * <ul> | |
| * <li>自建应用条目:填写应用对应的 corpSecret 和 agentId</li> | |
| * <li>通讯录同步条目:填写通讯录同步 Secret,agentId 可不填(null)</li> | |
| * </ul> | |
| * 但同一 corpId 下不允许出现重复的 agentId(包括多个 null)。 | |
| * </p> | |
| * <p>同一企业(corpId 相同)下可配置多个条目以使用不同的权限 Secret,例如:</p> | |
| * <ul> | |
| * <li>自建应用条目:填写应用对应的 corpSecret 和 agentId</li> | |
| * <li>通讯录同步条目:填写通讯录同步 Secret,agentId 可不填(null)</li> | |
| * </ul> | |
| * <p>但同一 corpId 下不允许出现重复的 agentId(包括多个 null)。</p> |
Copilot
AI
Apr 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
注释里说明“重复的 agentId(包括多个 null)”是对的,但当前唯一性校验实现用 null -> 0 做分组键,会把合法的 agentId=0 与 null 视为同一组并误判重复。建议改为对 null 使用不会与任何合法 agentId 冲突的哨兵值(例如 Integer.MIN_VALUE)或改为按 Objects.toString(agentId, "null") 分组。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这里提到“可配置多个条目…通讯录同步条目不填 agent-id”,同时表格中也有多个“不填 agent-id”的 Secret 类型。需要补充说明:当前 starter/插件实现会校验同一
corp-id下agent-id必须唯一,且 只能有一个条目agent-id为空(否则 token/ticket 缓存 key 会冲突并直接抛异常)。否则用户可能按表格同时配置多个不填 agent-id 的条目而启动失败。