using Furion.DatabaseAccessor; using Furion.DataEncryption; using Furion.DependencyInjection; using Furion.DynamicApiController; using Furion.FriendlyException; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Newtonsoft.Json; using Senparc.Weixin.WxOpen.Helpers; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Threading.Tasks; using Znyc.Dispatching.Application.Dto.Input; using Znyc.Dispatching.Core; using Znyc.Dispatching.Core.Entitys; using Znyc.Dispatching.Core.Extension; using Znyc.Dispatching.WeChat.Core.CommonService.TemplateMessage.WxOpen; namespace Znyc.Dispatching.Application { /// /// 用户服务 /// [ApiDescriptionSettings(Name = "user", Order = 10)] public class UserService : IUserService, IDynamicApiController, ITransient { private readonly ICacheService _cacheService; private readonly IRepository _companyRepository; private readonly IRepository _employeeRepository; private readonly IRepository _repository; private readonly SmsProviderOptions _smsProviderOptions; private readonly IUserManager _userManager; private readonly WeixinSettingOptions _weixinSettingOptions; private readonly IRepository _userRoleRepository; private readonly IWxUserRelationService _wxUserRelationService; private readonly IRoleMenuService _roleMenuService; private readonly ILogger _logger; private readonly IRepository _vehiclePersonRepository; private readonly IRepository _projectPersonRepository; public UserService( IUserManager userManager, ICacheService cacheService, IRepository companyRepository, IRepository repository, IRepository employeeRepository, IRepository userRoleRepository, IOptions smsProviderOptions, IWxUserRelationService wxUserRelationService, IRoleMenuService roleMenuService, IOptions weixinSettingOptions, ILogger logger, IRepository vehiclePersonRepository, IRepository projectPersonRepository) { _repository = repository; _userManager = userManager; _cacheService = cacheService; _companyRepository = companyRepository; _employeeRepository = employeeRepository; _smsProviderOptions = smsProviderOptions.Value; _weixinSettingOptions = weixinSettingOptions.Value; _userRoleRepository = userRoleRepository; _wxUserRelationService = wxUserRelationService; _roleMenuService = roleMenuService; _logger = logger; _vehiclePersonRepository = vehiclePersonRepository; _projectPersonRepository = projectPersonRepository; } /// /// 个人资料 /// /// [HttpGet] [Route("api/v1/user")] public async Task GetUserAsync() { var userOutput = await _cacheService.GetUserAsync(_userManager.UserId); if (userOutput.IsNull()) { var user = await _repository.Where(x => x.Id == _userManager.UserId).Select(x => new { x.Id, x.UserName, x.Phone, x.AvatarUrl }).FirstOrDefaultAsync(); var employeeList = await _employeeRepository.Where(x => x.UserId == user.Id && x.Status == (int)CommonStatusEnum.ENABLE).ToListAsync(); var cIds = employeeList.Select(x => x.CompanyId).ToArray(); //有管理员优先登陆管理员 if (employeeList.Any(x => x.RoleId == (int)RoleStatusEnum.Administrator)) { cIds = employeeList.Where(x => x.RoleId == (long)RoleStatusEnum.Administrator).Select(x => x.CompanyId).ToArray(); } var company = await _companyRepository.Where(x => cIds.Contains(x.Id) && x.Status == (int)CommonStatusEnum.ENABLE).Select(x => new { x.Id, x.CompanyName }).FirstOrDefaultAsync(); var employee = employeeList.Where(x => x.CompanyId == company.Id).Select(x => new { x.RoleId, x.RoleName, x.CompanyId, x.UserId, x.EmployeeName, x.IsDefault }).FirstOrDefault(); userOutput = new UserOutput { Id = user.Id, AvatarUrl = user.AvatarUrl, UserName = employee.EmployeeName, RoleId = employee.RoleId, RoleName = employee.RoleName, CompanyId = employee.CompanyId, CompanyName = company.CompanyName, Phone = user.Phone }; await _cacheService.SetUserAsync(userOutput); } return userOutput; } /// /// 邀请用户注册并登陆 /// /// /// [HttpPost] [AllowAnonymous] [UnitOfWork] [Route("api/v1/user/register")] public async Task RegisterUserAsync(UserAddInput input) { var jsCode2JsonResult = await SnsApi.JsCode2JsonAsync(_weixinSettingOptions.WxOpenAppId, _weixinSettingOptions.WxOpenAppSecret, input.DecryptPhoneAddInput.JsCode); if (jsCode2JsonResult.IsNull()) { throw Oops.Bah("jsCode2JsonResult为空"); } var company = await _companyRepository.FindOrDefaultAsync(input.CompanyId); if (company.IsNull()) throw Oops.Bah("公司不存在"); if (company.Status == (int)CommonStatusEnum.REVIEW) { throw Oops.Bah("您注册公司正在审核中,请稍等").StatusCode(4012); } if (company.Status == (int)CommonStatusEnum.DISABLE) { throw Oops.Bah("公司已被停用,请联系管理员"); } var user = await _repository.FirstOrDefaultAsync(x => x.OpenId == jsCode2JsonResult.openid); var employee = new Employee(); if (user.IsNull()) { //解密电话 string phone = " "; if (input.DecryptPhoneAddInput.EncryptedData.IsNotNull() && input.DecryptPhoneAddInput.Iv.IsNotNull()) { try { var rijndael = new RijndaelManaged { BlockSize = 128, Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7 }; var encryptedData = Convert.FromBase64String(input.DecryptPhoneAddInput.EncryptedData); var key = Convert.FromBase64String(jsCode2JsonResult.session_key);//第一步获取到的session_key var iv = Convert.FromBase64String(input.DecryptPhoneAddInput.Iv); var decryptor = rijndael.CreateDecryptor(key, iv); using (var msDecrypt = new MemoryStream(encryptedData)) { using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) { using (var srDecrypt = new StreamReader(csDecrypt)) { var plaintext = srDecrypt.ReadToEnd(); var json = Newtonsoft.Json.JsonConvert.DeserializeObject(plaintext); var phoneNumber = json.phoneNumber; var purePhoneNumber = json.purePhoneNumber; //至此,成功获取到手机号 phone = Convert.ToString(purePhoneNumber); } } } } catch (Exception ex) { Console.WriteLine($"RegisterUserAsync:{ex.StackTrace}"); _logger.LogError(ex.StackTrace); } } //用户 var userEntity = await _repository.InsertNowAsync(new User { OpenId = jsCode2JsonResult.openid, UserName = input.UserName, AvatarUrl = input.AvatarUrl, Phone = phone, Status = CommonStatusEnum.ENABLE }); var isDefault = input.RoleId == (int)RoleStatusEnum.Outside ? false : true; //员工 var employeeEntity = await _employeeRepository.InsertNowAsync(new Employee { UserId = userEntity.Entity.Id, AvatarUrl = input.AvatarUrl, EmployeeName = input.UserName, EmployeePhone = phone, CompanyId = input.CompanyId, RoleId = input.RoleId, RoleName = typeof(RoleStatusEnum).GetDescription(input.RoleId.ObjToInt()), IsDefault = isDefault, Status = (int)CommonStatusEnum.ENABLE }); //用户角色 //await _userRoleRepository.InsertNowAsync(new UserRole //{ // UserId = userEntity.Entity.Id, // RoleId = input.RoleId //}); //清除员工列表Cache await _cacheService.RemoveEmployeeListAsync(input.CompanyId); //用户中间表 await _wxUserRelationService.AddOrUpdateAsync(userEntity.Entity.Id, jsCode2JsonResult.openid, jsCode2JsonResult.unionid); user = userEntity.Entity; employee = employeeEntity.Entity; } else { employee = await _employeeRepository.Where(x => x.UserId == user.Id && x.Status == (int)CommonStatusEnum.ENABLE && x.CompanyId == input.CompanyId).FirstOrDefaultAsync(); if (employee.IsNull()) { var employeenew = new Employee { UserId = user.Id, AvatarUrl = input.AvatarUrl, EmployeeName = input.UserName, EmployeePhone = user.Phone, CompanyId = input.CompanyId, RoleId = input.RoleId, RoleName = typeof(RoleStatusEnum).GetDescription((int)input.RoleId), IsDefault = true, Status = (int)CommonStatusEnum.ENABLE }; Console.WriteLine($"{JsonConvert.SerializeObject(employeenew)}"); var isDefault = input.RoleId == (int)RoleStatusEnum.Outside ? false : true; //员工 var employeeEntity = await _employeeRepository.InsertNowAsync(new Employee { UserId = user.Id, AvatarUrl = input.AvatarUrl, EmployeeName = input.UserName, EmployeePhone = user.Phone, CompanyId = input.CompanyId, RoleId = input.RoleId, RoleName = typeof(RoleStatusEnum).GetDescription(input.RoleId.ObjToInt()), IsDefault = isDefault, Status = (int)CommonStatusEnum.ENABLE }); employee = employeeEntity.Entity; company = new Company() { Id = input.CompanyId }; } } // 生成 token string accessToken = JWTEncryption.Encrypt(new Dictionary { {ClaimConst.CLAINM_USERID, user.Id}, {ClaimConst.CLAINM_COMPANYID, company.Id}, {ClaimConst.CLAINM_ROLEID, employee.RoleId}, {ClaimConst.CLAINM_USERNAME, user.UserName}, {ClaimConst.CLAINM_SUPERADMIN,new long[] { (long)RoleStatusEnum.Administrator, (long)RoleStatusEnum.Scheduling,(long)RoleStatusEnum.CarCaptain }.Contains(employee.RoleId) } }); //RedisToken await _cacheService.SetTokenAsync(user.Id, accessToken); await _cacheService.RemoveEmployeeListAsync(input.CompanyId); LoginOutput loginOutput = new LoginOutput() { Token = accessToken, Menus = await _roleMenuService.GetRoleMenuListByIdAsync(employee.RoleId) }; switch (employee.RoleId) { case (long)RoleStatusEnum.Administrator: case (long)RoleStatusEnum.Scheduling: case (long)RoleStatusEnum.CarCaptain: case (long)RoleStatusEnum.Salesman: case (long)RoleStatusEnum.Financial: case (long)RoleStatusEnum.WareHouse: case (long)RoleStatusEnum.PartTimeSalesman: loginOutput.Url = CommonConst.DEFAULT_SUPERADMIN_INDEX; break; case (long)RoleStatusEnum.CrewMembers: case (long)RoleStatusEnum.ProjectPerson: loginOutput.Url = CommonConst.DEFAULT_DRIVER_INDEX; break; case (long)RoleStatusEnum.Outside: loginOutput.Url = CommonConst.DEFAULT_OUTSIDE_INDEX; break; default: loginOutput.Url = CommonConst.DEFAULT_DRIVER_INDEX; break; } return loginOutput; } /// /// 修改用户信息 /// /// /// [HttpPut] [Route("api/v1/user")] public async Task UpdateAsync(UserUpdateInput input) { var user = await _repository.FirstOrDefaultAsync(x => x.Id == input.Id); if (user.IsNull()) { throw Oops.Oh("用户不存在"); } var repeatPhone = await _repository.DetachedEntities.FirstOrDefaultAsync(x => x.Id != input.Id && x.Phone == input.Phone); if (repeatPhone.IsNotNull()) { throw Oops.Bah("电话已存在"); } user.Phone = input.Phone; user.UserName = input.UserName; user.AvatarUrl = CommonConst.Prefix_AvataUrl + input.AvatarUrl[(input.AvatarUrl.LastIndexOf("/") + 1)..]; await _repository.UpdateNowAsync(user); //更新当前用户下所有角色姓名 var employees =await _employeeRepository.Where(x => x.UserId == user.Id).ToListAsync(); foreach (var employee in employees) { if (employee.IsNotNull()) { employee.EmployeePhone = input.Phone; employee.EmployeeName = input.UserName; employee.AvatarUrl = CommonConst.Prefix_AvataUrl + input.AvatarUrl[(input.AvatarUrl.LastIndexOf("/") + 1)..]; await _employeeRepository.UpdateNowAsync(employee); await _cacheService.RemoveEmployeeAsync(employee.Id); await _cacheService.RemoveEmployeeListAsync(employee.CompanyId); } } await _cacheService.RemoveUserAsync(user.Id); //同步车组人员表 var vehiclePersons = await _vehiclePersonRepository.Where(x => x.IsDeleted == false && x.UserId == input.Id).ToListAsync(); foreach (var item in vehiclePersons) { item.UserName = input.UserName; item.UserPhone = input.Phone; await _vehiclePersonRepository.UpdateNowAsync(item); //删除车组人员Cache await _cacheService.RemoveVehiclePersonAsync(item.VehicleId); } //同步工程联系人表 var projectPersons = await _projectPersonRepository.Where(x => x.IsDeleted == false && x.ProjectPersonId == input.Id).ToListAsync(); foreach (var item in projectPersons) { item.ProjectPersonName = input.UserName; item.ProjectPersonPhone = input.Phone; await _projectPersonRepository.UpdateNowAsync(item); //清除工程信息Cache await _cacheService.RemoveProjectAsync(item.ProjectId); //清除工程列表信息Cache await _cacheService.RemoveProjectListAsync(_userManager.CompanyId); } } /// /// 更新用户信息 /// /// /// /// [HttpPut] [AllowAnonymous] public async Task UpdateAsync(string openId, string account) { //var user = await _repository.FirstOrDefaultAsync(x => x.Account == account); //if (user.IsNotNull()) //{ // user.OpenId = openId; // await _repository.UpdateNowAsync(user); //} } /// /// 解密电话号码 /// /// /// [HttpPost] [AllowAnonymous] [Route("api/v1/decryptphone")] public async Task DecryptPhoneNumber([FromBody] DecryptPhoneAddInput decryptPhone) { var jsCode2JsonResult = await SnsApi.JsCode2JsonAsync(_weixinSettingOptions.WxOpenAppId, _weixinSettingOptions.WxOpenAppSecret, decryptPhone.JsCode); if (jsCode2JsonResult.IsNull()) { throw Oops.Oh("jsCode2JsonResult为空!"); } string phone = ""; if (decryptPhone.EncryptedData.IsNotNull() && decryptPhone.Iv.IsNotNull()) { var phoneNumber = EncryptHelper.DecryptPhoneNumberBySessionKey(jsCode2JsonResult.session_key, decryptPhone.EncryptedData, decryptPhone.Iv); if (phoneNumber.IsNull()) { phone = phoneNumber.purePhoneNumber; } } return phone; } } }