From 5d3e045e1204999e53df75d925d7932afea42110 Mon Sep 17 00:00:00 2001 From: admin Date: Tue, 26 May 2026 20:55:13 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8DBepUsdt=E7=AD=BE?= =?UTF-8?q?=E5=90=8D=E9=94=99=E8=AF=AF=E5=92=8C=E5=BE=85=E6=94=AF=E4=BB=98?= =?UTF-8?q?=E8=AE=A2=E5=8D=95=E4=BB=98=E6=AC=BE=E5=85=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - payment.go: 添加timestamp字段到签名和请求体(参照官方epusdt实现) - payment.go: 修复amount格式化,使用strconv.FormatFloat替代Sprintf - payment.go: 修复expiration_time处理(毫秒转秒,计算剩余秒数) - payment.go: 修复apiURL尾部斜杠处理 - OrderDetail.vue: 添加去支付按钮(pending_payment状态) - Orders.vue: 添加去支付按钮(bepusdt跳转收银台) --- backend/internal/api/handlers/payment.go | 79 ++++++++++++------------ frontend/src/views/user/OrderDetail.vue | 12 +++- frontend/src/views/user/Orders.vue | 11 ++++ 3 files changed, 63 insertions(+), 39 deletions(-) diff --git a/backend/internal/api/handlers/payment.go b/backend/internal/api/handlers/payment.go index 0019531..01981b0 100644 --- a/backend/internal/api/handlers/payment.go +++ b/backend/internal/api/handlers/payment.go @@ -10,6 +10,7 @@ import ( "sort" "strconv" "strings" + "time" "sale/internal/models" "sale/internal/utils" @@ -24,27 +25,13 @@ func NewPaymentHandler() *PaymentHandler { } type BepUsdtCreateRequest struct { - Address string `json:"address"` - TradeType string `json:"trade_type"` + TradeType string `json:"trade_type,omitempty"` OrderID string `json:"order_id"` Amount float64 `json:"amount"` - Signature string `json:"signature"` NotifyURL string `json:"notify_url"` - RedirectURL string `json:"redirect_url"` - Timeout int `json:"timeout"` - Rate string `json:"rate"` -} - -type BepUsdtCreateResponse struct { - StatusCode int `json:"status_code"` - Message string `json:"message"` - TradeID string `json:"trade_id"` - OrderID string `json:"order_id"` - Amount string `json:"amount"` - ActualAmount string `json:"actual_amount"` - Token string `json:"token"` - Expiration int `json:"expiration_time"` - PaymentURL string `json:"payment_url"` + RedirectURL string `json:"redirect_url,omitempty"` + Signature string `json:"signature"` + Timestamp int64 `json:"timestamp"` } func (h *PaymentHandler) CreatePayment(c *gin.Context) { @@ -73,17 +60,12 @@ func (h *PaymentHandler) CreatePayment(c *gin.Context) { var config map[string]string json.Unmarshal([]byte(channel.Config), &config) - apiURL := config["bepusdt_api_url"] + apiURL := strings.TrimSuffix(config["bepusdt_api_url"], "/") apiToken := config["bepusdt_api_token"] tradeType := config["bepusdt_trade_type"] if tradeType == "" { tradeType = "usdt.trc20" } - timeout, _ := strconv.Atoi(config["bepusdt_timeout"]) - if timeout < 60 { - timeout = 600 - } - rate := config["bepusdt_rate"] scheme := "http" if c.Request.TLS != nil || c.GetHeader("X-Forwarded-Proto") == "https" { @@ -94,19 +76,17 @@ func (h *PaymentHandler) CreatePayment(c *gin.Context) { notifyURL := fmt.Sprintf("%s/api/payment/bepusdt/notify", baseURL) redirectURL := fmt.Sprintf("%s/orders/%d", baseURL, order.ID) + timestamp := time.Now().Unix() params := map[string]string{ "order_id": strconv.Itoa(int(order.ID)), - "amount": fmt.Sprintf("%.2f", order.TotalAmount), + "amount": strconv.FormatFloat(order.TotalAmount, 'f', -1, 64), "notify_url": notifyURL, "redirect_url": redirectURL, - "trade_type": tradeType, + "timestamp": strconv.FormatInt(timestamp, 10), } - if timeout > 0 { - params["timeout"] = strconv.Itoa(timeout) - } - if rate != "" { - params["rate"] = rate + if tradeType != "" { + params["trade_type"] = tradeType } signature := signBepUsdt(params, apiToken) @@ -115,11 +95,10 @@ func (h *PaymentHandler) CreatePayment(c *gin.Context) { TradeType: tradeType, OrderID: strconv.Itoa(int(order.ID)), Amount: order.TotalAmount, - Signature: signature, NotifyURL: notifyURL, RedirectURL: redirectURL, - Timeout: timeout, - Rate: rate, + Signature: signature, + Timestamp: timestamp, } body, _ := json.Marshal(reqBody) @@ -144,11 +123,35 @@ func (h *PaymentHandler) CreatePayment(c *gin.Context) { return } - data := result["data"].(map[string]interface{}) + data, ok := result["data"].(map[string]interface{}) + if !ok { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Invalid response from payment gateway"}) + return + } + tradeID, _ := data["trade_id"].(string) - actualAmount, _ := data["actual_amount"].(string) token, _ := data["token"].(string) - expiration, _ := data["expiration_time"].(float64) + + var actualAmount float64 + if v, ok := data["actual_amount"].(float64); ok { + actualAmount = v + } + + var expiration int64 + if v, ok := data["expiration_time"].(float64); ok { + expiration = int64(v) + } + if expiration > 1e12 { + expiration = expiration / 1000 + } + + var remainingSeconds int64 + if expiration > 0 { + remainingSeconds = expiration - time.Now().Unix() + if remainingSeconds < 0 { + remainingSeconds = 0 + } + } utils.DB.Model(&order).Updates(map[string]interface{}{ "payment_method": "bepusdt", @@ -160,7 +163,7 @@ func (h *PaymentHandler) CreatePayment(c *gin.Context) { "amount": data["amount"], "actual_amount": actualAmount, "token": token, - "expiration_time": int(expiration), + "expiration_time": remainingSeconds, "trade_type": tradeType, "channel_id": channel.ID, } diff --git a/frontend/src/views/user/OrderDetail.vue b/frontend/src/views/user/OrderDetail.vue index ddc8227..30b5802 100644 --- a/frontend/src/views/user/OrderDetail.vue +++ b/frontend/src/views/user/OrderDetail.vue @@ -6,6 +6,7 @@
{{ statusText(order.status) }} 支付方式: {{ paymentMethodText(order.payment_method) }} + 去支付
订单信息
@@ -57,12 +58,13 @@