fix(payment): restore public resume and result flows

This commit is contained in:
IanShaw027
2026-04-22 11:17:23 +08:00
parent c229f33e9e
commit dd314c41e3
15 changed files with 435 additions and 90 deletions

View File

@@ -64,7 +64,7 @@ func TestNormalizePaymentSource(t *testing.T) {
func TestCanonicalizeReturnURL(t *testing.T) {
t.Parallel()
got, err := CanonicalizeReturnURL("https://example.com/payment/result?b=2#a", "example.com")
got, err := CanonicalizeReturnURL("https://example.com/payment/result?b=2#a", "example.com", "")
if err != nil {
t.Fatalf("CanonicalizeReturnURL returned error: %v", err)
}
@@ -76,7 +76,7 @@ func TestCanonicalizeReturnURL(t *testing.T) {
func TestCanonicalizeReturnURLRejectsRelativeURL(t *testing.T) {
t.Parallel()
if _, err := CanonicalizeReturnURL("/payment/result", "example.com"); err == nil {
if _, err := CanonicalizeReturnURL("/payment/result", "example.com", ""); err == nil {
t.Fatal("CanonicalizeReturnURL should reject relative URLs")
}
}
@@ -84,15 +84,31 @@ func TestCanonicalizeReturnURLRejectsRelativeURL(t *testing.T) {
func TestCanonicalizeReturnURLRejectsExternalHost(t *testing.T) {
t.Parallel()
if _, err := CanonicalizeReturnURL("https://evil.example/payment/result", "app.example.com"); err == nil {
if _, err := CanonicalizeReturnURL("https://evil.example/payment/result", "app.example.com", ""); err == nil {
t.Fatal("CanonicalizeReturnURL should reject external hosts")
}
}
func TestCanonicalizeReturnURLAllowsConfiguredFrontendHost(t *testing.T) {
t.Parallel()
got, err := CanonicalizeReturnURL(
"https://app.example.com/payment/result?from=checkout",
"api.example.com",
"https://app.example.com/purchase",
)
if err != nil {
t.Fatalf("CanonicalizeReturnURL returned error: %v", err)
}
if got != "https://app.example.com/payment/result?from=checkout" {
t.Fatalf("CanonicalizeReturnURL = %q, want %q", got, "https://app.example.com/payment/result?from=checkout")
}
}
func TestCanonicalizeReturnURLRejectsNonCanonicalPath(t *testing.T) {
t.Parallel()
if _, err := CanonicalizeReturnURL("https://app.example.com/orders/42", "app.example.com"); err == nil {
if _, err := CanonicalizeReturnURL("https://app.example.com/orders/42", "app.example.com", ""); err == nil {
t.Fatal("CanonicalizeReturnURL should reject non-canonical result paths")
}
}
@@ -100,7 +116,7 @@ func TestCanonicalizeReturnURLRejectsNonCanonicalPath(t *testing.T) {
func TestBuildPaymentReturnURL(t *testing.T) {
t.Parallel()
got, err := buildPaymentReturnURL("https://example.com/payment/result?from=checkout#fragment", 42, "resume-token")
got, err := buildPaymentReturnURL("https://example.com/payment/result?from=checkout#fragment", 42, "sub2_42", "resume-token")
if err != nil {
t.Fatalf("buildPaymentReturnURL returned error: %v", err)
}
@@ -119,6 +135,9 @@ func TestBuildPaymentReturnURL(t *testing.T) {
if query.Get("order_id") != strconv.FormatInt(42, 10) {
t.Fatalf("order_id = %q", query.Get("order_id"))
}
if query.Get("out_trade_no") != "sub2_42" {
t.Fatalf("out_trade_no = %q", query.Get("out_trade_no"))
}
if query.Get("resume_token") != "resume-token" {
t.Fatalf("resume_token = %q", query.Get("resume_token"))
}
@@ -127,10 +146,34 @@ func TestBuildPaymentReturnURL(t *testing.T) {
}
}
func TestBuildPaymentReturnURLWithoutResumeTokenStillIncludesOutTradeNo(t *testing.T) {
t.Parallel()
got, err := buildPaymentReturnURL("https://example.com/payment/result", 42, "sub2_42", "")
if err != nil {
t.Fatalf("buildPaymentReturnURL returned error: %v", err)
}
parsed, err := url.Parse(got)
if err != nil {
t.Fatalf("url.Parse returned error: %v", err)
}
query := parsed.Query()
if query.Get("order_id") != "42" {
t.Fatalf("order_id = %q", query.Get("order_id"))
}
if query.Get("out_trade_no") != "sub2_42" {
t.Fatalf("out_trade_no = %q", query.Get("out_trade_no"))
}
if query.Get("resume_token") != "" {
t.Fatalf("resume_token = %q, want empty", query.Get("resume_token"))
}
}
func TestBuildPaymentReturnURLEmptyBase(t *testing.T) {
t.Parallel()
got, err := buildPaymentReturnURL("", 42, "resume-token")
got, err := buildPaymentReturnURL("", 42, "sub2_42", "resume-token")
if err != nil {
t.Fatalf("buildPaymentReturnURL returned error: %v", err)
}