feat: snapshot payment provider keys on orders
This commit is contained in:
@@ -45,7 +45,7 @@ func (s *PaymentService) confirmPayment(ctx context.Context, oid int64, tradeNo
|
||||
if inst, instErr := s.getOrderProviderInstance(ctx, o); instErr == nil && inst != nil {
|
||||
instanceProviderKey = inst.ProviderKey
|
||||
}
|
||||
expectedProviderKey := expectedNotificationProviderKey(s.registry, o.PaymentType, instanceProviderKey)
|
||||
expectedProviderKey := expectedNotificationProviderKey(s.registry, o.PaymentType, psStringValue(o.ProviderKey), instanceProviderKey)
|
||||
if expectedProviderKey != "" && strings.TrimSpace(pk) != "" && !strings.EqualFold(expectedProviderKey, strings.TrimSpace(pk)) {
|
||||
s.writeAuditLog(ctx, o.ID, "PAYMENT_PROVIDER_MISMATCH", pk, map[string]any{
|
||||
"expectedProvider": expectedProviderKey,
|
||||
@@ -69,10 +69,13 @@ func (s *PaymentService) confirmPayment(ctx context.Context, oid int64, tradeNo
|
||||
return s.toPaid(ctx, o, tradeNo, paid, pk)
|
||||
}
|
||||
|
||||
func expectedNotificationProviderKey(registry *payment.Registry, orderPaymentType string, instanceProviderKey string) string {
|
||||
func expectedNotificationProviderKey(registry *payment.Registry, orderPaymentType string, orderProviderKey string, instanceProviderKey string) string {
|
||||
if key := strings.TrimSpace(instanceProviderKey); key != "" {
|
||||
return key
|
||||
}
|
||||
if key := strings.TrimSpace(orderProviderKey); key != "" {
|
||||
return key
|
||||
}
|
||||
if registry != nil {
|
||||
if key := strings.TrimSpace(registry.GetProviderKey(payment.PaymentType(orderPaymentType))); key != "" {
|
||||
return key
|
||||
|
||||
@@ -198,7 +198,7 @@ func TestExpectedNotificationProviderKeyPrefersOrderInstanceProvider(t *testing.
|
||||
|
||||
assert.Equal(t,
|
||||
payment.TypeEasyPay,
|
||||
expectedNotificationProviderKey(registry, payment.TypeAlipay, payment.TypeEasyPay),
|
||||
expectedNotificationProviderKey(registry, payment.TypeAlipay, "", payment.TypeEasyPay),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -213,7 +213,7 @@ func TestExpectedNotificationProviderKeyUsesRegistryMappingForLegacyOrders(t *te
|
||||
|
||||
assert.Equal(t,
|
||||
payment.TypeEasyPay,
|
||||
expectedNotificationProviderKey(registry, payment.TypeAlipay, ""),
|
||||
expectedNotificationProviderKey(registry, payment.TypeAlipay, "", ""),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -222,6 +222,21 @@ func TestExpectedNotificationProviderKeyFallsBackToPaymentType(t *testing.T) {
|
||||
|
||||
assert.Equal(t,
|
||||
payment.TypeWxpay,
|
||||
expectedNotificationProviderKey(nil, payment.TypeWxpay, ""),
|
||||
expectedNotificationProviderKey(nil, payment.TypeWxpay, "", ""),
|
||||
)
|
||||
}
|
||||
|
||||
func TestExpectedNotificationProviderKeyPrefersOrderSnapshotProviderKey(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
registry := payment.NewRegistry()
|
||||
registry.Register(paymentFulfillmentTestProvider{
|
||||
key: payment.TypeAlipay,
|
||||
supportedTypes: []payment.PaymentType{payment.TypeAlipay},
|
||||
})
|
||||
|
||||
assert.Equal(t,
|
||||
payment.TypeEasyPay,
|
||||
expectedNotificationProviderKey(registry, payment.TypeAlipay, payment.TypeEasyPay, ""),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -251,7 +251,13 @@ func (s *PaymentService) invokeProvider(ctx context.Context, order *dbent.Paymen
|
||||
slog.Error("[PaymentService] CreatePayment failed", "provider", sel.ProviderKey, "instance", sel.InstanceID, "error", err)
|
||||
return nil, infraerrors.ServiceUnavailable("PAYMENT_GATEWAY_ERROR", fmt.Sprintf("payment gateway error: %s", err.Error()))
|
||||
}
|
||||
_, err = s.entClient.PaymentOrder.UpdateOneID(order.ID).SetNillablePaymentTradeNo(psNilIfEmpty(pr.TradeNo)).SetNillablePayURL(psNilIfEmpty(pr.PayURL)).SetNillableQrCode(psNilIfEmpty(pr.QRCode)).SetNillableProviderInstanceID(psNilIfEmpty(sel.InstanceID)).Save(ctx)
|
||||
_, err = s.entClient.PaymentOrder.UpdateOneID(order.ID).
|
||||
SetNillablePaymentTradeNo(psNilIfEmpty(pr.TradeNo)).
|
||||
SetNillablePayURL(psNilIfEmpty(pr.PayURL)).
|
||||
SetNillableQrCode(psNilIfEmpty(pr.QRCode)).
|
||||
SetNillableProviderInstanceID(psNilIfEmpty(sel.InstanceID)).
|
||||
SetNillableProviderKey(psNilIfEmpty(sel.ProviderKey)).
|
||||
Save(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("update order with payment details: %w", err)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
dbent "github.com/Wei-Shaw/sub2api/ent"
|
||||
@@ -241,7 +242,10 @@ func (s *PaymentService) getOrderProvider(ctx context.Context, o *dbent.PaymentO
|
||||
if err == nil {
|
||||
cfg, err := s.loadBalancer.GetInstanceConfig(ctx, instID)
|
||||
if err == nil {
|
||||
providerKey := s.registry.GetProviderKey(o.PaymentType)
|
||||
providerKey := strings.TrimSpace(psStringValue(o.ProviderKey))
|
||||
if providerKey == "" {
|
||||
providerKey = s.registry.GetProviderKey(o.PaymentType)
|
||||
}
|
||||
if providerKey == "" {
|
||||
providerKey = o.PaymentType
|
||||
}
|
||||
@@ -255,3 +259,10 @@ func (s *PaymentService) getOrderProvider(ctx context.Context, o *dbent.PaymentO
|
||||
s.EnsureProviders(ctx)
|
||||
return s.registry.GetProvider(o.PaymentType)
|
||||
}
|
||||
|
||||
func psStringValue(value *string) string {
|
||||
if value == nil {
|
||||
return ""
|
||||
}
|
||||
return *value
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user