Markdown Editor

E-commerce Checkout and Inventory System Design Template

Cart, quote boundary for pricing, tax and promotions, stock reservation, oversell prevention, payment handoff, order state machine, flash-sale throttling

系统设计完整designecommercecheckoutinventory

使用方法: Use it when designing cart, checkout and stock for an online store or commerce platform. Fill the invariants (2.2), reservation timing (7.2) and oversell control (7.3) first. The main pitfall is computing totals in several services, so the charged amount differs from what the shopper saw.

预览

System Design: [Commerce platform name] cart, checkout and inventory

Reference design for the cart, checkout and inventory core of an online store or multi-merchant commerce platform. It covers cart storage, price and tax quotes with clear boundaries to pricing, tax and promotion services, stock reservation across warehouses, oversell prevention, the payment handoff, the order state machine, and flash-sale throttling with a checkout queue. It follows the structure of the System Design Document template and is pre-filled with a worked design to adapt. Replace every [bracketed] value and every row marked Example; values marked Example are assumptions, not benchmarks. This is an engineering format, not tax, consumer-protection or payment-compliance advice.

Document control

FieldValue
Document ID[SDD-CHK-001]
System / feature[Cart, checkout and inventory]
Version[0.1]
Status[Draft / In review / Approved / Implemented / Superseded]
Owner[@owner]
Author(s)[@author]
Approvers / reviewers[@reviewer-1], [@reviewer-2]
Last updatedYYYY-MM-DD
Classification[Internal]
Selling model[Single store / marketplace / multi-tenant platform]
Related[PRD], [Payment ledger design], [Fraud design], [Tax engine contract], [Threat model]

Approvals

RoleNameDecisionDate
Tech lead[@name][Approved / Changes requested]YYYY-MM-DD
Staff / principal engineer[@name][Decision]YYYY-MM-DD
Merchandising and pricing[@name][Decision]YYYY-MM-DD
Fulfilment and warehouse[@name][Decision]YYYY-MM-DD
Payments[@name][Decision]YYYY-MM-DD
SRE / operations[@name][Decision]YYYY-MM-DD

Revision history

VersionDateAuthorChange summary
0.1YYYY-MM-DD[@name]First draft for design review
0.2YYYY-MM-DD[@name]Example: Moved reservation from add-to-cart to checkout start
0.3YYYY-MM-DD[@name]Example: Added edge checkout throttle for flash sales
1.0YYYY-MM-DD[@name]Example: Approved

Contents

1. Overview

1.1 Problem statement

[Example: We run 40 000 stores on one platform. During a sneaker drop last spring one store sold 1 400 pairs it did not have, because stock was decremented after payment and two checkout pods read the same count. The same drop sent write traffic to the shared order database that slowed checkout for every store on that shard for 25 minutes. Promotions are computed in three places, so the cart, the review page and the receipt sometimes show different totals, and support refunds the difference by hand.]

1.2 Proposed solution

[Example: A quote service is the only place that computes a total: it calls pricing, promotions and tax and returns a signed, versioned quote. Checkout reserves stock for the quoted lines with a conditional decrement and a 10-minute expiry when the customer starts checkout. Payment is authorised against the quote; the order is created in placed and moves through an explicit state machine to fulfilment. Stock is held per SKU and location in an inventory service partitioned by SKU. Flash sales are recognised ahead of time; a throttle at the edge admits shoppers into checkout at the rate the hot SKU partition and the payment provider can absorb, and everyone else waits on a cached queue page.]

1.3 Decisions requested from reviewers

IDQuestionRecommended optionSection
Q-01Example: When to reserve stock?At checkout start, 10-minute TTL, re-validated at payment7.2
Q-02Example: Oversell prevention mechanism?Conditional decrement on SKU-location row; sharded counters for drop SKUs7.3
Q-03Example: Payment order?Authorise, create order, commit reservation, capture at shipment7.4
Q-04Example: Flash-sale control?Edge throttle with signed pass, enabled per store or SKU7.5
Q-05Example: Price lock duration?Quote valid 30 minutes; recompute and show changes after expiry7.1
[Q-nn][Question][Option][Section]

1.4 45-minute interview path

