301 lines
12 KiB
C#
301 lines
12 KiB
C#
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
|
|
{
|
|
/// <summary>
|
|
/// 订单数据
|
|
/// </summary>
|
|
public class OrderBLL : MiaoYuBase
|
|
{
|
|
public OrderBLL(IServiceProvider serviceProvider) : base(serviceProvider)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// 创建订单
|
|
/// </summary>
|
|
/// <param name="paymentMethod"></param>
|
|
/// <param name="productId"></param>
|
|
/// <returns></returns>
|
|
/// <exception cref="ArgumentNullException"></exception>
|
|
/// <exception cref="NullReferenceException"></exception>
|
|
/// <exception cref="Exception"></exception>
|
|
public async Task<BaseResponse<IntentOrderDto>> 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<IntentOrderDto>(ResonseCode.Success, "", intentOrderDto);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取订单状态
|
|
/// </summary>
|
|
/// <param name="orderId"></param>
|
|
/// <returns></returns>
|
|
public async Task<BaseResponse<bool>> 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<bool>(ResonseCode.Success, "", false);
|
|
}
|
|
return new BaseResponse<bool>(ResonseCode.Success, tips, true);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 购买产品
|
|
/// </summary>
|
|
/// <param name="productId"></param>
|
|
/// <param name="buyCount"></param>
|
|
/// <returns></returns>
|
|
/// <exception cref="Exception"></exception>
|
|
public async Task<BaseResponse<bool>> 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<string> tips = new List<string>();
|
|
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<bool>(ResonseCode.Success, $"购买成功,获得{product.ProductName}*{buyCount}", true) { };
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 订单扩展类
|
|
/// </summary>
|
|
public static class OrderExtend
|
|
{
|
|
/// <summary>
|
|
/// 带锁版本
|
|
/// </summary>
|
|
/// <param name="product"></param>
|
|
/// <param name="user"></param>
|
|
/// <param name="pay"></param>
|
|
/// <param name="orderId"></param>
|
|
/// <param name="price"></param>
|
|
/// <param name="intentDate"></param>
|
|
/// <param name="dao"></param>
|
|
/// <returns></returns>
|
|
public static async Task<bool> 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;
|
|
}
|
|
/// <summary>
|
|
/// 不带锁,出现异常需要自己处理
|
|
/// </summary>
|
|
/// <param name="product"></param>
|
|
/// <param name="user"></param>
|
|
/// <param name="pay"></param>
|
|
/// <param name="orderId"></param>
|
|
/// <param name="price"></param>
|
|
/// <param name="intentDate"></param>
|
|
/// <param name="dao"></param>
|
|
/// <returns></returns>
|
|
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<string> tips = new List<string>();
|
|
//List<T_User_Currency> user_Currencies = new List<T_User_Currency>();
|
|
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();
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|