9e94d69e2edbb6592511531959ed15b79d8811ca
buildPayPalOrderRequest split the text delivery address at fixed offsets and called toFixed on the delivery price, and the items that were computed but never sent read the product of every cart line. A missing or two-line delivery address, a delivery method whose price is null, such as a pickup, and a cart line whose product was deleted each threw a TypeError, which the checkout answered 502 (D1 to D4). The request is now built in whole cents, with the shipping address from the first one entered of the structured delivery address, the structured invoice address and the text delivery address: - fullName is givenName and familyName, addressLine1 streetAddress, adminArea2 addressLevel2, countryCode the country upper-cased or DE; a structured address that is entered but incomplete is rejected instead of replaced by another address; - a text address needs three lines: the name, the street, and "<postal code> <city>" split at the first whitespace; lines between the name and the street become addressLine2; - a delivery price that is null counts as 0; - itemTotal is the net of the subtotal, round(subtotal cents * 100 / 119), taxTotal the order's VAT. The breakdown must add up to the total to the cent, as PayPal requires, so totals computed before a price changed are rejected here instead of by PayPal. The items are gone. With items, PayPal requires item_total and tax_total to be the sums of the amounts rounded per unit, which miss the net and the VAT of the subtotal that the invoice states: 3 x 12.50 gives 31.50 and 6.00, the subtotal 31.51 and 5.99. An empty cart, a missing total or VAT, totals that do not add up and a missing or unusable address throw CheckoutNotReadyError, which the checkout answers 400 "Order is not ready for checkout" with the reason. A deleted product throws ProductUnavailableError, answered 409 "A product in the cart is no longer available". Both are thrown before PayPal is asked and are logged as warnings; other errors stay 502. Tests: D1 to D4 are regular tests. The test of an order without a total expects CheckoutNotReadyError instead of a plain Error, and the item test is replaced by one that shows why no items are sent. The order of paypal-verify.test.ts gains the cart line the builder now requires, and its amount test builds the request for every total up to 3000.00 instead of assuming toFixed(2). Refs libretech/mp#71 Refs libretech/mp#67
libreshop/cms
Strapi-based content backend (catalogue, orders, customers).
Part of the libreshop toolkit. Image
published at git.librete.ch/libreshop/cms on every push to main
and on v* tags.
Source
This repo was extracted from mp/cms/ on 2026-04-29; mp was the
first concrete adapter consuming the toolkit. mp's compose.yml now
pulls git.librete.ch/libreshop/cms:<pin> instead of building locally.
Build locally
docker build -t libreshop/cms:dev .
Adapter contract
See docker-entrypoint.sh and Dockerfile for the runtime surface.
Adapters configure the component via env vars and bind-mounted volumes;
do not patch the running container or rely on internal paths.
Languages
TypeScript
95%
Shell
4.4%
JavaScript
0.4%
Dockerfile
0.2%