The PayPal Adapter

Step 2: The PayPal Adapter

Now add a second gateway. PayPal's SDK is different again: make_payment takes dollars directly (no cents conversion) and returns success and txn instead of paid and id.

Because both adapters implement the same target interface, the rest of your system will not be able to tell them apart. That is the whole point of Adapter. After this step, StripeAdapter and PayPalAdapter both answer charge(amount_dollars) with the same {"ok", "id"} shape.

  • PayPalAdapter.charge(amount_dollars). Call make_payment(amount_dollars) and map the reply to {"ok": resp["success"], "id": resp["txn"]}
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):
        """Adapt to PayPal's dollars API and return {"ok", "id"}."""
        # TODO: PayPal already speaks dollars, so pass the amount straight
        # through to self._api.make_payment with no unit conversion, then
        # rename its success and txn fields into the very same ok and id keys
        # StripeAdapter produces, so callers cannot tell the two apart.
        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.