Uniform Failure Handling

Step 4: Uniform Failure Handling

Payments decline. Each SDK signals it differently: the given StripeApi returns paid False for a non-positive amount, and PayPalApi returns success False. But your adapters already fold both of those into a single field. Ok, so the caller never has to learn each provider's failure dialect.

Lean on that uniformity to write a client helper that reacts to the result. process_payment charges through any processor and returns the string SUCCESS when ok is true and DECLINED otherwise. One decision branch now covers every gateway, present and future.

  • process_payment(processor, amount). Call processor.charge(amount); return "SUCCESS" if the result's ok is true, else "DECLINED"
Hints
Starter code
class StripeApi:
    def create_charge(self, amount_cents):
        if amount_cents <= 0:
            return {"id": "ch_declined", "paid": False}
        return {"id": "ch_" + str(amount_cents), "paid": True}


class PayPalApi:
    def make_payment(self, dollars):
        if dollars <= 0:
            return {"success": False, "txn": "pp_declined"}
        return {"success": True, "txn": "pp_" + str(dollars)}


class PaymentProcessor:
    def charge(self, amount_dollars):
        raise NotImplementedError


class StripeAdapter(PaymentProcessor):
    def __init__(self, api):
        self._api = api

    def charge(self, amount_dollars):
        cents = int(round(amount_dollars * 100))
        resp = self._api.create_charge(cents)
        return {"ok": resp["paid"], "id": resp["id"]}


class PayPalAdapter(PaymentProcessor):
    def __init__(self, api):
        self._api = api

    def charge(self, amount_dollars):
        resp = self._api.make_payment(amount_dollars)
        return {"ok": resp["success"], "id": resp["txn"]}


def checkout(processor, amount):
    return processor.charge(amount)


def process_payment(processor, amount):
    """Return "SUCCESS" or "DECLINED" based on the charge result."""
    # TODO: charge the amount through whatever processor you were handed, then
    # branch on the ok field the adapters already normalized for you: hand back
    # the string SUCCESS when it is true and the string DECLINED when it is not.
    # Return those strings themselves, never booleans.
    pass
Write it on a laptop

The editor and the test runner need a wide screen. Open this page on a desktop browser and your progress will be waiting.