fix
This commit is contained in:
@@ -7,12 +7,31 @@ import (
|
||||
"github.com/shopspring/decimal"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"tyapi-server/internal/config"
|
||||
"tyapi-server/internal/domains/finance/entities"
|
||||
"tyapi-server/internal/domains/finance/repositories"
|
||||
"tyapi-server/internal/shared/database"
|
||||
"tyapi-server/internal/shared/interfaces"
|
||||
)
|
||||
|
||||
// calculateAlipayRechargeBonus 计算支付宝充值赠送金额
|
||||
func calculateAlipayRechargeBonus(rechargeAmount decimal.Decimal, walletConfig *config.WalletConfig) decimal.Decimal {
|
||||
if walletConfig == nil || len(walletConfig.AliPayRechargeBonus) == 0 {
|
||||
return decimal.Zero
|
||||
}
|
||||
|
||||
// 按充值金额从高到低排序,找到第一个匹配的赠送规则
|
||||
// 由于配置中规则是按充值金额从低到高排列的,我们需要反向遍历
|
||||
for i := len(walletConfig.AliPayRechargeBonus) - 1; i >= 0; i-- {
|
||||
rule := walletConfig.AliPayRechargeBonus[i]
|
||||
if rechargeAmount.GreaterThanOrEqual(decimal.NewFromFloat(rule.RechargeAmount)) {
|
||||
return decimal.NewFromFloat(rule.BonusAmount)
|
||||
}
|
||||
}
|
||||
|
||||
return decimal.Zero
|
||||
}
|
||||
|
||||
// RechargeRecordService 充值记录服务接口
|
||||
type RechargeRecordService interface {
|
||||
// 对公转账充值
|
||||
@@ -47,6 +66,7 @@ type RechargeRecordServiceImpl struct {
|
||||
walletService WalletAggregateService
|
||||
txManager *database.TransactionManager
|
||||
logger *zap.Logger
|
||||
cfg *config.Config
|
||||
}
|
||||
|
||||
func NewRechargeRecordService(
|
||||
@@ -56,6 +76,7 @@ func NewRechargeRecordService(
|
||||
walletService WalletAggregateService,
|
||||
txManager *database.TransactionManager,
|
||||
logger *zap.Logger,
|
||||
cfg *config.Config,
|
||||
) RechargeRecordService {
|
||||
return &RechargeRecordServiceImpl{
|
||||
rechargeRecordRepo: rechargeRecordRepo,
|
||||
@@ -64,6 +85,7 @@ func NewRechargeRecordService(
|
||||
walletService: walletService,
|
||||
txManager: txManager,
|
||||
logger: logger,
|
||||
cfg: cfg,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,6 +295,10 @@ func (s *RechargeRecordServiceImpl) HandleAlipayPaymentSuccess(ctx context.Conte
|
||||
return nil
|
||||
}
|
||||
|
||||
// 计算充值赠送金额
|
||||
bonusAmount := calculateAlipayRechargeBonus(amount, &s.cfg.Wallet)
|
||||
totalAmount := amount.Add(bonusAmount)
|
||||
|
||||
// 在事务中执行所有更新操作
|
||||
err = s.txManager.ExecuteInTx(ctx, func(txCtx context.Context) error {
|
||||
// 更新支付宝订单状态为成功
|
||||
@@ -291,8 +317,22 @@ func (s *RechargeRecordServiceImpl) HandleAlipayPaymentSuccess(ctx context.Conte
|
||||
return err
|
||||
}
|
||||
|
||||
// 使用钱包聚合服务更新钱包余额
|
||||
err = s.walletService.Recharge(txCtx, rechargeRecord.UserID, amount)
|
||||
// 如果有赠送金额,创建赠送充值记录
|
||||
if bonusAmount.GreaterThan(decimal.Zero) {
|
||||
giftRechargeRecord := entities.NewGiftRechargeRecord(rechargeRecord.UserID, bonusAmount, "充值活动赠送")
|
||||
_, err = s.rechargeRecordRepo.Create(txCtx, *giftRechargeRecord)
|
||||
if err != nil {
|
||||
s.logger.Error("创建赠送充值记录失败", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
s.logger.Info("创建赠送充值记录成功",
|
||||
zap.String("user_id", rechargeRecord.UserID),
|
||||
zap.String("bonus_amount", bonusAmount.String()),
|
||||
zap.String("gift_recharge_id", giftRechargeRecord.ID))
|
||||
}
|
||||
|
||||
// 使用钱包聚合服务更新钱包余额(包含赠送金额)
|
||||
err = s.walletService.Recharge(txCtx, rechargeRecord.UserID, totalAmount)
|
||||
if err != nil {
|
||||
s.logger.Error("更新钱包余额失败", zap.String("user_id", rechargeRecord.UserID), zap.Error(err))
|
||||
return err
|
||||
@@ -307,7 +347,9 @@ func (s *RechargeRecordServiceImpl) HandleAlipayPaymentSuccess(ctx context.Conte
|
||||
|
||||
s.logger.Info("支付宝支付成功回调处理成功",
|
||||
zap.String("user_id", rechargeRecord.UserID),
|
||||
zap.String("amount", amount.String()),
|
||||
zap.String("recharge_amount", amount.String()),
|
||||
zap.String("bonus_amount", bonusAmount.String()),
|
||||
zap.String("total_amount", totalAmount.String()),
|
||||
zap.String("out_trade_no", outTradeNo),
|
||||
zap.String("trade_no", tradeNo),
|
||||
zap.String("recharge_id", rechargeRecord.ID),
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"tyapi-server/internal/config"
|
||||
)
|
||||
|
||||
func TestCalculateAlipayRechargeBonus(t *testing.T) {
|
||||
// 创建测试配置
|
||||
walletConfig := &config.WalletConfig{
|
||||
AliPayRechargeBonus: []config.AliPayRechargeBonusRule{
|
||||
{RechargeAmount: 1000.00, BonusAmount: 50.00}, // 充1000送50
|
||||
{RechargeAmount: 5000.00, BonusAmount: 300.00}, // 充5000送300
|
||||
{RechargeAmount: 10000.00, BonusAmount: 800.00}, // 充10000送800
|
||||
},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
rechargeAmount decimal.Decimal
|
||||
expectedBonus decimal.Decimal
|
||||
}{
|
||||
{
|
||||
name: "充值500元,无赠送",
|
||||
rechargeAmount: decimal.NewFromFloat(500.00),
|
||||
expectedBonus: decimal.Zero,
|
||||
},
|
||||
{
|
||||
name: "充值1000元,赠送50元",
|
||||
rechargeAmount: decimal.NewFromFloat(1000.00),
|
||||
expectedBonus: decimal.NewFromFloat(50.00),
|
||||
},
|
||||
{
|
||||
name: "充值2000元,赠送50元",
|
||||
rechargeAmount: decimal.NewFromFloat(2000.00),
|
||||
expectedBonus: decimal.NewFromFloat(50.00),
|
||||
},
|
||||
{
|
||||
name: "充值5000元,赠送300元",
|
||||
rechargeAmount: decimal.NewFromFloat(5000.00),
|
||||
expectedBonus: decimal.NewFromFloat(300.00),
|
||||
},
|
||||
{
|
||||
name: "充值8000元,赠送300元",
|
||||
rechargeAmount: decimal.NewFromFloat(8000.00),
|
||||
expectedBonus: decimal.NewFromFloat(300.00),
|
||||
},
|
||||
{
|
||||
name: "充值10000元,赠送800元",
|
||||
rechargeAmount: decimal.NewFromFloat(10000.00),
|
||||
expectedBonus: decimal.NewFromFloat(800.00),
|
||||
},
|
||||
{
|
||||
name: "充值15000元,赠送800元",
|
||||
rechargeAmount: decimal.NewFromFloat(15000.00),
|
||||
expectedBonus: decimal.NewFromFloat(800.00),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
bonus := calculateAlipayRechargeBonus(tt.rechargeAmount, walletConfig)
|
||||
assert.True(t, bonus.Equal(tt.expectedBonus),
|
||||
"充值金额: %s, 期望赠送: %s, 实际赠送: %s",
|
||||
tt.rechargeAmount.String(), tt.expectedBonus.String(), bonus.String())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCalculateAlipayRechargeBonus_EmptyConfig(t *testing.T) {
|
||||
// 测试空配置
|
||||
walletConfig := &config.WalletConfig{
|
||||
AliPayRechargeBonus: []config.AliPayRechargeBonusRule{},
|
||||
}
|
||||
|
||||
bonus := calculateAlipayRechargeBonus(decimal.NewFromFloat(1000.00), walletConfig)
|
||||
assert.True(t, bonus.Equal(decimal.Zero), "空配置应该返回零赠送金额")
|
||||
|
||||
// 测试nil配置
|
||||
bonus = calculateAlipayRechargeBonus(decimal.NewFromFloat(1000.00), nil)
|
||||
assert.True(t, bonus.Equal(decimal.Zero), "nil配置应该返回零赠送金额")
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user