using Furion.DataEncryption; using Furion.DependencyInjection; using Nirvana.Common; using Nirvana.Common.ApiBase; using Senparc.Weixin; using Senparc.Weixin.WxOpen.AdvancedAPIs.Sns; using Senparc.Weixin.WxOpen.Containers; using Senparc.Weixin.WxOpen.Helpers; using SqlSugar; using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Text; using System.Threading.Tasks; using System.Web; using YBDevice.Core; using YBDevice.Entity; namespace YBDevice.NApi.Application.BusinessClient.AccountInfo { public class AccountService : IAccountService, ITransient { public string WxOpenAppId = Senparc.Weixin.Config.SenparcWeixinSetting.WxOpenAppId; public string WxOpenAppSecret = Senparc.Weixin.Config.SenparcWeixinSetting.WxOpenAppSecret; public string WxOpenToken = Senparc.Weixin.Config.SenparcWeixinSetting.WxOpenToken; public string WxOpenEncodingAESKey = Senparc.Weixin.Config.SenparcWeixinSetting.WxOpenEncodingAESKey; private readonly ISqlSugarRepository repository; private readonly SqlSugarClient dbClient; private readonly ILoggerService _loggerService; private readonly IHttpClientFactory _clientFactory; public AccountService(ISqlSugarRepository sqlSugarRepository, ILoggerService loggerService, IHttpClientFactory clientFactory) { repository = sqlSugarRepository; dbClient = repository.Context; _loggerService = loggerService; _clientFactory = clientFactory; } /// /// 手机号授权,如果未注册会自动进行注册 /// /// /// public async Task DecryptPhoneAsync(BusinessDecryptSubmitModel model) { var sessionBag = await SessionContainer.GetSessionAsync(model.sessionId); if (sessionBag == null) { return new ResultInfo(ResultState.FAIL, "sessionId未找到"); } var phone = EncryptHelper.DecryptPhoneNumber(model.sessionId, model.encryptedData, model.iv); _loggerService.AddLogger($"手机号解密信息:{phone.ToJson()}"); return await InsertOrUpdateAccountInfoAsync(new BusinessRegDto { isvrcode = false, sessionId = model.sessionId, NickName = phone.purePhoneNumber, Password = phone.purePhoneNumber, RePassword = phone.purePhoneNumber, Phone = phone.purePhoneNumber, code = "" }); } /// /// 小程序登录 /// /// /// public async Task OnLoginAsync(WXOpenLoginSubmitModel model) { #region 获取当前可用的appid if (!string.IsNullOrEmpty(model.appid)) { var itemlist = Config.SenparcWeixinSetting.Items; foreach (var item in itemlist) { if (item.Value.WxOpenAppId == model.appid) { WxOpenAppId = item.Value.WxOpenAppId; WxOpenAppSecret = item.Value.WxOpenAppSecret; break; } } } #endregion var jsonResult = await SnsApi.JsCode2JsonAsync(WxOpenAppId, WxOpenAppSecret, model.code); if (jsonResult.errcode == ReturnCode.请求成功) { //检查此openid是否已注册 var wxdata = await dbClient.Queryable().FirstAsync(x => x.OpenId == jsonResult.openid); TimeSpan val = new TimeSpan(1, 0, 0);//一个小时 if (wxdata == null) { //记录信息 var sessionBag = await SessionContainer.UpdateSessionAsync(jsonResult.openid, jsonResult.openid, jsonResult.session_key, jsonResult.unionid, val); return new ResultInfo(ResultState.WXUNAUTHORITY, "此账户还未注册", new WxOpenLoginData { sessionid = sessionBag.Key }); } //刷新key var sessionbag = await SessionContainer.UpdateSessionAsync(jsonResult.openid, jsonResult.openid, jsonResult.session_key, jsonResult.unionid, val); //生成token return await GenTokenAsync(wxdata.UserId, wxdata.BusinessId, wxdata.OpenId, sessionbag.Key); } return new ResultInfo(ResultState.FAIL, jsonResult.errmsg); } /// /// 根据手机号进行注册 /// /// /// public async Task RegisterAsync(BusinessRegDto model) { //检查此手机号是否已注册 if (await dbClient.Queryable().AnyAsync(x => x.Phone == model.Phone)) { return new ResultInfo(ResultState.FAIL, "此手机号已注册,可直接登录"); } if (model.isvrcode) { if (string.IsNullOrEmpty(model.code)) { return new ResultInfo(ResultState.FAIL, "验证码不可为空"); } //检查验证码 var yzm = RedisHelpers.stringGet($"ybdeviceclient_yam_{model.Phone}"); if (model.code != yzm) { return new ResultInfo() { code = ResultState.FAIL, message = "验证码错误" }; } } //检查两次密码是否一致 if (model.Password != model.RePassword) { return new ResultInfo(ResultState.FAIL, "两次密码不一致"); } return await InsertOrUpdateAccountInfoAsync(model); } /// /// 生成code /// /// /// private string GenCode(int cnt) => cnt switch { < 9 => $"000{cnt + 1}", < 99 and >= 9 => $"00{cnt + 1}", < 999 and >= 99 => $"0{cnt + 1}", < 9999 and >= 999 => $"{cnt + 1}", _ => "" }; /// /// 生成token /// /// private async Task GenTokenAsync(int userid, int businessid, string openid, string sessionid) { openid = openid.ToStr(); sessionid = sessionid.ToStr(); var business = await dbClient.Queryable().FirstAsync(x => x.BusinessId == businessid); //生成token var token = JWTEncryption.Encrypt(new Dictionary() { {"UserId",userid}, {"BusinessId",businessid}, {"loginttime",DateTime.Now }, {"fansid",openid }, {"AccountType",business !=null?business.AccountType:1 } }); var refreshToken = JWTEncryption.GenerateRefreshToken(token, 43200); return new ResultInfo(ResultState.SUCCESS, "登录成功", new { token = token, sessionid = sessionid, refreshtoken = refreshToken }); } /// /// 添加或者更新商户信息 /// /// /// public async Task InsertOrUpdateAccountInfoAsync(BusinessRegDto businessRegDto) { SessionBag sessionBag = null; if (!businessRegDto.sessionId.IsEmpty()) { sessionBag = await SessionContainer.GetSessionAsync(businessRegDto.sessionId); if (sessionBag == null) { return new ResultInfo(ResultState.FAIL, "sessionId未找到"); } } var busienss = await dbClient.Queryable().FirstAsync(x => x.Phone == businessRegDto.Phone); //如果未注册自动进行注册 if (busienss == null) { //生成编码 int cnt = await dbClient.Queryable().CountAsync(x => x.ParentId == 0); string scode = GenCode(cnt); if (string.IsNullOrEmpty(scode)) { return new ResultInfo(ResultState.FAIL, "超过最大注册数量"); } var buss = new YB_Business { CreateTime = DateTime.Now, Status = (int)StatusType.Enabled, Name = businessRegDto.NickName, Phone = businessRegDto.Phone, Remark = "", ParentId = 0, Type = 2, //1-系统默认,2-通过商户小程序自主注册的 Code = scode }; var bid = await dbClient.Insertable(buss).ExecuteReturnIdentityAsync(); var secretkey = Md5.md5(Common.CreateNo(), 16).ToLower(); var password = Md5.md5(DESEncrypt.Encrypt(Md5.md5(businessRegDto.Password, 32).ToLower(), secretkey).ToLower(), 32).ToLower(); var user = new YB_Account { Secret = secretkey, AccountType = (int)AccountType.agent, Status = (int)StatusType.Enabled, BusinessId = bid, CreateTime = DateTime.Now, LastVisitIP = "", LastVisitTime = DateTime.Now, Phone = businessRegDto.Phone, RealName = businessRegDto.NickName, RoleId = 2, UserName = businessRegDto.Phone, Password = password }; int userid = await dbClient.Insertable(user).ExecuteReturnIdentityAsync(); //插入商户数据 await dbClient.Insertable(new YB_BusinessRealData { BusinessCount = 0, CreateTime = DateTime.Now, Balance = 0, BusinessId = bid, DevCount = 0, TodayIncome = 0, TodayResultCnt = 0, TotalIncome = 0, TotalResultCnt = 0, TotalTxAmount = 0, TodayRealCnt = 0, TotalRealCnt = 0, TodayDevCount = 0 }).ExecuteCommandAsync(); //更新汇总表 int devcnt = await dbClient.Queryable().CountAsync(); int businesscnt = await dbClient.Queryable().CountAsync(); int todaydevactinvecnt = await dbClient.Queryable().Where(x => SqlFunc.DateIsSame(x.LastHeartTime, DateTime.Now)).CountAsync(); if (await dbClient.Queryable().AnyAsync(x => x.Id == 1)) { await dbClient.Updateable().SetColumns(x => new YB_Combined { TotalDevCnt = devcnt, BusinessCnt = businesscnt, TodayDevCnt = todaydevactinvecnt }).Where(x => x.Id == 1).ExecuteCommandAsync(); } else { await dbClient.Insertable(new YB_Combined { TodayDevCnt = todaydevactinvecnt, BusinessCnt = businesscnt, TodayIncome = 0, TodayRegCnt = 0, TodayResultCnt = 0, TotalDevCnt = devcnt, TotalIncome = 0, TotalRegCnt = 0, TotalResultCnt = 0, Id = 1 }).ExecuteCommandAsync(); } //增加关联记录 if (sessionBag != null) { await dbClient.Insertable(new YB_BusinessWX { BusinessId = bid, CreateTime = DateTime.Now, OpenId = sessionBag.OpenId, UnionId = sessionBag.UnionId.ToStr(), UserId = userid }).ExecuteCommandAsync(); } //生成token return await GenTokenAsync(userid, user.BusinessId, sessionBag?.OpenId, businessRegDto.sessionId); } else { var user = await dbClient.Queryable().FirstAsync(x => x.BusinessId == busienss.Id); //更新数据 if (sessionBag != null && !await dbClient.Queryable().AnyAsync(x => x.BusinessId == busienss.Id && x.OpenId == sessionBag.OpenId)) { await dbClient.Insertable(new YB_BusinessWX { BusinessId = busienss.Id, CreateTime = DateTime.Now, OpenId = sessionBag.OpenId, UnionId = sessionBag.UnionId.ToStr(), UserId = user.Id }).ExecuteCommandAsync(); } //更新登录时间 await dbClient.Updateable().SetColumns(x => new YB_Account { LastVisitIP = Net.Ip, LastVisitTime = DateTime.Now }).Where(x => x.Id == user.Id).ExecuteCommandAsync(); //生成token return await GenTokenAsync (user.Id, user.BusinessId, sessionBag?.OpenId, businessRegDto.sessionId); } } /// /// 根据手机号和密码进行登录 /// /// /// public async Task LoginAsync(BusinessLoginDto businessLoginDto) { //检查此手机号是否已注册 if (!await dbClient.Queryable().AnyAsync(x => x.Phone == businessLoginDto.Phone)) { return new ResultInfo(ResultState.FAIL, "此手机号还未注册账户"); } var user = await dbClient.Queryable().FirstAsync(x => x.Phone == businessLoginDto.Phone); if (user == null) { return new ResultInfo(ResultState.FAIL, "此手机号还未注册账户"); } //检查密码是否正确 var checkpassword = Md5.md5(DESEncrypt.Encrypt(Md5.md5(businessLoginDto.Password, 32).ToLower(), user.Secret).ToLower(), 32).ToLower(); if (checkpassword != user.Password) { return new ResultInfo(ResultState.FAIL, "密码不正确"); } return await InsertOrUpdateAccountInfoAsync(new BusinessRegDto { code = "", sessionId = businessLoginDto.sessionId, isvrcode = false, NickName = businessLoginDto.Phone, Phone = businessLoginDto.Phone, Password = businessLoginDto.Password, RePassword = businessLoginDto.Password }); } /// /// 手机号快捷登录 /// /// /// public async Task SLoginAsync(BusinessQLoginDto businessQLoginDto) { if (businessQLoginDto.isvrcode) { if (string.IsNullOrEmpty(businessQLoginDto.code)) { return new ResultInfo(ResultState.FAIL, "验证码不可为空"); } //检查验证码 var yzm = RedisHelpers.stringGet($"ybdeviceclient_yam_{businessQLoginDto.Phone}"); if (businessQLoginDto.code != yzm) { return new ResultInfo() { code = ResultState.FAIL, message = "验证码错误" }; } } return await InsertOrUpdateAccountInfoAsync(new BusinessRegDto { code = "", sessionId = businessQLoginDto.sessionId, isvrcode = false, NickName = businessQLoginDto.Phone, Password = businessQLoginDto.Phone, Phone = businessQLoginDto.Phone, RePassword = businessQLoginDto.Phone }); } /// /// 发送短信验证码 /// /// /// public async Task SendCodeAsync(string phone) { if (string.IsNullOrEmpty(phone)) { return new ResultInfo(ResultState.FAIL, "手机号不可为空"); } if (!Validate.IsValidMobile(phone)) { return new ResultInfo(ResultState.FAIL, "手机号码不合法"); } Random rd = new Random(); var yzm = rd.Next(100000, 999999); var platform = "每日一称"; var content = $"【{platform}】您好,欢迎使用{platform},您的手机验证码是:{yzm},验证码一分钟内有效,若非本人操作,请忽略!"; var data = new { phone = phone, Content = HttpUtility.UrlEncode(content) }; var par = $"ybdeviceclient_yam_{phone}"; if (!string.IsNullOrEmpty(RedisHelpers.stringGet(par))) { return new ResultInfo(ResultState.FAIL, "请求频繁"); } var url = "http://sms.ybhdmob.com/Message/Send?token=ybhdmob"; var request = new HttpRequestMessage(HttpMethod.Post, url); string body = data.ToJson(); request.Content = new StringContent(body, Encoding.UTF8, "application/json"); var client = _clientFactory.CreateClient(); var response = await client.SendAsync(request); if (response.IsSuccessStatusCode) { var result = await response.Content.ReadAsStringAsync(); var results = result.ToObject(); //记录日志 var msg = $"短信发送:参数:{data.ToJson()}\r\n返回值:{result}"; _loggerService.AddLogger(msg); if (results != null && results.code == 0) { RedisHelpers.Insert(par, yzm.ToString(), 60); } return new ResultInfo(ResultState.SUCCESS, "验证码已发送"); } else { return new ResultInfo(ResultState.FAIL, "短信发送失败"); } } } }