.NET微信网页开发之通过UnionID机制解决多应用用户帐号统一问题

背景

随着公司微信相关业务场景的不断拓展,从最初的一个微信移动应用、然后发展成微信公众号应用、然后又有了微信小程序应用。但是随着应用的拓展,如何保证相同用户的微信用户在不同应用中登录的同一个账号呢?今天的主题就来了.NET微信网页开发之通过UnionID机制解决多应用用户帐号统一问题。

UnionID 机制

如果开发者拥有多个移动应用、网站应用、和公众账号(包括小程序),可通过 UnionID 来区分用户的唯一性,因为只要是同一个微信开放平台账号下的移动应用、网站应用和公众账号(包括小程序),用户的 UnionID 是唯一的。换句话说,同一用户,对同一个微信开放平台下的不同应用,UnionID是相同的。

获取用户基本信息(UnionID机制)

在关注者与公众号产生消息交互后,公众号可获得关注者的OpenID(加密后的微信号,每个用户对每个公众号的OpenID是唯一的。对于不同公众号,同一用户的openid不同)。公众号可通过对应接口来根据OpenID获取用户基本信息,包括语言和关注时间。

请注意,如果开发者有在多个公众号,或在公众号、移动应用之间统一用户账号的需求,需要前往微信开放平台(open.weixin.qq.com)绑定公众号后,才可利用UnionID机制来满足上述需求。

微信开放平台配置

登录地址:https://open.weixin.qq.com/

微信公众号微信登录配置

在基本配置中获取微信公众号的appid和appsecrect(一定是要自己公众号的),白名单是你在本地调试的微信项目的时候需要添加的你本地的ip地址,不然获取不到你想要的accsee_token。

配置服务器地址(url):这里是你的项目与微信服务器通讯的地方,一定不能填错,Token是你项目中的,将其复制到这里即可,消息加密解密密钥是微信端随机生成的。

在微信公众号设置设置对应业务域名,js接口安全域名,以及网页授权域名:

微信网页公众号获取用户UnionID(用户统一标识)

注意:用户统一标识(针对一个微信开放平台账号下的应用,同一用户的 unionid 是唯一的),只有当scope为"snsapi_userinfo"时返回

用户同意授权获取code

在确保微信公众账号拥有授权作用域(scope参数)的权限的前提下(已认证服务号,默认拥有scope参数中的snsapi_base和snsapi_userinfo 权限),引导关注者打开如下页面:

若提示"该链接无法访问",请检查参数是否填写错误,是否拥有scope参数对应的授权作用域权限。跳转回调redirect_uri,应当使用https链接来确保授权code的安全性,并且是在微信公众号后台配置的网页授权域名的访问地址。

请求参数:

通过code获取用户UnionID(用户统一标识)

请求参数:

返回参数:

请求示例代码:

复制代码
`    public class WeChatLogin : Controller`
`    {`

`        /// <summary>`
`        /// 获取用户UnionID(用户统一标识)`
`        /// </summary>`
`        /// <param name="state">自定义参数</param>`
`        /// <param name="code">通过用户授权后得到的code</param>`
`        /// <returns></returns>`
`        public async Task<Response> GetWeChatUnionID(string state, string code)`
`        {`
`            string appId = "YourAppId";`
`            string appSecret = "YourAppSecret";`
`            string requestUrl = $"https://api.weixin.qq.com/sns/oauth2/access_token?appid={appId}&secret={appSecret}&code={code}&grant_type=authorization_code";`

`            using (var httpClient = new HttpClient())`
`            {`
`                var httpRequest = new HttpRequestMessage(HttpMethod.Get, requestUrl);`
`                using (var response = await httpClient.SendAsync(httpRequest))`
`                {`
`                    if (response.IsSuccessStatusCode)`
`                    {`
`                        var responseString = await response.Content.ReadAsStringAsync();`
`                        var responseData = JsonConvert.DeserializeObject<WeChatTokenResponse>(responseString);`

