Files
verify/backend/internal/service/payment/payment.go
T
2026-04-27 17:22:56 +08:00

106 lines
2.6 KiB
Go

package payment
import (
"encoding/json"
"fmt"
"strconv"
"verification-platform-backend/internal/model"
)
type PaymentResult struct {
OrderID string
TradeID string
PaymentURL string
ActualAmount string
Token string
ExpirationTime int
}
type PaymentService interface {
CreateOrder(orderID string, amount float64, notifyURL, redirectURL, name string) (*PaymentResult, error)
VerifyCallback(data interface{}) bool
}
func GetPaymentService(channel model.PaymentChannel, callbackBaseURL string) (PaymentService, error) {
switch channel.Type {
case "bepusdt":
config, err := parseBEpusdtConfig(channel.Config)
if err != nil {
return nil, fmt.Errorf("parse bepusdt config: %w", err)
}
return NewBEpusdtAdapter(config, callbackBaseURL), nil
default:
return nil, fmt.Errorf("unsupported payment type: %s", channel.Type)
}
}
func parseBEpusdtConfig(configStr string) (BEpusdtConfig, error) {
var config BEpusdtConfig
if err := json.Unmarshal([]byte(configStr), &config); err != nil {
return config, fmt.Errorf("invalid config format: %w", err)
}
if config.ApiURL == "" {
return config, fmt.Errorf("api_url is required")
}
if config.ApiToken == "" {
return config, fmt.Errorf("api_token is required")
}
if config.TradeType == "" {
config.TradeType = "usdt.trc20"
}
return config, nil
}
func interfaceToString(v interface{}) string {
switch val := v.(type) {
case string:
return val
case float64:
return strconv.FormatFloat(val, 'f', -1, 64)
case int:
return strconv.Itoa(val)
default:
return fmt.Sprintf("%v", val)
}
}
type BEpusdtAdapter struct {
client *BEpusdtClient
callbackBaseURL string
}
func NewBEpusdtAdapter(config BEpusdtConfig, callbackBaseURL string) *BEpusdtAdapter {
return &BEpusdtAdapter{
client: NewBEpusdtClient(config),
callbackBaseURL: callbackBaseURL,
}
}
func (a *BEpusdtAdapter) CreateOrder(orderID string, amount float64, notifyURL, redirectURL, name string) (*PaymentResult, error) {
resp, err := a.client.CreateTransaction(orderID, amount, notifyURL, redirectURL, name)
if err != nil {
return nil, err
}
return &PaymentResult{
OrderID: resp.Data.OrderID,
TradeID: resp.Data.TradeID,
PaymentURL: resp.Data.PaymentURL,
ActualAmount: interfaceToString(resp.Data.ActualAmount),
Token: resp.Data.Token,
ExpirationTime: resp.Data.ExpirationTime,
}, nil
}
func (a *BEpusdtAdapter) VerifyCallback(data interface{}) bool {
switch v := data.(type) {
case CallbackData:
return a.client.VerifyCallback(v)
default:
return false
}
}