fix(epay): upgrade go-epay to v0.0.5

This commit is contained in:
CaIon committed 2026-10-07 21:26:35 +08:00
1 parent c6bac617d4
commit 0908d9e7b9
3 files changed
+119 -3

No files matched your search

@@ -1,10 +1,19 @@
package controller
import (
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
"github.com/Calcium-Ion/go-epay/epay"
"github.com/QuantumNous/new-api/model"
"github.com/QuantumNous/new-api/setting"
"github.com/QuantumNous/new-api/setting/operation_setting"
"github.com/QuantumNous/new-api/setting/system_setting"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -167,3 +176,110 @@ func TestEpayWebhookEnabledRequiresTopUpAndWebhookConfig(t *testing.T) {
operation_setting.PayMethods = nil
require.False(t, isEpayWebhookEnabled())
}
func TestEpayCallbacksVerifyBeforeSettlement(t *testing.T) {
confirmPaymentComplianceForTest(t)
originalPayAddress := operation_setting.PayAddress
originalEpayID := operation_setting.EpayId
originalEpayKey := operation_setting.EpayKey
originalPayMethods := operation_setting.PayMethods
originalServerAddress := system_setting.ServerAddress
originalDB := model.DB
t.Cleanup(func() {
operation_setting.PayAddress = originalPayAddress
operation_setting.EpayId = originalEpayID
operation_setting.EpayKey = originalEpayKey
operation_setting.PayMethods = originalPayMethods
system_setting.ServerAddress = originalServerAddress
model.DB = originalDB
})
operation_setting.PayAddress = "https://pay.example.com"
operation_setting.EpayId = "epay_id"
operation_setting.EpayKey = "test-key"
operation_setting.PayMethods = []map[string]string{{"type": "alipay"}}
system_setting.ServerAddress = "https://dashboard.example.com"
// Rejected callbacks and valid non-success events must never reach settlement.
// A nil database makes an accidental attempt to settle fail the test.
model.DB = nil
require.True(t, isEpayWebhookEnabled())
// Both ambiguous maps below had this same valid signing string in v0.0.4.
// This must fail because of parameter ambiguity, not a mismatched signature.
ambiguousSign := epay.MD5String("money=1.00&name=item&out_trade_no=other&out_trade_no=order&pid=epay_id&trade_status=TRADE_SUCCESS&type=alipay", "test-key")
pendingSign := epay.MD5String("money=1.00&name=item%26other&out_trade_no=order&pid=epay_id&trade_status=WAIT_BUYER_PAY&type=alipay", "test-key")
cases := []struct {
name string
productName string
tradeNo string
status string
sign string
validPending bool
}{
{"separator in product name", "item&out_trade_no=other", "order", epay.StatusTradeSuccess, ambiguousSign, false},
{"separator in order number", "item", "other&out_trade_no=order", epay.StatusTradeSuccess, ambiguousSign, false},
{"invalid signature", "item", "order", epay.StatusTradeSuccess, "invalid", false},
{"missing signature", "item", "order", epay.StatusTradeSuccess, "", false},
{"valid pending with literal percent escape", "item%26other", "order", "WAIT_BUYER_PAY", pendingSign, true},
}
endpoints := []struct {
name string
path string
handler gin.HandlerFunc
status int
rejectedBody string
pendingBody string
rejectedLocation string
pendingLocation string
}{
{
name: "topup notify", path: "/api/user/epay/notify", handler: EpayNotify,
status: http.StatusOK, rejectedBody: "fail", pendingBody: "success",
},
{
name: "subscription notify", path: "/api/subscription/epay/notify", handler: SubscriptionEpayNotify,
status: http.StatusOK, rejectedBody: "fail", pendingBody: "fail",
},
{
name: "subscription return", path: "/api/subscription/epay/return", handler: SubscriptionEpayReturn,
status: http.StatusFound,
rejectedLocation: "https://dashboard.example.com/wallet?pay=fail",
pendingLocation: "https://dashboard.example.com/wallet?pay=pending",
},
}
router := gin.New()
for _, endpoint := range endpoints {
router.Any(endpoint.path, endpoint.handler)
}
for _, endpoint := range endpoints {
for _, method := range []string{http.MethodGet, http.MethodPost} {
for _, tc := range cases {
t.Run(endpoint.name+"/"+method+"/"+tc.name, func(t *testing.T) {
params := url.Values{
"pid": {"epay_id"}, "type": {"alipay"}, "money": {"1.00"},
"name": {tc.productName}, "out_trade_no": {tc.tradeNo},
"trade_status": {tc.status}, "sign_type": {"MD5"},
}
if tc.sign != "" {
params.Set("sign", tc.sign)
}
request := httptest.NewRequest(method, endpoint.path+"?"+params.Encode(), nil)
if method == http.MethodPost {
request = httptest.NewRequest(method, endpoint.path, strings.NewReader(params.Encode()))
request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
}
recorder := httptest.NewRecorder()
require.NotPanics(t, func() { router.ServeHTTP(recorder, request) })
assert.Equal(t, endpoint.status, recorder.Code)
wantBody, wantLocation := endpoint.rejectedBody, endpoint.rejectedLocation
if tc.validPending {
wantBody, wantLocation = endpoint.pendingBody, endpoint.pendingLocation
}
if wantBody != "" {
assert.Equal(t, wantBody, recorder.Body.String())
}
assert.Equal(t, wantLocation, recorder.Header().Get("Location"))
})
}
}
}
}
+1 -1
View File
@@ -4,7 +4,7 @@ module github.com/QuantumNous/new-api
go 1.25.1
require (
github.com/Calcium-Ion/go-epay v0.0.4
github.com/Calcium-Ion/go-epay v0.0.5
github.com/abema/go-mp4 v1.4.1
github.com/andybalholm/brotli v1.2.0
github.com/anknown/ahocorasick v0.0.0-20190904063843-d75dbd5169c0
+2 -2
View File
@@ -631,8 +631,8 @@ github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbi
github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk=
github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Calcium-Ion/go-epay v0.0.4 h1:C96M7WfRLadcIVscWzwLiYs8etI1wrDmtFMuK2zP22A=
github.com/Calcium-Ion/go-epay v0.0.4/go.mod h1:cxo/ZOg8ClvE3VAnCmEzbuyAZINSq7kFEN9oHj5WQ2U=
github.com/Calcium-Ion/go-epay v0.0.5 h1:TgIx44c/bhdFqso4kbmDzZFzgyDJLma5hMDNA6sOXbo=
github.com/Calcium-Ion/go-epay v0.0.5/go.mod h1:cxo/ZOg8ClvE3VAnCmEzbuyAZINSq7kFEN9oHj5WQ2U=
github.com/Calcium-Ion/moejs v0.1.0-alpha.5 h1:hkTuLRIhtyXMPQciULZHTbdrw/LEJYvO2MDzl+/F1Y8=
github.com/Calcium-Ion/moejs v0.1.0-alpha.5/go.mod h1:9YqHj36EV7pzV/vlEYSw49f3oggeJFdmqcjM9TmDpHs=
github.com/ClickHouse/ch-go v0.58.2/go.mod h1:Ap/0bEmiLa14gYjCiRkYGbXvbe8vwdrfTYWhsuQ99aw=