Marketplace flows separate order, payment, payout, refund, and dispute states with explicit handling for uncertain payment-provider outcomes so partial failures never double-charge or double-pay sellers.
Package status: AI-assisted reference package. Static package validation has passed; implementation scenarios remain not run and human domain review is required before stable adoption.
Decision
Marketplace commerce is modeled as loosely coupled state machines for order fulfillment, buyer payment capture, seller payout, refunds, and disputes. Each machine exposes explicit transitions and guards; uncertain outcomes from external payment providers land in investigation states with idempotent reconciliation rather than assuming success or failure. Payout cannot proceed from ambiguous payment state. Refunds reference original capture ids and cannot exceed captured totals across partial refunds.
Scope
- State definitions and allowed transitions for order, payment, payout, refund, dispute.
- Provider uncertainty handling, webhook idempotency, and reconciliation jobs.
- Compensation when payout succeeded but later chargeback arrives.
- Audit fields linking entities: order_id, payment_intent_id, payout_id, refund_id.
- Metrics on stuck uncertain states and duplicate provider event suppression.
Outside this block
- Tax calculation and invoicing formatting.
- Seller onboarding KYC legal requirements.
- Product catalog search.
Contract
- Order, payment, payout, refund, and dispute states are stored separately; composite views are derived, not authoritative.
- Payment capture success is recorded only on provider-confirmed terminal event or reconciled equivalent.
- Uncertain provider outcomes enter provider_pending or provider_unknown until reconciliation; payout guard blocks until payment is captured.
- Refund transitions require captured payment reference and enforce remaining refundable balance.
- Dispute opening freezes payout release for affected capture until resolved, escalated to operator-review-required after profile timeout, or explicitly closed; timeout alone does not auto-release payout unless a separately reviewed policy enables it.
- Provider webhook handlers are idempotent on provider event id; duplicates do not double-capture or double-payout.
- Chargeback after payout moves payout to clawback-pending rather than silently negative balance without audit.
Implementation guidance
- Use outbox or saga orchestration for cross-entity transitions with compensating actions documented.
- Run scheduled reconciliation against provider APIs for unknown states beyond profile SLA.
- Never infer success from client-side redirect alone.
Failure handling and safeguards
- If payout worker fails after provider success, retry with same payout id until terminal state.
- Manual operator overrides require dual control and immutable audit reason.
- Block duplicate order submission with same client reference key; replays return the original order outcome.
- Payout worker retries use the same payout_id until terminal state without double transfer.
Verification and operations
- Monitor age of provider_unknown records, duplicate webhook suppression count, and clawback backlog.
- Reconcile daily totals between internal ledger and provider reports.
- Execute acceptance scenarios in the target repository; packaged scenarios are not executed evidence.
Adoption assumptions
- Provider names and SLA minutes in fixtures are profile choices, not vendor guarantees.
- Teams map payment processors and ledger accounts locally with finance review.