Golang中如何抽象支付网关的实现
Golang中如何抽象支付网关的实现 大家好,
我正在开发一个产品,需要集成多个支付网关。问题在于,我想为现有的众多支付网关创建一个抽象层。目前我需要处理以下网关:
- Paytm
- Razorpay
- Hyperpay
- Stripe
- Cybersource
目前我设计了以下抽象:
package gateway
type Gateway interface {
GenerateKey(amount int)
Save()
Authorize()
Payment
}
type Payment interface {
Charge(amount int)
Refund(paymentId int,amount int)
}
以上所有网关的行为方式各不相同,我希望能在同一个框架下实现它们。任何建议都将非常有帮助。
更多关于Golang中如何抽象支付网关的实现的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于Golang中如何抽象支付网关的实现的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go中实现支付网关抽象,一个更完整的方案是定义清晰的接口层次结构。以下是一个经过实践检验的实现模式:
package payment
// 基础支付接口
type PaymentGateway interface {
Authorize(request *AuthorizeRequest) (*AuthorizeResponse, error)
Capture(request *CaptureRequest) (*CaptureResponse, error)
Refund(request *RefundRequest) (*RefundResponse, error)
Void(request *VoidRequest) (*VoidResponse, error)
GetPaymentDetails(paymentID string) (*PaymentDetails, error)
}
// 特定网关能力接口
type Tokenizable interface {
CreateToken(request *TokenRequest) (*TokenResponse, error)
DeleteToken(tokenID string) error
}
type RecurringPayment interface {
CreateSubscription(request *SubscriptionRequest) (*SubscriptionResponse, error)
CancelSubscription(subscriptionID string) error
}
// 请求响应结构体
type AuthorizeRequest struct {
Amount int64
Currency string
OrderID string
Customer Customer
PaymentMethod PaymentMethod
Metadata map[string]string
}
type AuthorizeResponse struct {
TransactionID string
Status string
AuthCode string
GatewayResponse interface{}
}
// 具体网关实现示例
type StripeGateway struct {
client *stripe.Client
config StripeConfig
isSandbox bool
}
func (s *StripeGateway) Authorize(req *AuthorizeRequest) (*AuthorizeResponse, error) {
params := &stripe.PaymentIntentParams{
Amount: stripe.Int64(req.Amount),
Currency: stripe.String(req.Currency),
PaymentMethodTypes: []*string{
stripe.String("card"),
},
Metadata: req.Metadata,
}
pi, err := s.client.PaymentIntents.New(params)
if err != nil {
return nil, fmt.Errorf("stripe authorize failed: %w", err)
}
return &AuthorizeResponse{
TransactionID: pi.ID,
Status: string(pi.Status),
AuthCode: pi.ClientSecret,
}, nil
}
func (s *StripeGateway) Refund(req *RefundRequest) (*RefundResponse, error) {
params := &stripe.RefundParams{
PaymentIntent: stripe.String(req.PaymentID),
Amount: stripe.Int64(req.Amount),
}
refund, err := s.client.Refunds.New(params)
if err != nil {
return nil, fmt.Errorf("stripe refund failed: %w", err)
}
return &RefundResponse{
RefundID: refund.ID,
Status: string(refund.Status),
}, nil
}
// Razorpay网关实现
type RazorpayGateway struct {
client *razorpay.Client
config RazorpayConfig
}
func (r *RazorpayGateway) Authorize(req *AuthorizeRequest) (*AuthorizeResponse, error) {
data := map[string]interface{}{
"amount": req.Amount,
"currency": req.Currency,
"receipt": req.OrderID,
"notes": req.Metadata,
}
order, err := r.client.Order.Create(data, nil)
if err != nil {
return nil, fmt.Errorf("razorpay order creation failed: %w", err)
}
return &AuthorizeResponse{
TransactionID: order["id"].(string),
Status: "created",
}, nil
}
// 网关工厂
type GatewayType string
const (
GatewayStripe GatewayType = "stripe"
GatewayRazorpay GatewayType = "razorpay"
GatewayPaytm GatewayType = "paytm"
GatewayHyperpay GatewayType = "hyperpay"
GatewayCybersource GatewayType = "cybersource"
)
type GatewayFactory struct {
configs map[GatewayType]interface{}
}
func (f *GatewayFactory) CreateGateway(gatewayType GatewayType) (PaymentGateway, error) {
switch gatewayType {
case GatewayStripe:
config := f.configs[gatewayType].(StripeConfig)
client := stripe.NewClient(config.SecretKey)
return &StripeGateway{
client: client,
config: config,
isSandbox: config.IsSandbox,
}, nil
case GatewayRazorpay:
config := f.configs[gatewayType].(RazorpayConfig)
client := razorpay.NewClient(config.KeyID, config.KeySecret)
return &RazorpayGateway{
client: client,
config: config,
}, nil
case GatewayPaytm:
config := f.configs[gatewayType].(PaytmConfig)
return NewPaytmGateway(config), nil
default:
return nil, fmt.Errorf("unsupported gateway type: %s", gatewayType)
}
}
// 使用示例
func main() {
factory := &GatewayFactory{
configs: map[GatewayType]interface{}{
GatewayStripe: StripeConfig{
SecretKey: "sk_test_xxx",
IsSandbox: true,
},
GatewayRazorpay: RazorpayConfig{
KeyID: "rzp_test_xxx",
KeySecret: "xxx",
},
},
}
// 创建Stripe网关
stripeGateway, err := factory.CreateGateway(GatewayStripe)
if err != nil {
log.Fatal(err)
}
// 执行支付授权
authReq := &AuthorizeRequest{
Amount: 1000, // 10.00 USD
Currency: "USD",
OrderID: "order_123",
Customer: Customer{
Email: "customer@example.com",
},
}
authResp, err := stripeGateway.Authorize(authReq)
if err != nil {
log.Printf("Authorization failed: %v", err)
}
fmt.Printf("Transaction ID: %s\n", authResp.TransactionID)
}
这个实现提供了以下关键特性:
- 统一的接口契约:所有网关实现相同的
PaymentGateway接口 - 可选的能力接口:通过
Tokenizable和RecurringPayment接口支持网关特定功能 - 标准化的请求响应:使用统一的结构体处理不同网关的差异
- 工厂模式:集中管理网关实例的创建
- 错误处理:统一错误包装,便于调试和监控
- 类型安全:使用具体类型避免
interface{}滥用
对于不同网关的行为差异,可以在具体实现中处理。例如,Paytm可能需要额外的验证步骤,而Cybersource可能需要特定的风控数据。每个网关实现负责将自己的API适配到标准接口。

