Finally, hide the wiring. Callers should ask for a processor by name, "stripe" or "paypal", and get back the correctly wrapped adapter, without importing adapter classes or knowing which SDK sits underneath. A small factory keeps adapter selection in one place.
Write get_processor(name, api): return a StripeAdapter around api for "stripe", a PayPalAdapter for "paypal", and raise ValueError for anything else. Together with the adapters, this is a complete unified payments layer over two incompatible SDKs.
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):
result = processor.charge(amount)
return "SUCCESS" if result["ok"] else "DECLINED"
def get_processor(name, api):
"""Return the adapter for name, wrapping api; ValueError if unknown."""
# TODO: compare name against the two gateway names this factory knows and
# build the matching adapter class around the api argument you were given.
# Any other name is a configuration mistake, so raise ValueError for it
# instead of quietly returning None.
pass
The editor and the test runner need a wide screen. Open this page on a desktop browser and your progress will be waiting.
Finally, hide the wiring. Callers should ask for a processor by name, "stripe" or "paypal", and get back the correctly wrapped adapter, without importing adapter classes or knowing which SDK sits underneath. A small factory keeps adapter selection in one place.
Write get_processor(name, api): return a StripeAdapter around api for "stripe", a PayPalAdapter for "paypal", and raise ValueError for anything else. Together with the adapters, this is a complete unified payments layer over two incompatible SDKs.
Press Run Tests or ββ© to check your solution.