Saving an order is not the same as being paid. Your server doesn't handle cards itself: a payment provider does. The checkout route asks it with a request of its own, using fetch. The answer takes time, so the route is async and awaits it.
The course's provider listens at PAYMENTS_URL (http://127.0.0.1:8002). POST /payments with {"amount": …, "order_id": …} answers with the payment as JSON, like {"id": "pay_1", …}. It declines amounts over 1000 with 402 Payment Required. payment.ok is true only for a 2xx status.
Here is the same idea with another service, a shipping quote:
app.post("/api/shipping-quote", async (req, res) => {
const quote = await fetch(SHIPPING_URL + "/quotes", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ postal_code: req.body.postal_code }) });
if (!quote.ok) {
return res.status(502).json({ error: "No quote right now" });
}
const data = await quote.json();
res.json({ price: data.price });
});
The check places Ana's order for a Mug and a Lamp, raises her cart to 21 gift cards and tries again. Then it asks the provider and shop.db:
> click "Place order" (Mug + Lamp) → POST /api/checkout -> 201, status: Order 8 placed: $41
PUT /api/cart/8 {"quantity": 21} → 200 {"items": [{"name": "Gift card", …}], "total": 1050}
> click "Place order" (21 gift cards) → POST /api/checkout -> 402, alert: Your card was declined
GET /payments (the provider) → 200 [{"amount": 41, "id": "pay_1", "order_id": 8, "status": "succeeded"}]
shop.db: order 8 | paid | pay_1 | 41
order 9 | pending | NULL | 1050
cart_items still holds Ana's 21 gift cards
Your task: in server/app.js, below the items loop of POST /api/checkout, send the order's total to the provider. When it declines, answer 402 {"error": "Your card was declined"}. Otherwise read its JSON and mark the order paid with the payment's id.
Assignment
Follow the Coding Tutorial to charge the order through the payment provider, answer 402 on a declined card, and save the payment's id with the status 'paid'.
Hint
The amount is cart.total, never a value from req.body. The 402 return comes before the given DELETE of cart_items, so a declined card keeps the cart.
Free plan: 30 tutor messages. PRO is unlimited.