MinuteCoverNotes
0 to 5Scope: single store or platform, physical goods, number of warehousesName the oversell invariant
5 to 10Core requirements; below the line (search, recommendations, returns)Agree reservation timing as an open question
10 to 15Estimates with consequences (3.5)Show that normal traffic is easy and the drop is not
15 to 20API and data model with access patternsCart, quote, reservation, order
20 to 30High-level design, then deep dive 1: oversell prevention (7.3)Compare locks, conditional writes, sharded counters, queue per SKU
30 to 40Deep dive 2: flash-sale throttling (7.5) or order state machine (7.4)Pick throttling if the interviewer mentions drops or launches
40 to 45Failure modes, 10x and 0.1xClose on payment handoff and reconciliation

2. Requirements

2.1 Core functional requirements

IDRequirementPriority
FR-01Example: Add, update and remove items in a cart for signed-in and guest shoppersMust
FR-02Example: Show a quote with item prices, discounts, shipping, tax and totalMust
FR-03Example: Reserve stock when checkout starts and release it on expiry or abandonmentMust
FR-04Example: Choose shipping address and method; select fulfilment locationMust
FR-05Example: Pay through the payment service; place the order exactly onceMust
FR-06Example: Track order status through fulfilment, shipment, delivery and cancellationMust
FR-07Example: Limit quantity per customer for flagged SKUsMust
FR-08Example: Throttle checkout and queue shoppers during flash salesMust
FR-09Example: Allow pre-orders and backorders with explicit customer consentShould
[FR-nn][Requirement][Must / Should / Could]

2.2 Non-functional requirements and invariants

IDQualityTargetMeasured as
NFR-01No oversellExample: Units committed per SKU-location never exceed on-hand plus approved backorderNightly audit; real-time negative stock alert
NFR-02Price integrityExample: Captured amount equals the accepted quote totalDaily reconciliation of quotes to captures
NFR-03No lost paid orderExample: Every authorised payment maps to one order or one voidReconciliation with payment service
NFR-04Checkout latencyExample: Place-order p99 at or below 1.2 s excluding 3-D SecureService timing
NFR-05IsolationExample: A flash sale in one store raises p99 of other stores by no more than 10%Per-tenant latency dashboards
NFR-06AvailabilityExample: 99.95% for cart and checkoutSLO
NFR-07Reservation hygieneExample: Expired reservations released within 30 s p99Sweeper lag
[NFR-nn][Quality][Target][Measurement]

2.3 Below the line (out of scope)

  • [Example: product search and recommendations (see Recommendation System Design (system-design/design-recommendation-system))]
  • [Example: pricing algorithms and promotion authoring (consumed through the quote boundary)]
  • [Example: tax rule content (consumed from a tax engine)]
  • [Example: returns and exchanges workflow]
  • [Example: the payment ledger (see Payment Ledger System Design (system-design/design-payment-ledger))]
  • [Example: warehouse management and picking]
  • [Item deferred, with the release that will take it]

3. Capacity estimation

3.1 Assumptions

InputValueSource
Orders per day (normal)Example: 3 millionPlatform analytics
Cart writes per orderExample: 8Funnel data (adds, updates, removals)
Checkout starts per orderExample: 2.5Conversion from checkout start to order
Peak to average ratio (normal day)Example: 4Evening peak
Drop: shoppers arriving in first minuteExample: 600 000Store forecast
Drop: units availableExample: 20 000, limit 1 per customerMerchant
Payment provider authorisations per second available to the platformExample: 2 000Provider contract

3.2 Normal traffic

QuantityCalculationResultConsequence
Average orders/s3 million / 86 400about 35/sOrder writes are small
Peak orders/s35 x 4about 140/sOne sharded order store with headroom
Peak cart writes/s140 x 8about 1 100/sCart in a key-value store, not the order database
Peak checkout starts (reservations)/s140 x 2.5350/sReservations spread across many SKUs; little contention

3.3 Flash-sale traffic

QuantityCalculationResultConsequence
Arrival rate first minute600 000 / 6010 000 shoppers/sCannot all enter checkout: throttle at the edge
Orders to sell out20 000 units / 1 per order20 000 ordersSale is decided in seconds to minutes
Admission rate if payment is the ceiling for this storeExample: 25% of 2 000 auth/s reserved for one store500 orders/sSell-out in about 40 s at full admission
Writes on the drop SKU row500 reservation attempts/s, retries x 1.5750/s on one rowOne row with locks is too slow: sharded stock counters (7.3)

3.4 Storage

