fix(order): capture only the PayPal order the checkout stored, verified against the order
The capture took the PayPal order id from the URL and captured it with
Prefer: return=minimal, then marked the order paid on status COMPLETED.
The checkout never stored its PayPal order (the paypalOrderId written at
capture was no schema attribute and was dropped), and neither the order
nor the amount was compared. A buyer could pay a cheap order and call
the capture of an expensive one with that PayPal order id: the expensive
order was marked paid and invoiced. checkPaymentStatus also turned every
error into the string "/result/error", which failed the capture without
a log.
checkout now answers 409 for a paid order and 400 with the missing
fields for an order without email, invoice address or delivery method.
It stores the id of the PayPal order it created as paypalOrderId and
answers { id, links } as before. A PayPal error is answered 502.
capturePayment is an adapter for src/checkout/capture-payment.ts. It
reads the PayPal order with GET, captures with
Prefer: return=representation and a PayPal-Request-Id, and writes
paymentAuthorised, paymentStatus "captured", paypalCaptureId and
paymentCapturedAt with where { id, paypalOrderId }.
updateByUuid, addProduct and removeProduct set paypalOrderId to null in
the write that changes the order, so a changed cart or address needs a
new checkout, and an earlier approval cannot be captured for it.
PayPalApi gains getOrder and captureOrder, which return PayPal's parsed
JSON and let errors propagate. createSessionOrThrow logs an error by
name, message and status code instead of the error object, which holds
the request with its Authorization header; its request building is
unchanged.
Refs libretech/mp#71
This commit is contained in:
3 files changed
+89
-59
No files matched your search
@@ -46,12 +46,15 @@ const MAX = {
|
||||
};
|
||||
const MAX_TEXT = "Max Mustermann\nHauptstraße 5\n10115 Berlin";
|
||||
|
||||
// Every attribute of the order that only the server writes (src/api/order/content-types/order/schema.json), the fields Strapi
|
||||
// manages, and the paypalOrderId the capture writes; with values a client would send to get a paid order for less.
|
||||
// Every attribute of the order that only the server writes (src/api/order/content-types/order/schema.json), among them the PayPal
|
||||
// order the checkout stores and the capture it verified, and the fields Strapi manages; with values a client would send to get a
|
||||
// paid order for less.
|
||||
const SERVER_FIELDS = {
|
||||
paymentAuthorised: true,
|
||||
paymentStatus: "authorised",
|
||||
paymentStatus: "captured",
|
||||
paypalOrderId: "5O190127TN364715T",
|
||||
paypalCaptureId: "3C679366HH908993F",
|
||||
paymentCapturedAt: "2026-01-01T00:00:00.000Z",
|
||||
total: 0.01,
|
||||
subtotal: 0.01,
|
||||
VAT: 0,
|
||||
|
||||
Reference in new issue
Block a user