From d41d6eddd82ff4cec450b7a6d0d750f55cb8175a Mon Sep 17 00:00:00 2001 From: AnonymousDotNet <18776095145@163.com> Date: Fri, 13 Dec 2024 19:29:12 +0800 Subject: [PATCH] wip: Integrated WeChat login --- .../Repositories/IBotSharpRepository.cs | 2 +- .../Users/IWeChatUserService.cs | 2 + .../Users/Models/WeChatUser.cs | 22 ++++- .../Users/Services/WeChatUserService.cs | 88 ++++++++++++++++++- .../Controllers/UserController.cs | 15 +++- .../Collections/WeChatUserDocument.cs | 3 - .../Repository/MongoRepository.WeChatUser.cs | 6 +- src/WebStarter/appsettings.json | 10 +++ 8 files changed, 132 insertions(+), 16 deletions(-) diff --git a/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs b/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs index da5b2f3f..aafb5b5f 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs @@ -51,7 +51,7 @@ public interface IBotSharpRepository : IHaveServiceProvider bool UpdateUser(User user, bool updateUserAgents = false) => throw new NotImplementedException(); WeChatUser? GetWeChatUser(string openId) => throw new NotImplementedException(); - WeChatUser? CreateWeChatUser(WeChatUser weChatUser) => throw new NotImplementedException(); + WeChatUser CreateWeChatUser(WeChatUser weChatUser) => throw new NotImplementedException(); WeChatUser? UpdateWeChatUser(WeChatUser weChatUser) => throw new NotImplementedException(); #endregion diff --git a/src/Infrastructure/BotSharp.Abstraction/Users/IWeChatUserService.cs b/src/Infrastructure/BotSharp.Abstraction/Users/IWeChatUserService.cs index b25ba73d..a6b69865 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Users/IWeChatUserService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Users/IWeChatUserService.cs @@ -9,4 +9,6 @@ public interface IWeChatUserService Task CreateWeChatUser(WeChatUser weChatUser); Task UpdateWeChatUser(WeChatUser weChatUser); + + Task WeChatUserLogin(string code); } diff --git a/src/Infrastructure/BotSharp.Abstraction/Users/Models/WeChatUser.cs b/src/Infrastructure/BotSharp.Abstraction/Users/Models/WeChatUser.cs index 511ef236..165787a0 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Users/Models/WeChatUser.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Users/Models/WeChatUser.cs @@ -1,3 +1,5 @@ +using BotSharp.Abstraction.Users.Enums; + namespace BotSharp.Abstraction.Users.Models; public class WeChatUser @@ -9,8 +11,6 @@ public class WeChatUser /// public string OpenId { get; set; } = string.Empty; - public string SessionKey { get; set; } = string.Empty; - /// /// User unique identifier (cross application unique, requiring open platform binding) /// @@ -52,4 +52,22 @@ public class WeChatUser public DateTime? UpdatedAt { get; set; } public DateTime CreatedAt { get; set; } + + public User ToUser() + { + return new User + { + Id = Id, + Phone = PhoneNumber, + UserName = PhoneNumber, + FirstName = PhoneNumber, + LastName = PhoneNumber, + Email = null, + Password = string.Empty, + Role = UserRole.User, + Type = UserType.Client, + RegionCode = "CN", + ReferralCode = null, + }; + } } diff --git a/src/Infrastructure/BotSharp.Core/Users/Services/WeChatUserService.cs b/src/Infrastructure/BotSharp.Core/Users/Services/WeChatUserService.cs index ab776b28..d79c1648 100644 --- a/src/Infrastructure/BotSharp.Core/Users/Services/WeChatUserService.cs +++ b/src/Infrastructure/BotSharp.Core/Users/Services/WeChatUserService.cs @@ -1,23 +1,30 @@ using BotSharp.Abstraction.Users.Models; +using Microsoft.Extensions.Configuration; +using Newtonsoft.Json.Linq; namespace BotSharp.Core.Users.Services; public class WeChatUserService : IWeChatUserService { private readonly IServiceProvider _services; - public WeChatUserService(IServiceProvider services) + private readonly ILogger _logger; + private readonly IConfiguration _configuration; + + public WeChatUserService(IServiceProvider services, ILogger logger, IConfiguration configuration) { _services = services; + _logger = logger; + _configuration = configuration; } public async Task GetWeChatUser(string openId) { - var db = _services.GetRequiredService(); + var db = _services.GetRequiredService(); var weChatUser = db.GetWeChatUser(openId); return weChatUser; } - public async Task CreateWeChatUser(WeChatUser weChatUser) + public async Task CreateWeChatUser(WeChatUser weChatUser) { var db = _services.GetRequiredService(); return db.CreateWeChatUser(weChatUser); @@ -28,4 +35,79 @@ public class WeChatUserService : IWeChatUserService var db = _services.GetRequiredService(); return db.UpdateWeChatUser(weChatUser); } + + #region 微信扫码登录(OAuth 2.0 网页授权) + + public async Task WeChatUserLogin(string code) + { + // 实现获取 access_token 和 openid,再获取用户信息 + if (string.IsNullOrEmpty(code)) + { + _logger.LogError("Create WeChatUser Error: code is empty, Please check if the code has been obtained correctly!"); + throw new Exception("code is empty"); + } + + var appId = _configuration["WeChatQtoss:AppId"] ?? throw new Exception("AppId is not configured."); + var appSecret = _configuration["WeChatQtoss:AppSecret"] ?? throw new Exception("AppSecret is not configured."); + + try + { + // Step 1: 使用 code 获取 access_token 和 openid + var tokenUrl = $"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 tokenResponse = await httpClient.GetStringAsync(tokenUrl); + + var tokenData = JObject.Parse(tokenResponse); + var accessToken = tokenData["access_token"]?.ToString(); + var openId = tokenData["openid"]?.ToString(); + + if (string.IsNullOrEmpty(accessToken) || string.IsNullOrEmpty(openId)) + { + _logger.LogError("Create WeChatUser Error: Failed to get access_token or openid"); + throw new Exception("Failed to get access_token or openid"); + } + + // Step 2: Retrieve user information using access_token and openid + var userInfoUrl = $"https://api.weixin.qq.com/sns/userinfo?access_token={accessToken}&openid={openId}&lang=zh_CN"; + + var userInfoResponse = await httpClient.GetStringAsync(userInfoUrl); + var userInfo = JObject.Parse(userInfoResponse); + + // 提取用户信息 + var nickname = userInfo["nickname"]?.ToString() ?? string.Empty; + var avatar = userInfo["headimgurl"]?.ToString() ?? string.Empty; + var country = userInfo["country"]?.ToString() ?? string.Empty; + var province = userInfo["province"]?.ToString() ?? string.Empty; + var city = userInfo["city"]?.ToString() ?? string.Empty; + var sex = userInfo["sex"]?.ToString() ?? "0"; + var privilege = userInfo["privilege"]?.ToString() ?? string.Empty; + var unionId = userInfo["unionId"]?.ToString() ?? string.Empty; + + // 创建或更新 WeChatUser + var weChatUser = new WeChatUser + { + OpenId = openId, + NickName = nickname, + Sex = int.Parse(sex), + Province = province, + City = city, + Country = country, + Headimgurl = avatar, + Privilege = privilege.Split(','), + UnionId = unionId + }; + + return await CreateWeChatUser(weChatUser); + } + catch (Exception ex) + { + _logger.LogError($"Create WeChatUser Error: {ex.Message}"); + throw new Exception($"Failed to create WeChatUser: {ex.Message}", ex); + } + + } + + + #endregion 微信扫码登录(OAuth 2.0 网页授权) } diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/UserController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/UserController.cs index b72888f3..a39200e2 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/UserController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/UserController.cs @@ -78,10 +78,21 @@ public class UserController : ControllerBase public async Task CreateWeChatUser(string code) { // Get WeChat User Info + var wechatUser = await _weChatUserService.WeChatUserLogin(code); + if (wechatUser == null) + { + return; + } + var weChatUser = await _weChatUserService.CreateWeChatUser(wechatUser); - WeChatUser wechatUser = new(); - var user = await _weChatUserService.CreateWeChatUser(wechatUser); + if (wechatUser == null) + { + return; + } + + // Create User + var createdUser = await _userService.CreateUser(weChatUser.ToUser()); } [AllowAnonymous] diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/WeChatUserDocument.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/WeChatUserDocument.cs index 6898cb9c..c85c7f4e 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/WeChatUserDocument.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/WeChatUserDocument.cs @@ -11,8 +11,6 @@ public class WeChatUserDocument : MongoBase /// public string OpenId { get; set; } = string.Empty; - public string SessionKey { get; set; } = string.Empty; - /// /// User unique identifier (cross application unique, requiring open platform binding) /// @@ -61,7 +59,6 @@ public class WeChatUserDocument : MongoBase { Id = Id, OpenId = OpenId, - SessionKey = SessionKey, UnionId = UnionId, Sex = Sex, Province = Province, diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.WeChatUser.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.WeChatUser.cs index 4399a5df..91cca0bf 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.WeChatUser.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.WeChatUser.cs @@ -10,15 +10,12 @@ public partial class MongoRepository return weChatUser != null ? weChatUser.ToWeChatUser() : null; } - public WeChatUser? CreateWeChatUser(WeChatUser weChatUser) + public WeChatUser CreateWeChatUser(WeChatUser weChatUser) { - if (weChatUser == null) return null; - var weChatUserInfo = new WeChatUserDocument { Id = weChatUser.Id ?? Guid.NewGuid().ToString(), OpenId = weChatUser.OpenId, - SessionKey = weChatUser.SessionKey, UnionId = weChatUser.UnionId, Sex = weChatUser.Sex, Province = weChatUser.Province, @@ -43,7 +40,6 @@ public partial class MongoRepository var filter = Builders.Filter.Eq(x => x.Id, weChatUser.Id); var update = Builders.Update .Set(x => x.OpenId, weChatUser.OpenId) - .Set(x => x.SessionKey, weChatUser.SessionKey) .Set(x => x.UnionId, weChatUser.UnionId) .Set(x => x.Sex, weChatUser.Sex) .Set(x => x.Province, weChatUser.Province) diff --git a/src/WebStarter/appsettings.json b/src/WebStarter/appsettings.json index c3d4bdd5..3efc0b4d 100644 --- a/src/WebStarter/appsettings.json +++ b/src/WebStarter/appsettings.json @@ -273,6 +273,16 @@ "WeixinAppSecret": "#{WeixinAppSecret}#" }, + "WeChatQtoss": { + "AppId": "", + "AppSecret": "" + }, + + "WeChatQtossAI": { + "AppId": "", + "AppSecret": "" + }, + "KnowledgeBase": { "VectorDb": { "Provider": "Qdrant"