Payment Providers
FinalTX uses a provider-neutral architecture for payment processing. This abstraction allows the platform to support multiple payment providers while maintaining a consistent API.
Architecture Overview
┌─────────────────────────────────────────────────────────┐
│ FinalTX Core │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Funding │ │ Settlement │ │ Webhooks │ │
│ │ Service │ │ Service │ │ Service │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ ┌──────┴────────────────┴────────────────┴──────┐ │
│ │ Provider Abstraction Layer │ │
│ │ ┌─────────────────────────────────────────┐ │ │
│ │ │ IFundingService | ISettlementService │ │ │
│ │ │ IWebhookService | FundingOption │ │ │
│ │ └─────────────────────────────────────────┘ │ │
│ └───────────────────┬───────────────────────────┘ │
└──────────────────────┼──────────────────────────────────┘
│
┌─────────────┴─────────────┐
│ │
┌────┴────┐ ┌────┴────┐
│ Stripe │ │ Future │
│ Provider│ │ Provider│
└─────────┘ └─────────┘The provider layer normalizes different payment processors into a unified interface, handling the specifics of each provider internally while exposing consistent methods to the rest of the application.
Active Provider
Stripe
Currently Active Provider
- Checkout Sessions for human funding
- Payment Links for agent funding via MCP
- Connect for seller payouts
- Automatic refund handling
Provider Services
IFundingService
Handles payment initiation and verification.
interface IFundingService {
// Create a checkout session for human funding
createCheckoutSession(opts: CreateCheckoutOpts): Promise<CheckoutResult>;
// Verify a completed payment
verifyPayment(opts: VerifyPaymentOpts): Promise<PaymentVerification>;
// Get available funding options for a contract
getFundingOptions(contract: Contract): FundingOption[];
}ISettlementService
Handles fund release to sellers and refunds to buyers.
interface ISettlementService {
// Release funds to seller
releaseFunds(opts: ReleaseOpts): Promise<SettlementResult>;
// Refund funds to buyer
refundFunds(opts: RefundOpts): Promise<SettlementResult>;
// Check if seller can receive payouts
checkPayoutReadiness(sellerId: string): Promise<PayoutReadiness>;
}IWebhookService
Normalizes provider webhooks into internal events.
interface IWebhookService {
// Verify webhook signature
verifySignature(payload: string, sig: string): boolean;
// Parse webhook into normalized event
parseWebhook(payload: string): ProviderWebhookEvent | null;
// Check for duplicate events
isDuplicate(eventId: string): Promise<boolean>;
}Internal Event Types
Provider webhooks are normalized into these internal event types:
| Event | Description |
|---|---|
| payment.succeeded | Payment completed successfully |
| payment.failed | Payment failed or was declined |
| refund.succeeded | Refund processed successfully |
| refund.failed | Refund processing failed |
| transfer.succeeded | Seller payout completed |
| transfer.failed | Seller payout failed |
| account.updated | Seller account status changed |
Fee Structure
Platform Fee
1%
Minimum $1.00
Stripe Fee
2.9% + $0.30
Per transaction
// Fee calculation (centralized in lib/providers/constants.ts) const platformFee = Math.max( Math.round(amountCents * 0.01), // 1% 100 // Minimum $1.00 ); const sellerReceives = amountCents - platformFee;
Provider-Neutral Schema
The database stores both provider-specific and provider-neutral identifiers:
-- payments table provider TEXT DEFAULT 'stripe' -- Provider identifier external_payment_id TEXT -- Provider-neutral reference stripe_payment_intent_id TEXT -- Stripe-specific (legacy support) -- settlement_receipts table provider TEXT DEFAULT 'stripe' external_transfer_id TEXT -- Provider-neutral payout ref external_refund_id TEXT -- Provider-neutral refund ref
Adding New Providers
To add a new payment provider, implement these services:
lib/providers/[name]/funding-service.tslib/providers/[name]/settlement-service.tslib/providers/[name]/webhook-service.ts/api/webhooks/[name]/route.tsACTIVE_PROVIDER in constants