Contracts & bindings
Contracts & bindings
BillingServiceProvider registers one service provider per module, and each binds
its contracts to a default implementation. To replace a capability, bind your own
implementation of the contract in a service provider that boots after the
package's.
The core contracts
| Contract | Module | Default binding |
|---|---|---|
Metering\Contracts\Enforcement |
Metering | LeasedEnforcement |
Metering\Contracts\AllowanceLeaseSource |
Metering | host-provided (use FakeAllowanceLeaseSource in tests) |
Metering\Contracts\MeterPolicyResolver |
Metering | EntitlementMeterPolicyResolver |
Metering\Contracts\EventLog |
Metering | InMemoryEventLog / DatabaseEventLog |
Metering\Contracts\MeterIngest |
Metering | DefaultMeterIngest |
Wallet\Contracts\Wallet |
Wallet | InMemoryWallet |
Ledger\Contracts\Ledger |
Ledger | InMemoryLedger / DatabaseLedger |
Ledger\Contracts\TwoPhaseLedger |
Ledger | InMemoryTwoPhaseLedger |
Reconciliation\Contracts\Reconciler |
Reconciliation | DefaultReconciler |
Reconciliation\Contracts\CheckpointStore |
Reconciliation | InMemoryCheckpointStore / DatabaseCheckpointStore |
Account\Contracts\BillingCurrencyLock |
Account | InMemoryBillingCurrencyLock / DatabaseBillingCurrencyLock |
Account\Contracts\AccountStanding |
Account | InMemoryAccountStanding |
Catalog\Contracts\Catalog |
Catalog | InMemoryCatalog |
Seller\Contracts\EntityRouter |
Seller | DefaultEntityRouter |
Quote\Contracts\QuoteBuilder |
Quote | DefaultQuoteBuilder |
Invoice\Contracts\Invoicer |
Invoice | DefaultInvoicer |
Invoice\Contracts\InvoiceNumberSequence |
Invoice | InMemoryInvoiceNumberSequence |
Payment\Contracts\PaymentGateway |
Payment | ManualPaymentGateway |
Payment\Contracts\WebhookIngest |
Payment | DefaultWebhookIngest |
Payment\Contracts\WebhookVerifier |
Payment | DenyingWebhookVerifier (deny until an adapter binds one) |
Payment\Dunning\Contracts\DelinquencyPolicy |
Payment | DefaultDelinquencyPolicy |
Refund\Contracts\Refunder |
Refund | DefaultRefunder |
Refund\Contracts\ChargebackHandler |
Refund | DefaultChargebackHandler |
Entitlement\Contracts\EntitlementProjector |
Entitlement | DefaultEntitlementProjector |
Entitlement\Contracts\EntitlementWriter |
Entitlement | NullEntitlementWriter (host binds the real one) |
Entitlement\Rollout\Contracts\EntitlementRollout |
Entitlement | DefaultEntitlementRollout |
Entitlement\Audit\Contracts\EntitlementAudit |
Entitlement | DefaultEntitlementAudit |
Licensing\Contracts\LicenseProfileResolver |
Licensing | ConfiguredLicenseProfileResolver (empty map, deny-by-default) |
Licensing\Contracts\IssuedLicenseStore |
Licensing | InMemoryIssuedLicenseStore |
Licensing\Contracts\RevocationRegistry |
Licensing | InMemoryRevocationRegistry |
The unbound licensing key contracts
The licensing module deliberately leaves two crypto-core contracts unbound, because they hold the issuer private key — a host secret, not a package default:
| Contract | Module | Default binding |
|---|---|---|
Cbox\License\Contracts\LicenseIssuer |
Licensing | none — host binds Ed25519LicenseIssuer($privateKey) |
Cbox\License\Contracts\RevocationListIssuer |
Licensing | none — host binds Ed25519RevocationListIssuer($privateKey) |
LicenseMint and RevocationPublisher resolve these lazily, so resolving either one
before the host has bound the key surfaces a clear container error rather than minting
with no key:
use Cbox\License\Contracts\LicenseIssuer;
use Cbox\License\Contracts\RevocationListIssuer;
use Cbox\License\Ed25519LicenseIssuer;
use Cbox\License\Ed25519RevocationListIssuer;
public function register(): void
{
$this->app->singleton(LicenseIssuer::class, fn () => new Ed25519LicenseIssuer(config('services.licensing.private_key')));
$this->app->singleton(RevocationListIssuer::class, fn () => new Ed25519RevocationListIssuer(config('services.licensing.private_key')));
}
See Licensing.
Rebinding
use Cbox\Billing\Payment\Contracts\PaymentGateway;
public function register(): void
{
$this->app->bind(PaymentGateway::class, StripeGateway::class);
}
Two contracts you almost always bind yourself in production: the
AllowanceLeaseSource (your billing-side allowance authority) and the
EntitlementWriter (cbox-id ships the receiving contract). The rest have working
defaults.