using Azure.Core; using FlexJobApi.Core; using Furion; using Furion.DatabaseAccessor; using Furion.DataEncryption; using Furion.FriendlyException; using Mapster; using MediatR; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; using System.Security.Claims; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; namespace FlexJobApi.UserServer.Application { /// /// 登录命令处理器 /// public class LoginCommandHandler( IRepository rep, IRepository repUserAuth, IRepository repUserWallet, SmsUtils smsUtils, WxmpUtils wxmpUtils) : IRequestHandler, IRequestHandler, IRequestHandler, IRequestHandler, IRequestHandler, IRequestHandler, IRequestHandler, IRequestHandler { private readonly IRepository rep = rep; private readonly IRepository repUserAuth = repUserAuth; private readonly IRepository repUserWallet = repUserWallet; private readonly SmsUtils smsUtils = smsUtils; private readonly WxmpUtils wxmpUtils = wxmpUtils; /// /// 密码登录 /// /// /// /// public async Task Handle(PasswordLoginCommand request, CancellationToken cancellationToken) { var user = await rep.AsQueryable().AsNoTracking() .Where(it => it.UserName == request.UserName && it.Type == request.Type) .FirstOrDefaultAsync(cancellationToken); var supplierPassword = App.GetConfig("SupplierPassword"); if (user == null || !request.Password.CheckPassword(user.Password)) throw Oops.Oh(EnumUserErrorCodeType.u1000); if (user.Status == EnumUserStatus.Disabled) throw Oops.Oh(EnumUserErrorCodeType.u1001); return user.GetCurrentLogier(request.ClientType); } /// /// 短信登录 /// /// /// /// public async Task Handle(SmsLoginCommand request, CancellationToken cancellationToken) { await smsUtils.CheckVerifyCode(new CheckVerifyCodeModel { PhoneNumber = request.PhoneNumber, VerifyCode = request.VerifyCode, TemplateCode = EnumSmsTemplateCode.LoginOrRegister }); var user = await rep.AsQueryable().AsNoTracking() .Where(it => it.UserName == request.PhoneNumber && it.Type == request.Type) .FirstOrDefaultAsync(cancellationToken); if (user == null) throw Oops.Oh(EnumUserErrorCodeType.u1000); if (user.Status == EnumUserStatus.Disabled) throw Oops.Oh(EnumUserErrorCodeType.u1001); return user.GetCurrentLogier(request.ClientType); } /// /// 微信小程序登录 /// /// /// /// public async Task Handle(WxmpLoginCommand request, CancellationToken cancellationToken) { if (request.Type == EnumUserType.Operation) { throw Oops.Oh(EnumErrorCodeType.s400, "不支持此类型账号登录"); } var snsJscode2session = await wxmpUtils.SnsJscode2sessionAsync(request.Type, request.Code, cancellationToken); var user = await rep.AsQueryable().AsNoTracking() .Where(it => it.WxmpOpenId == snsJscode2session.openid && it.Type == request.Type) .FirstOrDefaultAsync(cancellationToken); if (user == null) { user = new User { Type = request.Type, UserName = snsJscode2session.openid, WxmpOpenId = snsJscode2session.openid, Level = 1, Status = EnumUserStatus.Normal }; await rep.InsertAsync(user); } if (user == null) throw Oops.Oh(EnumUserErrorCodeType.u1000); if (user.Status == EnumUserStatus.Disabled) throw Oops.Oh(EnumUserErrorCodeType.u1001); return user.GetCurrentLogier(EnumClientType.Wxmp, snsJscode2session.session_key); } /// /// 更换手机号 /// /// /// /// public async Task Handle(ChangePhoneNumberCommand request, CancellationToken cancellationToken) { await smsUtils.CheckVerifyCode(new CheckVerifyCodeModel { PhoneNumber = request.PhoneNumber, VerifyCode = request.VerifyCode, TemplateCode = EnumSmsTemplateCode.UpdateUserPhoneNumber }); var logier = JwtUtils.GetCurrentLogier(); var user = await rep.AsQueryable() .FirstOrDefaultAsync(it => it.Id == logier.Id); if (user == null) throw Oops.Oh(EnumErrorCodeType.s404, "当前账号不存在"); var exist = await rep.AsQueryable() .Where(it => it.Type == logier.Type && it.PhoneNumber == request.PhoneNumber && it.Id != user.Id) .AnyAsync(cancellationToken); if (exist) throw Oops.Oh(EnumUserErrorCodeType.u1010); user.UserName = request.PhoneNumber; user.PhoneNumber = request.PhoneNumber; user.IsCheckPhoneNumber = true; return true; } /// /// 绑定微信小程序用户信息 /// /// /// /// /// public async Task Handle(BindWxmpUserInfoCommand request, CancellationToken cancellationToken) { var claims = JWTEncryption.ReadJwtToken(request.AccessToken).Claims; var claimIdentity = new ClaimsIdentity("AuthenticationTypes.Federation"); claimIdentity.AddClaims(claims); var claimsPrincipal = new ClaimsPrincipal(claimIdentity); var id = claimsPrincipal.FindFirstValue("Id").ToGuid(); var type = claimsPrincipal.FindFirstValue("Type").ToEnum(); var user = await rep.AsQueryable() .Where(it => it.Type == type && it.Id == id) .FirstOrDefaultAsync(cancellationToken); if (user == null) throw Oops.Oh(EnumErrorCodeType.s404, "当前账号"); if (user.WxmpOpenId.IsNull()) throw Oops.Oh(EnumUserErrorCodeType.u1100); if (user.PhoneNumber.IsNull()) { var result = string.Empty; RijndaelManaged rijalg = new RijndaelManaged(); rijalg.KeySize = 128; rijalg.Padding = PaddingMode.PKCS7; rijalg.Mode = CipherMode.CBC; rijalg.Key = Convert.FromBase64String(request.SessionKey); rijalg.IV = Convert.FromBase64String(request.Iv); byte[] encryptedData = Convert.FromBase64String(request.EncryptedData); ICryptoTransform decryptor = rijalg.CreateDecryptor(rijalg.Key, rijalg.IV); using (MemoryStream msDecrypt = new MemoryStream(encryptedData)) { using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) { using (StreamReader srDecrypt = new StreamReader(csDecrypt)) { result = srDecrypt.ReadToEnd(); } } } var info = result.JsonTo(); if (info == null || info.PhoneNumber.IsNull()) { throw Oops.Oh(EnumUserErrorCodeType.u1110); } var bindPhoneNumberUser = await rep.AsQueryable() .Where(it => it.Type == type && it.PhoneNumber == info.PhoneNumber && it.Id != user.Id) .FirstOrDefaultAsync(cancellationToken); if (bindPhoneNumberUser == null) { if (type == EnumUserType.Enterprise) { throw Oops.Oh(EnumErrorCodeType.s404, "账号"); } user.PhoneNumber = info.PhoneNumber; user.ContactPhoneNumber = info.PhoneNumber; user.IsCheckPhoneNumber = true; if (user.UserName == user.WxmpOpenId) { user.UserName = info.PhoneNumber; } } else if (bindPhoneNumberUser.WxmpOpenId.IsNull()) { bindPhoneNumberUser.WxmpOpenId = user.WxmpOpenId; await rep.DeleteAsync(user); return bindPhoneNumberUser.GetCurrentLogier(EnumClientType.Wxmp); } else if (bindPhoneNumberUser.WxmpOpenId != user.WxmpOpenId) { throw Oops.Oh(EnumUserErrorCodeType.u1120); } } return user.GetCurrentLogier(EnumClientType.Wxmp); } /// /// 注册个人账号 /// /// /// /// public async Task Handle(RegisterPersonalUserCommand request, CancellationToken cancellationToken) { await smsUtils.CheckVerifyCode(new CheckVerifyCodeModel { PhoneNumber = request.PhoneNumber, VerifyCode = request.VerifyCode, TemplateCode = EnumSmsTemplateCode.LoginOrRegister }); var user = await rep.AsQueryable() .FirstOrDefaultAsync(it => it.Type == EnumUserType.Personal && it.UserName == request.PhoneNumber); if (user != null) throw Oops.Oh(EnumUserErrorCodeType.u1010); user = new User { Type = EnumUserType.Personal, UserName = request.PhoneNumber, PhoneNumber = request.PhoneNumber, ContactPhoneNumber = request.PhoneNumber, IsCheckPhoneNumber = true, Level = 1, Status = EnumUserStatus.Normal, }; await rep.InsertAsync(user); return true; } /// /// 查询个人用户登录信息 /// /// /// /// public async Task Handle(GetPersonalLoginInfoQuery request, CancellationToken cancellationToken) { var model = await rep.GetPersonalQueryable(true) .GetDetail(cancellationToken); var taskUserQueryable = rep.Change().AsQueryable().AsNoTracking() .Where(it => it.EnterpriseEmployee.UserId == model.Id); model.TaskCount = await taskUserQueryable.CountAsync(tu => tu.HireStatus == EnumTaskUserHireStatus.Wait || tu.EnterpriseEmployee.UserSignContractStatus == EnumTaskUserSignContractStatus.Wait); model.HirePassTaskCount = await taskUserQueryable.CountAsync(tu => tu.ArrangeStatus == EnumTaskUserArrangeStatus.Complete); model.HireRefuseTaskCount = await taskUserQueryable.CountAsync(tu => tu.HireStatus == EnumTaskUserHireStatus.Refuse || tu.EnterpriseEmployee.UserSignContractStatus == EnumTaskUserSignContractStatus.Refuse || tu.EnterpriseEmployee.EnterpriseSignContractStatus == EnumTaskUserSignContractStatus.Refuse); model.Balance = await repUserWallet.AsQueryable().AsNoTracking() .Where(it => it.UserId == model.Id) .Select(it => it.Balance) .FirstOrDefaultAsync(); var auth = await repUserAuth.AsQueryable().AsNoTracking() .Where(it => it.Id == model.Id) .Select(it => new { it.RealStatus, it.RealFailMessage }) .FirstOrDefaultAsync(); model.RealStatus = auth?.RealStatus ?? EnumPersonalUserRealStatus.UnReal; model.RealFailMessage = auth?.RealFailMessage; return model; } /// /// 查询企业用户登录信息 /// /// /// /// public async Task Handle(GetEnterpriseLoginInfoQuery request, CancellationToken cancellationToken) { var logier = JwtUtils.GetCurrentLogier(); var model = await rep.AsQueryable().AsNoTracking() .Where(it => it.Id == logier.Id) .GetDetail(cancellationToken); model.Roles = await rep.Change().AsQueryable().AsNoTracking() .Where(it => it.UserRoles.Any(ur => ur.UserId == logier.Id)) .Select(it => it.Name) .ToListAsync(); var collects = await rep.Change().AsQueryable().AsNoTracking() .Where(it => it.EnterpriseId == logier.EnterpriseId) .Select(it => new { it.UserId, it.IsCollected, it.IsContacted }) .ToListAsync(); model.CollectedUserCount = collects.Count(it => it.IsCollected); model.ContactedRecordCount = collects.Count(it => it.IsContacted); return model; } } }