第三方平台集成指南钉钉与企业微信扫码登录实战在多智能体平台、SaaS 系统或企业内部工具的开发中接入国内主流办公平台的扫码登录是提升用户体验的关键一环。本文将基于OAuth 2.0 授权码模式提供一份详尽的、可直接落地的钉钉与企业微信扫码登录集成代码与配置步骤。⚠️核心原则所有涉及AppSecret/ClientSecret的操作必须在服务端完成前端仅负责展示二维码和传递临时授权码AuthCode。一、 钉钉扫码登录集成 (DingTalk OAuth 2.0)钉钉已全面升级至 OAuth 2.0 协议旧版 SNS 接口已废弃。以下是基于新协议的完整流程。1. 开放平台配置登录 钉钉开发者后台创建「企业内部应用」。记录凭证Client ID(AppKey) 和Client Secret(AppSecret)。配置回调进入「登录与分享」添加授权回调域如https://yourdomain.com。申请权限确保开通Contact.User.Read读取用户基本信息及openid相关权限。2. 后端实现 (Python/FastAPI 示例)配置文件 (config.yaml)dingtalk_conf:client_id:dingxxxxxxxxclient_secret:your_client_secret# 必须与钉钉后台配置的回调地址完全一致redirect_uri:https://yourdomain.com/api/v1/auth/dingtalk/callback认证接口 (auth.py)importhttpxfromfastapiimportAPIRouter,HTTPExceptionfrompydanticimportBaseModel routerAPIRouter()classDingTalkCallbackReq(BaseModel):code:str# 前端传来的临时授权码router.get(/auth/dingtalk/url)asyncdefget_dingtalk_login_url():生成钉钉扫码登录URL供前端使用confsettings.DINGTALK_CONF params{redirect_uri:conf.redirect_uri,response_type:code,client_id:conf.client_id,scope:openid,prompt:consent}query.join(f{k}{v}fork,vinparams.items())return{url:fhttps://login.dingtalk.com/oauth2/auth?{query}}router.post(/auth/dingtalk/callback)asyncdefdingtalk_callback(req:DingTalkCallbackReq):用AuthCode换取Token并获取用户信息confsettings.DINGTALK_CONF# Step 1: 换取 AccessTokenasyncwithhttpx.AsyncClient()asclient:token_respawaitclient.post(https://api.dingtalk.com/v1.0/oauth2/userAccessToken,json{clientId:conf.client_id,clientSecret:conf.client_secret,code:req.code,grantType:authorization_code})iftoken_resp.status_code!200:raiseHTTPException(status_code400,detail获取钉钉Token失败)access_tokentoken_resp.json().get(accessToken)# Step 2: 获取用户信息user_respawaitclient.get(https://api.dingtalk.com/v1.0/contact/users/me,headers{x-acs-dingtalk-access-token:access_token})user_infouser_resp.json()# TODO: 根据 unionId 查询/创建本地用户生成系统JWTreturn{user:user_info,token:your_system_jwt}3. 前端实现 (React 官方SDK)// 引入钉钉登录SDK script srchttps://g.alicdn.com/dingding/dinglogin/0.4.7/dingLogin.js/script // 在组件中初始化 useEffect(() { DDLogin({ id: dd_qrcode_container, goto: encodeURIComponent(dingtalkLoginUrl), // 从后端 /auth/dingtalk/url 获取 style: border:none;background-color:#FFFFFF;, width: 365, height: 400 }); const handleMessage (event) { if (event.data.type dingtalk-login-success) { // 将 authCode 发送给后端 handleDingTalkCallback(event.data.code); } }; window.addEventListener(message, handleMessage); return () window.removeEventListener(message, handleMessage); }, [dingtalkLoginUrl]);二、 企业微信扫码登录集成 (WeCom OAuth 2.0)企业微信采用标准的 OAuth 2.0 构造链接方式无需额外 JS SDK通过 iframe 或重定向即可实现。1. 管理后台配置登录 企业微信管理后台进入「应用管理」→「自建应用」。记录凭证CorpID(企业ID)、AgentId(应用ID)、Secret(应用密钥)。配置可信域名在「网页授权及JS-SDK」中设置回调域名需验证文件所有权。注意扫码登录使用的是「企业微信授权登录」需在「客户联系」或「身份验证」中确认已开启。2. 后端实现 (Python/FastAPI 示例)配置文件 (config.yaml)wecom_conf:corp_id:wwxxxxxxxxxxxxxxagent_id:1000002secret:your_wecom_secretredirect_uri:https://yourdomain.com/api/v1/auth/wecom/callback认证接口 (auth.py)router.get(/auth/wecom/url)asyncdefget_wecom_login_url():构造企业微信扫码登录链接confsettings.WECOM_CONF params{appid:conf.corp_id,agentid:conf.agent_id,redirect_uri:urllib.parse.quote(conf.redirect_uri),response_type:code,scope:snsapi_base,# 静默授权如需手机号可用 snsapi_privateinfostate:generate_random_state()# 防CSRF攻击}query.join(f{k}{v}fork,vinparams.items())return{url:fhttps://login.work.weixin.qq.com/wwlogin/sso/login?{query}}router.get(/auth/wecom/callback)asyncdefwecom_callback(code:str,state:str):企业微信回调GET请求注意与钉钉POST不同confsettings.WECOM_CONF# Step 1: 获取 access_tokenasyncwithhttpx.AsyncClient()asclient:token_respawaitclient.get(https://qyapi.weixin.qq.com/cgi-bin/gettoken,params{corpid:conf.corp_id,corpsecret:conf.secret})access_tokentoken_resp.json().get(access_token)# Step 2: 获取用户身份user_respawaitclient.get(https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo,params{access_token:access_token,code:code})user_datauser_resp.json()useriduser_data.get(userid)# 企业内唯一标识# TODO: 根据 userid 关联本地账号签发JWT并重定向前端returnRedirectResponse(urlfhttps://yourdomain.com/login?tokenxxx)3. 前端实现企业微信无需专用 SDK直接使用 iframe 嵌入或按钮跳转// 方式一iframe 嵌入推荐体验类似钉钉 iframe src{wecomLoginUrl} width365 height400 frameBorder0 / // 方式二直接跳转 Button onClick{() window.location.href wecomLoginUrl} 企业微信扫码登录 /Button回调差异提示企业微信回调是GET 请求浏览器重定向而钉钉新版 SDK 回调是POST 请求前端 message 事件。后端接口设计时需特别注意区分。三、 关键差异对比与安全清单维度钉钉 (DingTalk)企业微信 (WeCom)协议版本OAuth 2.0 (新版)OAuth 2.0 (SSO)前端集成官方 JS SDK (DDLogin)iframe / URL 重定向回调方式POST (前端 message 事件)GET (浏览器 302 重定向)用户唯一标识unionId(跨应用统一)userid(企业内唯一)Token 获取/v1.0/oauth2/userAccessToken/cgi-bin/gettoken/cgi-bin/auth/getuserinfo状态参数(state)可选但推荐强烈推荐(防CSRF) 安全最佳实践Secret 零暴露永远不要在前端代码、环境变量公开文件或日志中出现 Secret。State 防 CSRF企业微信回调务必校验state参数防止恶意伪造授权请求。Token 缓存企业微信access_token有效期 2 小时钉钉userAccessToken同样 2 小时。必须做服务端缓存避免每次登录都请求官方接口触发限流。HTTPS 强制生产环境回调地址必须使用 HTTPS且证书有效。精确匹配redirect_uri在代码、配置文件、开放平台后台三处必须字符级完全一致包括末尾斜杠和端口号。错误兜底对用户取消扫码、二维码过期、网络超时等异常场景做好前端提示和重试机制。 本地调试方案由于扫码登录要求公网 HTTPS 回调地址本地开发推荐使用以下工具ngrok/cpolar/花生壳将本地端口映射为公网 HTTPS 地址。每次启动后更新config.yaml和开放平台后台的回调地址。钉钉提供「模拟器」可在客户端内调试减少反复修改配置的麻烦。四、 常见问题排查错误现象可能原因解决方案回调地址不匹配URI 拼写差异 / 协议不一致逐字符比对三处配置获取 Token 返回 invalid_codeAuthCode 已过期或重复使用AuthCode 一次性有效5分钟过期确保及时调用用户信息缺少手机号未申请对应权限在开放平台补充申请mobile字段权限企业微信提示“不安全的URL”可信域名未验证下载验证文件放置于域名根目录扫码后白屏前端 message 监听未生效检查 SDK 版本、容器 ID 是否正确总结钉钉和企业微信的扫码登录本质都是标准 OAuth 2.0 的实现核心难点不在代码本身而在配置的精确性和安全细节的把控。建议将上述配置项纳入项目的 CI/CD 检查清单避免因环境差异导致线上故障。如果本文对你有帮助欢迎点赞收藏。实际集成中遇到具体问题可在评论区交流讨论。