
后端即时通讯金融科技【免费下载链接】WeiXinMPSDK微信全平台 .NET SDK Senparc.Weixin for C#支持 .NET Framework 及 .NET Core、.NET 10.0。已支持微信公众号、小程序、小游戏、微信支付、企业微信/企业号、开放平台、JSSDK、微信周边等全平台。 WeChat SDK for C#.项目地址https://gitcode.com/gh_mirrors/we/WeiXinMPSDK点击查看免费下载在开发企业微信WeChat Work应用时经常需要在网页端获取访问用户的 UserId、头像、称谓等身份信息。这要求网页与微信服务器之间通过 OAuth 2.0 协议完成一次授权登录闭环。本文以 Senparc.Weixin.Work SDK 的官方示例Samples/Work/Senparc.Weixin.Sample.Work为蓝本讲解企业微信网页授权登录的完整三步配置流程并深入到 SDK 源码src/Senparc.Weixin.Work剖析OAuth2Api.GetCode、OAuth2Api.GetUserIdAsync、MailListApi.GetMemberAsync等核心接口的底层实现。读完本文你将能够在自己的 ASP.NET Core或 .NET Framework MVC项目中用 3 个步骤快速接入企业微信网页授权正确处理snsapi_base/snsapi_userinfo两种授权方式并理解 code 有效期、刷新失效等实战要点。一、何时需要企业微信 OAuth 2.0 网页授权当网页需要获得访问者的 UserId、头像、称谓salutation等用户信息时就必须使用 OAuth 2.0 与企业微信服务器通信。SDK 已将授权相关的全部流程封装完毕开发者只需要参照示例完成简单的三步配置设置登录页在登录页放置官方 OAuth 2.0 请求 URL即AuthorizeUrl并携带登录成功后的returnUrl前端登录页跳转页面引导用户点击/打开 AuthorizeUrl配置登录后的回调页授权成功后微信自动跳转到回调地址SDK 用回调带来的code换取用户身份信息。企业微信网页授权存在两种作用域scopesnsapi_userinfo静默授权无需用户确认可直接获取用户身份snsapi_base需要用户确认授权可获得更详细的用户信息敏感信息需配合user_ticket。企业自建应用固定使用snsapi_base这也是OAuth2Api.GetCode的默认 scope该方式在所有场景下均兼容本文示例即围绕此方式展开。二、Step 1设置登录页生成 AuthorizeUrl在登录页的 Controller Action 中调用OAuth2Api.GetCode()生成授权链接并将登录成功后的回跳地址returnUrl一并传入。参考示例OAuth2Controller.cspublic IActionResult Index(string returnUrl) { // Set your own URL var url https://4424-222-93-135-159.ngrok.io; // This page directs the user to click on authorisation var oauthUrl OAuth2Api.GetCode(_corpId, ${url}/OAuth2/BaseCallback?returnUrl{returnUrl.UrlEncode()}, null, null);//snsapi_base way callback address ViewData[UrlBase] oauthUrl; ViewData[returnUrl] returnUrl; return View(); }其中_corpId与_corpSecret来自企业微信后台的应用配置通过Senparc.Weixin.Config.SenparcWeixinSetting[企业微信OAuth2.0]读取详见下文应用配置一节returnUrl通常是跳转到登录页之前的 URL也可以是你希望用户完成授权后前往的目标页面returnUrl.UrlEncode()将回跳地址做 URL 编码保证作为回调 URL 参数时不丢失语义。GetCode 方法的签名与 URL 拼接逻辑在 SDK 源码 OAuth2Api.cs 中GetCode的完整签名如下public static string GetCode(string corpId, string redirectUrl, string state, string agentId, string responseType code, string scope snsapi_base)各参数含义参数说明corpId企业的 CorpID即_corpIdredirectUrl授权后重定向的回调链接地址需先进行 URL 编码state重定向后原样带回的参数企业可填写a-zA-Z0-9的值用于防 CSRF 或业务标识agentId企业应用 ID。当 scope 为snsapi_userinfo或snsapi_privateinfo时必填且 redirect_uri 的域名必须与该应用的可信域名一致responseType返回类型固定为code默认值scope应用授权作用域企业自建应用固定为snsapi_base默认值示例中传入null, null即不携带state与agentId自建应用snsapi_base场景下二者非必填。其内部拼接出如下标准授权地址https://open.weixin.qq.com/connect/oauth2/authorize?appid{corpId}redirect_uri{redirectUrl}response_typecodescopesnsapi_basestate{state}#wechat_redirect注意#wechat_redirect是微信终端用来判断是否需要携带身份信息的参数。用户点击该链接后页面会跳转至redirect_uri/?codeCODEstateSTATE企业即可根据code参数换取员工的 UserId。注意上述 URL 与路径中的域名必须在企业微信管理后台将该应用的回调域名配置为你自己服务器的公网地址如示例中的 ngrok 域名仅为演示用途。三、Step 2前端登录页引导用户授权登录页的最终职责是把用户引导到AuthorizeUrl。最简单的做法是直接输出一个链接。参考示例视图Views/OAuth2/Index.cshtmla hrefViewData[UrlBase]Click here to test snsapi_base/a该示例页面还提供了调试辅助信息显示当前returnUrl状态——若不带returnUrl授权完成后会停留在 Callback 页面此时刷新或后退会导致code过期报错仅建议测试阶段使用携带returnUrl后页面最终会跳转到returnUrl对应页面避免刷新导致code失效同时用textarea展示将要链接到的完整授权地址方便开发者核对参数。四、Step 3配置授权成功后的回调页授权成功后微信会自动跳转到第一步设定的回调地址即${url}/OAuth2/BaseCallback?returnUrl{returnUrl.UrlEncode()}。回调 Action 需要完成三步操作校验 code → 用 code 换取 UserId → 用 UserId 获取成员详情。public async TaskActionResult BaseCallback(string code, string returnUrl) { if (string.IsNullOrEmpty(code)) { return Content(You have declined authorisation!); } try { var appKey AccessTokenContainer.BuildingKey(_workWeixinSetting); var accessToken await AccessTokenContainer.GetTokenAsync(_corpId, _corpSecret); // Get user information var oauthResult await OAuth2Api.GetUserIdAsync(accessToken, code); var userId oauthResult.UserId; GetMemberResult result await MailListApi.GetMemberAsync(appKey, userId); if (result.errcode ! ReturnCode_Work.请求成功) { return Content(Error: result.errmsg); } ViewData[returnUrl] returnUrl; /* Caution: * In the actual scenario, you should jump to returnUrl instead of staying on the Callback page. * Because when the user refreshes the URL of this page, the actual code and other parameters * are invalid, and the user will get an error message. */ return View(result); } catch (Exception ex) { return Content(Error: ex.Message); } }4.1 AccessToken 的获取容器与缓存AccessTokenContainer.BuildingKey(_workWeixinSetting)根据配置对象生成缓存的 KeyAppKeyAccessTokenContainer.GetTokenAsync(_corpId, _corpSecret)从容器中获取必要时自动刷新企业微信 AccessToken。SDK 的 AccessToken 容器负责令牌的自动获取与过期刷新开发者无需手工维护令牌有效期这也是与微信服务器交互前必须完成的一步。4.2 用 code 换取访问用户身份OAuth2Api.GetUserIdAsync在源码 OAuth2Api.cs 中的实现为public static async TaskGetUserInfoResult GetUserIdAsync(string accessToken, string code) { var url string.Format(Config.ApiWorkHost /cgi-bin/auth/getuserinfo?access_token{0}code{1}, accessToken.AsUrlData(), code.AsUrlData()); return await CommonJsonSend.SendAsyncGetUserInfoResult(null, url, null, CommonJsonSendType.GET) .ConfigureAwait(false); }它对应官方接口GET /cgi-bin/auth/getuserinfo返回结果类型为GetUserInfoResult定义于 OAuth2Result.cs关键字段包括字段说明UserId员工 UserID企业成员授权时返回OpenId非企业成员的 OpenIduser_ticket成员票据最大 512 字节当 scope 为snsapi_userinfo或snsapi_privateinfo且用户在应用可见范围内时返回expires_inuser_ticket 的有效时间秒external_userid外部联系人 id用户是企业的客户且跟进人在应用可见范围内时返回DeviceId手机设备号由微信在安装时随机生成需要特别注意的是code的使用约束源码注释中亦明确标注每次员工授权带上的 code 不一样code 只能使用一次5 分钟未被使用将自动过期。因此回调逻辑中拿到 code 后应立即换取身份信息。4.3 根据 UserId 获取成员详情示例中随后调用MailListApi.GetMemberAsync(appKey, userId)获取成员详细信息姓名、头像、部门、职位等底层请求为/cgi-bin/user/get见 MailListApi.cspublic static GetMemberResult GetMember(string accessTokenOrAppKey, string userId) { return ApiHandlerWapper.TryCommonApi(accessToken { var url string.Format(Config.ApiWorkHost /cgi-bin/user/get?access_token{0}userid{1}, accessToken.AsUrlData(), userId.AsUrlData()); return CommonJsonSend.SendGetMemberResult(null, url, null, CommonJsonSendType.GET); }, accessTokenOrAppKey); }注意这里的第一个参数是accessTokenOrAppKey——ApiHandlerWapper.TryCommonApi会自动识别传入的是 AppKey 还是 AccessToken并自动完成令牌解析这正是上一步用AccessTokenContainer.BuildingKey构建appKey的原因。4.4 敏感信息GetUserDetail可选若授权 scope 为snsapi_userinfo/snsapi_privateinfo且需要在拿到user_ticket后进一步获取手机号、邮箱、个人二维码等敏感信息可调用OAuth2Api.GetUserDetailAsync(accessToken, userTicket)对应/cgi-bin/auth/getuserdetail。返回的GetUserDetailResultOAuth2Result.cs包含userid、name、department、position、mobile、gender、email、avatar、qr_code、biz_mail、address等字段其中mobile、email、qr_code、biz_mail、address仅在用户同意snsapi_privateinfo授权时返回。兼容性说明旧版GetUserId(string accessToken, string code, string agentId)与GetUserIdAsync(accessToken, code, agentId)重载已被标记为[Obsolete]请使用新方法 GetUserId(string accessToken, string code)新代码应直接使用不带agentId的版本。五、应用配置corpId 与 corpSecret 的来源示例 Controller 的构造函数从 SDK 全局配置中读取应用凭据_workWeixinSetting Senparc.Weixin.Config.SenparcWeixinSetting[企业微信OAuth2.0]; _corpId _workWeixinSetting.WeixinCorpId; _corpSecret _workWeixinSetting.WeixinCorpSecret;对应的配置文件为 appsettings.json。企业微信相关的顶层配置项包括WeixinCorpId: #{WeixinCorpId}#, WeixinCorpAgentId: #{WeixinCorpAgentId}#, WeixinCorpSecret: #{WeixinCorpSecret}#, WeixinCorpToken: #{WeixinCorpToken}#, WeixinCorpEncodingAESKey: #{WeixinCorpEncodingAESKey}#,当企业需要同时管理多个企业微信应用时可通过Items增加命名配置节例如企业微信OAuth2.0配置节名即SenparcWeixinSetting的索引 KeyItems: { 企业微信审批: { WeixinCorpId: #{WeixinCorpId2}#, WeixinCorpAgentId: #{WeixinCorpAgentId2}#, WeixinCorpSecret: #{WeixinCorpSecret2}# }, 企业微信OAuth2.0: { WeixinCorpId: #{WeixinCorpId3}#, WeixinCorpAgentId: #{WeixinCorpAgentId3}#, WeixinCorpSecret: #{WeixinCorpSecret3}# } }配置文件的注释明确提示所有字符串值都可能被用于字典索引因此请勿留空字符串不使用的参数可以删除但修改 key 后 SDK 将无法自动识别。实际部署时请将#{...}#占位符替换为你自己的真实凭据。六、回调页视图与完整登录闭环授权成功的回调视图 Views/OAuth2/BaseCallback.cshtml 以GetMemberResult为模型展示了授权后能拿到的信息userid、address、alias、avatar头像图片、biz_mail、department、email、name、mobile、position、gender、open_userid、qr_code等。至此完整的闭环逻辑是用户访问受保护页面携带returnUrl→ 被引导至IndexIndex用OAuth2Api.GetCode生成 AuthorizeUrl页面展示授权链接用户点击授权 → 微信回调BaseCallback?code...returnUrl...回调中用code换取 UserId再用 UserId 获取成员详情实际生产场景中应使用returnUrl跳转回登录前页面而不是停留在 Callback 页面——因为用户刷新 Callback 页面时URL 中的code等参数已失效用户会收到错误信息示例代码与页面注释均对此作出了明确警示。七、源码参考索引授权示例控制器Samples/Work/Senparc.Weixin.Sample.Work/Controllers/OAuth2Controller.cs授权入口视图Samples/Work/Senparc.Weixin.Sample.Work/Views/OAuth2/Index.cshtml授权回调视图Samples/Work/Senparc.Weixin.Sample.Work/Views/OAuth2/BaseCallback.cshtml应用配置文件Samples/Work/Senparc.Weixin.Sample.Work/appsettings.jsonOAuth2 接口实现src/Senparc.Weixin.Work/Senparc.Weixin.Work/AdvancedAPIs/OAuth2/OAuth2Api.csOAuth2 返回结果模型src/Senparc.Weixin.Work/Senparc.Weixin.Work/AdvancedAPIs/OAuth2/OAuth2Result.cs通讯录成员接口src/Senparc.Weixin.Work/Senparc.Weixin.Work/AdvancedAPIs/MailList/MailListApi.cs本文对应的英文原始文档docs/en/guide/work/oauth2.0.md掌握以上三步配置与源码调用链后你便可以在自己的企业微信应用中快速完成网页授权登录并规避code一次性使用、刷新失效等常见坑点。赞分享后端即时通讯金融科技【免费下载链接】WeiXinMPSDK微信全平台 .NET SDK Senparc.Weixin for C#支持 .NET Framework 及 .NET Core、.NET 10.0。已支持微信公众号、小程序、小游戏、微信支付、企业微信/企业号、开放平台、JSSDK、微信周边等全平台。 WeChat SDK for C#.项目地址https://gitcode.com/gh_mirrors/we/WeiXinMPSDK点击查看免费下载相关推荐Real-Time Video Face Detection with Dlib and OpenCV: A Practical Guide from the faceai ProjectReal Time Video Face Detection with Dlib and OpenCV: A Practical Guide from the计算机视觉人工智能深度学习Data Visualization Principles and Dashboard Design: A Practical Guide from the Easy-Vibe ProjectData Visualization Principles and Dashboard Design: A Practical Guide from the E教程文档KernelSU 安装指南LKM 与 GKI 双模式原理、KMI 匹配与完整刷写实战KernelSU 安装指南LKM 与 GKI 双模式原理、KMI 匹配与完整刷写实战 本文以 KernelSU 官方安装文档为主体系统讲解在 Android人工智能大模型微调模型推理服务上一篇FastSAM API完全指南如何快速上手50倍加速的Segment Anything模型下一篇rsuite Avatar 头像加载失败后备方案Fallback深入解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考