Marketplace Payment
How manual-first marketplace payment confirmation works and which provider automation promises are gated.
Marketplace Payment
Marketplace payment is manual-first and enterprise-gated. The goal is to let a buyer choose a quote, create an order, have manual payment proof reviewed by operations, and open the production gate in a controlled way.
Enterprise-gated scope
Card payment, provider payment automation, automatic refunds, disputes money movement, and provider payout execution are gated. They are not public-enabled until live provider, compliance, reconciliation, help/docs, runtime, and clean CI evidence are green.
Marketplace payment and order mutations use server-side idempotency. Retrying the same action should return the first recorded response; reusing the same key with a changed request is rejected instead of creating duplicate work.
Manual-first flow
- The buyer compares quotes.
- The buyer chooses one quote.
- The order is created with
payment_pendingandnot_startedproduction state. - The buyer shares proof or terms for bank transfer, open account, or agreed corporate payment.
- Operations or finance admin manually approves or rejects the payment.
- Approval moves the order payment status to
approvedand opens the production gate. - Production can move to
in_productiononly after payment approval. - PrintTalk, print-shop bridge jobs, PDF Tools, Edge Hub, XJDF execution, and fulfillment remain out of scope for this phase.
Supported public methods
The public/self-service payment surface keeps methods narrow:
- Bank transfer
- Open account
- Manual payment approval by operations
document_payment, check, deferred_terms, and direct_deal exist as supplier-terms contract vocabulary in the marketplace package. They are not public checkout choices; they require an operator-approved corporate terms or import scenario.
Evidence and retry guarantees
Payment verification, supplier terms confirmation, and production-stage updates use server-side idempotency. A retry returns the first recorded response; reusing the same key with changed content is rejected. If a committed response carries x-marketplace-idempotency-recovery, keep the same key and exact request body: retryable means an exact retry may start immediately, while lease-pending means abandoned transport ownership will be reclaimed after its bounded lease. Response and audit summaries do not expose raw idempotency keys, actor ids, provider secrets, or local file paths.
For manual payment verification, 409 means the order changed and operations
must refresh before deciding again. A retryable 503 means the durable command
could not reach its store; retry the exact request with the same key. A
non-retryable integrity response requires operator investigation and must not
be converted into an automatic retry loop. Payment event and outbox evidence
store only the command/key hash, not the raw client key.
Marketplace APIs also use a shared distributed admission limit before route processing. A 429 response includes Retry-After; wait for that duration and retry the same idempotent request without changing its key or body. A 503 MARKETPLACE_ADMISSION_UNAVAILABLE is fail-closed protection: do not start a new payment attempt, and retry the exact request after the indicated delay. No raw client IP is stored by this control.
The gated card rail has one provider-neutral initiation boundary and one Iyzico return boundary. Iyzico returns only a Checkout Form token to the callback; the server retrieves the result from Iyzico, validates Iyzico's ordered HMAC-SHA256 response signature, and binds order, basket, amount, currency, and replay state to the server-side checkout intent before any payment effect. Custom callback IP allowlists, timestamp headers, and parallel callback routes are not payment authorities.
The intent stores the provider token only as an encrypted value at a hash-based address. It also keeps the accepted legal-document versions, acceptance time, actor, and order/quote/RFQ binding. Raw provider tokens and raw idempotency keys are not written into settlement or audit evidence.
Before contacting Iyzico, the server takes a short-lived order-level checkout lease. A second request cannot expose another live card form for the same order, even when it uses a different idempotency key. The provider call has a bounded timeout, and callback and reconciliation both execute the same verification and settlement command.
Reconciliation starts from the provider checkout's explicit expiry, not from
how old the database row is, and waits a two-minute clock/network grace before
retrieving the final provider result. Expired intents are read in stable
expiry/document-id cursor pages with an eight-page and five-minute pass budget.
A structurally malformed initialized row is atomically failed, together with
its matching lease when that binding can still be proven, so it cannot pin
later payments behind the first query page. If Iyzico reports SUCCESS but callback
binding or settlement cannot be proven safe, the intent and its matching order
lease become manual_review. That durable receipt keeps the provider payment
identifier plus hashed payment/event evidence and a bounded reason code; it
must be investigated rather than downgraded to an ordinary failed checkout.
The browser supplies the buyer's consent signal, but it is not the authority for document titles, links, locale, version, or acceptance time. The server rebuilds that evidence from the canonical legal-document set and its own clock. Production Iyzico initialization also requires canonical buyer identity, address, city, and a trusted client IP; missing evidence keeps the rail fail-closed.
Internally, every captured provider callback path must co-commit one provider inbox receipt, balanced settlement journal and postings, reconciliation result, restricted audit record, and durable payment event with the payment/order update. Notifications and other follow-up work start only after that transaction succeeds; the durable event remains the recovery authority if a later effect is unavailable. Provider tokens, event identifiers, and callback bodies are stored in settlement evidence only as hashes. This preparation is an integrity control; it does not mean card checkout is public-enabled.
The journal also carries a versioned settlement lifecycle snapshot. Captured evidence reaches reconciled only through a valid optimistic-revision transition, while the snapshot keeps automation quarantined and payout authorization false. Reconciliation is therefore accounting evidence, not permission to pay a supplier or activate an online rail.
Provider inbox records, settlement journal/posting records, reconciliation snapshots, and the settlement-event copy required for exact replay are classified as financial evidence. The delivery outbox may reset with pilot aggregates, but this evidence is excluded from bulk marketplace resets; corrections require new traceable records.
Refund and chargeback evidence never rewrites the captured-payment journal. Finance records a new balanced reversal journal against the exact payment revision. Duplicate provider events, changed event bodies, currency drift, allocation mismatch, and cumulative reversals above the captured amount are rejected. If supplier payout has already happened, supplier recovery is recorded as a receivable and the case remains on payout hold for manual review. This ledger preparation does not start a provider refund, chargeback, transfer reversal, or payout automatically.
Not promised in this phase
- Card checkout
- Automated supplier payout execution
- Automatic payment provider integration
- Automatic refund or payment dispute screens
- Automatic production or handoff after payment confirmation
Provider-neutral contracts may exist behind the gated package surface, but they are not public enablement. These capabilities are not part of the current public promise.
The exported refund request seam currently returns
PROVIDER_REFUND_CAPABILITY_UNAVAILABLE without creating a refund record,
calling a provider, or inventing a provider refund identifier. A missing,
unknown, replayed, mismatched, or incorrectly signed Iyzico result is rejected
before payment or order effects.
When does an order enter production?
An order existing does not by itself mean production has started. Payment approval opens the production-release gate; only after that can operations advance the production state. Automatic print-shop job creation and fulfillment integration are not promised in this pilot.
Was this article helpful?
Related articles
Last updated on