QuantityCalculationResultConsequence
Orders per year3 million x 365about 1.1 billionPartition orders by store and month
Order size with linesExample: 4 KBabout 4.4 TB/yearArchive closed orders after 2 years to cheaper storage
SKU-location rowsExample: 50 million SKUs x 1.5 locations75 million rowsInventory fits a sharded store partitioned by SKU

3.5 Summary

QuantityEstimateDesign consequence
Normal checkout140 orders/sSimple; correctness, not scale, drives design
Drop arrivals10 000 shoppers/sEdge throttle and cached queue page
Hot SKU writes750/s on one SKUSharded counters or single-writer queue per SKU
Payment ceiling2 000 auth/s platform-widePer-store admission share protects other tenants (NFR-05)

4. API design

4.1 Endpoints

Method and pathPurposeIdempotent
PUT /v1/carts/{id}/lines/{sku}Set quantity of a SKUYes (set semantics)
GET /v1/carts/{id}Cart with indicative pricesYes (read)
POST /v1/checkoutsStart checkout from a cart: create quote and reservationsYes, with Idempotency-Key
PATCH /v1/checkouts/{id}Set address, shipping method; returns a new quote versionYes (set semantics)
POST /v1/checkouts/{id}/place-orderAuthorise payment and create order for quote version NYes, with Idempotency-Key
GET /v1/orders/{id}Order and status historyYes (read)
POST /v1/orders/{id}/cancelCancel if state allowsYes, with Idempotency-Key

4.2 Request and response examples

POST /v1/checkouts/chk_31b9/place-order
Idempotency-Key: 0d9e6f12-7a44-4c1b-8e3f-5b2a9c7d1e08
Authorization: Bearer [token]
Content-Type: application/json

{"quote_id": "q_31b9_v3", "payment_method": "pm_tok_8f2", "accepted_total": {"value": 12999, "currency": "USD"}}
HTTP/1.1 201 Created
Content-Type: application/json

{"order_id": "ord_7e21", "status": "placed", "total": {"value": 12999, "currency": "USD"}}

The client sends the total it displayed. If the server's quote total differs, place-order fails with 409 quote-changed and returns the new quote, so the customer is never charged an amount they did not see (NFR-02).

4.3 Errors

Errors use RFC 9457 problem details.

StatusProblem typeMeaning
409quote-changedPrice, tax or promotion changed; new quote attached
409out-of-stockReservation failed for listed lines; alternatives attached
410reservation-expiredCheckout took longer than the TTL
402payment-declinedProvider declined; reservation kept until TTL for retry
429checkout-queuedFlash-sale throttle; body carries the queue page URL
403quantity-limitPer-customer limit reached

5. Data model

5.1 Entities

The cart is indicative and cheap; the quote, reservation and order are authoritative. Stock is counted inventory, one row per SKU and location.

5.2 Storage choices and invariants

DataStorePartition keyInvariant enforced by
CartsExample: Key-value store with TTL 30 dayscart_idNone (indicative only)
QuotesDocument store, immutable versionscheckout_idSigned hash of lines, prices and versions
StockSharded relational or key-value store with conditional writesskureserved + qty <= on_hand + backorder_allowed in the update predicate
ReservationsSame shard as the stock rowskuStatus machine; expiry swept
Orders, lines, eventsSharded relationalstore_id then order_idAllowed transitions table (7.4); outbox in same transaction
Idempotency recordsSame shard as ordersstore_id, keyUnique constraint

5.3 Access patterns

IDQueryServed byPartition key rationale
AP-01Example: Read cartcart_id lookupSingle key; cart never joins
AP-02Example: Reserve qty of SKU at best locationConditional update on stock(sku, location_id)All locations of one SKU on one shard so location fallback is local
AP-03Example: Release expired reservationsIndex on (expires_at) per shardSweeper scans its own shard
AP-04Example: Place order and record payment referenceInsert into order on store shardStore-level reports and isolation (NFR-05)
AP-05Example: Customer's order historySecondary index customer_id in a read modelAvoids cross-shard scans on the primary
AP-06Example: Stock level for product pageCached availability projectionProduct page never touches the stock row

6. High-level design

