WechatAuthtimeController(企业微信集成管理)¶
管理企业域的企业微信集成配置:微信代理类型/CorpID/Secret/外网 host、扫码登录代理应用、测试扫码、企业微信组织架构同步与查询。
- 类级基址:
${myapps.context-path.manager:}/api/authtime(完整路径:{manager-context}/api/authtime<相对路径>) - Tag:微信配置模块
- 控制器源码:
obpm-manager/src/main/java/cn/myapps/manager/authtime/controller/wechat/WechatAuthtimeController.java - 公共说明:
- 类继承
BaseAuthTimeController,通过其success(errmsg, data)/error(errcode, errmsg, errors)返回统一Resource(字段errcode/errmsg/data/errors,结构见 ../index.md「统一响应结构」)。 - 几乎所有端点在
try/catch内捕获Exception并e.printStackTrace()后返回errcode=500、errmsg=e.getMessage()、data=null(HTTP 状态码仍为 200)。 - 鉴权说明见 index.md「鉴权说明」。
- 路径变量
domainid为企业域 id;applicationid为软件 id。
1. 微信配置¶
查询指定企业域的企业微信集成配置(代理类型、CorpID、通讯录 Secret、只读通讯录 AgentId/Secret、外网 serverHost、扫码登录 AgentId/Secret/CallbackUrl),并列出该域下所有软件的 weixinAgentId 与 weixinSecret。
- 接口类型:REST 资源
- 请求方式:
GET - 请求路径:
/domain/{domainid}/wechat(完整:{manager-context}/api/authtime/domain/{domainid}/wechat) - 鉴权:是(需管理员 accessToken,详见 index.md「鉴权说明」)
- Tag:微信配置模块
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| domainid | path | string | 是 | 企业域 id |
请求示例¶
响应¶
结构:统一 Resource(见 ../index.md「统一响应结构」)。
data:JSONObject,字段:
- weixinProxyType (string):微信代理类型
- weixinCorpID (string):企业微信 CorpID(启用企业微信组,必填)
- weixinCorpSecret (string):通讯录 Secret(双向同步读/写)
- weixinAgentId (string):只读通讯录应用 AgentId(单向同步读;存于 WEIXIN_CONFIG 保留键 EnterpriseWeChat)
- weixinSecret (string):只读通讯录应用 Secret(单向同步读;同上保留键)
- serverHost (string):外网访问 host
- weixinQrCodeAgentId (string):扫码登录代理应用 AgentId
- weixinQrCodeSecret (string):扫码登录代理应用 Secret
- weixinQrCodeCallbackUrl (string):扫码登录回调 URL
- weixinVerifyFileName (string):企业微信可信域名认证文件名(如 WW_verify_AIlEBTeMZWjzofq8.txt)
- weixinSyncRwEnable (boolean):是否开启双向同步(读/写)通讯录
- weixinSyncReadEnable (boolean):是否开启单向同步(读)通讯录
- weixinQrCodeEnable (boolean):是否开启扫码登录
- apps (array\<JSONObject>):软件列表,元素字段 id/name/description/weixinAgentId/weixinSecret
成功示例:
{
"errcode": 0,
"errmsg": "ok",
"data": {
"weixinProxyType": "EnterpriseWeChat",
"weixinCorpID": "ww1234567890abcdef",
"weixinCorpSecret": "***",
"weixinAgentId": "1000001",
"weixinSecret": "***",
"serverHost": "https://example.com",
"weixinQrCodeAgentId": "1000002",
"weixinQrCodeSecret": "***",
"weixinQrCodeCallbackUrl": "https://example.com/manager/api/qrcode/callback",
"weixinVerifyFileName": "WW_verify_AIlEBTeMZWjzofq8.txt",
"apps": [
{ "id": "__APPID1", "name": "协同办公", "description": "", "weixinAgentId": "1000003", "weixinSecret": "***" }
]
},
"errors": null
}
2. 保存微信配置¶
更新企业域的企业微信集成配置(代理类型、CorpID、通讯录 Secret、只读通讯录 AgentId/Secret、外网 host、扫码登录 AgentId/Secret/CallbackUrl)。CorpID/通讯录 Secret/serverHost 仅在字段非空且与原值不同时更新;只读通讯录与扫码三项与原值不同即更新(含空值)。任一字段变更会触发 doCreateOrUpdate 与微信 Secret 缓存清理。
- 接口类型:REST 资源
- 请求方式:
PUT - 请求路径:
/domain/{domainid}/wechat(完整:{manager-context}/api/authtime/domain/{domainid}/wechat) - 鉴权:是
- Tag:微信配置模块
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| domainid | path | string | 是 | 企业域 id |
请求体¶
JSON 对象(application/json):
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| weixinProxyType | string | 否 | 微信代理类型;空或与原值相同则不更新 |
| weixinCorpID | string | 否 | 企业微信 CorpID;空或与原值相同则不更新 |
| weixinCorpSecret | string | 否 | 通讯录 Secret(双向同步读/写);空或与原值相同则不更新 |
| weixinAgentId | string | 否 | 只读通讯录 AgentId;写入 WEIXIN_CONFIG 保留键 EnterpriseWeChat;与原值不同即更新(含空值) |
| weixinSecret | string | 否 | 只读通讯录 Secret;同上保留键;与原值不同即更新(含空值) |
| serverHost | string | 否 | 外网访问 host;空或与原值相同则不更新 |
| weixinQrCodeAgentId | string | 否 | 扫码登录代理应用 AgentId;与原值不同即更新(含空值) |
| weixinQrCodeSecret | string | 否 | 扫码登录代理应用 Secret;与原值不同即更新(含空值) |
| weixinQrCodeCallbackUrl | string | 否 | 扫码登录回调 URL;与原值不同即更新(含空值) |
| weixinSyncRwEnable | boolean | 否 | 双向同步(读/写)通讯录开关;写入 WEIXIN_SYNC_RW_ENABLE |
| weixinSyncReadEnable | boolean | 否 | 单向同步(读)通讯录开关;写入 WEIXIN_SYNC_READ_ENABLE |
| weixinQrCodeEnable | boolean | 否 | 扫码登录开关;写入 WEIXIN_QRCODE_ENABLE |
请求示例¶
PUT /api/authtime/domain/__P1UD2yVWpnFpUedONr/domain/wechat HTTP/1.1
Content-Type: application/json
{
"weixinProxyType": "EnterpriseWeChat",
"weixinCorpID": "ww1234567890abcdef",
"weixinCorpSecret": "new-secret",
"weixinAgentId": "1000001",
"weixinSecret": "contacts-read-secret",
"serverHost": "https://example.com",
"weixinQrCodeAgentId": "1000002",
"weixinQrCodeSecret": "new-qrcode-secret",
"weixinQrCodeCallbackUrl": "https://example.com/signon/api/runtime/login/wxqrcodelogin"
}
响应¶
结构:统一 Resource。
data:字符串 "保存成功"。
成功示例:
失败示例:2.1 上传企业微信域名认证文件¶
将企业微信后台下载的 WW_verify_xxx.txt 保存到存储目录 {storageRoot}/weixin-verify/,并把文件名写入该域 WEIXIN_CONFIG.verifyFileName。上传后企业微信访问 https://{host}/WW_verify_xxx.txt 由 WeixinDomainVerifyFilter 匿名返回文件原文。
- 接口类型:REST 资源
- 请求方式:
POST - 请求路径:
/domain/{domainid}/wechat/verifyfile(完整:{manager-context}/api/authtime/domain/{domainid}/wechat/verifyfile) - 鉴权:是
- Tag:微信配置模块
- Content-Type:
multipart/form-data
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| domainid | path | string | 是 | 企业域 id |
| file | form | file | 是 | 认证文件;原名必须匹配 ^WW_verify_[A-Za-z0-9]+\.txt$,大小不超过 16KB |
请求示例¶
POST /api/authtime/domain/__P1UD2yVWpnFpUedONr/wechat/verifyfile HTTP/1.1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary
------WebKitFormBoundary
Content-Disposition: form-data; name="file"; filename="WW_verify_AIlEBTeMZWjzofq8.txt"
Content-Type: text/plain
AIlEBTeMZWjzofq8
------WebKitFormBoundary--
响应¶
结构:统一 Resource。
data:JSONObject,字段 fileName。
成功示例:
{ "errcode": 0, "errmsg": "ok", "data": { "fileName": "WW_verify_AIlEBTeMZWjzofq8.txt" }, "errors": null }
公开访问(匿名,非本控制器):GET/HEAD /WW_verify_{token}.txt 返回 text/plain 文件内容;文件不存在则 HTTP 404。微服务需由网关将站点根路径反代到 manager。
2.2 测试扫码登录(开始)¶
生成一次性 ticket,并返回企业微信 PC 扫码组件(WwLogin)所需参数。扫码成功只记录 UserId,不登录系统。需已开启扫码登录并保存 CorpID / AgentId / Secret / CallbackUrl。
- 接口类型:REST 资源
- 请求方式:
POST - 请求路径:
/domain/{domainid}/wechat/qrcode/test(完整:{manager-context}/api/authtime/domain/{domainid}/wechat/qrcode/test) - 鉴权:是
- Tag:微信配置模块
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| domainid | path | string | 是 | 企业域 id |
响应¶
结构:统一 Resource。
data:JSONObject,字段:
- ticket (string):测试会话 id,同时作为 state
- appId (string):企业 CorpID
- agentId (string):扫码应用 AgentId
- redirectUri (string):测试回调绝对地址(未 URLEncode;前端交给 WwLogin 前需 encode)
- state (string):同 ticket
redirectUri 的协议与域名取自已保存的 weixinQrCodeCallbackUrl,路径为 {manager-context}/api/authtime/domain/{domainid}/wechat/qrcode/test/callback。
成功示例:
{
"errcode": 0,
"errmsg": "ok",
"data": {
"ticket": "a1b2c3d4e5f6",
"appId": "ww1234567890abcdef",
"agentId": "1000002",
"redirectUri": "https://example.com/manager/api/authtime/domain/__P1UD2yVWpnFpUedONr/wechat/qrcode/test/callback",
"state": "a1b2c3d4e5f6"
},
"errors": null
}
2.3 测试扫码登录(状态)¶
轮询 ticket:pending / success / fail / expired(约 5 分钟过期)。
- 接口类型:REST 资源
- 请求方式:
GET - 请求路径:
/domain/{domainid}/wechat/qrcode/test/status(完整:{manager-context}/api/authtime/domain/{domainid}/wechat/qrcode/test/status) - 鉴权:是
- Tag:微信配置模块
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| domainid | path | string | 是 | 企业域 id |
| ticket | query | string | 是 | 开始接口返回的 ticket |
响应¶
data:status、userId(成功时)、message。
成功示例:
{ "errcode": 0, "errmsg": "ok", "data": { "status": "success", "userId": "zhangsan", "message": "扫码成功" }, "errors": null }
2.4 测试扫码登录(回调)¶
企业微信扫码后重定向到此地址。匿名(无管理员 cookie)。用扫码应用 Secret 换 UserId 后写入 ticket,返回简易 HTML(可 postMessage 给父窗口)。不设置登录 cookie。
- 接口类型:页面
- 请求方式:
GET - 请求路径:
/domain/{domainid}/wechat/qrcode/test/callback - 鉴权:否
- Content-Type:
text/html;charset=UTF-8
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| domainid | path | string | 是 | 企业域 id |
| code | query | string | 否 | 企业微信授权码 |
| state | query | string | 是 | ticket |
| error | query | string | 否 | 企业微信错误码 |
3. 外网访问地址验证¶
校验所给企业微信 CorpID + 通讯录 Secret 能否换取 accessToken,并验证 serverHost 外网可访问其移动端静态首页。两步均通过才返回成功。
- 接口类型:REST 资源
- 请求方式:
GET - 请求路径:
/domain/{domainid}/wechat/corp/{corpid}/corpsecret/{corpsecret}(完整:{manager-context}/api/authtime/domain/{domainid}/wechat/corp/{corpid}/corpsecret/{corpsecret}) - 鉴权:是
- Tag:微信配置模块
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| domainid | path | string | 是 | 企业域 id |
| corpid | path | string | 是 | 企业微信 CorpID |
| corpsecret | path | string | 是 | 通讯录同步 Secret |
| serverHost | query | string | 是 | 待验证的外网 host;内部将其中的 /obpm 替换为 /,再拼 /static/mobile/index.html 验证 |
请求示例¶
GET /api/authtime/domain/__P1UD2yVWpnFpUedONr/domain/wechat/corp/ww1234567890abcdef/corpsecret/xxx-secret?serverHost=https://example.com/obpm HTTP/1.1
响应¶
结构:统一 Resource。
data:字符串 "验证成功" / 验证失败时 data=null。
| 条件 | errcode | errmsg | data |
|---|---|---|---|
| 取 accessToken 返回 null | 1 | 验证失败 | null |
| serverHost 静态页 HTTP 状态非 200 | 500 | serverHost (<host>) 无法访问 |
null |
| 验证成功 | 0 | ok | 验证成功 |
| 抛异常 | 500 | <异常信息> |
null |
成功示例:
失败示例:3.1 验证企业微信 Secret(access_token)¶
用企业 CorpID + 应用 Secret 调用企业微信 gettoken。拿到 access_token 即验证通过;响应中不返回 token。管理台「单向同步(读)通讯录」组的 验证 使用本接口(Secret 为开通通讯录权限的应用 Secret)。gettoken 本身不使用 AgentId,前端仍要求 AgentId、Secret 均已填写。
- 接口类型:REST 资源
- 请求方式:
GET - 请求路径:
/domain/{domainid}/wechat/accesstoken(完整:{manager-context}/api/authtime/domain/{domainid}/wechat/accesstoken) - 鉴权:是
- Tag:微信配置模块
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| domainid | path | string | 是 | 企业域 id |
| corpid | query | string | 是 | 企业微信 CorpID |
| corpsecret | query | string | 是 | 应用 Secret |
响应¶
data:成功时字符串 "验证成功"。
| 条件 | errcode | errmsg |
|---|---|---|
| CorpID 或 Secret 为空 | 4001 | CorpID或Secret为空 |
| gettoken 返回空 | 1 | 验证失败 |
| 验证成功 | 0 | ok |
| 抛异常 | 500 | 企业微信 errmsg 或异常信息 |
成功示例:
失败示例:4. 同步微信企业号组织架构到企业域¶
调用 DomainProcess.synchFromWeixin 从企业微信拉取组织架构并同步到本地企业域。
- 接口类型:REST 资源
- 请求方式:
PUT - 请求路径:
/domain/{domainid}/synchfromwechat(完整:{manager-context}/api/authtime/domain/{domainid}/synchfromwechat) - 鉴权:是
- Tag:微信配置模块
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| domainid | path | string | 是 | 企业域 id |
请求示例¶
响应¶
结构:统一 Resource。
data:net.sf.json.JSONObject,企业微信同步接口返回的结果(含 errcode/errmsg 等字段,由企业微信 API 决定)。
注:本端点未捕获异常,抛出时由 Spring 默认异常处理(HTTP 500,无统一
Resource体)。
成功示例:
{
"errcode": 0,
"errmsg": "ok",
"data": { "errcode": 0, "errmsg": "ok", "invaliduser": [], "invalidparty": [] },
"errors": null
}
5. 同步企业域组织架构到微信企业号¶
调用 DomainProcess.synch2Weixin 把本地企业域组织架构推送到企业微信。
- 接口类型:REST 资源
- 请求方式:
PUT - 请求路径:
/domain/{domainid}/synch2wechat(完整:{manager-context}/api/authtime/domain/{domainid}/synch2wechat) - 鉴权:是
- Tag:微信配置模块
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| domainid | path | string | 是 | 企业域 id |
请求示例¶
响应¶
结构:统一 Resource。
data:net.sf.json.JSONObject,企业微信同步接口返回的结果。
注:本端点未捕获异常,抛出时由 Spring 默认异常处理(HTTP 500,无统一
Resource体)。
成功示例:
6. 生成跳转链接¶
按企业域的企业微信 CorpID、应用 AgentId 与外网 host,生成 OAuth2 跳转链接(用于「进入系统」入口)。applicationid 取值为 KMAPPID 时生成 KMS 移动端入口;否则按软件 id 拼接 runtime 移动端入口。
- 接口类型:REST 资源
- 请求方式:
GET - 请求路径:
/domain/{domainid}/application/{applicationid}/getwechaturl(完整:{manager-context}/api/authtime/domain/{domainid}/application/{applicationid}/getwechaturl) - 鉴权:是
- Tag:微信配置模块
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| domainid | path | string | 是 | 企业域 id |
| applicationid | path | string | 是 | 软件 id;特殊值 KMAPPID 走 KMS 入口分支 |
请求示例¶
响应¶
结构:统一 Resource。
data:Map<String, String>,键固定为「进入系统」,值为 OAuth2 跳转 URL。
| 条件 | errcode | errmsg | data |
|---|---|---|---|
| AgentId 为空 | 500 | WeixinAgentId为空 |
null |
| CorpID 为空 | 500 | WeixinCorpID为空 |
null |
软件 id 非 KMAPPID 且软件不存在 |
1 | 查不对应的软件 |
null |
| 成功 | 0 | ok | { "进入系统": "<OAuth2 URL>" } |
| 抛异常 | 500 | <异常信息> |
null |
成功示例:
{
"errcode": 0,
"errmsg": "ok",
"data": {
"进入系统": "https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww...&redirect_uri=...&response_type=code&scope=snsapi_base&agentid=1000003&state=__P1UD2yVWpnFpUedONr#wechat_redirect"
},
"errors": null
}
7. 保存微信应用 AgentId¶
更新指定企业域下指定软件的企业微信应用 AgentId。
- 接口类型:REST 资源
- 请求方式:
PUT - 请求路径:
/domain/{domainid}/application/{applicationid}/updateWeixinAgentId(完整:{manager-context}/api/authtime/domain/{domainid}/application/{applicationid}/updateWeixinAgentId) - 鉴权:是
- Tag:微信配置模块
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| domainid | path | string | 是 | 企业域 id |
| applicationid | path | string | 是 | 软件 id |
| id | query | string | 是 | 企业微信应用 AgentId |
请求示例¶
PUT /api/authtime/domain/__P1UD2yVWpnFpUedONr/application/__APPID1/updateWeixinAgentId?id=1000003 HTTP/1.1
响应¶
结构:统一 Resource。
data:字符串 "保存成功"。
成功示例:
失败示例:8. 保存微信应用 secret¶
更新指定企业域下指定软件的企业微信应用 Secret。
- 接口类型:REST 资源
- 请求方式:
PUT - 请求路径:
/domain/{domainid}/application/{applicationid}/updateWeixinSecret(完整:{manager-context}/api/authtime/domain/{domainid}/application/{applicationid}/updateWeixinSecret) - 鉴权:是
- Tag:微信配置模块
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| domainid | path | string | 是 | 企业域 id |
| applicationid | path | string | 是 | 软件 id |
| secret | query | string | 是 | 企业微信应用 Secret |
请求示例¶
PUT /api/authtime/domain/__P1UD2yVWpnFpUedONr/application/__APPID1/updateWeixinSecret?secret=xxx HTTP/1.1
响应¶
结构:统一 Resource。
data:字符串 "保存成功"。
成功示例:
失败示例:9. 获取企业微信部门列表¶
按 parentid 拉取子部门列表(不含用户),每个部门标注 hasChild。
- 接口类型:REST 资源
- 请求方式:
GET - 请求路径:
/domain/{domainid}/wechat/departments(完整:{manager-context}/api/authtime/domain/{domainid}/wechat/departments) - 鉴权:是
- Tag:微信配置模块
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| domainid | path | string | 是 | 企业域 id |
| parentid | query | string | 否 | 父级部门 id;默认 0(根) |
请求示例¶
响应¶
结构:统一 Resource。
data:List<Department>。
成功示例:
{
"errcode": 0,
"errmsg": "ok",
"data": [
{ "id": 2, "name": "总部", "parentid": 0, "hasChild": true }
],
"errors": null
}
10. 获取企业微信用户列表¶
按部门 id 调用企业微信 API(QyApiService.getUsersByDepartment)拉取该部门下的用户列表。
- 接口类型:REST 资源
- 请求方式:
GET - 请求路径:
/domain/{domainid}/wechat/departments/{deptId}/users(完整:{manager-context}/api/authtime/domain/{domainid}/wechat/departments/{deptId}/users) - 鉴权:是
- Tag:微信配置模块
请求参数¶
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| domainid | path | string | 是 | 企业域 id |
| deptId | path | string | 是 | 部门 id(路径变量,必须提供) |
请求示例¶
响应¶
结构:统一 Resource。
data:List<User>。
成功示例:
失败示例: