""" Payment Client Interface and Implementation This module provides an abstraction layer for payment providers to make the system payment-agnostic """ import abc from typing import Dict, Any, Optional from dataclasses import dataclass from datetime import datetime @dataclass class PaymentCustomer: id: str email: str name: str created_at: datetime @dataclass class PaymentMethod: id: str type: str brand: Optional[str] = None last4: Optional[str] = None exp_month: Optional[int] = None exp_year: Optional[int] = None @dataclass class Subscription: id: str customer_id: str plan_id: str status: str # active, canceled, past_due, etc. current_period_start: datetime current_period_end: datetime created_at: datetime billing_cycle_anchor: Optional[datetime] = None cancel_at_period_end: Optional[bool] = None # 3DS Authentication fields payment_intent_id: Optional[str] = None payment_intent_status: Optional[str] = None payment_intent_client_secret: Optional[str] = None requires_action: Optional[bool] = None trial_end: Optional[datetime] = None billing_interval: Optional[str] = None @dataclass class Invoice: id: str customer_id: str subscription_id: str amount: float currency: str status: str # draft, open, paid, void, etc. created_at: datetime due_date: Optional[datetime] = None description: Optional[str] = None invoice_pdf: Optional[str] = None # URL to PDF invoice hosted_invoice_url: Optional[str] = None # URL to hosted invoice page class PaymentProvider(abc.ABC): """ Abstract base class for payment providers. All payment providers should implement this interface. """ @abc.abstractmethod async def create_customer(self, customer_data: Dict[str, Any]) -> PaymentCustomer: """ Create a customer in the payment provider system """ pass @abc.abstractmethod async def create_subscription(self, customer_id: str, plan_id: str, payment_method_id: str, trial_period_days: Optional[int] = None) -> Subscription: """ Create a subscription for a customer """ pass @abc.abstractmethod async def update_payment_method(self, customer_id: str, payment_method_id: str) -> PaymentMethod: """ Update the payment method for a customer """ pass @abc.abstractmethod async def cancel_subscription( self, subscription_id: str, cancel_at_period_end: bool = True ) -> Subscription: """ Cancel a subscription Args: subscription_id: Subscription ID to cancel cancel_at_period_end: If True, cancel at end of billing period. Default True. """ pass @abc.abstractmethod async def get_invoices(self, customer_id: str) -> list[Invoice]: """ Get invoices for a customer """ pass @abc.abstractmethod async def get_subscription(self, subscription_id: str) -> Subscription: """ Get subscription details """ pass @abc.abstractmethod async def get_customer(self, customer_id: str) -> PaymentCustomer: """ Get customer details """ pass @abc.abstractmethod async def create_setup_intent(self) -> Dict[str, Any]: """ Create a setup intent for saving payment methods """ pass @abc.abstractmethod async def create_payment_intent(self, amount: float, currency: str, customer_id: str, payment_method_id: str) -> Dict[str, Any]: """ Create a payment intent for one-time payments """ pass