Skip to content

Architecture

payments-hub is structured in two main layers: Core (gateway-agnostic business logic) and WooCommerce (integration layer). The Core layer must never depend on the WooCommerce layer.

Layer overview

src/
├── Config/          # Gateway config classes and factories
├── Core/
│   ├── Contracts/   # Interfaces for adapters, gateways, repos, loggers, requests, responses
│   ├── Controllers/ # REST-facing controllers (PaymentStatusController, WebhookController)
│   ├── Enums/       # GatewayProvider, PaymentStatus, AgreementStatus, …
│   ├── Exceptions/  # Domain exceptions
│   ├── Factories/   # Request factories (PaymentRequestFactory, AgreementRequestFactory)
│   ├── Gateways/    # Gateway implementations (Frisbii, MobilePay)
│   ├── Loggers/     # WooCommerce-backed loggers
│   ├── Migrations/  # Versioned DB migrations via Migrator
│   ├── Models/      # Request/response value objects
│   ├── Persistence/ # Entities (Agreement, Payment, Webhook, …) + repositories
│   ├── ServiceProviders/  # PaymentServiceProvider, WooCommerceIntegrationServiceProvider
│   ├── Services/    # Domain services (AgreementService, PaymentService, WebhookService, …)
│   └── Utilities/   # ArrayUtil, StringUtil, SubscriptionUtil
└── WooCommerce/
    ├── Admin/       # Meta boxes, order/subscription admin UI
    ├── API/REST/    # WooCommerce REST endpoint extensions
    ├── CLI/         # WP-CLI commands
    ├── Extensions/  # ApplicationStatus, BusinessCentral, GraphQL integrations
    ├── Frontend/    # Checkout, payment verification view
    ├── Gateways/    # WooCommerce gateway classes (Frisbii: CreditCard, ApplePay, GooglePay, …)
    └── Services/    # Event handlers, subscription service, WooCommerce setup

Container wiring

Everything is wired via League Container inside PaymentServiceProvider.

Key shared services:

Service Implementation
GatewayApiService Routes operations to the active gateway
AgreementService Agreement lifecycle (create, update, cancel)
PaymentService Payment lifecycle (create, capture, refund, cancel)
WebhookService Routes incoming webhooks to the correct handler
PaymentGatewayConfig Built from env vars via PaymentConfigFactory
AgreementRepositoryInterface AgreementRepository
PaymentRepositoryInterface PaymentRepository

Boot sequence

  1. PaymentServiceProvider::boot() runs via League Container.
  2. Migrator::get_instance() applies any pending DB migrations.
  3. Container inflectors inject LoggerInterface into all LoggerAwareInterface implementations.
  4. Webhook handlers receive state services and repositories via inflector.

Adding a new gateway

  1. Create src/Core/Gateways/{Provider}/ with a client, adapters, webhook handler, and a class implementing BasePaymentGatewayInterface.
  2. Add the provider constant to GatewayProvider.
  3. Register it in PaymentServiceProvider::register() (follow the maybeRegisterFrisbii pattern).
  4. Add the provider to GatewayApiService wiring.
  5. Create the WooCommerce gateway class(es) in src/WooCommerce/Gateways/{Provider}/.