wip: Integrated WeChat login
This commit is contained in:
parent
d11e91ca84
commit
d41d6eddd8
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -9,4 +9,6 @@ public interface IWeChatUserService
|
|||
Task<WeChatUser?> CreateWeChatUser(WeChatUser weChatUser);
|
||||
|
||||
Task<WeChatUser?> UpdateWeChatUser(WeChatUser weChatUser);
|
||||
|
||||
Task<WeChatUser> WeChatUserLogin(string code);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
using BotSharp.Abstraction.Users.Enums;
|
||||
|
||||
namespace BotSharp.Abstraction.Users.Models;
|
||||
|
||||
public class WeChatUser
|
||||
|
|
@ -9,8 +11,6 @@ public class WeChatUser
|
|||
/// </summary>
|
||||
public string OpenId { get; set; } = string.Empty;
|
||||
|
||||
public string SessionKey { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// User unique identifier (cross application unique, requiring open platform binding)
|
||||
/// </summary>
|
||||
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<WeChatUserService> logger, IConfiguration configuration)
|
||||
{
|
||||
_services = services;
|
||||
_logger = logger;
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public async Task<WeChatUser?> GetWeChatUser(string openId)
|
||||
{
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
var weChatUser = db.GetWeChatUser(openId);
|
||||
return weChatUser;
|
||||
}
|
||||
|
||||
public async Task<WeChatUser?> CreateWeChatUser(WeChatUser weChatUser)
|
||||
public async Task<WeChatUser> CreateWeChatUser(WeChatUser weChatUser)
|
||||
{
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
return db.CreateWeChatUser(weChatUser);
|
||||
|
|
@ -28,4 +35,79 @@ public class WeChatUserService : IWeChatUserService
|
|||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
return db.UpdateWeChatUser(weChatUser);
|
||||
}
|
||||
|
||||
#region 微信扫码登录(OAuth 2.0 网页授权)
|
||||
|
||||
public async Task<WeChatUser> 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 网页授权)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -11,8 +11,6 @@ public class WeChatUserDocument : MongoBase
|
|||
/// </summary>
|
||||
public string OpenId { get; set; } = string.Empty;
|
||||
|
||||
public string SessionKey { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// User unique identifier (cross application unique, requiring open platform binding)
|
||||
/// </summary>
|
||||
|
|
@ -61,7 +59,6 @@ public class WeChatUserDocument : MongoBase
|
|||
{
|
||||
Id = Id,
|
||||
OpenId = OpenId,
|
||||
SessionKey = SessionKey,
|
||||
UnionId = UnionId,
|
||||
Sex = Sex,
|
||||
Province = Province,
|
||||
|
|
|
|||
|
|
@ -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<WeChatUserDocument>.Filter.Eq(x => x.Id, weChatUser.Id);
|
||||
var update = Builders<WeChatUserDocument>.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)
|
||||
|
|
|
|||
|
|
@ -273,6 +273,16 @@
|
|||
"WeixinAppSecret": "#{WeixinAppSecret}#"
|
||||
},
|
||||
|
||||
"WeChatQtoss": {
|
||||
"AppId": "",
|
||||
"AppSecret": ""
|
||||
},
|
||||
|
||||
"WeChatQtossAI": {
|
||||
"AppId": "",
|
||||
"AppSecret": ""
|
||||
},
|
||||
|
||||
"KnowledgeBase": {
|
||||
"VectorDb": {
|
||||
"Provider": "Qdrant"
|
||||
|
|
|
|||
Loading…
Reference in a new issue