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 } }