`                        return new Response`
`                        {`
`                            Code = 1,`
`                            Message = responseData.UnionId`
`                        };`
`                    }`
`                    else`
`                    {`
`                        var errorResponseString = await response.Content.ReadAsStringAsync();`
`                        var errorData = JsonConvert.DeserializeObject<ErrorResponse>(errorResponseString);`

`                        return new Response`
`                        {`
`                            Code = 0,`
`                            Message = $"Failed to get access token: {errorData.ErrMsg}"`
`                        };`
`                    }`
`                }`
`            }`
`        }`
`    }`

`    public class WeChatTokenResponse`
`    {`
`        [JsonProperty("access_token")]`
`        public string AccessToken { get; set; }`

`        [JsonProperty("expires_in")]`
`        public int ExpiresIn { get; set; }`

`        [JsonProperty("refresh_token")]`
`        public string RefreshToken { get; set; }`

`        [JsonProperty("openid")]`
`        public string OpenId { get; set; }`

`        [JsonProperty("scope")]`
`        public string Scope { get; set; }`

`        [JsonProperty("is_snapshotuser")]`
`        public int IsSnapshotUser { get; set; }`

`        [JsonProperty("unionid")]`
`        public string UnionId { get; set; }`
`    }`

`    public class ErrorResponse`
`    {`
`        [JsonProperty("errcode")]`
`        public int ErrCode { get; set; }`

`        [JsonProperty("errmsg")]`
`        public string ErrMsg { get; set; }`
`    }`

.NET微信网页开发相关文章教程

https://github.com/YSGStudyHards/DotNetGuide

DotNetGuide技术社区交流群

  • DotNetGuide技术社区是一个面向.NET开发者的开源技术社区,旨在为开发者们提供全面的C#/.NET/.NET Core相关学习资料、技术分享和咨询、项目推荐、招聘资讯和解决问题的平台。
  • 在这个社区中,开发者们可以分享自己的技术文章、项目经验、遇到的疑难技术问题以及解决方案,并且还有机会结识志同道合的开发者。
  • 我们致力于构建一个积极向上、和谐友善的.NET技术交流平台,为广大.NET开发者带来更多的价值和成长机会。

欢迎加入DotNetGuide技术社区微信交流群👪

参考文章

https://developers.weixin.qq.com/doc/offiaccount/User_Management/Get_users_basic_information_UnionID.html

相关推荐
追逐时光者4 小时前
一款.NET开源的屏幕实时翻译工具
【.net】·【c#】·【开源项目】·【实用工具】
追逐时光者1 天前
C# 单例模式的多种实现
【.net】·【c#】·【.net core】·【拾遗补漏】·【设计模式】
追逐时光者2 天前
一个.NET开源、轻量级的运行耗时统计库 - MethodTimer
【.net】·【c#】·【开源项目】·【.net core】·【拾遗补漏】
追逐时光者3 天前
2款使用.NET开发的数据库系统
【.net】·【c#】·【开源项目】·【.net core】
追逐时光者4 天前
.NET开发者福音:JetBrains官方宣布 Rider 非商用免费开放!
【.net】·【c#】·【实用工具】·【.net core】
追逐时光者6 天前
C#/.NET/.NET Core技术前沿周刊 | 第 11 期(2024年10.21-10.31)
【.net】·【c#】·【.net core】·【技术前沿周刊】
追逐时光者7 天前
C#/.NET/.NET Core优秀项目和框架2024年10月简报
【.net】·【c#】·【开源项目】·【实用工具】·【.net core】·【每月简报】
追逐时光者8 天前
一份阅读量30万+免费且全面的C#/.NET面试宝典
【.net】·【c#】·【.net core】·【wpf】·【winform】·【面试指南】
追逐时光者10 天前
基于Material Design风格开源、免费的WinForms UI控件库
【.net】·【c#】·【winform】
追逐时光者11 天前
.NET使用Moq开源模拟库简化单元测试
【.net】·【c#】·【开源项目】·【.net core】