feat(checkout): verify the approved PayPal order and its capture against the order
verifyApprovedOrder accepts PayPal's order only if it is APPROVED, its first purchase unit's custom_id is the order's uuid, and its amount is the order total in EUR. verifyCompletedCapture accepts the order after the capture only if it and its first capture are COMPLETED for the order total in EUR, and returns the capture id. Both read PayPal's Orders v2 JSON in snake_case, as PayPalApi parses the response body. Money is compared in integer cents: PayPal's "12.34" is parsed strictly, the order total is Math.round(total * 100). For every total up to 3000.00 the amount the checkout sends (total.toFixed(2)) parses to the cents the capture compares. A rejection reason repeats only PayPal's statuses, currency codes and amounts, never the payer's or the shipping data of the response. Refs libretech/mp#71
This commit is contained in:
4 files changed
+577
No files matched your search
@@ -0,0 +1,131 @@
|
||||
{
|
||||
"id": "5O190127TN364715T",
|
||||
"intent": "CAPTURE",
|
||||
"status": "COMPLETED",
|
||||
"payment_source": {
|
||||
"paypal": {
|
||||
"email_address": "erika.buyer@example.org",
|
||||
"account_id": "QYR5Z8XDVJNXQ",
|
||||
"account_status": "VERIFIED",
|
||||
"name": {
|
||||
"given_name": "Erika",
|
||||
"surname": "Mustermann"
|
||||
},
|
||||
"address": {
|
||||
"country_code": "DE"
|
||||
}
|
||||
}
|
||||
},
|
||||
"purchase_units": [
|
||||
{
|
||||
"reference_id": "11111111-2222-4333-8444-555555555555",
|
||||
"amount": {
|
||||
"currency_code": "EUR",
|
||||
"value": "22.85",
|
||||
"breakdown": {
|
||||
"item_total": {
|
||||
"currency_code": "EUR",
|
||||
"value": "15.04"
|
||||
},
|
||||
"shipping": {
|
||||
"currency_code": "EUR",
|
||||
"value": "4.95"
|
||||
},
|
||||
"tax_total": {
|
||||
"currency_code": "EUR",
|
||||
"value": "2.86"
|
||||
}
|
||||
}
|
||||
},
|
||||
"payee": {
|
||||
"email_address": "merchant@example.com",
|
||||
"merchant_id": "7KNGBPH2U58GQ"
|
||||
},
|
||||
"custom_id": "11111111-2222-4333-8444-555555555555",
|
||||
"invoice_id": "R-12-4711",
|
||||
"shipping": {
|
||||
"name": {
|
||||
"full_name": "Erika Mustermann"
|
||||
},
|
||||
"address": {
|
||||
"address_line_1": "Musterstraße 1",
|
||||
"admin_area_2": "Stuttgart",
|
||||
"postal_code": "70190",
|
||||
"country_code": "DE"
|
||||
}
|
||||
},
|
||||
"payments": {
|
||||
"captures": [
|
||||
{
|
||||
"id": "3C679366HH908993F",
|
||||
"status": "COMPLETED",
|
||||
"amount": {
|
||||
"currency_code": "EUR",
|
||||
"value": "22.85"
|
||||
},
|
||||
"final_capture": true,
|
||||
"seller_protection": {
|
||||
"status": "ELIGIBLE",
|
||||
"dispute_categories": ["ITEM_NOT_RECEIVED", "UNAUTHORIZED_TRANSACTION"]
|
||||
},
|
||||
"seller_receivable_breakdown": {
|
||||
"gross_amount": {
|
||||
"currency_code": "EUR",
|
||||
"value": "22.85"
|
||||
},
|
||||
"paypal_fee": {
|
||||
"currency_code": "EUR",
|
||||
"value": "0.92"
|
||||
},
|
||||
"net_amount": {
|
||||
"currency_code": "EUR",
|
||||
"value": "21.93"
|
||||
}
|
||||
},
|
||||
"custom_id": "11111111-2222-4333-8444-555555555555",
|
||||
"invoice_id": "R-12-4711",
|
||||
"links": [
|
||||
{
|
||||
"href": "https://api.sandbox.paypal.com/v2/payments/captures/3C679366HH908993F",
|
||||
"rel": "self",
|
||||
"method": "GET"
|
||||
},
|
||||
{
|
||||
"href": "https://api.sandbox.paypal.com/v2/payments/captures/3C679366HH908993F/refund",
|
||||
"rel": "refund",
|
||||
"method": "POST"
|
||||
},
|
||||
{
|
||||
"href": "https://api.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T",
|
||||
"rel": "up",
|
||||
"method": "GET"
|
||||
}
|
||||
],
|
||||
"create_time": "2026-10-08T19:13:02Z",
|
||||
"update_time": "2026-10-08T19:13:02Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"payer": {
|
||||
"name": {
|
||||
"given_name": "Erika",
|
||||
"surname": "Mustermann"
|
||||
},
|
||||
"email_address": "erika.buyer@example.org",
|
||||
"payer_id": "QYR5Z8XDVJNXQ",
|
||||
"address": {
|
||||
"country_code": "DE"
|
||||
}
|
||||
},
|
||||
"create_time": "2026-10-08T19:12:40Z",
|
||||
"update_time": "2026-10-08T19:13:02Z",
|
||||
"links": [
|
||||
{
|
||||
"href": "https://api.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T",
|
||||
"rel": "self",
|
||||
"method": "GET"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in new issue
Block a user