451 lines
19 KiB
C#
451 lines
19 KiB
C#
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<YB_OfficlaAccount> repository;
|
|
private readonly SqlSugarClient dbClient;
|
|
private readonly ILoggerService _loggerService;
|
|
private readonly IHttpClientFactory _clientFactory;
|
|
public AccountService(ISqlSugarRepository<YB_OfficlaAccount> sqlSugarRepository, ILoggerService loggerService, IHttpClientFactory clientFactory)
|
|
|
|
{
|
|
repository = sqlSugarRepository;
|
|
dbClient = repository.Context;
|
|
_loggerService = loggerService;
|
|
_clientFactory = clientFactory;
|
|
}
|
|
/// <summary>
|
|
/// 手机号授权,如果未注册会自动进行注册
|
|
/// </summary>
|
|
/// <param name="model"></param>
|
|
/// <returns></returns>
|
|
public async Task<ResultInfo> 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 = ""
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// 小程序登录
|
|
/// </summary>
|
|
/// <param name="model"></param>
|
|
/// <returns></returns>
|
|
public async Task<ResultInfo> 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<YB_BusinessWX>().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);
|
|
}
|
|
/// <summary>
|
|
/// 根据手机号进行注册
|
|
/// </summary>
|
|
/// <param name="model"></param>
|
|
/// <returns></returns>
|
|
public async Task<ResultInfo> RegisterAsync(BusinessRegDto model)
|
|
{
|
|
//检查此手机号是否已注册
|
|
if (await dbClient.Queryable<YB_Business>().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<string>($"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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 生成code
|
|
/// </summary>
|
|
/// <param name="cnt"></param>
|
|
/// <returns></returns>
|
|
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}",
|
|
_ => ""
|
|
};
|
|
/// <summary>
|
|
/// 生成token
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private async Task<ResultInfo> GenTokenAsync(int userid, int businessid, string openid, string sessionid)
|
|
{
|
|
openid = openid.ToStr();
|
|
sessionid = sessionid.ToStr();
|
|
var business = await dbClient.Queryable<YB_Account>().FirstAsync(x => x.BusinessId == businessid);
|
|
//生成token
|
|
var token = JWTEncryption.Encrypt(new Dictionary<string, object>() {
|
|
{"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
|
|
});
|
|
}
|
|
/// <summary>
|
|
/// 添加或者更新商户信息
|
|
/// </summary>
|
|
/// <param name="businessRegDto"></param>
|
|
/// <returns></returns>
|
|
public async Task<ResultInfo> 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<YB_Business>().FirstAsync(x => x.Phone == businessRegDto.Phone);
|
|
//如果未注册自动进行注册
|
|
if (busienss == null)
|
|
{
|
|
//生成编码
|
|
int cnt = await dbClient.Queryable<YB_Business>().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<YB_Device>().CountAsync();
|
|
int businesscnt = await dbClient.Queryable<YB_Business>().CountAsync();
|
|
int todaydevactinvecnt = await dbClient.Queryable<YB_Device>().Where(x => SqlFunc.DateIsSame(x.LastHeartTime, DateTime.Now)).CountAsync();
|
|
if (await dbClient.Queryable<YB_Combined>().AnyAsync(x => x.Id == 1))
|
|
{
|
|
await dbClient.Updateable<YB_Combined>().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<YB_Account>().FirstAsync(x => x.BusinessId == busienss.Id);
|
|
//更新数据
|
|
if (sessionBag != null && !await dbClient.Queryable<YB_BusinessWX>().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<YB_Account>().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);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// 根据手机号和密码进行登录
|
|
/// </summary>
|
|
/// <param name="businessLoginDto"></param>
|
|
/// <returns></returns>
|
|
public async Task<ResultInfo> LoginAsync(BusinessLoginDto businessLoginDto)
|
|
{
|
|
//检查此手机号是否已注册
|
|
if (!await dbClient.Queryable<YB_Business>().AnyAsync(x => x.Phone == businessLoginDto.Phone))
|
|
{
|
|
return new ResultInfo(ResultState.FAIL, "此手机号还未注册账户");
|
|
}
|
|
var user = await dbClient.Queryable<YB_Account>().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
|
|
});
|
|
}
|
|
/// <summary>
|
|
/// 手机号快捷登录
|
|
/// </summary>
|
|
/// <param name="businessQLoginDto"></param>
|
|
/// <returns></returns>
|
|
public async Task<ResultInfo> SLoginAsync(BusinessQLoginDto businessQLoginDto)
|
|
{
|
|
if (businessQLoginDto.isvrcode)
|
|
{
|
|
if (string.IsNullOrEmpty(businessQLoginDto.code))
|
|
{
|
|
return new ResultInfo(ResultState.FAIL, "验证码不可为空");
|
|
}
|
|
//检查验证码
|
|
var yzm = RedisHelpers.stringGet<string>($"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
|
|
});
|
|
|
|
}
|
|
/// <summary>
|
|
/// 发送短信验证码
|
|
/// </summary>
|
|
/// <param name="phone"></param>
|
|
/// <returns></returns>
|
|
public async Task<ResultInfo> 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<string>(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<SMSMODEL>();
|
|
//记录日志
|
|
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, "短信发送失败");
|
|
}
|
|
}
|
|
}
|
|
}
|