ComponentResponsibilityScales by
Edge throttleAdmit shoppers into checkout per store or SKU; issue signed passEdge workers
Quote serviceSingle source of totals; signs quotesHorizontally; caches pricing
Inventory serviceReserve, commit, release stockSKU shards
Order serviceCreate order, run state machine, publish eventsStore shards
Payment serviceAuthorise, capture, void, refundHorizontally; provider limits
Availability projectionProduct-page stock indicatorsCache

7. Detailed design

7.1 Quote boundary: pricing, tax and promotions

  • The quote service owns the arithmetic: list price from pricing, discounts from promotions in a fixed evaluation order, shipping, then tax on the discounted amounts according to the tax engine's rules.
  • A quote is immutable. Any change (address, shipping, quantity) creates a new version. The quote records the versions of the price list, promotion set and tax rules it used.
  • Promotions with limited redemptions (first 1 000 uses) are reserved like stock at checkout start and committed at order placement.
  • Rounding happens once, in the quote, per the tax engine's rule (per line or per invoice). No other service rounds.

Options: compute totals in checkout; compute in each service and sum; central quote. Choice: central quote. Reason: one place to test and audit totals, and NFR-02 becomes a comparison of two numbers.

7.2 Deep dive: when to reserve stock

OptionBenefitCost
At add-to-cartShopper sees guaranteed stock earlyAbandoned carts lock stock for hours; easy denial of inventory by bots
At checkout start (TTL)Short holds tied to intent; fair at drop timeShopper can lose items between cart and checkout
At payment authorisationNo wasteMany shoppers pay for items that are gone; refunds and anger
At order placement without holdSimplestOversell under concurrency unless the decrement is conditional

Choice: reserve at checkout start with a Example 10-minute TTL, extendable once during 3-D Secure, and re-validate the reservation at place-order. Reason: it binds stock to real intent, bounds waste and lets the cart stay a cheap, non-authoritative store.

7.3 Deep dive: oversell prevention under contention

OptionHow it worksFits
Row lock (SELECT ... FOR UPDATE)Serialise reservations on the SKU rowLow traffic only; lock queue under drops
Conditional decrementUPDATE stock SET reserved = reserved + :q WHERE sku = :s AND location_id = :l AND reserved + :q <= on_hand + backorder_allowedNormal traffic: one statement, no read-then-write gap
Sharded countersSplit a drop SKU's stock into K buckets; reserve from a random bucket, try the next on failureDrop SKUs: parallel writes, small leftover fragmentation
Single-writer queue per SKUAll reservations for a SKU go through one ordered consumerExtreme contention; adds queue latency
In-memory counter with durable logDecrement in an in-memory store, append to log, reconcileVery high rates; needs careful recovery

Choice: conditional decrement by default; sharded counters (Example K = 8) for SKUs flagged as drops. Reason: 750 writes/s on one row (3.3) exceeds a safe row update rate, while 8 buckets bring each to about 95 writes/s. When most buckets are empty, a final pass merges remaining units into one bucket so the last items still sell.

UPDATE stock_bucket
SET reserved = reserved + :qty, version = version + 1
WHERE sku = :sku AND bucket = :b
  AND reserved + :qty <= on_hand;
-- 0 rows: try next bucket; after K misses return 409 out-of-stock.

7.4 Deep dive: payment handoff and order state machine

Place-order sequence:

  • Options for capture: at order placement; at shipment; split capture per shipment. Choice: capture at shipment for physical goods, at placement for digital goods. Reason: the shopper is never charged for items that cannot ship, and cancellations before shipment are voids, not refunds. Check the authorisation validity period of your card networks and re-authorise if fulfilment is slow.
  • An order that cannot commit its reservations after authorisation (expired meanwhile) attempts to re-reserve; on failure it voids the authorisation and returns 410.
  • Every transition writes an order_event and an outbox row in one transaction; illegal transitions are rejected by a transitions table.

7.5 Deep dive: flash-sale throttling

OptionBenefitCost
Autoscale onlyNo user-facing queueDatabases and payment provider do not autoscale in seconds
Rate limit with 429SimpleShoppers hammer refresh; unfair
Edge throttle with cached queue page and signed passOrigin sees only admitted shoppers; isolates other storesQueue fairness must be designed
Full virtual waiting room with randomised positionsFair at openingMore infrastructure (see Ticket and Hotel Booking System Design (system-design/design-ticket-booking))

