跳到主要内容

企业微信登录

本方案用「自定义 OAuth 2.0 身份源 + 云托管中转服务」完成企业微信自建应用登录。中转服务对 CloudBase 扮演标准 OAuth 2.0 授权服务器,对企业微信调用网页授权接口,把两套协议对齐。

企业微信授权后直接把 code 回跳给云开发,中转服务不承接浏览器回调。所有对企业微信接口的请求都从云托管固定公网出口 IP 发出,把这个 IP 填进企业微信「企业可信 IP」,无需自建 NAT 网关或 EIP。

平台支持

仅支持 Web 端,且页面需在企业微信客户端内置浏览器中打开。小程序端不支持。

协议差异​

环节标准 OAuth 2.0企业微信网页授权
授权请求client_id redirect_uri response_type=code scopeappid agentid redirect_uri scope=snsapi_base
换取凭证POST 到 Token 端点,客户端凭证随请求体或 Basic Header先取企业 access_token,再用 code 换 UserId
用户信息标准 claims:sub name email phone_numberauth/getuserinfo 与 auth/getuserdetail,字段为 userid mobile email
来源 IP无限制需配置企业可信 IP,否则返回 60020

差异全部由中转服务消化,CloudBase 侧只配置一个标准 OAuth 2.0 身份源。

方案结构​

组件职责
业务页面未登录时跳转托管登录页或发起 OAuth 授权,回调后读取 Session
CloudBase 身份认证发起 OAuth 授权,接收企业微信回跳的 code,换 Token、拉取用户信息,创建用户并签发 Session
云托管中转服务翻译授权参数;用 CloudBase 传入的 CorpID 与 Secret 调企业微信接口换 UserId;签发自己的 access_token
企业微信展示页面授权,颁发 code,返回 UserId 与敏感字段

前置条件​

项要求
云开发环境个人版及以上套餐,固定公网出口 IP 依赖套餐能力
云托管服务已部署,可绑定公网域名,并启用固定公网出口 IP
企业微信已创建自建应用,持有 CorpID、AgentId、Secret
域名云开发回调地址的域名已加入企业微信可信域名并完成归属校验

第一步:配置企业微信自建应用​

  1. 企业微信管理后台 → 应用管理 → 自建,创建应用,记录 AgentId 与 Secret
  2. 我的企业 → 企业信息,记录 CorpID
  3. 应用详情 → 网页授权及JS-SDK → 设置可信域名,填写云开发回调地址的域名,并按提示把 WW_verify_xxx.txt 放到该域名根目录完成校验
  4. 应用详情 → 开发者接口 → 企业可信IP,填入云托管服务的固定公网出口 IP

⚠️ 未配置企业可信 IP 时,调用 qyapi.weixin.qq.com 返回 60020 not allow to access from your ip。

可信域名约束的是授权链接里的 redirect_uri。本方案 redirect_uri 指向云开发回调地址,因此校验的是云开发回调域名,不是中转服务域名。

第二步:部署云托管中转服务​

对外接口​

路径方法作用调用方
/authorizeGET把标准 OAuth 授权请求翻译成企业微信授权链接,302 给浏览器CloudBase
/tokenPOST用企业微信回跳的 code 换 UserId,签发 access_tokenCloudBase
/userinfoGET用 Bearer access_token 换标准用户信息CloudBase

不需要回调路径。企业微信把 code 直接回跳给云开发,中转服务只在服务端被调用。

环境变量​

# 自建应用的 AgentId,应用详情页获取
WECOM_AGENT_ID=1000002

# 允许的云开发回调地址,多个用逗号分隔,精确匹配
CLOUDBASE_REDIRECT_URIS=https://{envId}.{region}.tcb-api.tencentcloudapi.com/auth/v1/callback

CorpID 与 Secret 不在中转服务里配置:CloudBase 会把身份源里填的 Client ID 与 Client Secret 传过来,中转服务直接用它们当 corpid 与 corpsecret。

授权端点​

接收 client_id、redirect_uri、response_type、state、scope,做两件事后 302:

  1. 校验 redirect_uri 与 CLOUDBASE_REDIRECT_URIS 中的某一项完全一致,不一致直接返回 400
  2. 拼企业微信授权链接:appid 直接用 client_id(即企业 CorpID),redirect_uri 与 state 原样透传
https://open.weixin.qq.com/connect/oauth2/authorize
?appid={client_id}
&redirect_uri={urlencode(CloudBase 传入的 redirect_uri)}
&response_type=code
&scope=snsapi_base
&state={CloudBase 传入的 state}
&agentid={WECOM_AGENT_ID}
#wechat_redirect

redirect_uri 与 state 都原样透传:企业微信回跳时直接落到云开发,state 由云开发自己校验。透传的前提是上面第 1 条的白名单校验,否则等于开放重定向。授权阶段拿不到 client_secret,client_id 是否有效留给 /token 由企业微信判定。

Token 端点​

