37 lines
1.2 KiB
Python
37 lines
1.2 KiB
Python
"""Payment gateway abstraction with idempotent callbacks.
|
|
|
|
Payments never talk to a concrete gateway directly; the gateway is selected
|
|
from configuration and isolated behind an interface.
|
|
"""
|
|
from typing import Protocol
|
|
|
|
from django.conf import settings
|
|
|
|
|
|
class PaymentGatewayInterface(Protocol):
|
|
def request_payment(self, amount, currency, order_number: str, callback_url: str) -> dict:
|
|
"""Return {'authority': str, 'redirect_url': str}."""
|
|
...
|
|
|
|
def verify(self, authority: str, amount) -> dict:
|
|
"""Return {'transaction_id': str, 'status': 'success'|'failed'|'cancelled'}."""
|
|
...
|
|
|
|
|
|
class MockGateway:
|
|
def request_payment(self, amount, currency, order_number: str, callback_url: str) -> dict:
|
|
return {
|
|
"authority": f"MOCK-AUTH-{order_number}",
|
|
"redirect_url": f"{callback_url}?authority=MOCK-AUTH-{order_number}",
|
|
}
|
|
|
|
def verify(self, authority: str, amount) -> dict:
|
|
return {"transaction_id": f"MOCK-TXN-{authority}", "status": "success"}
|
|
|
|
|
|
def get_gateway() -> PaymentGatewayInterface:
|
|
if settings.PAYMENT_GATEWAY_PROVIDER == "mock":
|
|
return MockGateway()
|
|
# Real gateways (GatewayA, GatewayB, ...) are selected here.
|
|
return MockGateway()
|