Choice: edge throttle with a cached queue page and a signed pass, plus randomised positions for drops announced in advance. Reason: it caps checkout writes per store at the admission rate in 3.3, keeping other tenants within NFR-05, and the queue page costs the origin nothing.

How real systems do it (paraphrased from a public write-up; not copied)

Shopify's engineering blog describes how flash sales on a shared multi-tenant platform produced bursts of checkout writes large enough to hurt other stores on the same database shard. Rather than keep enough capacity running for the worst sale, the team put scripted logic into its Nginx load balancers (OpenResty with Lua): a leaky-bucket style throttle admitted a fixed number of checkout requests per short interval, sent the rest to a queue page cached at the load balancer that polled for entry, and gave admitted shoppers a signed cookie so they were not throttled again during their session. The post is candid that random polling made waits unfair for some shoppers, which led to a later redesign. This template keeps the edge throttle and signed pass and adds ordered or randomised positions to address fairness.

Source: Emil Stolarsky, "Surviving Flashes of High-Write Traffic Using Scriptable Load Balancers (Part I)", Shopify Engineering, 3 February 2017, https://shopify.engineering/surviving-flashes-of-high-write-traffic-using-scriptable-load-balancers-part-i

7.6 Multi-location allocation

The inventory service picks a location at reservation time using a simple rule (Example: nearest location with full quantity, else split shipment if the store allows it). Fulfilment may reallocate later; reallocation moves the reservation between rows of the same SKU on the same shard.

8. Scalability and performance

ConcernApproachLimit before redesign
Hot SKUSharded counters; single-writer queue as fallbackExample: about 300 writes/s per bucket in load test
Tenant isolationPer-store admission share at the edge; order shards by storeLargest store's share of the payment ceiling
Cart writesKey-value store, no transactionsStore throughput
Product page stockAvailability projection, 2-second cacheProjection lag
Quote computationCache price lists and promotion sets by versionTax engine latency

Latency budget for place-order (p99 target 1.2 s):

StepBudget
Quote and reservation verification (60 ms) and fraud check (100 ms) in parallel100 ms
Payment authorisation600 ms
Order creation and reservation commit80 ms
Network and headroom420 ms

9. Reliability, security and operations

9.1 Failure modes

IDComponentFailureDetectionBlast radiusMitigationRTO
FM-01Payment providerTimeoutStep timeoutOrders in flightQuery by key; void if order not createdExample: 10 min
FM-02Inventory shardFailoverError rate per shardSKUs on one shardEdge pauses admission for affected drops; retries with keysExample: 2 min
FM-03Reservation sweeperStalledExpired-but-reserved countStock appears sold outLazy expiry in predicate; restartExample: 5 min
FM-04Tax engineUnavailableError rateAll new quotesCached rules for known addresses; block checkout otherwiseExample: 15 min
FM-05Order outboxStopsOutbox ageFulfilment and emails delayedRestart; consumers dedupeExample: 10 min
FM-06Edge throttleMisconfigured rateAdmission vs order rateOne store or platformPer-store caps with safe defaults; config reviewExample: 5 min
[FM-nn][Component][Failure][Signal][Scope][Mitigation][RTO]

Score these in a Software FMEA (ops/fmea-software).

9.2 Security and abuse

IDThreatControl
SEC-01Bots buying drop stockEdge bot controls, per-customer, per-card and per-address limits, randomised queue
SEC-02Inventory denial through reservationsReservations per session and account limited; short TTL
SEC-03Price tampering in clientServer-side quote with signature; client total only compared
SEC-04Promotion abuseRedemption reservation; per-customer limits; fraud scoring
SEC-05Card testing at checkoutRate limits, fraud scoring (see Payment Fraud Detection System Design (system-design/design-fraud-detection))
[SEC-nn][Threat][Control]

9.3 Observability

SignalMetricAlert threshold
OversellNegative available stock per SKU-locationAny
Quote mismatchquote-changed rate at place-orderAbove 2%
Reservation wasteShare of reservations expiringAbove 70% outside drops
Paid order integrityAuthorisations without orders after 10 minAny
Tenant isolationp99 checkout for non-drop stores during a dropOver NFR-05

10. Trade-offs and alternatives

