using HuanMeng.MiaoYu.Code.AppExtend; using HuanMeng.MiaoYu.Code.Cache.Special; using HuanMeng.MiaoYu.Code.DataAccess; using HuanMeng.MiaoYu.Code.Payment; using HuanMeng.MiaoYu.Code.Users; using HuanMeng.MiaoYu.Model.DbSqlServer.Db_MiaoYu; using HuanMeng.MiaoYu.Model.Dto.Order; using HuanMeng.MiaoYu.Model.EnumModel.User; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using StackExchange.Redis; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace HuanMeng.MiaoYu.Code.Order { /// /// 订单数据 /// public class OrderBLL : MiaoYuBase { public OrderBLL(IServiceProvider serviceProvider) : base(serviceProvider) { } /// /// 创建订单 /// /// /// /// /// /// /// public async Task> CreateOrder(string paymentMethod, string productId) { if (_UserId == 0) { throw new ArgumentNullException("未登录"); } if (string.IsNullOrEmpty(productId)) { throw new ArgumentNullException("产品不能为空"); } ProductEntityCache productEntityCache = new ProductEntityCache(this); var products = productEntityCache.GetDataList(); var product = products.FirstOrDefault(it => it.ProductId == productId); if (product == null) { throw new NullReferenceException("未找到所属产品"); } var redisLock = $"lock:payment:{_UserId}:{productId}"; if (!RedisCache.StringSetLock(redisLock, "", 5)) { throw new ArgumentNullException("重复创建订单"); } //productEntityCache.get IntentOrderDto intentOrderDto = null; //创建订单 try { var ip = HttpContextAccessor.HttpContext.GetClientIpAddress(); var price = product.Price; var payment = PaymentExtend.GetPayment(paymentMethod, this); UserInfoBLL userInfo = new UserInfoBLL(Dao, _UserId); if (userInfo.User.IsTest ?? false) { price = (decimal)0.01; } (var orderId, var order) = await payment.CreateOrder(product.Id, product.ProductName, price, product, ip); var t = product.ToIntentOrder(paymentMethod, orderId); t.UserId = _UserId; Dao.daoDbMiaoYu.context.Add(t); await Dao.daoDbMiaoYu.context.SaveChangesAsync(); intentOrderDto = new IntentOrderDto() { OrderId = orderId, Payment = order }; RedisCache.KeyDelete(redisLock); } catch (Exception ex) { RedisCache.KeyDelete(redisLock); throw new Exception("创建订单失败"); } return new BaseResponse(ResonseCode.Success, "", intentOrderDto); } /// /// 获取订单状态 /// /// /// public async Task> GetOrderRewardsInfo(string orderId) { var tips = await Dao.daoDbMiaoYu.context.T_OrderItems.Where(it => it.OrderId == orderId).Select(it => it.RewardTips).FirstOrDefaultAsync(); if (string.IsNullOrEmpty(tips)) { return new BaseResponse(ResonseCode.Success, "", false); } return new BaseResponse(ResonseCode.Success, tips, true); } /// /// 购买产品 /// /// /// /// /// public async Task> BuyProduct(string productId, int buyCount = 1) { if (buyCount < 1) { buyCount = 1; } var product = await Dao.daoDbMiaoYu.context.T_Products.Where(it => it.ProductId == productId && it.ProductType == 1).FirstOrDefaultAsync(); if (product == null) { throw new Exception("未找到产品"); } var image = product.ProductImgId.GetImageUrl(this); var user = await Dao.daoDbMiaoYu.context.T_User.FirstOrDefaultAsync(it => it.Id == _UserId); if (user == null) { throw new Exception("用户不存在"); } var baseKey = $"pay:lock:{_UserId}:{productId}"; if (!RedisCache.StringSetLock(baseKey, "", 10)) { throw new Exception("正在购买中"); } using (IDbContextTransaction transaction = Dao.daoDbMiaoYu.context.Database.BeginTransaction(System.Data.IsolationLevel.ReadUncommitted)) { try { var price = (((int)product.Price) * buyCount); user.ConsumeMoneyNoWork(UserCurrencyType.语珠, -price, Dao, title: $"购买{product.ProductName}*{buyCount}"); for (int i = 0; i < buyCount; i++) { var productReward = await Dao.daoDbMiaoYu.context.T_Products_Reward.Where(it => it.ProductId == product.ProductId).ToListAsync(); if (productReward != null && productReward.Count > 0) { List tips = new List(); foreach (var reward in productReward) { var money = reward.Money; var currency = (UserCurrencyType)reward.CurrencyType; var userCurrency = new T_User_Currency(); 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(); } } await transaction.CommitAsync(); } catch (Exception ex) { await transaction.RollbackAsync(); RedisCache.KeyDelete(baseKey); throw ex; } } RedisCache.KeyDelete(baseKey); return new BaseResponse(ResonseCode.Success, $"购买成功,获得{product.ProductName}*{buyCount}", true) { }; } } /// /// 订单扩展类 /// public static class OrderExtend { /// /// 带锁版本 /// /// /// /// /// /// /// /// /// public static async Task OrderRewardsAsync(this T_Products product, T_User user, string pay, string orderId, decimal price, DateTime intentDate, DAO dao) { using (IDbContextTransaction transaction = dao.daoDbMiaoYu.context.Database.BeginTransaction()) { try { await OrderRewardsNoWorkAsync(product, user, pay, orderId, price, intentDate, dao); await transaction.CommitAsync(); } catch (Exception ex) { await transaction.RollbackAsync(); return false; } } return true; } /// /// 不带锁,出现异常需要自己处理 /// /// /// /// /// /// /// /// /// public static async Task OrderRewardsNoWorkAsync(this T_Products product, T_User user, string pay, string orderId, decimal price, DateTime intentDate, DAO dao, T_OrderItems orderItems = null) { var userId = user.Id; var chargeMoneyCount = dao.daoDbMiaoYu.context.T_Order.Count(it => it.UserId == userId && it.ProductId == product.ProductId); var productReward = await dao.daoDbMiaoYu.context.T_Products_Reward.Where(it => it.ProductId == product.ProductId).ToListAsync(); if (productReward != null && productReward.Count > 0) { List tips = new List(); //List user_Currencies = new List(); foreach (var reward in productReward) { var money = reward.Money; var currency = (UserCurrencyType)reward.CurrencyType; var userCurrency = new T_User_Currency(); user.ConsumeMoneyNoWork(currency, money, dao, userCurrency, orderId); tips.Add($"获得{currency}*{money}"); if (product.IsFirstCharge && chargeMoneyCount == 0 && reward.FirstChargeMoney > 0) { user.ConsumeMoneyNoWork(currency, reward.FirstChargeMoney ?? 0, dao, userCurrency, orderId, $"首充赠送{currency}{reward.FirstChargeMoney}"); tips.Add($"首充赠送{currency}*{money}"); } } var rewardTips = string.Join(',', tips.ToArray()); T_Order order = new T_Order() { OrderId = orderId, CreatedAt = DateTime.Now, OrderDate = intentDate, PaymentDate = DateTime.Now, PaymentDay = DateOnly.FromDateTime(DateTime.Now), PaymentMethod = pay, ProductId = product.ProductId, Status = (int)OrderState.已完成, TenantId = product.TenantId, TotalPrice = price, UpdatedAt = DateTime.Now, UserId = userId, }; if (orderItems == null) { orderItems = new T_OrderItems(); } orderItems.OrderId = orderId; orderItems.RewardTips = rewardTips; orderItems.Product = product.Id; orderItems.TenantId = product.TenantId; orderItems.ProductId = product.ProductId; orderItems.RewardInfo = JsonConvert.SerializeObject(productReward); orderItems.RewardTips = rewardTips; dao.daoDbMiaoYu.context.T_OrderItems.Add(orderItems); dao.daoDbMiaoYu.context.T_Order.Add(order); await dao.daoDbMiaoYu.context.SaveChangesAsync(); } } } }