Start learning free

LESSON 108 OF 188 · BACKEND: PAYMENTS AND OTHER SERVICES

Declined Cards

Practice

Not every payment goes through: the card has no money left, it is blocked, or the bank says no. Then the payment provider answers 402 Payment Required with an error instead of a payment. Our provider declines every amount over 1000 and answers {"error": "card_declined"}. There is no "id" in it, so payment["id"] crashes and the customer gets an error page.

Check the status code first. Before you use another service's answer, look at response.status_code. The same idea with the supplier and a product it doesn't sell:

response = requests.get(SUPPLIER + "/stock/99")
if response.status_code == 404:
    return jsonify({"error": "Unknown product"}), 404
data = response.json()

A declined card is not a bug in your shop, so the answer is not 500. It is not 502 either: the provider worked and gave a clear answer. Answer 402 yourself, pass the provider's reason on, and return before the UPDATE, so the order stays pending and the customer can try another card.

POST /orders/9/pay  →  402  {"error": "Payment declined", "reason": "card_declined"}
GET /orders/9       →  200  {…, "payment_id": null, "status": "pending", "total": 1250}
POST /orders/8/pay  →  201  {"amount": 80, "order_id": 8, "payment_id": "pay_1"}

Your task: in pay_order, right after payment = response.json(), check whether the provider answered 402. If it did, answer "Payment declined" with 402, and pass the provider's "error" on under "reason".


Assignment
Follow the Coding Tutorial to handle a declined card in POST /orders/<id>/pay.


Hint
The provider's reason is payment["error"]. A return ends the function, so with the if above the UPDATE, a declined order is never marked paid.


STEP 1 OF 2
    Ctrl + Enter to check