DecisionOptionsChosenWhyWhat we give up
Reservation timingCart; checkout; paymentCheckout start with TTLIntent-bound, bounded wasteItems can vanish before checkout
Oversell controlLocks; conditional; buckets; queueConditional plus buckets for dropsParallel and exactBucket fragmentation logic
Capture timingPlacement; shipmentShipment (physical)No charge without goodsRe-authorisation for slow fulfilment
TotalsDistributed; central quoteCentral quoteOne auditable numberQuote service is critical path
Drop controlAutoscale; 429; edge throttleEdge throttle with passProtects tenantsShoppers wait
At 10x (1 400 orders/s, 100 000 shoppers/s at drops)More shards; queue per SKUSingle-writer queue per drop SKU, multiple payment providersBucket retries and payment ceiling dominateMore moving parts, provider routing
At 0.1x (14 orders/s)One databaseOne relational database, conditional decrement onlyContention is rareMust re-shard if a drop business grows
[Decision][Options][Chosen][Why][Cost]

11. Delivery plan and risks

11.1 Milestones

MilestoneScopeExit criterionTarget date
M1Quote service as single source of totalsZero quote-to-capture mismatches for 30 daysYYYY-MM-DD
M2Reservations at checkout with conditional decrementNo oversell in a 5 000 concurrent-shopper testYYYY-MM-DD
M3Order state machine with outboxAll transitions covered by tests; reconciliation cleanYYYY-MM-DD
M4Edge throttle and drop SKUs with bucketsRehearsal drop at 2x forecast with NFR-05 metYYYY-MM-DD

11.2 Rollout and rollback

[Example: Enable reservations per store cohort behind a flag. Rollback returns the cohort to decrement-at-order with conditional writes, which is still oversell-safe. Drops are only run on stores already migrated.]

11.3 Risks

IDRiskLikelihoodImpactMitigationOwner
R-01Example: Warehouse on-hand counts are wrong, so reservations promise phantom stockMediumHighCycle counts, safety stock per SKU, Data Contract (ai-data/data-contract) with WMS feed[@name]
R-02Example: Tax engine rounding differs from quote assumptionLowMediumContract tests with engine per jurisdiction[@name]
R-03Example: Long fulfilment exceeds authorisation validityMediumMediumRe-authorise job; capture at placement for preorders with consent[@name]
[R-nn][Risk][L / M / H][L / M / H][Mitigation][@name]

12. Appendices

12.1 Traceability

RequirementDesign elementVerification
NFR-017.3 conditional decrement and bucketsConcurrency test; nightly audit
NFR-027.1 quote; 4.2 accepted totalQuote-capture reconciliation
NFR-037.4 place-order sequenceFault injection on payment timeout
NFR-057.5 per-store admissionDrop rehearsal with tenant latency
[ID][Element][Test]

12.2 Open questions

IDQuestionOwnerDue
OQ-01Example: Should guest carts reserve during drops at all?[@name]YYYY-MM-DD
OQ-02Example: Do we show the queue position or only an estimate?[@name]YYYY-MM-DD
[OQ-nn][Question][@name]YYYY-MM-DD

12.3 Glossary

TermMeaning
QuoteImmutable, signed price calculation for a checkout version
ReservationTemporary claim on stock with an expiry
OversellCommitting more units than sellable stock
DropPre-announced sale of scarce stock with a traffic spike
Sharded counterStock for one SKU split into buckets to allow parallel writes
AuthorisationHold on customer funds before capture

12.4 References

ReferenceUse
Emil Stolarsky, "Surviving Flashes of High-Write Traffic Using Scriptable Load Balancers (Part I)", Shopify Engineering, 2017Edge throttle pattern (7.5); paraphrased
RFC 9457 Problem Details for HTTP APIsError format (4.3)
Ticket and Hotel Booking System Design (system-design/design-ticket-booking)Holds, waiting room, identified inventory
Payment Ledger System Design (system-design/design-payment-ledger)Authorisation, capture and ledger
Distributed Message Queue System Design (system-design/design-message-queue)Outbox and event delivery
Rate Limiter System Design (system-design/design-rate-limiter)Throttle algorithms
Resilience and Load Shedding Design (system-design/resilience-load-shedding-design)Shedding under overload

Standard and licence note

Based on common industry practice for commerce checkout and inventory systems and on the public references in 12.4. Company blogs were used as inspiration only; the text, diagrams and numbers are original and illustrative. Tax, consumer-protection and card-network rules vary by jurisdiction and change; check the current official rules. This is an engineering format, not legal advice. Template licence: MIT.

相关模板