fix: sanitize payment response NUL bytes

This commit is contained in:
MoRanHuiShou-pug
2026-07-05 03:55:40 +08:00
parent b650bdd68d
commit e76e0499d7
2 changed files with 52 additions and 0 deletions
+17
View File
@@ -453,6 +453,7 @@ func (s *PaymentService) invokeProvider(ctx context.Context, order *dbent.Paymen
}
return nil, classifyCreatePaymentError(req, sel.ProviderKey, err)
}
sanitizeCreatePaymentResponseDetails(pr)
_, err = s.entClient.PaymentOrder.UpdateOneID(order.ID).
SetNillablePaymentTradeNo(psNilIfEmpty(pr.TradeNo)).
SetNillablePayURL(psNilIfEmpty(pr.PayURL)).
@@ -480,6 +481,22 @@ func (s *PaymentService) invokeProvider(ctx context.Context, order *dbent.Paymen
return resp, nil
}
func sanitizeCreatePaymentResponseDetails(pr *payment.CreatePaymentResponse) {
if pr == nil {
return
}
pr.TradeNo = removePostgresTextNUL(pr.TradeNo)
pr.PayURL = removePostgresTextNUL(pr.PayURL)
pr.QRCode = removePostgresTextNUL(pr.QRCode)
}
func removePostgresTextNUL(value string) string {
if !strings.ContainsRune(value, 0) {
return value
}
return strings.ReplaceAll(value, "\x00", "")
}
func buildProviderCreatePaymentRequest(req CreateOrderRequest, sel *payment.InstanceSelection, orderID, amount, subject string) payment.CreatePaymentRequest {
return payment.CreatePaymentRequest{
OrderID: orderID,
@@ -91,6 +91,41 @@ func TestBuildCreateOrderResponseCopiesJSAPIPayload(t *testing.T) {
}
}
func TestSanitizeCreatePaymentResponseDetailsRemovesNULBytes(t *testing.T) {
t.Parallel()
resp := &payment.CreatePaymentResponse{
TradeNo: "trade\x00-no",
PayURL: "https://pay.example.com/\x00checkout",
QRCode: "wxp://payment-token\x00",
ClientSecret: "secret\x00unchanged",
}
sanitizeCreatePaymentResponseDetails(resp)
if strings.ContainsRune(resp.TradeNo, 0) {
t.Fatalf("trade_no still contains NUL: %q", resp.TradeNo)
}
if strings.ContainsRune(resp.PayURL, 0) {
t.Fatalf("pay_url still contains NUL: %q", resp.PayURL)
}
if strings.ContainsRune(resp.QRCode, 0) {
t.Fatalf("qr_code still contains NUL: %q", resp.QRCode)
}
if resp.TradeNo != "trade-no" {
t.Fatalf("trade_no = %q, want trade-no", resp.TradeNo)
}
if resp.PayURL != "https://pay.example.com/checkout" {
t.Fatalf("pay_url = %q, want sanitized URL", resp.PayURL)
}
if resp.QRCode != "wxp://payment-token" {
t.Fatalf("qr_code = %q, want sanitized QR code", resp.QRCode)
}
if resp.ClientSecret != "secret\x00unchanged" {
t.Fatalf("client_secret = %q, should not be touched by payment detail sanitization", resp.ClientSecret)
}
}
func TestValidateSelectedCreateOrderAmountCurrencyRejectsFractionalZeroDecimal(t *testing.T) {
t.Parallel()