mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-23 03:36:30 +00:00
fix(payment): restore double URL decode for EasyPay webhook values
EasyPay callbacks arrive with double-encoded query values (e.g. %25E5 instead of %E5) due to redirect chains. url.ParseQuery decodes once; decodeURLValue applies a second safe decode so the sign matches what EasyPay computed. Also removes temporary debug logging.
This commit is contained in:
@@ -95,7 +95,8 @@ func (h *PaymentWebhookHandler) handleNotify(c *gin.Context, providerKey string)
|
||||
if len(truncatedBody) > webhookLogTruncateLen {
|
||||
truncatedBody = truncatedBody[:webhookLogTruncateLen] + "...(truncated)"
|
||||
}
|
||||
slog.Error("[Payment Webhook] verify failed", "provider", providerKey, "error", err, "method", c.Request.Method, "bodyLen", len(rawBody), "rawBody", truncatedBody)
|
||||
slog.Error("[Payment Webhook] verify failed", "provider", providerKey, "error", err, "method", c.Request.Method, "bodyLen", len(rawBody))
|
||||
slog.Debug("[Payment Webhook] verify failed body", "provider", providerKey, "rawBody", truncatedBody)
|
||||
c.String(http.StatusBadRequest, "verify failed")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sort"
|
||||
@@ -177,18 +176,18 @@ func (e *EasyPay) VerifyNotification(_ context.Context, rawBody string, _ map[st
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parse notify: %w", err)
|
||||
}
|
||||
// url.ParseQuery already decodes values — no additional decode needed.
|
||||
// EasyPay callbacks may arrive with double-encoded values (e.g. via redirect
|
||||
// chains), so url.ParseQuery decodes once, then decodeURLValue decodes again.
|
||||
// If a value is NOT double-encoded, QueryUnescape returns it unchanged.
|
||||
params := make(map[string]string)
|
||||
for k := range values {
|
||||
params[k] = values.Get(k)
|
||||
params[k] = decodeURLValue(values.Get(k))
|
||||
}
|
||||
sign := params["sign"]
|
||||
if sign == "" {
|
||||
return nil, fmt.Errorf("missing sign")
|
||||
}
|
||||
if !easyPayVerifySign(params, e.config["pkey"], sign) {
|
||||
expected := easyPaySign(params, e.config["pkey"])
|
||||
slog.Error("[EasyPay] sign mismatch", "expected", expected, "got", sign, "pkeyLen", len(e.config["pkey"]), "instanceID", e.instanceID, "paramCount", len(params))
|
||||
return nil, fmt.Errorf("invalid signature")
|
||||
}
|
||||
status := payment.ProviderStatusFailed
|
||||
|
||||
@@ -229,15 +229,10 @@ func (s *PaymentService) GetWebhookProvider(ctx context.Context, providerKey, ou
|
||||
if err == nil {
|
||||
p, pErr := s.getOrderProvider(ctx, order)
|
||||
if pErr == nil {
|
||||
slog.Info("[Webhook] using order's provider instance", "outTradeNo", outTradeNo, "instanceID", order.ProviderInstanceID, "providerKey", p.ProviderKey())
|
||||
return p, nil
|
||||
}
|
||||
slog.Warn("[Webhook] order provider creation failed, falling back to registry", "outTradeNo", outTradeNo, "instanceID", order.ProviderInstanceID, "error", pErr)
|
||||
} else {
|
||||
slog.Warn("[Webhook] order lookup failed", "outTradeNo", outTradeNo, "error", err)
|
||||
slog.Warn("[Webhook] order provider creation failed, falling back to registry", "outTradeNo", outTradeNo, "error", pErr)
|
||||
}
|
||||
} else {
|
||||
slog.Info("[Webhook] no out_trade_no extracted, using registry", "providerKey", providerKey)
|
||||
}
|
||||
s.EnsureProviders(ctx)
|
||||
return s.registry.GetProviderByKey(providerKey)
|
||||
|
||||
Reference in New Issue
Block a user