From fb4d1cc9d21a2b46846522d3c41936cd4e308ce8 Mon Sep 17 00:00:00 2001 From: zpc Date: Tue, 3 Sep 2024 16:41:35 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AppExtend/AppConfigurationExtend.cs | 59 ++++++ .../HuanMeng.MiaoYu.Code/Base/MiaoYuBase.cs | 24 ++- .../Character/CharacterBLL.cs | 3 +- .../HuanMeng.MiaoYu.Code/Chat/ChatBLL.cs | 47 ++--- .../MiaoYuMultiTenantExtension.cs | 3 +- .../HuanMeng.MiaoYu.Code/Order/OrderBLL.cs | 21 ++- .../Users/CurrencyTransactionParams.cs | 69 +++++++ .../PhoneAccount/PhoneAccountLogin.cs | 7 +- .../HuanMeng.MiaoYu.Code/Users/UserBLL.cs | 5 +- .../Users/UserCurrencyBLL.cs | 176 ++++++++++++------ .../HuanMeng.MiaoYu.Code/Users/UserInfoBLL.cs | 13 +- .../Dto/Chat/CharacterInfoDto.cs | 7 +- .../Dto/Chat/ChatHistoryInfo.cs | 5 + .../Dto/RequestUserInfo.cs | 1 + .../Controllers/PaymentController.cs | 3 +- .../Controllers/PayController.cs | 2 +- 16 files changed, 326 insertions(+), 119 deletions(-) create mode 100644 src/0-core/HuanMeng.MiaoYu.Code/Users/CurrencyTransactionParams.cs diff --git a/src/0-core/HuanMeng.MiaoYu.Code/AppExtend/AppConfigurationExtend.cs b/src/0-core/HuanMeng.MiaoYu.Code/AppExtend/AppConfigurationExtend.cs index ed27bfa..03f054e 100644 --- a/src/0-core/HuanMeng.MiaoYu.Code/AppExtend/AppConfigurationExtend.cs +++ b/src/0-core/HuanMeng.MiaoYu.Code/AppExtend/AppConfigurationExtend.cs @@ -17,6 +17,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.IdentityModel.Protocols; using SKIT.FlurlHttpClient.Wechat.TenpayV3.Models; using HuanMeng.MiaoYu.Code.Payment; +using System.Collections.Frozen; namespace HuanMeng.MiaoYu.Code.AppExtend { @@ -240,6 +241,64 @@ namespace HuanMeng.MiaoYu.Code.AppExtend } #endregion + + #region 测试用户 + /// + /// 测试账号数据 + /// + public static ConcurrentDictionary>? TestAccountList { get; set; } + /// + /// 获取测试账号 + /// + /// + /// + public static FrozenDictionary GetTestAccount(DAO dao) + { + if (TestAccountList == null) + { + TestAccountList = new ConcurrentDictionary>(); + } + var t = dao.daoDbMiaoYu.context.TenantInfo.TenantId; + if (TestAccountList.ContainsKey(t)) + { + return TestAccountList[t]; + } + + var dir = dao.daoDbMiaoYu.context.T_User.Where(it => it.IsTest == true && it.State == 0).Select(it => + new + { + PhoneNumAccount = dao.daoDbMiaoYu.context.T_User_Phone_Account.FirstOrDefault(item => item.UserId == it.Id).PhoneNum, + userid = it.Id + }).Where(it => !string.IsNullOrEmpty(it.PhoneNumAccount)).ToDictionary(it => it.PhoneNumAccount, kvp => kvp.userid); + var f = dir.ToFrozenDictionary(); + TestAccountList.TryAdd(t, f); + return f; + } + + /// + /// 是否是测试账号 + /// + /// + /// + /// + public static bool IsTestAccount(string phoneNum, DAO dao) + { + var t = GetTestAccount(dao); + return t.ContainsKey(phoneNum); + } + + /// + /// 是否是测试账号 + /// + /// + /// + /// + public static bool IsTestAccount(int userId, DAO dao) + { + var t = GetTestAccount(dao); + return t.Where(it => it.Value == userId).Any(); + } + #endregion } } diff --git a/src/0-core/HuanMeng.MiaoYu.Code/Base/MiaoYuBase.cs b/src/0-core/HuanMeng.MiaoYu.Code/Base/MiaoYuBase.cs index 76b65a3..8fbfd96 100644 --- a/src/0-core/HuanMeng.MiaoYu.Code/Base/MiaoYuBase.cs +++ b/src/0-core/HuanMeng.MiaoYu.Code/Base/MiaoYuBase.cs @@ -216,7 +216,7 @@ namespace HuanMeng.MiaoYu.Code.Base #endregion #region 用户信息 - private RequestUserInfo _userInfo; + private RequestUserInfo? _userInfo; /// /// 用户信息 /// @@ -227,17 +227,19 @@ namespace HuanMeng.MiaoYu.Code.Base if (_userInfo == null) { var accessToken = HttpContextAccessor.HttpContext.GetTokenAsync("Bearer", "access_token").Result; + if (string.IsNullOrEmpty(accessToken)) { - _userInfo = new RequestUserInfo() + var authorizationHeader = HttpContextAccessor.HttpContext.Request.Headers["Authorization"].ToString(); + if (!string.IsNullOrEmpty(authorizationHeader)) { - UserId = 0 - }; + accessToken = authorizationHeader.Replace("Bearer ", "").Trim(); + } } - else + if (!string.IsNullOrEmpty(accessToken)) { var (principal, jwtToken) = JwtAuthManager.DecodeJwtToken(accessToken); - if (jwtToken == null || !jwtToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256Signature)) + if (jwtToken == null)//|| !jwtToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256Signature) { throw new SecurityTokenException("无效的token"); } @@ -248,13 +250,21 @@ namespace HuanMeng.MiaoYu.Code.Base } var nickName = principal.FindFirst("NickName")?.Value; var userId = int.Parse(userIdStr); - _userInfo = new RequestUserInfo() + this._userInfo = new RequestUserInfo() { UserId = userId, NickName = nickName }; } + else + { + _userInfo = new RequestUserInfo() + { + UserId = 0 + }; + } } + return _userInfo; } } diff --git a/src/0-core/HuanMeng.MiaoYu.Code/Character/CharacterBLL.cs b/src/0-core/HuanMeng.MiaoYu.Code/Character/CharacterBLL.cs index d9bcf4c..f4e7eea 100644 --- a/src/0-core/HuanMeng.MiaoYu.Code/Character/CharacterBLL.cs +++ b/src/0-core/HuanMeng.MiaoYu.Code/Character/CharacterBLL.cs @@ -83,8 +83,9 @@ namespace HuanMeng.MiaoYu.Code.Character && it.CharacterId == info.CharacterId).FirstOrDefaultAsync(); info.Intimacy = intimacys?.IntimacyValue ?? 0; UserInfoBLL userInfoBLL = new UserInfoBLL(Dao, _UserId); - (var maxtoken, var memoryCardState) = userInfoBLL.GetMemoryCardMaxToken(requestCharacterInfo.CharacterId); + (var maxtoken, var memoryCardState, var card) = userInfoBLL.GetMemoryCardMaxToken(requestCharacterInfo.CharacterId); info.MemoryCardState = memoryCardState; + info.MemoryCardCount = card?.RemainingCount ?? 0; } return new BaseResponse(ResonseCode.Success, "", info); } diff --git a/src/0-core/HuanMeng.MiaoYu.Code/Chat/ChatBLL.cs b/src/0-core/HuanMeng.MiaoYu.Code/Chat/ChatBLL.cs index a3142ef..d38a640 100644 --- a/src/0-core/HuanMeng.MiaoYu.Code/Chat/ChatBLL.cs +++ b/src/0-core/HuanMeng.MiaoYu.Code/Chat/ChatBLL.cs @@ -1,3 +1,6 @@ +using HuanMeng.MiaoYu.Code.DataAccess; +using HuanMeng.MiaoYu.Model.Dto.Character; + namespace HuanMeng.MiaoYu.Code.Chat; /// @@ -231,7 +234,7 @@ public class ChatBLL : MiaoYuBase List mess = new List(); int maxToken = 7000; // var _memoryCardType = userInfoBLL[Model.EnumModel.UserMemoryCardType.记忆卡, charact.Id]; - (maxToken, var isMemoryCard) = userInfoBLL.GetMemoryCardMaxToken(charact.Id); + (maxToken, var isMemoryCard, var card) = userInfoBLL.GetMemoryCardMaxToken(charact.Id); //await AddMessage(userChatSession, mess); //递归获取聊天记录 var _token = await AddMessage(userChatSession.SessionId, _UserId, 1, 0, maxToken, mess); @@ -269,7 +272,7 @@ public class ChatBLL : MiaoYuBase #endregion var claudeChatResponse = await Chat(charact, mess); - if (claudeChatResponse.Message.Contains("香港") || claudeChatResponse.Message.Contains("台湾")|| claudeChatResponse.Message.Contains("摇头丸")) + if (claudeChatResponse.Message.Contains("香港") || claudeChatResponse.Message.Contains("台湾") || claudeChatResponse.Message.Contains("摇头丸")) { var chatMessage = new ChatMessageDto() { @@ -307,7 +310,7 @@ public class ChatBLL : MiaoYuBase Tokens = claudeChatResponse.OutputTokens }; #region 开启事务 - using (IDbContextTransaction transaction = Dao.daoDbMiaoYu.context.Database.BeginTransaction()) + using (IDbContextTransaction transaction = Dao.daoDbMiaoYu.context.Database.BeginTransaction(System.Data.IsolationLevel.ReadUncommitted)) { try { @@ -357,7 +360,7 @@ public class ChatBLL : MiaoYuBase } } #endregion - + //claudeChatResponse. ChatMessageDto chatMessageDto = new ChatMessageDto() { @@ -529,29 +532,6 @@ public class ChatBLL : MiaoYuBase return true; } - /// - /// 获取消息聊天记录列表 - /// - /// - //public async Task>> GetChatHistoryList() - //{ - // var userChatSessions = await Dao.daoDbMiaoYu.context.T_User_Chat.Where(it => it.UserId == _UserId && !it.IsDelete).ToListAsync(); - // List chatHistoryInfos = new List(); - // var charactersIds = MiaoYuCache.CharacterList.ToList(); - // userChatSessions.ForEach(it => - // { - // var model = charactersIds.FirstOrDefault(item => item.Id == it.CharacterId); - // if (model != null) - // { - // var info = Mapper.Map(model); - // info.LastContactTime = it.UpdateAt; - // chatHistoryInfos.Add(info); - // } - - // }); - // chatHistoryInfos = chatHistoryInfos.OrderByDescending(it => it.LastContactTime).ToList(); - // return new BaseResponse>(ResonseCode.Success, "", chatHistoryInfos) { }; - //} /// /// 获取消息聊天记录列表 @@ -560,10 +540,9 @@ public class ChatBLL : MiaoYuBase public async Task>> GetChatHistoryList() { var userChatSessions = await Dao.daoDbMiaoYu.context.T_User_Chat.Where(it => it.UserId == _UserId && !it.IsDelete).ToListAsync(); - - List chatHistoryInfos = new List(); var charactersIds = MiaoYuCache.CharacterList.ToList(); + var memoryCard = Dao.daoDbMiaoYu.context.T_User_MemoryCard.AsNoTracking().Where(it => it.UserId == _UserId && it.RemainingCount > 0 && it.CharacterId > 0).Select(it => it.CharacterId).ToList(); userChatSessions.ForEach(it => { var model = charactersIds.FirstOrDefault(item => item.Id == it.CharacterId); @@ -571,8 +550,6 @@ public class ChatBLL : MiaoYuBase { var info = Mapper.Map(model); - //获取最新的聊天记录 - //var c = Dao.daoDbMiaoYu.context.T_Chat.Where(it => it.SessionId == it.SessionId).OrderByDescending(it => it.SendMessageDay).FirstOrDefault(); info.LastContactTime = it.UpdateAt; info.LastMessage = it.LastMessage; if (string.IsNullOrEmpty(info.LastMessage)) @@ -587,11 +564,11 @@ public class ChatBLL : MiaoYuBase info.LastMessage = Regex.Replace(info.LastMessage, pattern, ""); } } + if (memoryCard.Contains(it.CharacterId)) + { + info.IsMemoryCard = true; + } - //if (c != null) - //{ - // info.LastMessage = c.Content; - //} chatHistoryInfos.Add(info); } }); diff --git a/src/0-core/HuanMeng.MiaoYu.Code/MultiTenantUtil/MiaoYuMultiTenantExtension.cs b/src/0-core/HuanMeng.MiaoYu.Code/MultiTenantUtil/MiaoYuMultiTenantExtension.cs index 15cb957..7e738a4 100644 --- a/src/0-core/HuanMeng.MiaoYu.Code/MultiTenantUtil/MiaoYuMultiTenantExtension.cs +++ b/src/0-core/HuanMeng.MiaoYu.Code/MultiTenantUtil/MiaoYuMultiTenantExtension.cs @@ -36,7 +36,7 @@ namespace HuanMeng.MiaoYu.Code.MultiTenantUtil MiaoYuMultiTenantConfig miaoYuMultiTenantConfig = new MiaoYuMultiTenantConfig(MiaoYu_SqlServer_Db); builder.Services.AddSingleton(miaoYuMultiTenantConfig); //添加单个租户的配置项 - builder.Services.AddScoped(); + builder.Services.AddScoped(); //添加系统数据库 builder.Services.AddDbContext((serviceProvider, options) => @@ -53,6 +53,7 @@ namespace HuanMeng.MiaoYu.Code.MultiTenantUtil } options .UseSqlServer(sunnySportConnectionString); + // //options.UseSqlServer }, ServiceLifetime.Scoped); diff --git a/src/0-core/HuanMeng.MiaoYu.Code/Order/OrderBLL.cs b/src/0-core/HuanMeng.MiaoYu.Code/Order/OrderBLL.cs index b1e9b94..1bb37b1 100644 --- a/src/0-core/HuanMeng.MiaoYu.Code/Order/OrderBLL.cs +++ b/src/0-core/HuanMeng.MiaoYu.Code/Order/OrderBLL.cs @@ -142,7 +142,7 @@ namespace HuanMeng.MiaoYu.Code.Order { throw new Exception("正在购买中"); } - using (IDbContextTransaction transaction = Dao.daoDbMiaoYu.context.Database.BeginTransaction()) + using (IDbContextTransaction transaction = Dao.daoDbMiaoYu.context.Database.BeginTransaction(System.Data.IsolationLevel.ReadUncommitted)) { try { @@ -161,10 +161,23 @@ namespace HuanMeng.MiaoYu.Code.Order var money = reward.Money; var currency = (UserCurrencyType)reward.CurrencyType; var userCurrency = new T_User_Currency(); - var _log = new T_User_Currency_Log(); - user.ConsumeMoneyNoWork(currency, money, Dao, userCurrency, productId: productId, imageUrl: image, log: _log); - _log.IsHide = true; + CurrencyTransactionParams currencyTransactionParams = new CurrencyTransactionParams() + { + UserCurrencyType = currency, + Money = money, + ImageUrl = image, + Currency = userCurrency, + Products = product + + }; + user.ConsumeMoneyNoWork(currencyTransactionParams, Dao); + if (currencyTransactionParams.Log != null) + { + currencyTransactionParams.Log.IsHide = true; + + } } + Dao.daoDbMiaoYu.context.SaveChanges(); } } diff --git a/src/0-core/HuanMeng.MiaoYu.Code/Users/CurrencyTransactionParams.cs b/src/0-core/HuanMeng.MiaoYu.Code/Users/CurrencyTransactionParams.cs new file mode 100644 index 0000000..a39657d --- /dev/null +++ b/src/0-core/HuanMeng.MiaoYu.Code/Users/CurrencyTransactionParams.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HuanMeng.MiaoYu.Code.Users +{ + /// + /// 货币交易的参数。 + /// + public class CurrencyTransactionParams + { + /// + /// 用户Id + /// + public int UserId { get; set; } + + /// + /// 货币类型 + /// + public UserCurrencyType UserCurrencyType { get; set; } + + /// + /// 扣除或添加的金额(负数为扣除,正数为充值) + /// + public decimal Money { get; set; } + /// + /// 交易备注 + /// + public string Remarks { get; set; } = string.Empty; + + /// + /// 交易标题 + /// + public string Title { get; set; } = string.Empty; + + /// + /// 关联的订单Id + /// + public string OrderId { get; set; } = string.Empty; + + /// + /// 关联的产品Id + /// + public string? ProductId { get; set; } = string.Empty; + + /// + /// 交易相关的图片URL + /// + public string? ImageUrl { get; set; } = string.Empty; + + /// + /// 可选参数:现有的用户货币数据 + /// + public T_User_Currency? Currency { get; set; } + + /// + /// 可选参数:现有的货币日志 + /// + public T_User_Currency_Log? Log { get; set; } + + /// + /// 购买的产品 + /// + public T_Products? Products { get; set; } + } + +} diff --git a/src/0-core/HuanMeng.MiaoYu.Code/Users/UserAccount/PhoneAccount/PhoneAccountLogin.cs b/src/0-core/HuanMeng.MiaoYu.Code/Users/UserAccount/PhoneAccount/PhoneAccountLogin.cs index f21d5b7..f20e8e2 100644 --- a/src/0-core/HuanMeng.MiaoYu.Code/Users/UserAccount/PhoneAccount/PhoneAccountLogin.cs +++ b/src/0-core/HuanMeng.MiaoYu.Code/Users/UserAccount/PhoneAccount/PhoneAccountLogin.cs @@ -1,4 +1,5 @@ using HuanMeng.DotNetCore.Base; +using HuanMeng.MiaoYu.Code.AppExtend; using HuanMeng.MiaoYu.Code.DataAccess; using HuanMeng.MiaoYu.Code.TencentUtile; using HuanMeng.MiaoYu.Code.Users.UserAccount.Contract; @@ -103,7 +104,9 @@ namespace HuanMeng.MiaoYu.Code.Users.UserAccount.PhoneAccount { throw new ArgumentNullException("请输入验证码"); } - if (phoneLoginParams.PhoneNumber == "999999999" && phoneLoginParams.VerificationCode == "123456") + + if (phoneLoginParams.PhoneNumber == "999999999" && phoneLoginParams.VerificationCode == "123456" || + AppConfigurationExtend.IsTestAccount(phoneLoginParams.PhoneNumber, dao)) { //测试账号 } @@ -132,7 +135,7 @@ namespace HuanMeng.MiaoYu.Code.Users.UserAccount.PhoneAccount LastLoginAt = DateTime.Now, LastLoginTypeAt = 1, Email = "", - NickName = "新用户", + NickName = "新用户" + new Random().Next(111, 999), PhoneNum = phoneLoginParams.PhoneNumber, RegisterType = 1, TenantId = dao.daoDbMiaoYu.context.TenantInfo.TenantId, diff --git a/src/0-core/HuanMeng.MiaoYu.Code/Users/UserBLL.cs b/src/0-core/HuanMeng.MiaoYu.Code/Users/UserBLL.cs index 7a68d31..c39d204 100644 --- a/src/0-core/HuanMeng.MiaoYu.Code/Users/UserBLL.cs +++ b/src/0-core/HuanMeng.MiaoYu.Code/Users/UserBLL.cs @@ -173,7 +173,7 @@ namespace HuanMeng.MiaoYu.Code.Users { return new BaseResponse>(ResonseCode.Success, "", new List()); } - var logs = await Dao.daoDbMiaoYu.context.T_User_Currency_Log.Where(it => it.UserId == _UserId && !(it.CurrencyType == (int)UserCurrencyType.聊天次数 && it.ConsumeType == 0) && !it.IsHide).OrderByDescending(it => it.Id).Take(50).ToListAsync(); + var logs = await Dao.daoDbMiaoYu.context.T_User_Currency_Log.Where(it => it.UserId == _UserId && (it.CurrencyType == (int)UserCurrencyType.聊天次数 && it.ConsumeType == 1) && !it.IsHide).OrderByDescending(it => it.Id).Take(50).ToListAsync(); List list = new List(); foreach (var item in logs) { @@ -182,10 +182,9 @@ namespace HuanMeng.MiaoYu.Code.Users transactionDto.TransactionTime = item.CreateTime; transactionDto.CurrencyType = item.CurrencyType; transactionDto.TransactionContent = item.Title; - transactionDto.TransactionAmount = $"{item.Consume}{(item.CurrencyType == 1 ? UserCurrencyType.语珠.ToString() : "")}"; + transactionDto.TransactionAmount = $"{(item.Consume > 0 ? "+" : "")}{item.Consume:D2}{(item.CurrencyType == 1 ? UserCurrencyType.语珠.ToString() : "")}"; list.Add(transactionDto); } - //var obj = JsonConvert.DeserializeObject>("[{\"TransactionContent\":\"购买记忆提升道具卡\",\"TransactionTime\":\"2024-07-18 12:58:52.963\",\"TransactionAmount\":\"-10\",\"TransactionType\":0,\"CurrencyType\":0},{\"TransactionContent\":\"充值语珠\",\"TransactionTime\":\"2024-07-17 12:58:52.963\",\"TransactionAmount\":\"+100\",\"TransactionType\":0,\"CurrencyType\":0},{\"TransactionContent\":\"充值语珠\",\"TransactionTime\":\"2024-07-16 12:58:52.963\",\"TransactionAmount\":\"+200\",\"TransactionType\":0,\"CurrencyType\":0}]"); return new BaseResponse>(ResonseCode.Success, "", list); } /// diff --git a/src/0-core/HuanMeng.MiaoYu.Code/Users/UserCurrencyBLL.cs b/src/0-core/HuanMeng.MiaoYu.Code/Users/UserCurrencyBLL.cs index d739ca4..615f9ad 100644 --- a/src/0-core/HuanMeng.MiaoYu.Code/Users/UserCurrencyBLL.cs +++ b/src/0-core/HuanMeng.MiaoYu.Code/Users/UserCurrencyBLL.cs @@ -110,16 +110,32 @@ namespace HuanMeng.MiaoYu.Code.Users /// /// /// - public static bool ConsumeMoneyNoWork(this T_User user, UserCurrencyType userCurrencyType, decimal money, DAO dao, T_User_Currency? _currency = null, string orderId = "", string title = "", string productId = "", string imageUrl = "" - , - T_User_Currency_Log? log = null) + public static bool ConsumeMoneyNoWork(this T_User user, UserCurrencyType userCurrencyType, decimal money, DAO dao, T_User_Currency? _currency = null, string orderId = "", string title = "") { if (user == null || user.Id == 0) { throw new ArgumentNullException("用户不能为空"); } int userId = user.Id; - return ConsumeMoneyNoWork(userId, userCurrencyType, money, dao, _currency, orderId: orderId, title: title, productId: productId, imageUrl: imageUrl, log: log); + return ConsumeMoneyNoWork(userId, userCurrencyType, money, dao, _currency, orderId: orderId, title: title); + } + + /// + /// + /// + /// + /// + /// + /// + /// + public static bool ConsumeMoneyNoWork(this T_User user, CurrencyTransactionParams param, DAO dao) + { + if (user == null || user.Id == 0) + { + throw new ArgumentNullException("用户不能为空"); + } + param.UserId = user.Id; + return ConsumeMoneyNoWork(param, dao); } /// /// 扣除或者充值货币 @@ -191,6 +207,7 @@ namespace HuanMeng.MiaoYu.Code.Users } return UserMemoryCardType.记忆卡; } + /// /// 扣除或者充值货币,没有事务 /// > @@ -206,119 +223,166 @@ namespace HuanMeng.MiaoYu.Code.Users /// /// /// - public static bool ConsumeMoneyNoWork(int userId, UserCurrencyType userCurrencyType, decimal money, DAO dao, T_User_Currency? _currency = null, string remarks = "", string title = "", string orderId = "", string productId = "", string imageUrl = "", - T_User_Currency_Log? log = null) + public static bool ConsumeMoneyNoWork(int userId, UserCurrencyType userCurrencyType, decimal money, DAO dao, T_User_Currency? _currency = null, string remarks = "", string title = "", string orderId = "") { - bool isJiyika = false; - //记忆卡特殊处理 - if (MUserCurrencyType.Contains(userCurrencyType) && money > 0) + CurrencyTransactionParams currencyTransactionParams = new CurrencyTransactionParams() { - isJiyika = true; - var memoryCardType = userCurrencyType.GetUserMemoryCardType(); - T_User_MemoryCard t_User_MemoryCard = new T_User_MemoryCard() + UserId = userId, + UserCurrencyType = userCurrencyType, + + Money = money, + OrderId = orderId, + Remarks = remarks, + Title = title, + Currency = _currency + }; + if (ConsumeMoneyNoWork(currencyTransactionParams, dao)) + { + _currency = currencyTransactionParams.Currency; + return true; + } + return false; + } + /// + /// 扣除或充值货币,无事务处理。 + /// + /// 货币交易的参数 + /// + /// 成功时返回 true + /// 当余额不足时抛出异常 + public static bool ConsumeMoneyNoWork(CurrencyTransactionParams transactionParams, DAO dao) + { + bool isMemoryCardTransaction = false; + + // 记忆卡交易的特殊处理 + if (MUserCurrencyType.Contains(transactionParams.UserCurrencyType) && transactionParams.Money > 0) + { + isMemoryCardTransaction = true; + var memoryCardType = transactionParams.UserCurrencyType.GetUserMemoryCardType(); + T_User_MemoryCard memoryCard = new T_User_MemoryCard() { - RemainingCount = (int)money, + RemainingCount = (int)transactionParams.Money, CharacterId = 0, MemoryCardToken = memoryCardType.GetUserMemoryCardTypeToken(), CreateTime = DateTime.Now, MemoryCardType = (int)memoryCardType, UseCount = 0, - Name = userCurrencyType.ToString(), - PopId = productId, - Remark = remarks, + Name = transactionParams.Products?.ProductName ?? transactionParams.UserCurrencyType.ToString(), + PopId = transactionParams.Products?.ProductId ?? transactionParams.ProductId, + Remark = transactionParams.Remarks, TenantId = dao.daoDbMiaoYu.context.TenantInfo.TenantId, UpdateTime = DateTime.Now, - UserId = userId, - Image = imageUrl + UserId = transactionParams.UserId, + Image = transactionParams.ImageUrl }; - dao.daoDbMiaoYu.context.T_User_MemoryCard.Add(t_User_MemoryCard); - money = 1; + dao.daoDbMiaoYu.context.T_User_MemoryCard.Add(memoryCard); + var mlog = new T_User_Currency_Log() + { + Consume = 1, + ConsumeType = (int)UserCurrencyConsumeType.购买, + CreateTime = DateTime.Now, + CurrencyType = (int)transactionParams.UserCurrencyType, + TenantId = dao.daoDbMiaoYu.context.TenantInfo.TenantId, + UpdateTime = DateTime.Now, + UserId = transactionParams.UserId, + Remarks = transactionParams.Remarks, + Title = $"{transactionParams.UserCurrencyType}", + OrderId = transactionParams.OrderId, + IsHide = false + }; + mlog.Remarks += $"于{DateTime.Now:yyyy-MM-dd HH:mm:ss}购买[{transactionParams.UserCurrencyType}][{Math.Abs(transactionParams.Money)}]"; + dao.daoDbMiaoYu.context.T_User_Currency_Log.Add(mlog); + transactionParams.Log = mlog; + dao.daoDbMiaoYu.context.SaveChanges(); + return true; + //transactionParams.Money = 1; } - var userCurrency = dao.daoDbMiaoYu.context.T_User_Currency.FirstOrDefault(it => it.UserId == userId && it.CurrencyType == (int)userCurrencyType); + var userCurrency = dao.daoDbMiaoYu.context.T_User_Currency.FirstOrDefault(it => it.UserId == transactionParams.UserId && it.CurrencyType == (int)transactionParams.UserCurrencyType); if (userCurrency == null) { userCurrency = new T_User_Currency() { CreateAt = DateTime.Now, CurrencyMoney = 0, - CurrencyName = userCurrencyType.ToString(), - CurrencyType = (int)userCurrencyType, + CurrencyName = transactionParams.UserCurrencyType.ToString(), + CurrencyType = (int)transactionParams.UserCurrencyType, TenantId = dao.daoDbMiaoYu.context.TenantInfo.TenantId, UpdateAt = DateTime.Now, - UserId = userId + UserId = transactionParams.UserId }; dao.daoDbMiaoYu.context.Add(userCurrency); dao.daoDbMiaoYu.context.SaveChanges(); } - userCurrency.CurrencyMoney += money; + userCurrency.CurrencyMoney += transactionParams.Money; if (userCurrency.CurrencyMoney < 0) { - //余额不足 throw new Exception("余额不足"); } - - UserCurrencyConsumeType userCurrencyConsumeType = UserCurrencyConsumeType.消耗; - if (money >= 0) + UserCurrencyConsumeType consumeType = transactionParams.Money >= 0 ? UserCurrencyConsumeType.购买 : UserCurrencyConsumeType.消耗; + T_User_Currency_Log? log = null; + if (transactionParams.UserCurrencyType == UserCurrencyType.聊天次数 && consumeType == UserCurrencyConsumeType.消耗) { - userCurrencyConsumeType = UserCurrencyConsumeType.购买; + var recentLogs = DateTime.Now.AddMinutes(-5); + log = dao.daoDbMiaoYu.context.T_User_Currency_Log + .Where(it => it.CreateTime > recentLogs && it.ConsumeType == (int)UserCurrencyConsumeType.消耗 && it.CurrencyType == (int)transactionParams.UserCurrencyType) + .OrderByDescending(it => it.CreateTime) + .FirstOrDefault(); } - if (userCurrencyType == UserCurrencyType.聊天次数 && userCurrencyConsumeType == UserCurrencyConsumeType.消耗) + if (string.IsNullOrEmpty(transactionParams.Title) && !isMemoryCardTransaction) { - var mintes = DateTime.Now.AddMinutes(-5); - log = dao.daoDbMiaoYu.context.T_User_Currency_Log.Where(it => it.CreateTime > mintes && it.ConsumeType == (int)UserCurrencyConsumeType.消耗 && it.CurrencyType == (int)userCurrencyType).OrderByDescending(it => it.CreateTime).FirstOrDefault(); + transactionParams.Title = $"{consumeType}{transactionParams.Money}{transactionParams.UserCurrencyType}"; } - var tempMoney = Math.Abs(money); - if (string.IsNullOrEmpty(title) && !isJiyika) - { - title = $"{userCurrencyConsumeType}{money}{userCurrencyType}"; - } - //消费 if (log == null) { log = new T_User_Currency_Log() { Consume = 0, - ConsumeType = (int)userCurrencyConsumeType, + ConsumeType = (int)consumeType, CreateTime = DateTime.Now, - CurrencyType = (int)userCurrencyType, + CurrencyType = (int)transactionParams.UserCurrencyType, TenantId = dao.daoDbMiaoYu.context.TenantInfo.TenantId, UpdateTime = DateTime.Now, - UserId = userId, - Remarks = remarks, - Title = title, - OrderId = orderId, + UserId = transactionParams.UserId, + Remarks = transactionParams.Remarks, + Title = transactionParams.Title, + OrderId = transactionParams.OrderId, IsHide = false }; dao.daoDbMiaoYu.context.T_User_Currency_Log.Add(log); } - log.Consume += money; - log.Remarks += $"于{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}{userCurrencyConsumeType.ToString()}[{tempMoney}]{userCurrencyType.ToString()};"; + + log.Consume += transactionParams.Money; + log.Remarks += $"于{DateTime.Now:yyyy-MM-dd HH:mm:ss}{consumeType}[{Math.Abs(transactionParams.Money)}]{transactionParams.UserCurrencyType};"; if (log.Remarks.Length > 200) { - log.Remarks = log.Remarks.Substring(log.Remarks.Length - 200); + log.Remarks = transactionParams.Log.Remarks[^200..]; } + dao.daoDbMiaoYu.context.SaveChanges(); - if (_currency != null) + + if (transactionParams.Currency != null) { - _currency.CurrencyMoney = userCurrency.CurrencyMoney; - _currency.UpdateAt = userCurrency.UpdateAt; - _currency.Id = userCurrency.Id; - _currency.CurrencyName = userCurrency.CurrencyName; - _currency.CreateAt = userCurrency.CreateAt; - _currency.CurrencyType = userCurrency.CurrencyType; + transactionParams.Currency.CurrencyMoney = userCurrency.CurrencyMoney; + transactionParams.Currency.UpdateAt = userCurrency.UpdateAt; + transactionParams.Currency.Id = userCurrency.Id; + transactionParams.Currency.CurrencyName = userCurrency.CurrencyName; + transactionParams.Currency.CreateAt = userCurrency.CreateAt; + transactionParams.Currency.CurrencyType = userCurrency.CurrencyType; } else { - _currency = userCurrency; + transactionParams.Currency = userCurrency; } + transactionParams.Log = log; return true; } + #endregion #region 自带事务 /// diff --git a/src/0-core/HuanMeng.MiaoYu.Code/Users/UserInfoBLL.cs b/src/0-core/HuanMeng.MiaoYu.Code/Users/UserInfoBLL.cs index 93d8db4..82c59b9 100644 --- a/src/0-core/HuanMeng.MiaoYu.Code/Users/UserInfoBLL.cs +++ b/src/0-core/HuanMeng.MiaoYu.Code/Users/UserInfoBLL.cs @@ -149,17 +149,18 @@ namespace HuanMeng.MiaoYu.Code.Users if (_m.TryGetValue(UserMemoryCardType.高级记忆卡, out _memoryCards)) { - return _memoryCards[0]; + + return _memoryCards.FirstOrDefault(it => it.RemainingCount > 0); } if (_m.TryGetValue(UserMemoryCardType.中级记忆卡, out _memoryCards)) { - return _memoryCards[0]; + return _memoryCards.FirstOrDefault(it => it.RemainingCount > 0); } if (_m.TryGetValue(UserMemoryCardType.初级记忆卡, out _memoryCards)) { - return _memoryCards[0]; + return _memoryCards.FirstOrDefault(it => it.RemainingCount > 0); } } else @@ -195,14 +196,14 @@ namespace HuanMeng.MiaoYu.Code.Users /// /// /// - public (int maxToken, bool isMemoryCard) GetMemoryCardMaxToken(int characterId) + public (int maxToken, bool isMemoryCard, T_User_MemoryCard? card) GetMemoryCardMaxToken(int characterId) { var _m = this[UserMemoryCardType.记忆卡, characterId]; if (_m != null && _m.RemainingCount > 0) { - return (_m.MemoryCardToken, true); + return (_m.MemoryCardToken, true, _m); } - return (UserMemoryCardType.记忆卡.GetUserMemoryCardTypeToken(), false); + return (UserMemoryCardType.记忆卡.GetUserMemoryCardTypeToken(), false, null); } } diff --git a/src/0-core/HuanMeng.MiaoYu.Model/Dto/Chat/CharacterInfoDto.cs b/src/0-core/HuanMeng.MiaoYu.Model/Dto/Chat/CharacterInfoDto.cs index 8be6059..f198c10 100644 --- a/src/0-core/HuanMeng.MiaoYu.Model/Dto/Chat/CharacterInfoDto.cs +++ b/src/0-core/HuanMeng.MiaoYu.Model/Dto/Chat/CharacterInfoDto.cs @@ -83,7 +83,10 @@ namespace HuanMeng.MiaoYu.Model.Dto.Chat /// 记忆卡状态 /// public bool MemoryCardState { get; set; } - + /// + /// 记忆卡剩余次数 + /// + public int MemoryCardCount { get; set; } /// /// 余下聊天次数 /// @@ -100,7 +103,7 @@ namespace HuanMeng.MiaoYu.Model.Dto.Chat //} - + /// /// 聊天列表 diff --git a/src/0-core/HuanMeng.MiaoYu.Model/Dto/Chat/ChatHistoryInfo.cs b/src/0-core/HuanMeng.MiaoYu.Model/Dto/Chat/ChatHistoryInfo.cs index 28092da..e5ed669 100644 --- a/src/0-core/HuanMeng.MiaoYu.Model/Dto/Chat/ChatHistoryInfo.cs +++ b/src/0-core/HuanMeng.MiaoYu.Model/Dto/Chat/ChatHistoryInfo.cs @@ -57,5 +57,10 @@ namespace HuanMeng.MiaoYu.Model.Dto.Chat /// public string LastMessage { get; set; } + /// + /// 是否有记忆卡 + /// + public bool IsMemoryCard { get; set; } + } } diff --git a/src/0-core/HuanMeng.MiaoYu.Model/Dto/RequestUserInfo.cs b/src/0-core/HuanMeng.MiaoYu.Model/Dto/RequestUserInfo.cs index 2660e4b..07d2bb9 100644 --- a/src/0-core/HuanMeng.MiaoYu.Model/Dto/RequestUserInfo.cs +++ b/src/0-core/HuanMeng.MiaoYu.Model/Dto/RequestUserInfo.cs @@ -11,6 +11,7 @@ namespace HuanMeng.MiaoYu.Model.Dto /// public class RequestUserInfo { + public RequestUserInfo() { } /// /// 昵称 /// diff --git a/src/2-api/HuanMeng.MiaoYu.WebApi/Controllers/PaymentController.cs b/src/2-api/HuanMeng.MiaoYu.WebApi/Controllers/PaymentController.cs index 0cd3084..1bf2226 100644 --- a/src/2-api/HuanMeng.MiaoYu.WebApi/Controllers/PaymentController.cs +++ b/src/2-api/HuanMeng.MiaoYu.WebApi/Controllers/PaymentController.cs @@ -3,6 +3,7 @@ using HuanMeng.MiaoYu.Code.Order; using HuanMeng.MiaoYu.Model.Dto.Order; using HuanMeng.MiaoYu.WebApi.Base; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; @@ -14,7 +15,7 @@ namespace HuanMeng.MiaoYu.WebApi.Controllers /// [Route("api/[controller]/[action]")] [ApiController] - + [Authorize] public class PaymentController : MiaoYuControllerBase { public PaymentController(IServiceProvider _serviceProvider) : base(_serviceProvider) diff --git a/src/2-api/HuanMeng.MiaoYu.WebPayApi/Controllers/PayController.cs b/src/2-api/HuanMeng.MiaoYu.WebPayApi/Controllers/PayController.cs index 4affff5..be14dea 100644 --- a/src/2-api/HuanMeng.MiaoYu.WebPayApi/Controllers/PayController.cs +++ b/src/2-api/HuanMeng.MiaoYu.WebPayApi/Controllers/PayController.cs @@ -109,7 +109,7 @@ namespace HuanMeng.MiaoYu.WebPayApi.Controllers await dao.daoDbMiaoYu.context.SaveChangesAsync(); return $"error;用户不存在"; } - using (IDbContextTransaction transaction = dao.daoDbMiaoYu.context.Database.BeginTransaction()) + using (IDbContextTransaction transaction = dao.daoDbMiaoYu.context.Database.BeginTransaction(System.Data.IsolationLevel.RepeatableRead)) { try {