/token 收到的是企业微信回跳的 code,不是中转服务自己签发的 code。按 grant_type=authorization_code 处理:

  1. 从请求体或 Basic Header 取 client_id 与 client_secret,两种都要支持
  2. GET https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={client_id}&corpsecret={client_secret} 取企业 access_token,缓存 7200 秒并提前刷新。凭证是否正确由企业微信判定,失败返回 40001,中转服务转成 invalid_client
  3. GET https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo?access_token={TOKEN}&code={CODE} 取 UserId
  4. 需要手机号或邮箱时,授权链接的 scope 改为 snsapi_privateinfo,再用返回的 user_ticket 调 POST https://qyapi.weixin.qq.com/cgi-bin/auth/getuserdetail
  5. 签发中转服务自己的 access_token,返回 CloudBase
{
"access_token": "eyJhbGciOiJIUzI1NiJ9...",
"token_type": "Bearer",
"expires_in": 3600
}

code 一次性且 5 分钟有效,重复提交会失败。企业 access_token 在多实例间共享,建议存入 Redis 或数据库,避免并发刷新导致旧 Token 失效。

自己的 access_token 建议用 JWT 承载 userid、name、email 等字段,/userinfo 验签即可,不必回查会话存储。

用户信息端点​

GET /userinfo 从 Authorization: Bearer {access_token} 解出用户信息,转成标准 claims:

{
"sub": "zhangsan",
"name": "张三",
"picture": "https://example.com/avatar.png",
"email": "zhangsan@example.com",
"phone_number": "13800000000"
}

sub 用企业微信 UserId。同一企业内 UserId 唯一且稳定,改名、换手机号都不变,是跨次登录的唯一身份锚点。

部署与固定出口 IP​

下面以云托管为例。换成其他具备固定公网出口 IP 的服务同样可行。

  1. 云托管 → 服务 → 部署,任意语言,监听 PORT
  2. 服务详情页记录公网默认域名,作为身份源三个端点的域名
  3. 服务设置 → 网络设置 → 启用「固定公网出口 IP」
  4. 把该 IP 填入企业微信「企业可信 IP」

⚠️ 服务同时启用私有网络时,公网请求会默认路由进 VPC,此时需要配 NAT 网关,并用 NAT 网关的出口 IP 作为可信 IP。

第三步:配置云开发身份源​

  1. 云开发控制台 → 身份认证 → 企业身份源 → 添加自定义 OAuth 2.0 身份源
  2. 按下表填写。三个端点都指向中转服务所在的云托管服务:到该服务详情页复制公网默认域名(或已绑定的自定义域名),后面分别拼上 /authorize、/token、/userinfo,不要手写域名
配置项值
身份源名称企业微信
授权端点云托管服务域名 + /authorize
Token 端点云托管服务域名 + /token
用户信息端点云托管服务域名 + /userinfo
Client ID企业 CorpID,企业微信管理后台「我的企业 → 企业信息 → 企业 ID」
Client Secret自建应用的 Secret,应用详情页获取
Scopeopenid,中转服务按需解析
回调地址控制台生成的 https://{envId}.{region}.tcb-api.tencentcloudapi.com/auth/v1/callback,同时填进中转服务的 CLOUDBASE_REDIRECT_URIS
认证方式CLIENT_SECRET_POST
自动注册开启时首次登录即创建用户;关闭时需先注册再绑定身份源
  1. 身份认证 → 托管登录页,勾选「企业微信」并保存

登录时序​

联调检查​

现象排查点
企业微信提示 redirect_uri 参数错误授权链接的 redirect_uri 域名不在可信域名内,或 redirect_uri 未做 urlencode
企业微信提示 50001 redirect_url 未登记可信域名可信域名填的是中转服务域名,应填云开发回调地址的域名
/token 或 /userinfo 日志出现 60020企业可信 IP 未填、填错,或云托管未启用固定公网出口 IP
CloudBase 报 invalid_clientClient ID 填成了 CorpID 以外的值,或 Secret 不是自建应用 Secret;也可能是认证方式应为 CLIENT_SECRET_BASIC 却配成 CLIENT_SECRET_POST
登录成功但无手机号、邮箱授权 scope 仍是 snsapi_base,未改 snsapi_privateinfo 或未调 getuserdetail
首次登录提示用户不存在身份源关闭了自动注册,需先注册再用 bindWithProvider 绑定
授权端点返回 404 或超时端点域名不是云托管服务的公网默认域名,或服务的公网访问被关闭
打开页面没有任何跳转页面不在企业微信客户端内置浏览器中,企业微信网页授权不对外部浏览器生效

常见问题​

Q:中转服务为什么不需要回调地址?

企业微信只认一个 redirect_uri。把它指向云开发回调地址,code 就直达云开发,再由云开发转给中转服务的 /token。中转服务少一个公网回调入口,也少一份 state 存储和会话映射。

Q:可信域名为什么填云开发的域名?

企业微信校验的是 redirect_uri 的域名。本方案回跳目标是云开发回调地址,所以可信域名填云开发回调域名,与中转服务所在的云托管默认域名无关。

Q:中转服务必须用云托管吗?

不强制。选云托管的原因是它提供固定公网出口 IP,这是接入企业微信的硬要求,与企业微信是否内网互通无关。开发者用其他具备固定公网出口 IP 的服务同样可行。

Q:一个中转服务可以服务多个企业吗?

不可以。企业微信把一个可信 IP 绑定到一个企业,一个出口 IP 只能服务一个企业。要接入多个企业,就为每个企业单独部署一套中转服务,各自绑定独立的固定公网出口 IP。

相关文档​