using YD_WeChatApplet.Context; using Microsoft.EntityFrameworkCore; using YD_WeChatApplet.Commons; using YD_WeChatApplet.Api.Utilities; using Microsoft.AspNetCore.Mvc; using TGJ.NetworkFreight.SeckillAggregateServices.Pos.UserService; using YD_WeChatApplet.WeChat.Lib; using YD_WeChatApplet.WeChat; using YD_WeChatApplet.Api.Entitys; using YD_WeChatApplet.Commons.Users; using System.Linq.Expressions; using YD_WeChatApplet.Commons.Dto; using YD_WeChatApplet.Api.Services.Impl; using YD_WeChatApplet.Commons.Dto.User; using Newtonsoft.Json.Linq; using Microsoft.Extensions.Logging; using System.Net; using YD_WeChatApplet.Api.SmartSportsEntitys; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Authorization; using System.Text.Json; using Microsoft.EntityFrameworkCore.Metadata.Internal; using YD_WeChatApplet.Commons.Dto.ClientSide; using System.Reflection; namespace YD_WeChatApplet.Services { public class UserService : IUserService { public UserContext _userContext; public SmartSportsContext _smartSportsContext; private readonly ICacheService _caching; public UserService(UserContext userContext, SmartSportsContext smartSportsContext, ICacheService caching) { _userContext = userContext; _smartSportsContext = smartSportsContext; _caching = caching; } /// /// 账号密码登录 /// /// public async Task Login(LoginInfo paramDto) { User userModel = null; switch (paramDto.RoleId) { case 2: // 教师登录 userModel = await QueryUserByRole( x => x.UserName == paramDto.Key && EF.Functions.Collate(x.UserPwd, "SQL_Latin1_General_CP1_CS_AS") == paramDto.Password, () => GetTeacherUser(paramDto) ); break; case 3: // 家长登录 userModel = await QueryUserByRole( x => x.UserName == paramDto.Key && x.UserPwd == paramDto.Password, () => GetParentUser(paramDto) ); break; default: throw new Exception("无效的角色ID"); } if (userModel == null || userModel.User_Id <= 0) throw new Exception("用户新增失败"); var openId = _caching.Get(userModel.User_Id.ToString()); if (openId != null && openId.ToString() != paramDto.OpenId) throw new Exception("该用户已在其他设备上登陆,请退出后再登录"); else _caching.Add(userModel.User_Id.ToString(), paramDto.OpenId); return await GenerateUserInfoDto(userModel); } private async Task QueryUserByRole(Expression> queryCondition, Func> createUser) { var userModel = await _userContext.Users.FirstOrDefaultAsync(queryCondition); if (userModel == null) { var userData = await createUser(); if (userData == null) throw new Exception("账号或密码错误"); userModel = CreateUserModel(userData); // 保存新用户信息 await _userContext.Users.AddAsync(userModel); await _userContext.SaveChangesAsync(); } return userModel; } private async Task GetTeacherUser(LoginInfo paramDto) { //var user = await _userContext.Users.FirstOrDefaultAsync(x => x.Role_Id == paramDto.RoleId && x.UserName == paramDto.Key); //if (user == null) //{ var teacherUser = await _smartSportsContext.Teacher .Join(_smartSportsContext.School, t => t.SchoolCode, s => s.SchoolCode, (t, s) => new { t.Id, t.TeacherPhoneNo, t.AppletPwd, t.TeacherStatus, t.TeacherName, t.SchoolCode, t.Sex, t.TeacherPhoto, s.SchoolType }).FirstOrDefaultAsync(x => x.TeacherPhoneNo == paramDto.Key && x.AppletPwd == paramDto.Password && x.TeacherStatus == 1); if (teacherUser == null) return null; if (teacherUser.SchoolType == 1) { return new UserModelDataDto { PhoneNo = teacherUser.TeacherPhoneNo, UserPwd = teacherUser.AppletPwd, UserName = teacherUser.TeacherPhoneNo, UserTrueName = teacherUser.TeacherName, Gender = teacherUser.Sex, HeadImageUrl = teacherUser.TeacherPhoto, SchoolCode = teacherUser.SchoolCode, RoleName = "老师", RoleId = 2, RelevanceId = Guid.NewGuid(), OpenId = paramDto.OpenId }; } else { return new UserModelDataDto { PhoneNo = teacherUser.TeacherPhoneNo, UserPwd = teacherUser.AppletPwd, UserName = teacherUser.TeacherPhoneNo, UserTrueName = teacherUser.TeacherName, Gender = teacherUser.Sex, HeadImageUrl = teacherUser.TeacherPhoto, SchoolCode = teacherUser.SchoolCode, RoleName = "教练", RoleId = 4, RelevanceId = Guid.NewGuid(), OpenId = paramDto.OpenId }; } //} //return null; } private async Task GetParentUser(LoginInfo paramDto) { var parentUser = await _smartSportsContext.Student .FirstOrDefaultAsync(x => x.StudentName == paramDto.Key && x.StudentNo == paramDto.Password && x.StudentStatus == 1); if (parentUser == null) return null; return new UserModelDataDto { PhoneNo = parentUser.ParentPhoneNo, UserPwd = parentUser.StudentNo, UserName = parentUser.StudentName, UserTrueName = parentUser.StudentName, Gender = parentUser.Sex, HeadImageUrl = parentUser.Photo, Address = parentUser.HomeAddress, SchoolCode = parentUser.SchoolCode, RoleName = "家长", RoleId = 3, RelevanceId = Guid.NewGuid() }; } private User CreateUserModel(UserModelDataDto userData) { return new User() { ModifyDate = DateTime.Now, CreateDate = DateTime.Now, Enable = true, RoleName = userData.RoleName, Role_Id = userData.RoleId, HeadImageUrl = userData.HeadImageUrl, Address = userData.Address, Gender = userData.Gender, Email = userData.Email, PhoneNo = userData.PhoneNo, SchoolCode = userData.SchoolCode, UserName = userData.UserName, UserPwd = userData.UserPwd, UserTrueName = userData.UserTrueName, }; } private async Task GenerateUserInfoDto(User userModel) { string token = JwtHelper.IssueJwt(new UserInfoDto() { User_Id = userModel.User_Id, UserName = userModel.UserName, Role_Id = userModel.Role_Id, PhoneNo = userModel.PhoneNo ?? "", SchoolCode = userModel.SchoolCode, UserTrueName = userModel.UserName, UserNo = userModel.UserPwd }); var userAuth = await _userContext.User_Auth.CountAsync(x => x.Self_Id == userModel.User_Id && x.Bind_Id == userModel.User_Id); if (userAuth == 0) { await _userContext.User_Auth.AddAsync(new User_Auth() { Self_Id = userModel.User_Id, Bind_Id = userModel.User_Id, Role_Id = userModel.Role_Id, Token = token }); await _userContext.SaveChangesAsync(); } return new UserInfoDto() { SchoolCode = userModel.SchoolCode, Enable = userModel.Enable, PhoneNo = userModel.PhoneNo, RoleName = userModel.RoleName, Role_Id = userModel.Role_Id, UserName = userModel.UserName, UserTrueName = userModel.UserName, User_Id = userModel.User_Id, UserNo = userModel.UserPwd, Token = token }; } public async Task WxFirstLogin(WXLoginPo loginPo) { try { var wli = new WechatLoginInfo(); wli.code = loginPo.code; wli.encryptedData = loginPo.encryptedData; wli.iv = loginPo.iv; wli.rawData = loginPo.rawData; wli.signature = loginPo.signature; wli.appid = AppSettings.WeChat.Appid; wli.secret = AppSettings.WeChat.Secret; Console.WriteLine(JsonSerializer.Serialize(wli)); WechatUserInfo wechatResult = new WeChatAppDecrypt().Decrypt(wli); Console.WriteLine(JsonSerializer.Serialize(wechatResult)); if (wechatResult == null || string.IsNullOrWhiteSpace(wechatResult.phoneNumber)) { throw new Exception("手机号获取失败"); } var userInfo = await _userContext.Users.FirstOrDefaultAsync(x => x.wx_OpenID == wechatResult.openId); if (userInfo == null) { userInfo = new User() { ModifyDate = DateTime.Now, CreateDate = DateTime.Now, UserName = wechatResult.phoneNumber, PhoneNo = wechatResult.phoneNumber, wx_HeadImgUrl = wechatResult.avatarUrl, wx_NickName = wechatResult.nickName, UserTrueName = string.IsNullOrWhiteSpace(wechatResult.nickName) ? "" : wechatResult.nickName, wx_OpenID = wechatResult.openId, Enable = true, RoleName = "用户", Role_Id = 1 }; await _userContext.Users.AddAsync(userInfo); await _userContext.SaveChangesAsync(); if (userInfo == null || userInfo.User_Id <= 0) { throw new Exception("用户新增失败"); } } else { if (userInfo.UserName != wechatResult.phoneNumber) { throw new Exception("该微信已绑定手机号!"); } } string token = JwtHelper.IssueJwt(new UserInfoDto() { User_Id = userInfo.User_Id, UserName = userInfo.UserName, Role_Id = userInfo.Role_Id, SchoolCode = userInfo.PhoneNo }); var userAuth = await _userContext.User_Auth.CountAsync(x => x.Self_Id == userInfo.User_Id && x.Bind_Id == userInfo.User_Id); if (userAuth == 0) { await _userContext.User_Auth.AddAsync(new User_Auth() { Self_Id = userInfo.User_Id, Bind_Id = userInfo.User_Id, Role_Id = userInfo.Role_Id, Token = token }); await _userContext.SaveChangesAsync(); } return new UserInfoDto() { Enable = userInfo.Enable, PhoneNo = userInfo.PhoneNo, RoleName = userInfo.RoleName, Role_Id = userInfo.Role_Id, UserName = userInfo.UserName, UserTrueName = userInfo.UserName, User_Id = userInfo.User_Id, Token = token }; } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(e.InnerException); return new UserInfoDto() { }; } } /// /// 获取微信OpenID /// /// /// /// public async Task GetWxOpenID(string code) { var wxSession = await GetWeChatSession(code); if (wxSession == null || string.IsNullOrEmpty(wxSession.openid)) { throw new Exception("微信登录失败:无法获取openid"); } return wxSession.openid; } /// /// 移除唯一标识 /// /// /// public Task RemoveUniqueIdentity(string userId) { _caching.Remove(userId); return Task.CompletedTask; } /// /// 验证唯一标识 /// /// /// /// public Task VerifyUniqueIdentity(string userId, string openId) { if (string.IsNullOrWhiteSpace(userId)) throw new ArgumentNullException(nameof(userId)); if (string.IsNullOrWhiteSpace(openId)) throw new ArgumentNullException(nameof(openId)); var identity = _caching.Get(userId); if (string.IsNullOrWhiteSpace(identity)) _caching.Add(userId, openId); return Task.FromResult(string.IsNullOrWhiteSpace(identity) || identity == openId); } /// /// 微信登录 /// /// /// /// public async Task WxLogin(string code) { var wxSession = await GetWeChatSession(code); if (wxSession == null || string.IsNullOrEmpty(wxSession.openid)) { throw new Exception("微信登录失败:无法获取openid"); } var userInfo = await _userContext.Users.FirstOrDefaultAsync(x => x.wx_OpenID == wxSession.openid); if (userInfo == null) { return new UserInfoDto(); } string token = JwtHelper.IssueJwt(new UserInfoDto() { User_Id = userInfo.User_Id, UserName = userInfo.UserName, Role_Id = userInfo.Role_Id, SchoolCode = userInfo.PhoneNo }); // 异步启动一个后台任务,执行数据库插入逻辑,不影响主流程 _ = Task.Run(async () => { try { var authCount = await _userContext.User_Auth .CountAsync(x => x.Self_Id == userInfo.User_Id && x.Bind_Id == userInfo.User_Id); if (authCount == 0) { await _userContext.User_Auth.AddAsync(new User_Auth() { Self_Id = userInfo.User_Id, Bind_Id = userInfo.User_Id, Role_Id = userInfo.Role_Id, Token = token }); await _userContext.SaveChangesAsync(); } } catch (Exception ex) { // 记录异常,避免后台线程未捕获异常引发崩溃 Console.WriteLine($"[UserAuth Insert Error]: {ex.Message}"); } }); return new UserInfoDto() { Enable = userInfo.Enable, PhoneNo = userInfo.PhoneNo, RoleName = userInfo.RoleName, Role_Id = userInfo.Role_Id, UserName = userInfo.UserName, UserTrueName = userInfo.UserName, User_Id = userInfo.User_Id, Token = token }; } private async Task GetWeChatSession(string code) { string url = $"https://api.weixin.qq.com/sns/jscode2session?appid={AppSettings.WeChat.Appid}&secret={AppSettings.WeChat.Secret}&js_code={code}&grant_type=authorization_code"; using (var client = new HttpClient()) { var response = await client.GetAsync(url); var content = await response.Content.ReadAsStringAsync(); return JsonSerializer.Deserialize(content); } } /// /// 刷新Token /// /// public async Task ReplaceToken(string requestToken) { string error = ""; UserInfoDto userInfo = new UserInfoDto(); try { var userModel = JwtHelper.SerializeJwt(requestToken); string token = JwtHelper.IssueJwt(new UserInfoDto() { User_Id = userModel.User_Id, UserName = userModel.UserName, Role_Id = userModel.Role_Id, PhoneNo = userModel.PhoneNo ?? "", SchoolCode = userModel.SchoolCode, UserTrueName = userModel.UserName, UserNo = userModel.UserNo }); userInfo.Token = token; userInfo.User_Id = userModel.User_Id; userInfo.UserName = userModel.UserName; userInfo.Role_Id = userModel.Role_Id; userInfo.RoleName = userModel.RoleName; userModel.UserTrueName = userModel.UserTrueName; userInfo.PhoneNo = userInfo.PhoneNo; userInfo.UserNo = userInfo.UserNo; var userAuthList = await _userContext.User_Auth.Where(x => x.Bind_Id == userModel.User_Id).ToListAsync(); userAuthList.ForEach(x => { x.Token = token; }); _userContext.UpdateRange(userAuthList); await _userContext.SaveChangesAsync(); } catch (Exception ex) { error = ex.Message + ex.StackTrace + ex.Source; throw new Exception("token替换出错了.."); } return userInfo; } /// /// 获取关联账号 /// /// public async Task> RelatedAccounts() { var roleId = UserLoginContext.Current.RoleId; var userId = UserLoginContext.Current.UserId; var res = await (from auth in _userContext.User_Auth join user in _userContext.Users on auth.Bind_Id equals user.User_Id where auth.Self_Id == userId select new RelatedAccountsDto { RoleId = user.Role_Id, UserId = user.User_Id, IsCurrentLogin = user.Role_Id == roleId, UserTrueName = user.UserTrueName ?? user.wx_NickName ?? "微信用户", HeadImageUrl = user.HeadImageUrl ?? "", Token = auth.Token }).ToListAsync(); return res; } /// /// 添加关联账号 /// /// /// public async Task AddRelatedAccounts(AddRelatedAccountsDto dto) { var userId = UserLoginContext.Current.UserId; var userAuth = await _userContext.User_Auth.CountAsync(x => x.Bind_Id == dto.UserId && x.Self_Id == userId && x.Bind_Id != x.Self_Id); if (userAuth == 0) { var myToken = await _userContext.User_Auth.Where(x => x.Self_Id == userId && x.Bind_Id == userId).Select(x => x.Token).FirstOrDefaultAsync(); var entitys = new List() { new User_Auth() { Self_Id = userId, Bind_Id = dto.UserId, Role_Id = dto.RoleId, Token = dto.Token }, new User_Auth() { Self_Id = dto.UserId, Bind_Id = userId, Role_Id = dto.RoleId, Token = myToken??"" } }; await _userContext.User_Auth.AddRangeAsync(entitys); await _userContext.SaveChangesAsync(); } } /// /// 获取个人信息 /// /// public async Task PersonalInfo() { var userId = UserLoginContext.Current.UserId; var res = await _userContext.Users.Where(x => x.User_Id == userId).Select(x => new PersonalInfoDto() { HeadImageUrl = x.HeadImageUrl, Gender = x.Gender, BirthDate = x.BirthDate, Height = x.Height, Weight = x.Weight, UserTrueName = x.UserTrueName }).FirstOrDefaultAsync(); return res; } /// /// 更新个人信息 /// /// /// public async Task UpdatePersonalInfo(PersonalInfoDto dto) { var userId = UserLoginContext.Current.UserId; var res = await _userContext.Users.Where(x => x.User_Id == userId).FirstAsync(); res.HeadImageUrl = dto.HeadImageUrl; res.Gender = dto.Gender; res.BirthDate = dto.BirthDate; res.Height = dto.Height; res.Weight = dto.Weight; res.UserTrueName = dto.UserTrueName; _userContext.Users.Update(res); await _userContext.SaveChangesAsync(); } /// /// 上传头像 /// /// /// public async Task UploadPhoto(IFormFile file) { var userName = UserLoginContext.Current.UserName; var url = await Task.Run(() => ALiYunOss.Upload(file, $"Upload/User/Photo/", $"{userName}—{DateTime.Now.ToUnixTimestampMilliseconds()}")); return url; } } }