feat: 实现抽奖逻辑调用 - 修复支付成功后无抽奖结果问题

- OrderService: 添加 ILotteryEngine 依赖,余额支付时调用抽奖
- PaymentNotifyService: 添加 ILotteryEngine 依赖,微信支付回调时调用抽奖
- ServiceModule: 更新依赖注入配置
- 支持普通抽奖(一番赏等)和无限赏两种模式
This commit is contained in:
gpu 2026-01-22 01:30:54 +08:00
parent cf5e7dd0de
commit 85f410db3b
3 changed files with 178 additions and 15 deletions

View File

@ -3,6 +3,7 @@ using HoneyBox.Model.Data;
using HoneyBox.Model.Entities;
using HoneyBox.Model.Models;
using HoneyBox.Model.Models.Goods;
using HoneyBox.Model.Models.Lottery;
using HoneyBox.Model.Models.Order;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
@ -16,6 +17,7 @@ public class OrderService : IOrderService
{
private readonly HoneyBoxDbContext _dbContext;
private readonly ILogger<OrderService> _logger;
private readonly ILotteryEngine _lotteryEngine;
// 抽奖赏品ID范围 [10, 33]
private static readonly int[] ShangPrizeIdRange = { 10, 33 };
@ -26,10 +28,11 @@ public class OrderService : IOrderService
// 无限赏商品类型
private static readonly int[] InfiniteGoodsTypes = { 2, 8, 9, 10, 16, 17 };
public OrderService(HoneyBoxDbContext dbContext, ILogger<OrderService> logger)
public OrderService(HoneyBoxDbContext dbContext, ILogger<OrderService> logger, ILotteryEngine lotteryEngine)
{
_dbContext = dbContext;
_logger = logger;
_lotteryEngine = lotteryEngine;
}
#region
@ -1066,6 +1069,9 @@ public class OrderService : IOrderService
await _dbContext.SaveChangesAsync();
// 执行普通抽奖逻辑(一番赏等)
await ExecuteLotteryAsync(userId, order.Id, request.GoodsId, goods.Type, num, request.PrizeNum, orderNum);
response = new OrderBuyResponseDto
{
Status = 0, // 已支付完成
@ -1085,6 +1091,45 @@ public class OrderService : IOrderService
}
}
/// <summary>
/// 执行普通抽奖逻辑(一番赏、擂台赏、转转赏等)
/// </summary>
private async Task ExecuteLotteryAsync(int userId, int orderId, int goodsId, int orderType, int num, int prizeNum, string orderNum)
{
try
{
var drawRequest = new LotteryDrawRequest
{
UserId = userId,
GoodsId = goodsId,
Num = num,
OrderId = orderId,
OrderNum = orderNum,
OrderType = orderType,
Source = 1 // 抽奖获得
};
// 执行多次抽奖
var results = await _lotteryEngine.DrawMultipleAsync(drawRequest, prizeNum);
var successCount = results.Count(r => r.Success);
_logger.LogInformation("普通抽奖完成: UserId={UserId}, OrderId={OrderId}, GoodsId={GoodsId}, Num={Num}, PrizeNum={PrizeNum}, SuccessCount={SuccessCount}",
userId, orderId, goodsId, num, prizeNum, successCount);
if (successCount == 0)
{
_logger.LogWarning("普通抽奖全部失败: UserId={UserId}, OrderId={OrderId}, GoodsId={GoodsId}",
userId, orderId, goodsId);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "执行普通抽奖失败: UserId={UserId}, OrderId={OrderId}, GoodsId={GoodsId}",
userId, orderId, goodsId);
// 抽奖失败不影响订单创建,但需要记录日志以便后续处理
}
}
/// <summary>
/// 生成订单号
/// </summary>
@ -1443,6 +1488,9 @@ public class OrderService : IOrderService
await _dbContext.SaveChangesAsync();
// 执行无限赏抽奖逻辑
await ExecuteInfiniteLotteryAsync(userId, order.Id, request.GoodsId, goods.Type, prizeNum, orderNum);
response = new OrderBuyResponseDto
{
Status = 0, // 已支付完成
@ -1462,6 +1510,45 @@ public class OrderService : IOrderService
}
}
/// <summary>
/// 执行无限赏抽奖逻辑
/// </summary>
private async Task ExecuteInfiniteLotteryAsync(int userId, int orderId, int goodsId, int orderType, int prizeNum, string orderNum)
{
try
{
var drawRequest = new LotteryDrawRequest
{
UserId = userId,
GoodsId = goodsId,
Num = 0, // 无限赏固定为0
OrderId = orderId,
OrderNum = orderNum,
OrderType = orderType,
Source = 1 // 抽奖获得
};
// 执行多次抽奖
var results = await _lotteryEngine.DrawInfiniteMultipleAsync(drawRequest, prizeNum);
var successCount = results.Count(r => r.Success);
_logger.LogInformation("无限赏抽奖完成: UserId={UserId}, OrderId={OrderId}, GoodsId={GoodsId}, PrizeNum={PrizeNum}, SuccessCount={SuccessCount}",
userId, orderId, goodsId, prizeNum, successCount);
if (successCount == 0)
{
_logger.LogWarning("无限赏抽奖全部失败: UserId={UserId}, OrderId={OrderId}, GoodsId={GoodsId}",
userId, orderId, goodsId);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "执行无限赏抽奖失败: UserId={UserId}, OrderId={OrderId}, GoodsId={GoodsId}",
userId, orderId, goodsId);
// 抽奖失败不影响订单创建,但需要记录日志以便后续处理
}
}
/// <summary>
/// 生成无限赏订单号
/// </summary>

