Schema
Mọi schema OpenAPI dùng trong request/response body của v1.
V1Error
Body lỗi dùng chung cho mọi lỗi auth/registry/signing/origin/pool (SHIELD_KEY_*, SCOPE_DENIED, ORIGIN_NOT_ALLOWED, POOL_MISMATCH, SHIELD_REGISTRY_*, PAYMENT_ENV_MISMATCH, CAPTURED_PROOF_UNAVAILABLE). message/docs LUÔN có mặt. Khác với LegacyControllerError dưới đây — hình dạng lỗi theo từng endpoint của PayPal/Stripe — không bao giờ mang message/docs.
| trường | kiểu | mô tả | |
|---|---|---|---|
error | boolean | bắt buộc | |
data | object | bắt buộc |
|
LegacyControllerError
Body lỗi theo từng endpoint của PayPal/Stripe — CÙNG hình dạng mà API cũ (không-v1) luôn trả về cho các route này. Chỉ issue được đảm bảo; message/docs KHÔNG BAO GIỜ có mặt (khác với V1Error). Một vài response không mang data nào cả — xem mô tả riêng của từng response để biết body chính xác.
| trường | kiểu | mô tả | |
|---|---|---|---|
error | boolean | bắt buộc | |
data | object | bắt buộc |
|
LegacyStringError
Body {error:string} trần không có data nào cả — khác với LegacyGateError (cùng hình dạng) và với V1Error/LegacyControllerError (có mang data). Dùng cho các lỗi cấu hình/nội bộ chung: "Shield misconfigured" (lệch chế độ key pk/sk của Stripe), "Internal server error" (lỗi không xác định), "Shield unavailable" (shield chưa được cấu hình secret trên route PayPal).
| trường | kiểu | mô tả | |
|---|---|---|---|
error | string | bắt buộc |
StripeErrorPassthrough
Body 500 trên /v1/stripe/create-intent và /v1/stripe/complete khi lời gọi API Stripe gốc throw lỗi. issue là MỞ — nó chuyển tiếp nguyên văn error.code của Stripe (ví dụ card_declined, parameter_invalid_integer, amount_too_small) khi Stripe đặt một giá trị, chỉ fallback về chuỗi literal STRIPE_ERROR khi không có. KHÔNG phải thành viên của enum đóng V1Issue — không validate issue dựa trên enum đó cho response này.
| trường | kiểu | mô tả | |
|---|---|---|---|
error | boolean | bắt buộc | |
data | object | bắt buộc |
|
LegacyGateError
Body trần từ gate phân giải pk của Stripe và gate hostname của PayPal — error ở đây là một STRING, không phải true, và không có data/issue nào cả. Bao gồm Stripe MISSING_PK/UNKNOWN_PK/PK_POOL_MISMATCH và gate unknown-host/no-secret của PayPal; tên issue trong mô tả của từng response chỉ mang tính tài liệu, không bao giờ có mặt trong body thực tế.
| trường | kiểu | mô tả | |
|---|---|---|---|
error | string | bắt buộc |
V1Issue
Mọi mã issue một response v1 có thể mang. Nhóm đầu tiên (SHIELD_KEY_*, SCOPE_DENIED, ORIGIN_NOT_ALLOWED, POOL_MISMATCH, SHIELD_REGISTRY_*, SHIELD_ENV_MISCONFIGURED, PAYMENT_ENV_MISMATCH, SIGNING_UNAVAILABLE, LEGACY_API_DISABLED, CAPTURED_PROOF_UNAVAILABLE) là bảng auth/registry/signing v1 dùng chung (bảng V1_ISSUE_STATUS dùng chung — được contract-test khớp 1:1). Các mã còn lại là các issue validate/business theo từng endpoint do các controller PayPal/Stripe bên dưới trả về (cùng mã mà API legacy trả về cho cùng endpoint). NGOẠI LỆ: STRIPE_ERROR được liệt kê ở đây như giá trị fallback literal, nhưng response 500 của Stripe create-intent/complete KHÔNG đóng với enum này — xem StripeErrorPassthrough, nơi ghi lại issue là error.code mở của chính Stripe.
SignedEnvelope
Body thành công v1 trên /v1/capture_order và /v1/stripe/complete (envelope builder v1 dùng chung). Chỉ mang bằng chứng Ed25519 — không bao giờ có các field legacy signature/signed_fields/ payload_signature. Xác minh sig dựa trên các byte chính xác của signed_payload (một chuỗi JSON, không phải object — không re-serialize nó) dùng public key cho kid lấy từ /v1/keys.
| trường | kiểu | mô tả | |
|---|---|---|---|
error | boolean | bắt buộc | |
data | object | bắt buộc | Lặp lại hình dạng legacy cho endpoint này (kết quả PayPal OrdersCaptureRequest, hoặc signed_fields dạng flat của Stripe) — chỉ mang tính thông tin; bằng chứng là |
signed_payload | string | bắt buộc | chuỗi JSON chính xác đã được ký (xác minh dựa trên các byte chính xác này) |
sig | string | bắt buộc | chữ ký Ed25519 base64url trên |
kid | string | bắt buộc | key id — dùng nó để tra JWK khớp trên |
alg | string | bắt buộc | |
v | integer | bắt buộc | |
contact | object | tùy chọn | Chỉ Stripe |
PaypalCaptureV1Payload
Hình dạng đã parse của signed_payload cho /v1/capture_order (các field extra của PayPal capture signed-payload builder cộng với envelope builder v1 dùng chung). Mọi field dưới đây đều được ký — không field nào có thể bị thay đổi mà không làm sig không hợp lệ.
| trường | kiểu | mô tả | |
|---|---|---|---|
order_id | string | bắt buộc | |
capture_id | string | bắt buộc | |
status | string | bắt buộc | trạng thái capture của PayPal, ví dụ COMPLETED |
amount | string | bắt buộc | chuỗi decimal, ví dụ "19.99" |
currency | string | bắt buộc | |
invoice_id | string | bắt buộc | id đơn hàng của store |
reference_id | string | bắt buộc |
|
payee_merchant_id | string | bắt buộc |
|
shield | string | bắt buộc | shield domain đã xử lý capture |
iat | integer | bắt buộc | unix seconds |
typ | string | bắt buộc | |
v | integer | bắt buộc | |
partner_id | string | bắt buộc | ranh giới bảo mật — phải khớp partner id của chính caller |
key_id | string | bắt buộc | ranh giới bảo mật — phải là một trong các key id được caller cho phép |
env | string | bắt buộc | ranh giới bảo mật — một key |
store_domain | string | null | bắt buộc | DO CLIENT KHAI BÁO, KHÔNG chuẩn hóa ở phía server — chỉ mang tính thông tin/audit, không bao giờ là một phần của ranh giới tin cậy (không ràng buộc việc xác minh vào giá trị này). |
StripeAddress
Hình dạng con địa chỉ bưu chính bên trong Contact. KHÔNG ĐƯỢC KÝ (chỉ để hiển thị). Phản chiếu object address gốc của Stripe; bất kỳ field nào có thể là null khi Stripe không thu thập nó.
| trường | kiểu | mô tả | |
|---|---|---|---|
line1 | string | null | tùy chọn | |
line2 | string | null | tùy chọn | |
city | string | null | tùy chọn | |
state | string | null | tùy chọn | |
postal_code | string | null | tùy chọn | |
country | string | null | tùy chọn |
Contact
Thông tin liên hệ/giao hàng của người mua trả về cùng một envelope v1 Stripe. KHÔNG ĐƯỢC KÝ — KHÔNG phải một phần của bằng chứng đã xác minh, không dùng cho các quyết định fraud/compliance. name/address ưu tiên chi tiết SHIPPING, fallback về billing; email/phone ưu tiên BILLING (email fallback về receipt_email). Trên một lần replay v1, wallet_type có thể fallback về giá trị do client cung cấp trong request — coi đó là gợi ý từ client, không phải giá trị đáng tin, trên các lần gọi replay.
| trường | kiểu | mô tả | |
|---|---|---|---|
name | string | null | bắt buộc | |
address | một trong | bắt buộc | null khi Stripe không có cả shipping và billing address trên PaymentIntent |
email | string | null | bắt buộc | |
phone | string | null | bắt buộc | |
wallet_type | string | bắt buộc | nhãn wallet đáng tin suy ra từ lần charge (ví dụ apple_pay/google_pay); '' khi chưa biết; gợi ý từ client khi replay — xem mô tả ở trên |
StripeCompleteV1Payload
Hình dạng đã parse của signed_payload cho /v1/stripe/complete (các field dạng flat, cộng với mọi key meta_*). Mọi properties dưới đây cộng với mọi key meta_* đều ĐƯỢC KÝ (chống giả mạo); xác minh sig trên signed_payload chứng minh không field nào bị thay đổi sau khi shield tạo ra envelope này.
RANH GIỚI BẢO MẬT (những gì một verifier PHẢI assert): partner_id + key_id (∈ các key id được bạn cho phép) + env + invoice_id + amount_received + id (chống replay — từ chối nếu đã settle) + status === 'succeeded' + iat trong khoảng [-600s, +300s] so với hiện tại. store, store_domain, reference_id và mọi key meta_* đều DO CLIENT KHAI BÁO lúc create-time (SDK/caller cung cấp chúng; server chỉ flatten và ký để chống giả mạo, không bao giờ xác minh độc lập nội dung) — CHỈ MANG TÍNH THÔNG TIN/audit/hiển thị, không bao giờ dùng chúng cho quyết định ràng buộc ở trên.
| trường | kiểu | mô tả | |
|---|---|---|---|
id | string | bắt buộc | Stripe PaymentIntent id (pi_…) — RANH GIỚI BẢO MẬT: key chống replay của bạn, từ chối nếu đã settle |
amount_received | integer | bắt buộc | RANH GIỚI BẢO MẬT — số nguyên cent, chỉ USD (Stripe v1 chỉ hỗ trợ USD; không có field currency). Phải bằng tổng đơn hàng của bạn tính bằng cent. |
status | string | bắt buộc | RANH GIỚI BẢO MẬT — phải chính xác là 'succeeded' (complete() chỉ ký một PI đã succeeded) |
store | string | bắt buộc | DO CLIENT KHAI BÁO — |
invoice_id | string | bắt buộc | RANH GIỚI BẢO MẬT — id đơn hàng store của bạn, ràng buộc-kiểm tra giá trị này với đơn hàng của bạn |
reference_id | string | bắt buộc | '' khi không có. DO CLIENT KHAI BÁO lúc create-time — CHỈ MANG TÍNH THÔNG TIN trừ khi bạn tự đặt nó và assert lại |
ship_name | string | bắt buộc | '' khi không có |
ship_phone | string | bắt buộc | '' khi không có |
ship_line1 | string | bắt buộc | '' khi không có |
ship_line2 | string | bắt buộc | '' khi không có |
ship_city | string | bắt buộc | '' khi không có |
ship_state | string | bắt buộc | '' khi không có |
ship_postal | string | bắt buộc | '' khi không có |
ship_country | string | bắt buộc | '' khi không có |
bill_name | string | bắt buộc | '' khi không có |
bill_email | string | bắt buộc | '' khi không có |
bill_phone | string | bắt buộc | '' khi không có |
bill_line1 | string | bắt buộc | '' khi không có |
bill_line2 | string | bắt buộc | '' khi không có |
bill_city | string | bắt buộc | '' khi không có |
bill_state | string | bắt buộc | '' khi không có |
bill_postal | string | bắt buộc | '' khi không có |
bill_country | string | bắt buộc | '' khi không có |
typ | string | bắt buộc | |
v | integer | bắt buộc | |
partner_id | string | bắt buộc | RANH GIỚI BẢO MẬT — phải khớp partner id của chính caller |
key_id | string | bắt buộc | RANH GIỚI BẢO MẬT — phải là một trong các key id được caller cho phép |
env | string | bắt buộc | RANH GIỚI BẢO MẬT — một key |
store_domain | string | null | bắt buộc | DO CLIENT KHAI BÁO — |
iat | integer | bắt buộc | RANH GIỚI BẢO MẬT — unix seconds; verifier phải ép buộc khoảng [-600s, +300s] |
Jwks
Tập JWK OKP Ed25519 theo RFC 8037 phục vụ bởi /v1/keys.
| trường | kiểu | mô tả | |
|---|---|---|---|
keys | array | bắt buộc | mảng gồm:
|