Start learning free

LESSON 107 OF 173 · BACKEND: PAYMENTS AND OTHER SERVICES

Take a Payment

Practice

A shop never handles card numbers itself. A payment provider does: the shop asks it, through its API, to charge an amount, and the provider answers with the payment it made. Ours lives at the address in PAYMENTS, already written for you, and the type Payment at the top of the file describes its answer.

Sending JSON to another API is one fetch with three options: the method, the Content-Type header and a body made with JSON.stringify. Then await response.json() reads the answer, and as with a type tells TypeScript its shape. Here a shop asks a gift-card service for a card worth 25:

type GiftCard = { id: string; value: number };

const response = await fetch(GIFTS + "/cards", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ value: 25, customer_id: 4 }),
});
const card = await response.json() as GiftCard;
console.log(card.id);

Two rules. The amount comes from your own database, never from the customer's request: nobody gets to choose their own price. And the shop saves the provider's payment id in the order: it links the order to the provider's record of the money, so you can look the payment up, or refund it, later. Paying is a POST, because it changes things, and it answers 201.

The provider answers like {"id": "pay_1", "status": "succeeded", "amount": 80, "order_id": 8}. Your shop must answer:

GET /orders/8        →  200  {"customer_id": 5, "id": 8, "ordered": "2026-06-02", "payment_id": null, "status": "pending", "total": 80}
POST /orders/8/pay   →  201  {"amount": 80, "order_id": 8, "payment_id": "pay_1"}
GET /orders/8        →  200  {"customer_id": 5, "id": 8, "ordered": "2026-06-02", "payment_id": "pay_1", "status": "paid", "total": 80}
POST /orders/10/pay  →  201  {"amount": 21, "order_id": 10, "payment_id": "pay_2"}
POST /orders/99/pay  →  404  {"error": "Order not found"}

Your task: add POST /orders/:orderId/pay. Find the order (404 if there is none), ask the provider at PAYMENTS + "/payments" to charge its total, save status = 'paid' and the payment id in the order, and answer 201.


Assignment
Follow the Coding Tutorial to build the route that pays an order through the payment provider.


Hint
Use findOrder as the route for one order does: it also adds up the total. The route's function must be async, because it waits twice with await: for fetch and for response.json(), which you follow with as Payment. Give the UPDATE its two values in the order of the ? marks.


STEP 1 OF 12
    Ctrl + Enter to check