using Furion; using System; using GDZZ.Core; using GDZZ.Core.OAuth; using Furion.EventBus; using GDZZ.Core.Entity; using Furion.DataEncryption; using GDZZ.Application.Entity; using Furion.FriendlyException; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; using Microsoft.Extensions.Options; using Furion.DependencyInjection; using Furion.DynamicApiController; using Microsoft.AspNetCore.Http; using GDZZ.Application.Help; using Microsoft.AspNetCore.Authorization; using Mapster; using GDZZ.Core.Service; using TencentCloud.Sms.V20210111.Models; using TencentCloud.Common; namespace GDZZ.Application.Service.Auth { [ApiDescriptionSettings("Application", Name = "Auth", Order = 1)] public class AuthService : IAuthService, IDynamicApiController, ITransient { #region 仓储 private readonly SqlSugarRepository Baseuser; // wx用户仓储 private readonly SqlSugarRepository _sysUserRep; // 用户表仓储 private readonly SqlSugarRepository _sysTenantRep; //租户仓储 private readonly SqlSugarRepository Self; //职业仓储 private readonly SqlSugarRepository CompanyRep; private readonly SqlSugarRepository payTakeRep; //支付仓储 private readonly SqlSugarRepository _sysConfigRep; // 参数配置表仓储 #endregion #region 服务 private readonly ISysCacheService _sysCacheService; //缓存 private readonly ICacheService cacheService; private readonly WechatOAuth _wechatOAuth; //微信权限服务 private readonly IHttpContextAccessor _httpContextAccessor; //http服务 private readonly IEventPublisher _eventPublisher; //事件写入服务 #endregion /// /// 获取配置文件 /// private readonly ThirdParty _oauthConfig; public AuthService( IOptions options, SqlSugarRepository Baseuser, SqlSugarRepository sysTenantRep, SqlSugarRepository sysUserRep, SqlSugarRepository Self, SqlSugarRepository CompanyRep, SqlSugarRepository payTakeRep, SqlSugarRepository sysConfigRep, ISysCacheService sysCacheService, ICacheService cacheService, WechatOAuth wechatOAuth, IEventPublisher eventPublisher, IHttpContextAccessor httpContextAccessor) { this.CompanyRep= CompanyRep; this._eventPublisher= eventPublisher; this._sysUserRep = sysUserRep; this._sysTenantRep = sysTenantRep; this.Baseuser = Baseuser; this._httpContextAccessor = httpContextAccessor; this.cacheService = cacheService; this.Self = Self; this.payTakeRep = payTakeRep; this._sysCacheService= sysCacheService; this._sysConfigRep= sysConfigRep; _wechatOAuth = wechatOAuth; _oauthConfig = options.Value.Wechat; } /// /// 手机端登录(一键登录) /// /// [HttpPost("/Mini/SignIn")] [AllowAnonymous] public async Task SignInAsync(PhoneModel phoneModel) { AuthUserOut authUserOut = new AuthUserOut(); Company company = new Company(); //读取凭证 var tokenModel = await this._wechatOAuth.GetCode2SessionAsync(phoneModel.code); //解析电话 var phoneInfo = MiniProgramUtil.AESDecrypt(phoneModel.encryptedDataStr, tokenModel.SessionKey, phoneModel.iv); //查询系统用户 var sysUser = this._sysUserRep.AsQueryable() .Filter("TenantId", true) .First(x => x.Phone == phoneInfo.PhoneNumber); var wxUser = await this.Baseuser.AsQueryable() .Filter("TenantId", true) .Where(x => x.OpenID == tokenModel.OpenId).SingleAsync(); //账号不存在 生成系统账号 if (sysUser.IsEmpty()) { sysUser = await this._sysUserRep.InsertReturnEntityAsync(new SysUser() { Account = phoneInfo.PurePhoneNumber, AdminType = AdminType.None, Avatar = "https://gdzongzhi.com/assets/img/logo.png", Birthday = DateTime.Now, CreatedTime = DateTime.Now, CreatedUserId = null, CreatedUserName = null, Sex = Gender.UNKNOWN, Status = CommonStatus.ENABLE, Email = null, IsDeleted = false, Name = phoneInfo.PhoneNumber, Password = MD5Encryption.Encrypt("123456"), TenantId = 392820661919813, Phone = phoneInfo.PhoneNumber, NickName = "", Tel = null, }); } //区分不同类型账号 if (phoneModel.logInType ==(int)UserEnum.JOB) { if (wxUser.IsEmpty()) { wxUser = await this.Baseuser.InsertReturnEntityAsync(new BaseUser() { UnionId = tokenModel.Unionid, CreatedUserId = sysUser.Id, CreatedTime = DateTime.Now, CreatedUserName = sysUser.Name, AvatarUrl = "https://gdzongzhi.com/assets/img/logo.png", Status =(int)CommonStatus.ENABLE, OpenID = tokenModel.OpenId, TenantId = 392820661919813, Type = (int)UserEnum.JOB, UserName = phoneInfo.PhoneNumber, }); } else { wxUser.Type = (int)UserEnum.JOB; var bsUser = await this.Baseuser.UpdateAsync(wxUser); } } else { //如果是企业账号,应该是绑定了企业租户信息 if (wxUser.IsEmpty()|| wxUser.CompanyID.IsNullOrZero()) throw Oops.Oh(ErrorCode.xg1002); wxUser.Type= (int)UserEnum.ADVERTISE; var bsUser = await this.Baseuser.UpdateAsync(wxUser); //获取公司信息 company = await this.CompanyRep.SingleAsync(x=>x.Id == wxUser.CompanyID); authUserOut.companyDto = company.Adapt(); } if (wxUser.IsEmpty() || sysUser.IsEmpty()) throw Oops.Oh(ErrorCode.xg1002); var Self = await this.Self.FirstOrDefaultAsync(x => x.CreatedUserId == sysUser.Id); // 获取加密后的密码 var encryptPassword = MD5Encryption.Encrypt(sysUser.Password); // 验证账号是否被冻结 if (sysUser.Status == CommonStatus.DISABLE) throw Oops.Oh(ErrorCode.D1017); //获取对应租户 var tenant = this._sysTenantRep.Single(sysUser.TenantId); if (tenant.IsNullOrZero()) throw Oops.Oh(ErrorCode.F1001); // 生成Token令牌 authUserOut.Token = JWTEncryption.Encrypt(new Dictionary { {ClaimConst.CLAINM_USERID, sysUser.Id}, {ClaimConst.TENANT_ID, sysUser.TenantId}, {ClaimConst.CLAINM_ACCOUNT, sysUser.Account}, {ClaimConst.CLAINM_NAME, sysUser.Name}, {ClaimConst.CLAINM_SUPERADMIN, sysUser.AdminType}, { ClaimConst.CLAINM_TENANT_TYPE, tenant.TenantType }, { ClaimConst.CLAINM_TENANT_NAME, tenant.Name }, }); // 设置Swagger自动登录 _httpContextAccessor.HttpContext.SigninToSwagger(authUserOut.Token); // 生成刷新Token令牌 var refreshToken = JWTEncryption.GenerateRefreshToken(authUserOut.Token, 30); // 设置刷新Token令牌 _httpContextAccessor.HttpContext.Response.Headers["x-access-token"] = refreshToken; var httpContext = App.HttpContext; await _eventPublisher.PublishAsync(new ChannelEventSource("Update:UserLoginInfo", new SysUser { Id = sysUser.Id, LastLoginIp = httpContext.GetLocalIpAddressToIPv4(), LastLoginTime = DateTime.Now })); authUserOut.Avatar = sysUser.Avatar; authUserOut.Phone = sysUser.Phone; authUserOut.Sex = sysUser.Sex; authUserOut.UserId = sysUser.Id; authUserOut.UserName = sysUser.Name; authUserOut.Self = Self.IsEmpty() ? null : Self.Name; authUserOut.Type = (UserEnum)wxUser.Type; authUserOut.OpenID = tokenModel.OpenId; authUserOut.Tenant = tenant.Adapt(); authUserOut.Describe = wxUser.Describe; await this.cacheService.SetUserInfoAsync(authUserOut, authUserOut.UserId); return authUserOut; } /// /// 手机端登录(验证码登录) /// /// [HttpPost("/Mini/SignInCode")] [AllowAnonymous] public async Task SignInCodeAsync(PhoneModel phoneModel) { Company company = new Company(); AuthUserOut authUserOut = new AuthUserOut(); //验证电话和验证码一致 var verIfy = await this.cacheService.GetVerifyCode(phoneModel.phone); if (verIfy != phoneModel.checkingCode) throw new Exception("验证码错误"); //查询系统用户 var sysUser = this._sysUserRep.AsQueryable() .Filter("TenantId", true) .First(x => x.Phone == phoneModel.phone.ToString()); //账号不存在 生成系统账号 if (sysUser.IsEmpty()) { sysUser = await this._sysUserRep.InsertReturnEntityAsync(new SysUser() { Account = phoneModel.phone.ToString(), AdminType = AdminType.None, Avatar = "https://gdzongzhi.com/assets/img/logo.png", Birthday = DateTime.Now, CreatedTime = DateTime.Now, CreatedUserId = null, CreatedUserName = null, Sex = Gender.UNKNOWN, Status = CommonStatus.ENABLE, Email = null, IsDeleted = false, Name = phoneModel.phone.ToString(), Password = MD5Encryption.Encrypt("123456"), TenantId = 392820661919813, Phone = phoneModel.phone.ToString(), NickName = "", Tel = null, }); } //读取凭证 var tokenModel = await this._wechatOAuth.GetCode2SessionAsync(phoneModel.code); var wxUser = await this.Baseuser.AsQueryable() .Filter("TenantId", true) .Where(x => x.OpenID == tokenModel.OpenId).SingleAsync(); //区分不同类型账号 if (phoneModel.logInType == (int)UserEnum.JOB) { if (wxUser.IsEmpty()) { wxUser = await this.Baseuser.InsertReturnEntityAsync(new BaseUser() { UnionId = tokenModel.Unionid, CreatedUserId = sysUser.Id, CreatedTime = DateTime.Now, CreatedUserName = sysUser.Name, AvatarUrl = "https://gdzongzhi.com/assets/img/logo.png", Status = (int)CommonStatus.ENABLE, OpenID = tokenModel.OpenId, TenantId = 392820661919813, Type = (int)UserEnum.JOB, UserName = phoneModel.phone.ToString(), }); } else { wxUser.Type = (int)UserEnum.JOB; var bsUser = await this.Baseuser.UpdateAsync(wxUser); } } else { //如果是企业账号,应该是绑定了企业租户信息 if (wxUser.IsEmpty() || wxUser.CompanyID.IsNullOrZero()) throw Oops.Oh(ErrorCode.xg1002); wxUser.Type = (int)UserEnum.ADVERTISE; var bsUser = await this.Baseuser.UpdateAsync(wxUser); //获取公司信息 company = await this.CompanyRep.SingleAsync(x => x.Id == wxUser.CompanyID); authUserOut.companyDto = company.Adapt(); } if (wxUser.IsEmpty() || sysUser.IsEmpty()) throw Oops.Oh(ErrorCode.xg1002); var Self = await this.Self.FirstOrDefaultAsync(x => x.CreatedUserId == sysUser.Id); // 获取加密后的密码 var encryptPassword = MD5Encryption.Encrypt(sysUser.Password); // 验证账号是否被冻结 if (sysUser.Status == CommonStatus.DISABLE) throw Oops.Oh(ErrorCode.D1017); //获取对应租户 var tenant = this._sysTenantRep.Single(sysUser.TenantId); if (tenant.IsNullOrZero()) throw Oops.Oh(ErrorCode.F1001); // 生成Token令牌 authUserOut.Token = JWTEncryption.Encrypt(new Dictionary { {ClaimConst.CLAINM_USERID, sysUser.Id}, {ClaimConst.TENANT_ID, sysUser.TenantId}, {ClaimConst.CLAINM_ACCOUNT, sysUser.Account}, {ClaimConst.CLAINM_NAME, sysUser.Name}, {ClaimConst.CLAINM_SUPERADMIN, sysUser.AdminType}, { ClaimConst.CLAINM_TENANT_TYPE, tenant.TenantType }, { ClaimConst.CLAINM_TENANT_NAME, tenant.Name }, }); // 设置Swagger自动登录 _httpContextAccessor.HttpContext.SigninToSwagger(authUserOut.Token); // 生成刷新Token令牌 var refreshToken = JWTEncryption.GenerateRefreshToken(authUserOut.Token, 30); // 设置刷新Token令牌 _httpContextAccessor.HttpContext.Response.Headers["x-access-token"] = refreshToken; var httpContext = App.HttpContext; await _eventPublisher.PublishAsync(new ChannelEventSource("Update:UserLoginInfo", new SysUser { Id = sysUser.Id, LastLoginIp = httpContext.GetLocalIpAddressToIPv4(), LastLoginTime = DateTime.Now })); authUserOut.Avatar = sysUser.Avatar; authUserOut.Phone = sysUser.Phone; authUserOut.Sex = sysUser.Sex; authUserOut.UserId = sysUser.Id; authUserOut.UserName = sysUser.Name; authUserOut.Self = Self.IsEmpty() ? null : Self.Name; authUserOut.Type = (UserEnum)wxUser.Type; authUserOut.OpenID = tokenModel.OpenId; authUserOut.Tenant = tenant.Adapt(); authUserOut.Describe = wxUser.Describe; await this.cacheService.SetUserInfoAsync(authUserOut, authUserOut.UserId); return authUserOut; } /// /// 发送验证码 /// /// [HttpGet("/Mini/SendTextMessage")] [AllowAnonymous] public async Task SendTextMessage(string phone) { string code = ""; //生成随机数字 Random rand = new Random(); for (int i = 0; i < 6; i++) { code += rand.Next(0, 9).ToString(); } Credential credential = new Credential() { SecretId = await GetConfigCache("TENCENT_SMS_SECRET_ID"), SecretKey =await GetConfigCache("TENCENT_SMS_SECRET_KEY") }; SendSmsRequest sendSmsRequest = new SendSmsRequest() { SignName = await GetConfigCache("TENCENT_SMS_SIGN"), SmsSdkAppId = await GetConfigCache("TENCENT_SMS_SDK_APP_ID"), PhoneNumberSet = new string[] { "+86" + phone }, TemplateId = await GetConfigCache("TENCENT_SMS_TEMPLATEID"), TemplateParamSet = new string[] { code } }; TencentCloudExamples.SendTextMessage(sendSmsRequest,credential); await this.cacheService.SetVerifyCode(phone, code); } /// /// 获取当前登录用户信息 /// /// [HttpGet("/Mini/GetLoginUser")] public async Task GetLoginUserAsync() { return await this.cacheService.GetUserInfoAsync(UserManager.UserId); } /// /// 获取AccessToken /// /// [HttpGet("/Mini/GetAccessToken")] public async Task GetAccessTokenAsync() { var value = await cacheService.GetAccessTokenAsync(); if(value == null) { var token = this._wechatOAuth.GetTokenAsync(); await cacheService.SetAccessTokenAsync(token.Result.AccessToken); value = token.Result.AccessToken; } return value; } /// /// 获取二维分享码 /// /// [HttpGet("/Mini/GetShareCode")] public async Task GetShareCode(string scene, string page) { var value = await cacheService.GetAccessTokenAsync(); if (value == null) { var token = this._wechatOAuth.GetTokenAsync(); await cacheService.SetAccessTokenAsync(token.Result.AccessToken); value = token.Result.AccessToken; } var res = await this._wechatOAuth.GetShareCodeAsync(value,scene, page); return Convert.ToBase64String(res); } /// /// 获取配置信息 /// /// /// private async Task GetConfigCache(string code) { var value = await _sysCacheService.GetAsync(code); if (string.IsNullOrEmpty(value)) { var config = await _sysConfigRep.FirstOrDefaultAsync(u => u.Code == code); value = config != null ? config.Value : ""; await _sysCacheService.SetAsync(code, value); } return value; } } }