using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Volo.Abp.Application.Services; using Volo.Abp.EventBus.Local; using Volo.Abp.Users; using Yi.Framework.Bbs.Domain.Shared.Etos; using Yi.Framework.DigitalCollectibles.Application.Contracts.Dtos.Account; using Yi.Framework.DigitalCollectibles.Domain.Shared.Consts; using Yi.Framework.DigitalCollectibles.Domain.Shared.Enums; using Yi.Framework.DigitalCollectibles.Domain.Shared.Etos; using Yi.Framework.Rbac.Application.Contracts.Dtos.Account; using Yi.Framework.Rbac.Application.Contracts.IServices; using Yi.Framework.Rbac.Domain.Shared.Enums; using Yi.Framework.WeChat.MiniProgram; using Yi.Framework.WeChat.MiniProgram.HttpModels; namespace Yi.Framework.DigitalCollectibles.Application.Services.Account; /// /// 微信小程序账户应用服务 /// public class WeChatMiniProgramAccountService : ApplicationService { private readonly IWeChatMiniProgramManager _weChatMiniProgramManager; private readonly IAuthService _authService; private readonly IAccountService _accountService; private readonly ILocalEventBus _localEventBus; public WeChatMiniProgramAccountService(IWeChatMiniProgramManager weChatMiniProgramManager, IAuthService authService, IAccountService accountService, ILocalEventBus localEventBus) { _weChatMiniProgramManager = weChatMiniProgramManager; _authService = authService; _accountService = accountService; _localEventBus = localEventBus; } /// /// 使用小程序jsCode登录意社区账号 /// /// [HttpPost("wechat/mini-program/account/login")] public async Task PostLoginAsync(LoginInput intput) { var output = new LoginOutput(); //根据code去获取wxid //判断wxid中是否有对应的userid关系 //果然有,直接根据userid返回该用户token //如果没有,返回结果即可 var openId = (await _weChatMiniProgramManager.Code2SessionAsync(new Code2SessionInput(intput.JsCode))) .openid; var authInfo = await _authService.TryGetByOpenIdAsync(openId, AuthTypeConst.WeChatMiniProgram); if (authInfo is null) { throw new UserFriendlyException("该小程序没有绑定任何账号", "2000", "Auth未找到对应关系"); } //根据用户id获取到用户信息 var result = await _accountService.PostLoginAsync(authInfo.UserId); output.Token = result.Token; return output; } /// /// 将小程序第三方授权绑定给意社区账号 /// /// /// [HttpPost("wechat/mini-program/account/bind")] // [Authorize] public async Task PostBindAsync(BindInput input) { //验证手机号 await _accountService.ValidationPhoneCaptchaAsync(ValidationPhoneTypeEnum.Bind, input.Phone, input.Code); //校验手机号与验证码 //根据手机号查询用户信息 //根据code去获取wxid //将wxid和用户user绑定 var userInfo = await _accountService.GetAsync(null, input.Phone); if (userInfo is null) { throw new UserFriendlyException("该手机号未被注册,无法绑定微信小程序"); } //验证手机号的验证码 var openId = (await _weChatMiniProgramManager.Code2SessionAsync(new Code2SessionInput(input.JsCode))).openid; //是否已经授权过绑定过auth bool isAuthed =true; //如果openId没有绑定过,代表第一次进入,否则就是临时账号进行绑定 var authInfo= await _authService.TryGetByOpenIdAsync(openId,AuthTypeConst.WeChatMiniProgram); //从来没绑定过 if (authInfo is null) { isAuthed = false; } //账号绑定,不管什么情况,都将jscode与phone用户建立关系即可 await PostBindToAuthAsync(userInfo.User.Id, openId, userInfo.User.UserName); //发送账号绑定的事件,不同领域对账号数据进行迁移 //bbs:钱钱 (累加),禁用临时账号(修改) //dc: 价值、积分 (累加) //只有之前授权绑定过,才需要将临时账号进行账号数据转移, if (isAuthed) { await _localEventBus.PublishAsync(new BindAccountEto { NewUserId = userInfo.User.Id, OldUserId =authInfo.UserId },false); } } private async Task PostBindToAuthAsync(Guid userId, string openId, string? name = null) { await _authService.CreateAsync(new AuthCreateOrUpdateInputDto { UserId = userId, OpenId = openId, Name = name ?? "未知", AuthType = AuthTypeConst.WeChatMiniProgram }); } /// /// 使用小程序去注册意社区账号 /// /// [HttpPost("wechat/mini-program/account/register")] public async Task PostRegisterAsync(RegisterInput input) { //先校验code,openId var openId = (await _weChatMiniProgramManager.Code2SessionAsync(new Code2SessionInput(input.JsCode))).openid; //走普通注册流程 //同时再加一个小程序绑定即可 var userName = GenerateRandomString(6); await _accountService.PostTempRegisterAsync(new RegisterDto { UserName =$"ls_{userName}", Password = GenerateRandomString(20), Nick = $"临时账号-{userName}" }); var userInfo = await _accountService.GetAsync($"ls_{userName}", null); await PostBindToAuthAsync(userInfo.User.Id, openId, userInfo.User.UserName); } private string GenerateRandomString(int length) { const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; Random random = new Random(); char[] stringChars = new char[length]; for (int i = 0; i < length; i++) { stringChars[i] = chars[random.Next(chars.Length)]; } return new string(stringChars); } }