From 1430c820789f5682b7aafbbba1f070d6495e5b0d Mon Sep 17 00:00:00 2001 From: erio Date: Fri, 10 Apr 2026 16:40:42 +0800 Subject: [PATCH] fix(payment): restore decodeURLValue in EasyPay webhook verification The db139191 audit incorrectly removed the second URL decode pass. EasyPay providers send values that need decoding after url.ParseQuery, causing signature verification to fail on .147+. Production .146 worked because it still had decodeURLValue. --- backend/cmd/server/VERSION | 2 +- backend/internal/payment/provider/easypay.go | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/backend/cmd/server/VERSION b/backend/cmd/server/VERSION index 0e73dee820..a5eed0930c 100644 --- a/backend/cmd/server/VERSION +++ b/backend/cmd/server/VERSION @@ -1 +1 @@ -0.1.108.151 +0.1.108.152 diff --git a/backend/internal/payment/provider/easypay.go b/backend/internal/payment/provider/easypay.go index c54aba6aa9..40667ec094 100644 --- a/backend/internal/payment/provider/easypay.go +++ b/backend/internal/payment/provider/easypay.go @@ -176,10 +176,12 @@ 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. + // ParseQuery decodes percent-encoding once, but some EasyPay providers + // send values that still need a second decode pass (e.g. Chinese characters + // in the "name" field). Apply decodeURLValue to normalise. 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 == "" {