View File

@ -1,6 +1,7 @@
using HoneyBox.Core.Interfaces;
using HoneyBox.Model.Data;
using HoneyBox.Model.Entities;
using HoneyBox.Model.Models.Lottery;
using HoneyBox.Model.Models.Payment;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
@ -15,6 +16,7 @@ public class PaymentNotifyService : IPaymentNotifyService
private readonly HoneyBoxDbContext _dbContext;
private readonly IWechatPayService _wechatPayService;
private readonly IPaymentService _paymentService;
private readonly ILotteryEngine _lotteryEngine;
private readonly ILogger<PaymentNotifyService> _logger;
/// <summary>
@ -42,11 +44,13 @@ public class PaymentNotifyService : IPaymentNotifyService
HoneyBoxDbContext dbContext,
IWechatPayService wechatPayService,
IPaymentService paymentService,
ILotteryEngine lotteryEngine,
ILogger<PaymentNotifyService> logger)
{
_dbContext = dbContext;
_wechatPayService = wechatPayService;
_paymentService = paymentService;
_lotteryEngine = lotteryEngine;
_logger = logger;
}
@ -390,10 +394,8 @@ public class PaymentNotifyService : IPaymentNotifyService
_logger.LogInformation("一番赏订单支付处理成功: OrderId={OrderId}, UserId={UserId}, GoodsId={GoodsId}, Num={Num}, OrderType={OrderType}",
orderId, userId, goodsId, num, order.OrderType);
// 6. 触发抽奖逻辑
// 注意抽奖逻辑ordinary_prize_notice等需要在后续任务中实现
// 这里只完成支付回调的基础处理:订单状态更新、资产扣减、优惠券更新
// 抽奖逻辑涉及复杂的奖品分配算法,将在专门的抽奖服务中实现
// 6. 执行普通抽奖逻辑
await ExecuteLotteryAsync(userId, orderId, goodsId, order.OrderType, num, order.PrizeNum, order.OrderNum);
return true;
}
@ -409,6 +411,45 @@ public class PaymentNotifyService : IPaymentNotifyService
}
}
/// <summary>
/// 执行普通抽奖逻辑(一番赏、擂台赏、转转赏等)
/// </summary>
private async Task ExecuteLotteryAsync(int userId, int orderId, int goodsId, int orderType, int num, int prizeNum, string orderNum)
{
try
{
var drawRequest = new LotteryDrawRequest
{
UserId = userId,
GoodsId = goodsId,
Num = num,
OrderId = orderId,
OrderNum = orderNum,
OrderType = orderType,
Source = 1 // 抽奖获得
};
// 执行多次抽奖
var results = await _lotteryEngine.DrawMultipleAsync(drawRequest, prizeNum);
var successCount = results.Count(r => r.Success);
_logger.LogInformation("普通抽奖完成: UserId={UserId}, OrderId={OrderId}, GoodsId={GoodsId}, Num={Num}, PrizeNum={PrizeNum}, SuccessCount={SuccessCount}",
userId, orderId, goodsId, num, prizeNum, successCount);
if (successCount == 0)
{
_logger.LogWarning("普通抽奖全部失败: UserId={UserId}, OrderId={OrderId}, GoodsId={GoodsId}",
userId, orderId, goodsId);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "执行普通抽奖失败: UserId={UserId}, OrderId={OrderId}, GoodsId={GoodsId}",
userId, orderId, goodsId);
// 抽奖失败不影响支付回调处理,但需要记录日志以便后续处理
}
}
/// <inheritdoc />
public async Task<bool> ProcessInfiniteOrderAsync(int orderId, int userId, int goodsId)
{
@ -501,14 +542,8 @@ public class PaymentNotifyService : IPaymentNotifyService
_logger.LogInformation("无限赏订单支付处理成功: OrderId={OrderId}, UserId={UserId}, GoodsId={GoodsId}, OrderType={OrderType}, PrizeNum={PrizeNum}",
orderId, userId, goodsId, order.OrderType, order.PrizeNum);
// 6. 触发无限赏抽奖逻辑
// 注意无限赏抽奖逻辑infinite_drawprize等需要在后续任务中实现
// 这里只完成支付回调的基础处理:订单状态更新、资产扣减、优惠券更新
// 无限赏抽奖涉及复杂的概率计算和奖品分配算法,将在专门的抽奖服务中实现
// PHP中根据order_type调用不同的抽奖方法:
// - order_type=10: infinite_shangchengshang (商城赏)
// - order_type=17: infinite_drawprize_tesu (特殊无限赏)
// - 其他: infinite_drawprize (普通无限赏)
// 6. 执行无限赏抽奖逻辑
await ExecuteInfiniteLotteryAsync(userId, orderId, goodsId, order.OrderType, order.PrizeNum, order.OrderNum);
return true;
}
@ -524,6 +559,45 @@ public class PaymentNotifyService : IPaymentNotifyService
}
}
/// <summary>
/// 执行无限赏抽奖逻辑
/// </summary>
private async Task ExecuteInfiniteLotteryAsync(int userId, int orderId, int goodsId, int orderType, int prizeNum, string orderNum)
{
try
{
var drawRequest = new LotteryDrawRequest
{
UserId = userId,
GoodsId = goodsId,
Num = 0, // 无限赏固定为0
OrderId = orderId,
OrderNum = orderNum,
OrderType = orderType,
Source = 1 // 抽奖获得
};
// 执行多次抽奖
var results = await _lotteryEngine.DrawInfiniteMultipleAsync(drawRequest, prizeNum);
var successCount = results.Count(r => r.Success);
_logger.LogInformation("无限赏抽奖完成: UserId={UserId}, OrderId={OrderId}, GoodsId={GoodsId}, PrizeNum={PrizeNum}, SuccessCount={SuccessCount}",
userId, orderId, goodsId, prizeNum, successCount);
if (successCount == 0)
{
_logger.LogWarning("无限赏抽奖全部失败: UserId={UserId}, OrderId={OrderId}, GoodsId={GoodsId}",
userId, orderId, goodsId);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "执行无限赏抽奖失败: UserId={UserId}, OrderId={OrderId}, GoodsId={GoodsId}",
userId, orderId, goodsId);
// 抽奖失败不影响支付回调处理,但需要记录日志以便后续处理
}
}
/// <inheritdoc />
public async Task<bool> ProcessRechargeOrderAsync(string orderNo)
{

View File

@ -208,7 +208,8 @@ public class ServiceModule : Module
{
var dbContext = c.Resolve<HoneyBoxDbContext>();
var logger = c.Resolve<ILogger<OrderService>>();
return new OrderService(dbContext, logger);
var lotteryEngine = c.Resolve<ILotteryEngine>();
return new OrderService(dbContext, logger, lotteryEngine);
}).As<IOrderService>().InstancePerLifetimeScope();
// 注册仓库服务
@ -252,8 +253,9 @@ public class ServiceModule : Module
var dbContext = c.Resolve<HoneyBoxDbContext>();
var wechatPayService = c.Resolve<IWechatPayService>();
var paymentService = c.Resolve<IPaymentService>();
var lotteryEngine = c.Resolve<ILotteryEngine>();
var logger = c.Resolve<ILogger<PaymentNotifyService>>();
return new PaymentNotifyService(dbContext, wechatPayService, paymentService, logger);
return new PaymentNotifyService(dbContext, wechatPayService, paymentService, lotteryEngine, logger);
}).As<IPaymentNotifyService>().InstancePerLifetimeScope();
// 注册充值服务