diff --git a/Yi.Abp.Net8/framework/Yi.Framework.WeChat.MiniProgram/Yi.Framework.WeChat.MiniProgram.csproj b/Yi.Abp.Net8/framework/Yi.Framework.WeChat.MiniProgram/Yi.Framework.WeChat.MiniProgram.csproj
new file mode 100644
index 00000000..4513d436
--- /dev/null
+++ b/Yi.Abp.Net8/framework/Yi.Framework.WeChat.MiniProgram/Yi.Framework.WeChat.MiniProgram.csproj
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/Yi.Abp.Net8/framework/Yi.Framework.WeChat.MiniProgram/YiFrameworkWeChatMiniProgramModule.cs b/Yi.Abp.Net8/framework/Yi.Framework.WeChat.MiniProgram/YiFrameworkWeChatMiniProgramModule.cs
new file mode 100644
index 00000000..029b29ed
--- /dev/null
+++ b/Yi.Abp.Net8/framework/Yi.Framework.WeChat.MiniProgram/YiFrameworkWeChatMiniProgramModule.cs
@@ -0,0 +1,19 @@
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Caching;
+using Yi.Framework.Core;
+using Yi.Framework.WeChat.MiniProgram.Token;
+
+namespace Yi.Framework.WeChat.MiniProgram;
+
+[DependsOn(typeof(YiFrameworkCoreModule),
+ typeof(AbpCachingModule))]
+public class YiFrameworkWeChatMiniProgramModule: AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ var services = context.Services;
+ var configuration = context.Services.GetConfiguration();
+ Configure(configuration.GetSection("WeChatMiniProgram"));
+ services.AddSingleton();
+ }
+}
\ No newline at end of file
diff --git a/Yi.Abp.Net8/module/digital-collectibles/Yi.Framework.DigitalCollectibles.Application.Contracts/Dtos/Account/BindInput.cs b/Yi.Abp.Net8/module/digital-collectibles/Yi.Framework.DigitalCollectibles.Application.Contracts/Dtos/Account/BindInput.cs
new file mode 100644
index 00000000..d821ebec
--- /dev/null
+++ b/Yi.Abp.Net8/module/digital-collectibles/Yi.Framework.DigitalCollectibles.Application.Contracts/Dtos/Account/BindInput.cs
@@ -0,0 +1,8 @@
+namespace Yi.Framework.DigitalCollectibles.Application.Contracts.Dtos.Account;
+
+public class BindInput
+{
+ public string JsCode { get; set; }
+
+ public long Phone { get; set; }
+}
\ No newline at end of file
diff --git a/Yi.Abp.Net8/module/digital-collectibles/Yi.Framework.DigitalCollectibles.Application.Contracts/Dtos/Account/LoginInput.cs b/Yi.Abp.Net8/module/digital-collectibles/Yi.Framework.DigitalCollectibles.Application.Contracts/Dtos/Account/LoginInput.cs
index e4a419a2..58cc40a0 100644
--- a/Yi.Abp.Net8/module/digital-collectibles/Yi.Framework.DigitalCollectibles.Application.Contracts/Dtos/Account/LoginInput.cs
+++ b/Yi.Abp.Net8/module/digital-collectibles/Yi.Framework.DigitalCollectibles.Application.Contracts/Dtos/Account/LoginInput.cs
@@ -3,7 +3,7 @@
public class LoginInput
{
///
- /// 微信小程序code
+ /// 微信小程序jscode
///
- public string Code { get; set; }
+ public string JsCode { get; set; }
}
\ No newline at end of file
diff --git a/Yi.Abp.Net8/module/digital-collectibles/Yi.Framework.DigitalCollectibles.Application.Contracts/Dtos/Account/RegisterInput.cs b/Yi.Abp.Net8/module/digital-collectibles/Yi.Framework.DigitalCollectibles.Application.Contracts/Dtos/Account/RegisterInput.cs
new file mode 100644
index 00000000..6e4db2e7
--- /dev/null
+++ b/Yi.Abp.Net8/module/digital-collectibles/Yi.Framework.DigitalCollectibles.Application.Contracts/Dtos/Account/RegisterInput.cs
@@ -0,0 +1,43 @@
+namespace Yi.Framework.DigitalCollectibles.Application.Contracts.Dtos.Account;
+
+public class RegisterInput
+{
+
+ //电话号码,根据code的表示来获取
+
+ ///
+ /// 账号
+ ///
+ public string UserName { get; set; }
+
+ ///
+ /// 密码
+ ///
+ public string Password { get; set; }
+
+ ///
+ /// 唯一标识码
+ ///
+ public string? Uuid { get; set; }
+
+ ///
+ /// 电话
+ ///
+ public long Phone { get; set; }
+
+ ///
+ /// 验证码
+ ///
+ public string? Code { get; set; }
+
+ ///
+ /// 昵称
+ ///
+ public string? Nick{ get; set; }
+
+
+ ///
+ /// 微信小程序code
+ ///
+ public string JsCode { get; set; }
+}
\ No newline at end of file
diff --git a/Yi.Abp.Net8/module/digital-collectibles/Yi.Framework.DigitalCollectibles.Application/Services/Account/CollectiblesAccountService.cs b/Yi.Abp.Net8/module/digital-collectibles/Yi.Framework.DigitalCollectibles.Application/Services/Account/CollectiblesAccountService.cs
deleted file mode 100644
index 18bbc73b..00000000
--- a/Yi.Abp.Net8/module/digital-collectibles/Yi.Framework.DigitalCollectibles.Application/Services/Account/CollectiblesAccountService.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-using Volo.Abp.Application.Services;
-
-namespace Yi.Framework.DigitalCollectibles.Application.Services.Account;
-
-public class CollectiblesAccountService: ApplicationService
-{
- ///
- /// 小程序登录
- ///
- ///
- public Task PostLoginAsync()
- {
- throw new NotImplementedException();
- //根据code去获取wxid
- //判断wxid中是否有对应的userid关系
- //果然有,直接根据userid返回该用户token
- //如果没有,返回结果即可
- }
-
-
- ///
- /// 小程序绑定账号
- ///
- ///
- public Task PostBindAsync()
- {
- throw new NotImplementedException();
- //根据code去获取wxid
- //校验手机号
- //根据手机号查询用户信息
- //将wxid和用户user绑定
- }
-
- //小程序注册
- public Task PostRegisterAsync()
- {
- throw new NotImplementedException();
- //走普通注册流程
- //同时再加一个小程序绑定即可
- }
-}
\ No newline at end of file
diff --git a/Yi.Abp.Net8/module/digital-collectibles/Yi.Framework.DigitalCollectibles.Application/Services/Account/WeChatMiniProgramAccountService.cs b/Yi.Abp.Net8/module/digital-collectibles/Yi.Framework.DigitalCollectibles.Application/Services/Account/WeChatMiniProgramAccountService.cs
new file mode 100644
index 00000000..e309e958
--- /dev/null
+++ b/Yi.Abp.Net8/module/digital-collectibles/Yi.Framework.DigitalCollectibles.Application/Services/Account/WeChatMiniProgramAccountService.cs
@@ -0,0 +1,123 @@
+using Microsoft.AspNetCore.Mvc;
+using Volo.Abp.Application.Services;
+using Yi.Framework.DigitalCollectibles.Application.Contracts.Dtos.Account;
+using Yi.Framework.DigitalCollectibles.Domain.Shared.Consts;
+using Yi.Framework.DigitalCollectibles.Domain.Shared.Enums;
+using Yi.Framework.Rbac.Application.Contracts.Dtos.Account;
+using Yi.Framework.Rbac.Application.Contracts.IServices;
+using Yi.Framework.Rbac.Domain.Shared.Enums;
+using Yi.Framework.WeChat.MiniProgram;
+using Yi.Framework.WeChat.MiniProgram.HttpModels;
+
+namespace Yi.Framework.DigitalCollectibles.Application.Services.Account;
+
+///
+/// 微信小程序账户应用服务
+///
+public class WeChatMiniProgramAccountService : ApplicationService
+{
+ private readonly IWeChatMiniProgramManager _weChatMiniProgramManager;
+ private readonly IAuthService _authService;
+ private readonly IAccountService _accountService;
+
+ public WeChatMiniProgramAccountService(IWeChatMiniProgramManager weChatMiniProgramManager, IAuthService authService,
+ IAccountService accountService)
+ {
+ _weChatMiniProgramManager = weChatMiniProgramManager;
+ _authService = authService;
+ _accountService = accountService;
+ }
+
+ ///
+ /// 使用小程序jsCode登录意社区账号
+ ///
+ ///
+ [HttpPost("wechat/mini-program/account/login")]
+ public async Task PostLoginAsync(LoginInput intput)
+ {
+ var output = new LoginOutput();
+ //根据code去获取wxid
+ //判断wxid中是否有对应的userid关系
+ //果然有,直接根据userid返回该用户token
+ //如果没有,返回结果即可
+ var openId = (await _weChatMiniProgramManager.Code2SessionAsync(new Code2SessionInput(intput.JsCode))).openid;
+
+ var authInfo = await _authService.TryGetByOpenIdAsync(openId, AuthTypeConst.WeChatMiniProgram);
+ if (authInfo is null)
+ {
+ output.Result = LoginResultEnum.Error;
+ }
+
+ //根据用户id获取到用户信息
+ var result = await _accountService.PostLoginAsync(authInfo.UserId);
+ output.Result = LoginResultEnum.Success;
+ output.Token = result.Token;
+
+ return output;
+ }
+
+
+ ///
+ /// 将小程序第三方授权绑定给意社区账号
+ ///
+ ///
+ ///
+ [HttpPost("wechat/mini-program/account/bind")]
+ public async Task PostBindAsync(BindInput input)
+ {
+ //校验手机号与验证码
+ //根据手机号查询用户信息
+ //根据code去获取wxid
+ //将wxid和用户user绑定
+ var userInfo = await _accountService.GetAsync(null, input.Phone);
+ if (userInfo is null)
+ {
+ throw new UserFriendlyException("该手机号未被注册,无法绑定微信小程序");
+ }
+
+ //验证手机号的验证码
+ await _accountService.PostCaptchaPhoneAsync(ValidationPhoneTypeEnum.Register, new PhoneCaptchaImageDto
+ {
+ Phone = input.Phone.ToString()
+ });
+
+ var openId = (await _weChatMiniProgramManager.Code2SessionAsync(new Code2SessionInput(input.JsCode))).openid;
+
+
+ await PostBindToAuthAsync(userInfo.User.Id, openId, userInfo.User.UserName);
+ }
+
+ private async Task PostBindToAuthAsync(Guid userId, string openId, string? name = null)
+ {
+ await _authService.CreateAsync(new AuthCreateOrUpdateInputDto
+ {
+ UserId = userId,
+ OpenId = openId,
+ Name = name ?? "未知",
+ AuthType = AuthTypeConst.WeChatMiniProgram
+ });
+ }
+
+ ///
+ /// 使用小程序去注册意社区账号
+ ///
+ ///
+ [HttpPost("wechat/mini-program/account/register")]
+ public async Task PostRegisterAsync(RegisterInput input)
+ {
+ //走普通注册流程
+ //同时再加一个小程序绑定即可
+ await _accountService.PostRegisterAsync(new RegisterDto
+ {
+ UserName = input.UserName,
+ Password = input.Password,
+ Uuid = input.Uuid,
+ Phone = input.Phone,
+ Code = input.Code,
+ Nick = input.Nick
+ });
+ var userInfo = await _accountService.GetAsync(input.UserName, null);
+ var openId = (await _weChatMiniProgramManager.Code2SessionAsync(new Code2SessionInput(input.JsCode))).openid;
+ await PostBindToAuthAsync(userInfo.User.Id, openId, userInfo.User.UserName);
+ }
+}
\ No newline at end of file
diff --git a/Yi.Abp.Net8/module/digital-collectibles/Yi.Framework.DigitalCollectibles.Domain.Shared/Consts/AuthTypeConst.cs b/Yi.Abp.Net8/module/digital-collectibles/Yi.Framework.DigitalCollectibles.Domain.Shared/Consts/AuthTypeConst.cs
new file mode 100644
index 00000000..b3d1e1ea
--- /dev/null
+++ b/Yi.Abp.Net8/module/digital-collectibles/Yi.Framework.DigitalCollectibles.Domain.Shared/Consts/AuthTypeConst.cs
@@ -0,0 +1,6 @@
+namespace Yi.Framework.DigitalCollectibles.Domain.Shared.Consts;
+
+public class AuthTypeConst
+{
+ public const string WeChatMiniProgram = "WeChatMiniProgram";
+}
\ No newline at end of file
diff --git a/Yi.Abp.Net8/module/digital-collectibles/Yi.Framework.DigitalCollectibles.Domain/Yi.Framework.DigitalCollectibles.Domain.csproj b/Yi.Abp.Net8/module/digital-collectibles/Yi.Framework.DigitalCollectibles.Domain/Yi.Framework.DigitalCollectibles.Domain.csproj
index 431565d5..de97e8c8 100644
--- a/Yi.Abp.Net8/module/digital-collectibles/Yi.Framework.DigitalCollectibles.Domain/Yi.Framework.DigitalCollectibles.Domain.csproj
+++ b/Yi.Abp.Net8/module/digital-collectibles/Yi.Framework.DigitalCollectibles.Domain/Yi.Framework.DigitalCollectibles.Domain.csproj
@@ -10,10 +10,12 @@
+
+
diff --git a/Yi.Abp.Net8/module/digital-collectibles/Yi.Framework.DigitalCollectibles.Domain/YiFrameworkDigitalCollectiblesDomainModule.cs b/Yi.Abp.Net8/module/digital-collectibles/Yi.Framework.DigitalCollectibles.Domain/YiFrameworkDigitalCollectiblesDomainModule.cs
index 9171ca5b..4a0a0f59 100644
--- a/Yi.Abp.Net8/module/digital-collectibles/Yi.Framework.DigitalCollectibles.Domain/YiFrameworkDigitalCollectiblesDomainModule.cs
+++ b/Yi.Abp.Net8/module/digital-collectibles/Yi.Framework.DigitalCollectibles.Domain/YiFrameworkDigitalCollectiblesDomainModule.cs
@@ -4,12 +4,14 @@ using Volo.Abp.Modularity;
using Yi.Framework.DigitalCollectibles.Domain.Shared;
using Yi.Framework.Mapster;
using Yi.Framework.SettingManagement.Domain;
+using Yi.Framework.WeChat.MiniProgram;
namespace Yi.Framework.DigitalCollectibles.Domain
{
[DependsOn(
typeof(YiFrameworkDigitalCollectiblesDomainSharedModule),
-
+
+ typeof(YiFrameworkWeChatMiniProgramModule),
typeof(YiFrameworkSettingManagementDomainModule),
typeof(YiFrameworkMapsterModule),
typeof(AbpDddDomainModule),
diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application.Contracts/Dtos/Account/AuthCreateOrUpdateInputDto.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application.Contracts/Dtos/Account/AuthCreateOrUpdateInputDto.cs
new file mode 100644
index 00000000..84f9a22a
--- /dev/null
+++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application.Contracts/Dtos/Account/AuthCreateOrUpdateInputDto.cs
@@ -0,0 +1,12 @@
+namespace Yi.Framework.Rbac.Application.Contracts.Dtos.Account;
+
+public class AuthCreateOrUpdateInputDto
+{
+ public Guid UserId { get; set; }
+
+ public string OpenId { get; set; }
+
+ public string Name { get; set; }
+
+ public string AuthType { get; set; }
+}
\ No newline at end of file
diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application.Contracts/Dtos/Account/LoginOutputDto.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application.Contracts/Dtos/Account/LoginOutputDto.cs
new file mode 100644
index 00000000..d5958903
--- /dev/null
+++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application.Contracts/Dtos/Account/LoginOutputDto.cs
@@ -0,0 +1,7 @@
+namespace Yi.Framework.Rbac.Application.Contracts.Dtos.Account;
+
+public class LoginOutputDto
+{
+ public string Token { get; set; }
+ public string RefreshToken { get; set; }
+}
\ No newline at end of file
diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application.Contracts/IServices/IAccountService.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application.Contracts/IServices/IAccountService.cs
index 33263b8e..390e07de 100644
--- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application.Contracts/IServices/IAccountService.cs
+++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application.Contracts/IServices/IAccountService.cs
@@ -1,6 +1,7 @@
using Volo.Abp.Application.Services;
using Yi.Framework.Rbac.Application.Contracts.Dtos.Account;
using Yi.Framework.Rbac.Domain.Shared.Dtos;
+using Yi.Framework.Rbac.Domain.Shared.Enums;
namespace Yi.Framework.Rbac.Application.Contracts.IServices
{
@@ -8,8 +9,29 @@ namespace Yi.Framework.Rbac.Application.Contracts.IServices
{
Task GetAsync();
Task GetCaptchaImageAsync();
- Task