Merge pull request #1610 from touwaeriol/fix/alipay-wxpay-type-mapping
fix(payment): register Alipay/Wxpay providers for base payment types
This commit is contained in:
@@ -94,17 +94,21 @@ func (lb *DefaultLoadBalancer) SelectInstance(
|
||||
return lb.buildSelection(selected.inst)
|
||||
}
|
||||
|
||||
// queryEnabledInstances returns enabled instances for providerKey that support paymentType.
|
||||
// queryEnabledInstances returns enabled instances that support paymentType.
|
||||
// When providerKey is non-empty, only instances with that provider key are considered.
|
||||
// When providerKey is empty, instances across all providers are considered,
|
||||
// enabling cross-provider load balancing (e.g. EasyPay + Alipay direct for "alipay").
|
||||
func (lb *DefaultLoadBalancer) queryEnabledInstances(
|
||||
ctx context.Context,
|
||||
providerKey string,
|
||||
paymentType PaymentType,
|
||||
) ([]*dbent.PaymentProviderInstance, error) {
|
||||
instances, err := lb.db.PaymentProviderInstance.Query().
|
||||
Where(
|
||||
paymentproviderinstance.ProviderKey(providerKey),
|
||||
paymentproviderinstance.Enabled(true),
|
||||
).
|
||||
query := lb.db.PaymentProviderInstance.Query().
|
||||
Where(paymentproviderinstance.Enabled(true))
|
||||
if providerKey != "" {
|
||||
query = query.Where(paymentproviderinstance.ProviderKey(providerKey))
|
||||
}
|
||||
instances, err := query.
|
||||
Order(dbent.Asc(paymentproviderinstance.FieldSortOrder)).
|
||||
All(ctx)
|
||||
if err != nil {
|
||||
@@ -113,12 +117,12 @@ func (lb *DefaultLoadBalancer) queryEnabledInstances(
|
||||
|
||||
var matched []*dbent.PaymentProviderInstance
|
||||
for _, inst := range instances {
|
||||
if paymentType == providerKey || InstanceSupportsType(inst.SupportedTypes, paymentType) {
|
||||
if InstanceSupportsType(inst.SupportedTypes, paymentType) {
|
||||
matched = append(matched, inst)
|
||||
}
|
||||
}
|
||||
if len(matched) == 0 {
|
||||
return nil, fmt.Errorf("no enabled instance for provider %s type %s", providerKey, paymentType)
|
||||
return nil, fmt.Errorf("no enabled instance for payment type %s", paymentType)
|
||||
}
|
||||
return matched, nil
|
||||
}
|
||||
@@ -258,6 +262,7 @@ func (lb *DefaultLoadBalancer) buildSelection(selected *dbent.PaymentProviderIns
|
||||
|
||||
return &InstanceSelection{
|
||||
InstanceID: fmt.Sprintf("%d", selected.ID),
|
||||
ProviderKey: selected.ProviderKey,
|
||||
Config: config,
|
||||
SupportedTypes: selected.SupportedTypes,
|
||||
PaymentMode: selected.PaymentMode,
|
||||
|
||||
@@ -76,7 +76,7 @@ func (a *Alipay) getClient() (*alipay.Client, error) {
|
||||
func (a *Alipay) Name() string { return "Alipay" }
|
||||
func (a *Alipay) ProviderKey() string { return payment.TypeAlipay }
|
||||
func (a *Alipay) SupportedTypes() []payment.PaymentType {
|
||||
return []payment.PaymentType{payment.TypeAlipayDirect}
|
||||
return []payment.PaymentType{payment.TypeAlipay}
|
||||
}
|
||||
|
||||
// CreatePayment creates an Alipay payment page URL.
|
||||
|
||||
@@ -72,7 +72,7 @@ func NewWxpay(instanceID string, config map[string]string) (*Wxpay, error) {
|
||||
func (w *Wxpay) Name() string { return "Wxpay" }
|
||||
func (w *Wxpay) ProviderKey() string { return payment.TypeWxpay }
|
||||
func (w *Wxpay) SupportedTypes() []payment.PaymentType {
|
||||
return []payment.PaymentType{payment.TypeWxpayDirect}
|
||||
return []payment.PaymentType{payment.TypeWxpay}
|
||||
}
|
||||
|
||||
func formatPEM(key, keyType string) string {
|
||||
|
||||
@@ -148,6 +148,7 @@ type RefundResponse struct {
|
||||
// InstanceSelection holds the selected provider instance and its decrypted config.
|
||||
type InstanceSelection struct {
|
||||
InstanceID string
|
||||
ProviderKey string // Provider key of the selected instance (e.g. "alipay", "easypay")
|
||||
Config map[string]string
|
||||
SupportedTypes string // Comma-separated list of supported payment types from the instance
|
||||
PaymentMode string // Payment display mode: "qrcode", "redirect", "popup"
|
||||
|
||||
@@ -189,19 +189,16 @@ func (s *PaymentService) checkDailyLimit(ctx context.Context, tx *dbent.Tx, user
|
||||
}
|
||||
|
||||
func (s *PaymentService) invokeProvider(ctx context.Context, order *dbent.PaymentOrder, req CreateOrderRequest, cfg *PaymentConfig, payAmountStr string, payAmount float64, plan *dbent.SubscriptionPlan) (*CreateOrderResponse, error) {
|
||||
s.EnsureProviders(ctx)
|
||||
providerKey := s.registry.GetProviderKey(req.PaymentType)
|
||||
if providerKey == "" {
|
||||
return nil, infraerrors.ServiceUnavailable("PAYMENT_GATEWAY_ERROR", fmt.Sprintf("payment method (%s) is not configured", req.PaymentType))
|
||||
}
|
||||
sel, err := s.loadBalancer.SelectInstance(ctx, providerKey, req.PaymentType, payment.Strategy(cfg.LoadBalanceStrategy), payAmount)
|
||||
// Select an instance across all providers that support the requested payment type.
|
||||
// This enables cross-provider load balancing (e.g. EasyPay + Alipay direct for "alipay").
|
||||
sel, err := s.loadBalancer.SelectInstance(ctx, "", req.PaymentType, payment.Strategy(cfg.LoadBalanceStrategy), payAmount)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("select provider instance: %w", err)
|
||||
return nil, infraerrors.ServiceUnavailable("PAYMENT_GATEWAY_ERROR", fmt.Sprintf("payment method (%s) is not configured", req.PaymentType))
|
||||
}
|
||||
if sel == nil {
|
||||
return nil, infraerrors.TooManyRequests("NO_AVAILABLE_INSTANCE", "no available payment instance")
|
||||
}
|
||||
prov, err := provider.CreateProvider(providerKey, sel.InstanceID, sel.Config)
|
||||
prov, err := provider.CreateProvider(sel.ProviderKey, sel.InstanceID, sel.Config)
|
||||
if err != nil {
|
||||
return nil, infraerrors.ServiceUnavailable("PAYMENT_GATEWAY_ERROR", "payment method is temporarily unavailable")
|
||||
}
|
||||
@@ -209,7 +206,7 @@ func (s *PaymentService) invokeProvider(ctx context.Context, order *dbent.Paymen
|
||||
outTradeNo := order.OutTradeNo
|
||||
pr, err := prov.CreatePayment(ctx, payment.CreatePaymentRequest{OrderID: outTradeNo, Amount: payAmountStr, PaymentType: req.PaymentType, Subject: subject, ClientIP: req.ClientIP, IsMobile: req.IsMobile, InstanceSubMethods: sel.SupportedTypes})
|
||||
if err != nil {
|
||||
slog.Error("[PaymentService] CreatePayment failed", "provider", providerKey, "instance", sel.InstanceID, "error", err)
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user