diff --git a/docs/specification/order.md b/docs/specification/order.md index e28e79338..5197e946c 100644 --- a/docs/specification/order.md +++ b/docs/specification/order.md @@ -87,6 +87,24 @@ Expectations can be split, merged, or adjusted post-order. For example: (common examples: `processing`, `shipped`, `in_transit`, `delivered`, `failed_attempt`, `canceled`, `undeliverable`, `returned_to_sender`) +### Payment + +**Payment** describes how the order was paid, suitable for rendering on an +order confirmation. Like the rest of the order it reflects current state, so +it may change post-purchase (e.g. an order edit that adds or changes a tender). + +Each instrument reuses the base checkout +[Payment Instrument](checkout.md#payment), adjusted for the order context: + +* `display` is required — it is the buyer-facing record of the tender +* `handler_id` and selection state are absent; handler routing is a + Checkout processing concern, not an order property +* Credentials are never returned in responses (see + [Credential Flow & PCI Scope](overview.md#credential-flow-pci-scope)); + businesses omit `credential` on the order +* `amount` reports the amount charged to the instrument, in the order + currency's minor units (ISO 4217) + ### Attribution Businesses MAY surface a snapshot of the originating checkout's @@ -141,6 +159,16 @@ else if (fulfilled > 0) → "partial" else → "processing" ``` +### Payment Instrument + +Each instrument represents a single tender used on the order. It uses the +shared base Payment Instrument — handler instrument schemas extend the base +once and apply in both Checkout and Order contexts — with `display` required +and an order-specific `amount` reporting the charge in the order currency's +minor units (ISO 4217). + +{{ schema_fields('types/payment_instrument', 'order') }} + ### Expectation Expectations are buyer-facing groupings representing when/how items will be @@ -251,6 +279,36 @@ Examples: `refund`, `return`, `credit`, `price_adjustment`, `dispute`, } ] }, + "payment": { + "instruments": [ + { + "id": "pi_gift", + "type": "gift_card", + "amount": 5000, + "display": { + "description": "Gift card", + "last_digits": "9821" + } + }, + { + "id": "pi_card", + "type": "card", + "amount": 10342, + "billing_address": { + "street_address": "123 Main St", + "address_locality": "Austin", + "address_region": "TX", + "address_country": "US", + "postal_code": "78701" + }, + "display": { + "brand": "visa", + "last_digits": "4242", + "description": "Visa ending in 4242" + } + } + ] + }, "adjustments": [ { "id": "adj_1", diff --git a/docs/specification/payment-handler-guide.md b/docs/specification/payment-handler-guide.md index fa79966bb..b9b6fb76a 100644 --- a/docs/specification/payment-handler-guide.md +++ b/docs/specification/payment-handler-guide.md @@ -496,15 +496,21 @@ Each variant has its own config schema tailored to its context: **Base Instrument Schemas:** -| Schema | Description | -| :----------------------------------------------------------------------------------------- | :--------------------------------------------------------------- | -| [`payment_instrument.json`](site:schemas/shopping/types/payment_instrument.json) | Base: id, handler_id, type, billing_address, credential, display | -| [`card_payment_instrument.json`](site:schemas/shopping/types/card_payment_instrument.json) | Extends base with display: brand, last_digits, expiry, card art | - -UCP provides base schemas for universal payment instruments like `card`. Spec -authors **MAY** extend any of the base instruments to add handler-specific -display data or customize the credential reference. Handlers **MAY** define -multiple instrument types for different payment flows. +| Schema | Description | +| :------------------------------------------------------------------------------------------ | :----------------------------------------------------------------- | +| [`payment_instrument.json`](site:schemas/shopping/types/payment_instrument.json) | Entity-agnostic base: id, type, billing_address, credential, display | +| `payment_instrument.json#/$defs/selected_payment_instrument` | Checkout context: base plus required handler routing and selection state | +| [`card_payment_instrument.json`](site:schemas/shopping/types/card_payment_instrument.json) | Extends base with display: brand, last_digits, expiry, card art | + +UCP provides base schemas for universal payment instruments like `card`. +Handler instrument schemas extend the entity-agnostic base once to add +handler-specific display data or customize the credential reference; the same +schema then applies wherever instruments surface. Containing capabilities add +their own context: Checkout uses `selected_payment_instrument` to require +`handler_id` and add selection state, while Order uses the base without +processing-time routing. Handler authors **MUST NOT** redeclare routing fields +in their instrument schemas. Handlers **MAY** define multiple instrument types +for different payment flows. **Available Instrument Schemas:** diff --git a/source/schemas/shopping/order.json b/source/schemas/shopping/order.json index 51b0b41bc..fa47d6bb1 100644 --- a/source/schemas/shopping/order.json +++ b/source/schemas/shopping/order.json @@ -80,6 +80,31 @@ }, "description": "Fulfillment data: buyer expectations and what actually happened." }, + "payment": { + "type": "object", + "description": "How the order was paid. Reflects current state and may change post-purchase (e.g. order edits). Present when the business surfaces payment details on the order.", + "properties": { + "instruments": { + "type": "array", + "items": { + "allOf": [ + { "$ref": "types/payment_instrument.json" }, + { + "type": "object", + "required": ["display"], + "properties": { + "amount": { + "$ref": "../common/types/amount.json", + "description": "The amount charged to this instrument, in the order currency's minor units (ISO 4217)." + } + } + } + ] + }, + "description": "The payment instruments used on the order." + } + } + }, "adjustments": { "type": "array", "items": { diff --git a/source/schemas/shopping/types/payment_instrument.json b/source/schemas/shopping/types/payment_instrument.json index 1d70fda36..40314caf4 100644 --- a/source/schemas/shopping/types/payment_instrument.json +++ b/source/schemas/shopping/types/payment_instrument.json @@ -2,11 +2,10 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://ucp.dev/schemas/shopping/types/payment_instrument.json", "title": "Payment Instrument", - "description": "The base definition for any payment instrument. It links the instrument to a specific payment handler.", + "description": "The entity-agnostic base for a payment instrument. Payment handlers extend this schema once with their concrete credential, display, and instrument-specific fields; containing capabilities add contextual fields (e.g. Checkout adds handler routing and selection state).", "type": "object", "required": [ "id", - "handler_id", "type" ], "properties": { @@ -14,10 +13,6 @@ "type": "string", "description": "A unique identifier for this instrument instance, assigned by the platform." }, - "handler_id": { - "type": "string", - "description": "The unique identifier for the handler instance that produced this instrument. This corresponds to the 'id' field in the Payment Handler definition." - }, "type": { "type": "string", "description": "The broad category of the instrument (e.g., 'card', 'tokenized_card'). Specific schemas will constrain this to a constant value." @@ -38,12 +33,17 @@ "$defs": { "selected_payment_instrument": { "title": "Selected Payment Instrument", - "description": "A payment instrument with selection state.", + "description": "A Checkout payment instrument with handler routing and selection state.", "allOf": [ { "$ref": "#" }, { "type": "object", + "required": ["handler_id"], "properties": { + "handler_id": { + "type": "string", + "description": "The unique identifier for the handler instance that produced this instrument. This corresponds to the 'id' field in the Payment Handler definition." + }, "selected": { "type": "boolean", "description": "Whether this instrument is selected by the user."