From aba815f80522b2fd32cf96290328b712457f2687 Mon Sep 17 00:00:00 2001 From: wxd <123@qq.com> Date: Wed, 14 May 2025 18:23:53 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=89=E6=96=B9=E7=94=A8=E6=88=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BindThirdUserInAbpUserInputDto.cs | 19 ++ .../ThirdUsers/GetTokenReturn.cs | 13 ++ .../ThirdUsers/SignInResultDto.cs | 15 ++ .../ThirdUsers/ThirdLoginDto.cs | 6 + .../ThirdUsers/ThirdUserDto.cs | 38 ++++ .../ThirdUsers/ThirdUserInputDto.cs | 36 +++ .../ThirdUsers/WeChatUserLoginInputDto.cs | 17 ++ .../ThirdUsers/ThirdUserAppService.cs | 212 ++++++++++++++++-- .../Enums/CacheKeys.cs | 13 ++ .../Controllers/MiniProgramTokenController.cs | 117 +++++++--- 10 files changed, 439 insertions(+), 47 deletions(-) create mode 100644 src/Shentun.Peis.Application.Contracts/ThirdUsers/BindThirdUserInAbpUserInputDto.cs create mode 100644 src/Shentun.Peis.Application.Contracts/ThirdUsers/GetTokenReturn.cs create mode 100644 src/Shentun.Peis.Application.Contracts/ThirdUsers/SignInResultDto.cs create mode 100644 src/Shentun.Peis.Application.Contracts/ThirdUsers/ThirdUserDto.cs create mode 100644 src/Shentun.Peis.Application.Contracts/ThirdUsers/ThirdUserInputDto.cs create mode 100644 src/Shentun.Peis.Application.Contracts/ThirdUsers/WeChatUserLoginInputDto.cs create mode 100644 src/Shentun.Peis.Domain.Shared/Enums/CacheKeys.cs diff --git a/src/Shentun.Peis.Application.Contracts/ThirdUsers/BindThirdUserInAbpUserInputDto.cs b/src/Shentun.Peis.Application.Contracts/ThirdUsers/BindThirdUserInAbpUserInputDto.cs new file mode 100644 index 0000000..041e99c --- /dev/null +++ b/src/Shentun.Peis.Application.Contracts/ThirdUsers/BindThirdUserInAbpUserInputDto.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Shentun.Peis.ThirdUsers +{ + public class BindThirdUserInAbpUserInputDto + { + /// + /// 第三方系统用户Id + /// + public Guid ThirdUserId { get; set; } + + /// + /// 系统用户Id + /// + public Guid AbpUserId { get; set; } + } +} diff --git a/src/Shentun.Peis.Application.Contracts/ThirdUsers/GetTokenReturn.cs b/src/Shentun.Peis.Application.Contracts/ThirdUsers/GetTokenReturn.cs new file mode 100644 index 0000000..81cb837 --- /dev/null +++ b/src/Shentun.Peis.Application.Contracts/ThirdUsers/GetTokenReturn.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Shentun.Peis.ThirdUsers +{ + public class GetTokenReturn + { + public int code { get; set; } + public string message { get; set; } + public object data { get; set; } + } +} diff --git a/src/Shentun.Peis.Application.Contracts/ThirdUsers/SignInResultDto.cs b/src/Shentun.Peis.Application.Contracts/ThirdUsers/SignInResultDto.cs new file mode 100644 index 0000000..dc8d998 --- /dev/null +++ b/src/Shentun.Peis.Application.Contracts/ThirdUsers/SignInResultDto.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Shentun.Peis.ThirdUsers +{ + public class SignInResultDto + { + public string access_token { get; set; } + public string refresh_token { get; set; } + public string token_type { get; set; } + public int expires_in { get; set; } + + } +} diff --git a/src/Shentun.Peis.Application.Contracts/ThirdUsers/ThirdLoginDto.cs b/src/Shentun.Peis.Application.Contracts/ThirdUsers/ThirdLoginDto.cs index 00e3f43..04c4d67 100644 --- a/src/Shentun.Peis.Application.Contracts/ThirdUsers/ThirdLoginDto.cs +++ b/src/Shentun.Peis.Application.Contracts/ThirdUsers/ThirdLoginDto.cs @@ -10,6 +10,12 @@ namespace Shentun.Peis.ThirdUsers /// 是否有token /// public string IsToken { get; set; } = "Y"; + + /// + /// 提示 + /// + public string Message { get; set; } + /// /// 微信OpenId /// diff --git a/src/Shentun.Peis.Application.Contracts/ThirdUsers/ThirdUserDto.cs b/src/Shentun.Peis.Application.Contracts/ThirdUsers/ThirdUserDto.cs new file mode 100644 index 0000000..aa17ba9 --- /dev/null +++ b/src/Shentun.Peis.Application.Contracts/ThirdUsers/ThirdUserDto.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Text; + +namespace Shentun.Peis.ThirdUsers +{ + public class ThirdUserDto : AuditedEntityDtoName + { + /// + /// 手机号码 + /// + public string MobilePhone { get; set; } + + /// + /// abp用户表Id + /// + public Guid? AbpUserId { get; set; } + + + /// + /// 是否启用 + /// + public char IsActive { get; set; } + + + /// + /// 微信openid + /// + public string? WechatOpenId { get; set; } + + /// + /// 用户注册方式(0.小程序注册 1.后台添加) 默认0 + /// + public char UserRegisterFlag { get; set; } + + } +} diff --git a/src/Shentun.Peis.Application.Contracts/ThirdUsers/ThirdUserInputDto.cs b/src/Shentun.Peis.Application.Contracts/ThirdUsers/ThirdUserInputDto.cs new file mode 100644 index 0000000..15b9036 --- /dev/null +++ b/src/Shentun.Peis.Application.Contracts/ThirdUsers/ThirdUserInputDto.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Shentun.Peis.ThirdUsers +{ + public class ThirdUserInputDto + { + /// + /// 手机号码 + /// + public string MobilePhone { get; set; } + + /// + /// abp用户表Id + /// + public Guid? AbpUserId { get; set; } + + + /// + /// 是否启用 + /// + public char? IsActive { get; set; } + + + /// + /// 微信openid + /// + public string WechatOpenId { get; set; } + + /// + /// 用户注册方式(0.小程序注册 1.后台添加) 默认0 + /// + public char? UserRegisterFlag { get; set; } + } +} diff --git a/src/Shentun.Peis.Application.Contracts/ThirdUsers/WeChatUserLoginInputDto.cs b/src/Shentun.Peis.Application.Contracts/ThirdUsers/WeChatUserLoginInputDto.cs new file mode 100644 index 0000000..d274f40 --- /dev/null +++ b/src/Shentun.Peis.Application.Contracts/ThirdUsers/WeChatUserLoginInputDto.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Text; + +namespace Shentun.Peis.ThirdUsers +{ + public class WeChatUserLoginInputDto + { + public string JsCode { get; set; } + + /// + /// 手机号码 + /// + public string MobilePhone { get; set; } + } +} diff --git a/src/Shentun.Peis.Application/ThirdUsers/ThirdUserAppService.cs b/src/Shentun.Peis.Application/ThirdUsers/ThirdUserAppService.cs index 887ecbd..272c54e 100644 --- a/src/Shentun.Peis.Application/ThirdUsers/ThirdUserAppService.cs +++ b/src/Shentun.Peis.Application/ThirdUsers/ThirdUserAppService.cs @@ -1,39 +1,215 @@ using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Caching.Distributed; +using Microsoft.Extensions.Configuration; using OpenIddict.Abstractions; +using Shentun.Peis.Enums; +using Shentun.Peis.Models; +using Shentun.Peis.SysParmValues; +using SqlSugar; using System; using System.Collections.Generic; using System.Linq; +using System.Net.Http; +using System.Net.Http.Headers; using System.Security.Claims; using System.Text; +using System.Text.Json; using System.Threading.Tasks; using Volo.Abp; using Volo.Abp.Application.Services; +using Volo.Abp.Caching; using Volo.Abp.Domain.Repositories; using Volo.Abp.Identity; namespace Shentun.Peis.ThirdUsers { + /// + /// 第三方用户 + /// + [ApiExplorerSettings(GroupName = "Work")] + [Authorize] public class ThirdUserAppService : ApplicationService { - //private readonly IOpenIddictScopeManager _scopeManager; - //private readonly SignInManager _signInManager; - //private readonly IRepository _identityUserRepository; - //private readonly IdentityUserManager _identityUserManager; - - //public ThirdUserAppService( - // IOpenIddictScopeManager scopeManager, - // SignInManager signInManager, - // IRepository identityUserRepository, - // IdentityUserManager identityUserManager) - //{ - // _scopeManager = scopeManager; - // _signInManager = signInManager; - // _identityUserRepository = identityUserRepository; - // _identityUserManager = identityUserManager; - //} - - + + + private readonly IConfiguration _configuration; + private readonly IDistributedCache _cache; + private readonly IRepository _thirdUserRepository; + private readonly CacheService _cacheService; + private readonly IRepository _identityUserRepository; + public ThirdUserAppService( + IConfiguration configuration, + IDistributedCache cache, + IRepository thirdUserRepository, + CacheService cacheService, + IRepository identityUserRepository) + { + _configuration = configuration; + _cache = cache; + _thirdUserRepository = thirdUserRepository; + _cacheService = cacheService; + _identityUserRepository = identityUserRepository; + } + + /// + /// 微信用户登录 + /// + /// + /// + [AllowAnonymous] + [HttpPost("api/app/ThirdUser/WeChatUserLogin")] + public async Task WeChatUserLoginAsync(WeChatUserLoginInputDto input) + { + var dic = new Dictionary + { + {"jsCode",input.JsCode}, + {"client_id","Peis_MiniProgram"}, + {"mobile_phone",input.MobilePhone}, + {"grant_type","mini_program"}, + {"scope","Peis"} + }; + // + var dicStr = dic.Select(m => m.Key + "=" + m.Value).DefaultIfEmpty().Aggregate((m, n) => m + "&" + n); + var token = await GetTokenAsync(dicStr); + var options = new DistributedCacheEntryOptions() + .SetAbsoluteExpiration(TimeSpan.FromDays(3)); + var sessionKey = CacheKeys.SessionKey + Guid.NewGuid().ToString(); + var sessionKeyValue = Guid.NewGuid().ToString(); + _cache.Set(sessionKey, sessionKeyValue, options); + token.SessionKey = sessionKey; + token.SessionKeyValue = sessionKeyValue; + + return token; + + } + + + + /// + /// 获取第三方用户信息 + /// + /// + [HttpPost("api/app/ThirdUser/GetList")] + public async Task> GetListAsync(ThirdUserInputDto input) + { + var query = await _thirdUserRepository.GetQueryableAsync(); + if (input.AbpUserId != null) + { + query = query.Where(m => m.AbpUserId == input.AbpUserId); + } + if (input.UserRegisterFlag != null) + { + query = query.Where(m => m.UserRegisterFlag == input.UserRegisterFlag); + } + if (input.IsActive != null) + { + query = query.Where(m => m.IsActive == input.IsActive); + } + if (!string.IsNullOrWhiteSpace(input.MobilePhone)) + { + query = query.Where(m => m.MobilePhone == input.MobilePhone); + } + if (!string.IsNullOrWhiteSpace(input.WechatOpenId)) + { + query = query.Where(m => m.WechatOpenId == input.WechatOpenId); + } + + var entListDto = query.OrderByDescending(o => o.CreationTime).ToList().Select(s => new ThirdUserDto + { + AbpUserId = s.AbpUserId, + CreationTime = s.CreationTime, + CreatorId = s.CreatorId, + CreatorName = _cacheService.GetSurnameAsync(s.CreatorId).GetAwaiter().GetResult(), + Id = s.Id, + IsActive = s.IsActive, + LastModificationTime = s.LastModificationTime, + LastModifierId = s.LastModifierId, + LastModifierName = _cacheService.GetSurnameAsync(s.LastModifierId).GetAwaiter().GetResult(), + MobilePhone = s.MobilePhone, + UserRegisterFlag = s.UserRegisterFlag, + WechatOpenId = s.WechatOpenId + }).ToList(); + + return entListDto; + } + + /// + /// 绑定第三方用户归属到系统用户 + /// + /// + [HttpPost("api/app/ThirdUser/BindThirdUserInAbpUser")] + public async Task BindThirdUserInAbpUserAsync(BindThirdUserInAbpUserInputDto input) + { + var identityUser = await _identityUserRepository.FirstOrDefaultAsync(f => f.Id == input.AbpUserId); + if (identityUser == null) + { + throw new UserFriendlyException("系统用户不存在"); + } + + var thirdUser = await _thirdUserRepository.FirstOrDefaultAsync(f => f.Id == input.ThirdUserId); + if (thirdUser == null) + { + throw new UserFriendlyException("第三方用户不存在"); + } + + thirdUser.AbpUserId = input.AbpUserId; + + await _thirdUserRepository.UpdateAsync(thirdUser); + + } + + + private async Task GetTokenAsync(string request) + { + using var client = new HttpClient(); + HttpContent httpContent = new StringContent(request); + httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded"); + var url = _configuration.GetSection("AuthServer"). + GetSection("Authority").Value + "/connect/token"; + var tokenResult = await client.PostAsync(url + , httpContent); + var tokenResultStr = await tokenResult.Content.ReadAsStringAsync(); + if (tokenResult.IsSuccessStatusCode) + { + var thirdLoginDto = new ThirdLoginDto(); + + if (!string.IsNullOrEmpty(tokenResultStr)) + { + + if (tokenResultStr.ToLower().Contains("openid")) + { + thirdLoginDto = JsonSerializer.Deserialize(tokenResultStr, + new JsonSerializerOptions() { PropertyNameCaseInsensitive = true }); + } + else + { + var signResult = JsonSerializer.Deserialize(tokenResultStr, + new JsonSerializerOptions() { PropertyNameCaseInsensitive = true }); + thirdLoginDto = new ThirdLoginDto + { + IsToken = "Y", + ExpiresIn = signResult.expires_in, + AccessToken = signResult.access_token, + RefreshToken = signResult.refresh_token + }; + } + + return thirdLoginDto; + } + else + { + throw new UserFriendlyException("token值为空"); + } + + } + else + { + throw new UserFriendlyException("获取token失败:" + tokenResultStr); + } + } } } diff --git a/src/Shentun.Peis.Domain.Shared/Enums/CacheKeys.cs b/src/Shentun.Peis.Domain.Shared/Enums/CacheKeys.cs new file mode 100644 index 0000000..0192265 --- /dev/null +++ b/src/Shentun.Peis.Domain.Shared/Enums/CacheKeys.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Shentun.Peis.Enums +{ + public class CacheKeys + { + public const string OpenIdKey = "OpenIdKey"; + public const string SmsKey = "SmsKey"; + public const string SessionKey = "SessionKey"; + } +} diff --git a/src/Shentun.Peis.HttpApi.Host/Controllers/MiniProgramTokenController.cs b/src/Shentun.Peis.HttpApi.Host/Controllers/MiniProgramTokenController.cs index b57b547..40b61a2 100644 --- a/src/Shentun.Peis.HttpApi.Host/Controllers/MiniProgramTokenController.cs +++ b/src/Shentun.Peis.HttpApi.Host/Controllers/MiniProgramTokenController.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore.Identity; +using Hangfire.States; +using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using OpenIddict.Abstractions; @@ -11,6 +12,7 @@ using Volo.Abp; using Volo.Abp.Domain.Repositories; using Volo.Abp.Identity; using Volo.Abp.OpenIddict.Controllers; +using Volo.Abp.Uow; namespace Shentun.Peis.Controllers { @@ -51,23 +53,79 @@ namespace Shentun.Peis.Controllers if (grantType == "mini_program") { + var resultDto = new ThirdLoginDto(); + + //小程序登录 // 获取小程序 code 并换取 openid var jsCode = request.GetParameter("jsCode").ToString(); + var mobilePhone = request.GetParameter("mobile_phone").ToString(); var wechatSession = await WeChatHelper.GetWechatSession(_configuration, jsCode); - var thirdUserEnt = await _thirdUserRepository.FirstOrDefaultAsync(f => f.WechatOpenId == wechatSession.OpenId && f.IsActive == 'Y' && f.AbpUserId != null); + var thirdUserEnt = await _thirdUserRepository.FirstOrDefaultAsync(f => f.WechatOpenId == wechatSession.OpenId); + if (thirdUserEnt == null) { - throw new UserFriendlyException("用户未授权"); + //未注册 注册信息 + thirdUserEnt = new ThirdUser + { + AbpUserId = null, + IsActive = 'Y', + MobilePhone = mobilePhone, + UserRegisterFlag = '0', + WechatOpenId = wechatSession.OpenId + }; + + await _thirdUserRepository.InsertAsync(thirdUserEnt, true); + + resultDto = new ThirdLoginDto + { + IsToken = "N", + Message = "用户未授权", + OpenId = wechatSession.OpenId + }; + + return Ok(resultDto); + + } + else if (thirdUserEnt.IsActive == 'N') + { + resultDto = new ThirdLoginDto + { + IsToken = "N", + Message = "用户被禁用", + OpenId = wechatSession.OpenId + }; + + return Ok(resultDto); + } + else if (thirdUserEnt.AbpUserId == null) + { + resultDto = new ThirdLoginDto + { + IsToken = "N", + Message = "用户未授权", + OpenId = wechatSession.OpenId + }; + + return Ok(resultDto); } + + // 查询关联的 AbpUser var abpUser = await _identityUserRepository.FirstOrDefaultAsync(f => f.Id == thirdUserEnt.AbpUserId); if (abpUser == null) { - throw new UserFriendlyException("用户未关联权限"); + resultDto = new ThirdLoginDto + { + IsToken = "N", + Message = "用户未关联权限", + OpenId = wechatSession.OpenId + }; + + return Ok(resultDto); } // 生成声明主体 @@ -81,40 +139,41 @@ namespace Shentun.Peis.Controllers await SetClaimsDestinationsAsync(principal); return SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); + } - else if (grantType == "phone_verify") - { - //手机号+验证码登录认证 + //else if (grantType == "phone_verify") + //{ + // //手机号+验证码登录认证 - var mobilePhone = request.GetParameter("mobilePhone").ToString(); - var verifyCode = request.GetParameter("verifyCode").ToString(); + // var mobilePhone = request.GetParameter("mobilePhone").ToString(); + // var verifyCode = request.GetParameter("verifyCode").ToString(); - var thirdUserEnt = await _thirdUserRepository.FirstOrDefaultAsync(f => f.MobilePhone == mobilePhone && f.IsActive == 'Y' && f.AbpUserId != null); - if (thirdUserEnt == null) - { - throw new UserFriendlyException("用户未授权"); - } - // 查询关联的 AbpUser - var abpUser = await _identityUserRepository.FirstOrDefaultAsync(f => f.Id == thirdUserEnt.AbpUserId); - if (abpUser == null) - { - throw new UserFriendlyException("用户未关联权限"); - } + // var thirdUserEnt = await _thirdUserRepository.FirstOrDefaultAsync(f => f.MobilePhone == mobilePhone && f.IsActive == 'Y' && f.AbpUserId != null); + // if (thirdUserEnt == null) + // { + // throw new UserFriendlyException("用户未授权"); + // } + // // 查询关联的 AbpUser + // var abpUser = await _identityUserRepository.FirstOrDefaultAsync(f => f.Id == thirdUserEnt.AbpUserId); + // if (abpUser == null) + // { + // throw new UserFriendlyException("用户未关联权限"); + // } - // 生成声明主体 - var principal = await _signInManager.CreateUserPrincipalAsync(abpUser); + // // 生成声明主体 + // var principal = await _signInManager.CreateUserPrincipalAsync(abpUser); - var scopes = request.GetScopes(); - var resources = await GetResourcesAsync(scopes); - principal.SetScopes(scopes); - principal.SetResources(resources); + // var scopes = request.GetScopes(); + // var resources = await GetResourcesAsync(scopes); + // principal.SetScopes(scopes); + // principal.SetResources(resources); - await SetClaimsDestinationsAsync(principal); + // await SetClaimsDestinationsAsync(principal); - return SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); - } + // return SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); + //} else { return await base.HandleAsync();