fix(payment): keep subscription price as direct pay amount

This commit is contained in:
daoge_cmd
2026-06-28 06:29:01 +08:00
parent c275422251
commit b1403e8b29
3 changed files with 18 additions and 66 deletions
@@ -23,14 +23,6 @@ func calculateCreditedBalance(paymentAmount, multiplier float64) float64 {
InexactFloat64()
}
func calculateGatewayPaymentAmount(orderAmount, multiplier float64, currency string) float64 {
fractionDigits := int32(payment.CurrencyMaxFractionDigits(currency))
return decimal.NewFromFloat(orderAmount).
Div(decimal.NewFromFloat(normalizeBalanceRechargeMultiplier(multiplier))).
Round(fractionDigits).
InexactFloat64()
}
func calculateGatewayRefundAmount(orderAmount, payAmount, refundAmount float64, currency string) float64 {
if orderAmount <= 0 || payAmount <= 0 || refundAmount <= 0 {
return 0
+3 -15
View File
@@ -67,7 +67,8 @@ func (s *PaymentService) CreateOrder(ctx context.Context, req CreateOrderRequest
return nil, err
}
}
payAmountStr, payAmount, err := calculateCreateOrderPayAmountForOrder(req.OrderType, limitAmount, feeRate, cfg.BalanceRechargeMultiplier, methodCurrency)
// 订阅套餐 price 是直付价,余额充值倍率只影响余额充值到账,不参与订阅 pay_amount 计算。
payAmountStr, payAmount, err := calculateCreateOrderPayAmount(limitAmount, feeRate, methodCurrency)
if err != nil {
return nil, err
}
@@ -83,7 +84,7 @@ func (s *PaymentService) CreateOrder(ctx context.Context, req CreateOrderRequest
selectedCurrency = paymentProviderConfigCurrency(sel.ProviderKey, sel.Config)
}
if selectedCurrency != methodCurrency {
payAmountStr, payAmount, err = calculateCreateOrderPayAmountForOrder(req.OrderType, limitAmount, feeRate, cfg.BalanceRechargeMultiplier, selectedCurrency)
payAmountStr, payAmount, err = calculateCreateOrderPayAmount(limitAmount, feeRate, selectedCurrency)
if err != nil {
return nil, err
}
@@ -612,19 +613,6 @@ func calculateCreateOrderPayAmount(limitAmount, feeRate float64, currency string
return payAmountStr, payAmount, nil
}
func calculateCreateOrderPayAmountForOrder(orderType string, limitAmount, feeRate, multiplier float64, currency string) (string, float64, error) {
paymentAmount := calculateCreateOrderPaymentAmount(orderType, limitAmount, multiplier, currency)
return calculateCreateOrderPayAmount(paymentAmount, feeRate, currency)
}
func calculateCreateOrderPaymentAmount(orderType string, limitAmount, multiplier float64, currency string) float64 {
normalizedCurrency, err := payment.NormalizePaymentCurrency(currency)
if err != nil || normalizedCurrency != payment.DefaultPaymentCurrency || orderType != payment.OrderTypeSubscription {
return limitAmount
}
return calculateGatewayPaymentAmount(limitAmount, multiplier, normalizedCurrency)
}
func validateCreateOrderAmountCurrency(amount float64, currency string) error {
amountStr := strconv.FormatFloat(amount, 'f', -1, 64)
if _, err := payment.AmountToMinorUnit(amountStr, currency); err != nil {
@@ -126,69 +126,41 @@ func TestCalculateCreateOrderPayAmountUsesCurrencyPrecision(t *testing.T) {
}
}
func TestCalculateCreateOrderPayAmountForSubscriptionAppliesCNYMultiplier(t *testing.T) {
func TestCalculateCreateOrderPayAmountForSubscriptionKeepsDirectPrice(t *testing.T) {
t.Parallel()
amountStr, amount, err := calculateCreateOrderPayAmountForOrder(payment.OrderTypeSubscription, 7.99, 0, 0.14, "CNY")
amountStr, amount, err := calculateCreateOrderPayAmount(5, 0, "CNY")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if amountStr != "57.07" || amount != 57.07 {
t.Fatalf("subscription CNY pay amount = (%q, %v), want (57.07, 57.07)", amountStr, amount)
if amountStr != "5.00" || amount != 5 {
t.Fatalf("subscription CNY pay amount = (%q, %v), want (5.00, 5)", amountStr, amount)
}
}
func TestCalculateCreateOrderPayAmountForSubscriptionDefaultMultiplierKeepsPrice(t *testing.T) {
func TestCalculateCreateOrderPayAmountForSubscriptionAppliesFeeToDirectPrice(t *testing.T) {
t.Parallel()
for _, multiplier := range []float64{0, 1} {
amountStr, amount, err := calculateCreateOrderPayAmountForOrder(payment.OrderTypeSubscription, 7.99, 0, multiplier, "CNY")
if err != nil {
t.Fatalf("unexpected error for multiplier %v: %v", multiplier, err)
}
if amountStr != "7.99" || amount != 7.99 {
t.Fatalf("multiplier %v pay amount = (%q, %v), want (7.99, 7.99)", multiplier, amountStr, amount)
}
}
}
func TestCalculateCreateOrderPayAmountForSubscriptionDoesNotConvertNonCNY(t *testing.T) {
t.Parallel()
amountStr, amount, err := calculateCreateOrderPayAmountForOrder(payment.OrderTypeSubscription, 7.99, 0, 0.14, "USD")
amountStr, amount, err := calculateCreateOrderPayAmount(5, 2.5, "CNY")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if amountStr != "7.99" || amount != 7.99 {
t.Fatalf("subscription USD pay amount = (%q, %v), want (7.99, 7.99)", amountStr, amount)
if amountStr != "5.13" || amount != 5.13 {
t.Fatalf("subscription CNY pay amount with fee = (%q, %v), want (5.13, 5.13)", amountStr, amount)
}
}
func TestCalculateCreateOrderPayAmountForSubscriptionMatchesBalanceRechargeRatio(t *testing.T) {
func TestCalculateCreditedBalanceStillUsesRechargeMultiplier(t *testing.T) {
t.Parallel()
credited := calculateCreditedBalance(10, 0.14)
if credited != 1.4 {
t.Fatalf("credited balance = %v, want 1.4", credited)
got := calculateCreditedBalance(10, 0.14)
if got != 1.4 {
t.Fatalf("credited balance = %v, want 1.4", got)
}
amountStr, amount, err := calculateCreateOrderPayAmountForOrder(payment.OrderTypeSubscription, credited, 0, 0.14, "CNY")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if amountStr != "10.00" || amount != 10 {
t.Fatalf("subscription CNY pay amount = (%q, %v), want (10.00, 10)", amountStr, amount)
}
}
func TestCalculateCreateOrderPayAmountForSubscriptionAppliesFeeAfterMultiplier(t *testing.T) {
t.Parallel()
amountStr, amount, err := calculateCreateOrderPayAmountForOrder(payment.OrderTypeSubscription, 7.99, 2.5, 0.14, "CNY")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if amountStr != "58.50" || amount != 58.5 {
t.Fatalf("subscription CNY pay amount with fee = (%q, %v), want (58.50, 58.5)", amountStr, amount)
got = calculateCreditedBalance(5, 10)
if got != 50 {
t.Fatalf("credited balance = %v, want 50", got)
}
}