Skip to content

Commit 2bfda8e

Browse files
committed
introduce the payment authentication extension
1 parent 20bb02d commit 2bfda8e

12 files changed

Lines changed: 1090 additions & 0 deletions

File tree

.cspell/custom-words.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
# cspell-specific custom words related to UCP
2+
ACS
3+
AReq
24
Accor
35
Adyen
46
Affirm
@@ -14,10 +16,14 @@ Carrefour
1416
Centricity
1517
Chewy
1618
Commerce
19+
CReq
20+
CRes
1721
Credentialless
22+
DDC
1823
Depot
1924
Diffie
2025
EDITMSG
26+
EMVCo
2127
EWALLET
2228
Ed25519
2329
EdDSA
@@ -40,8 +46,11 @@ Paypal
4046
Petbarn
4147
Prasad
4248
Preorders
49+
PSP
4350
Queensway
4451
Quicktype
52+
RReq
53+
RRes
4554
Sephora
4655
Shopee
4756
Shopify
@@ -127,7 +136,10 @@ streamable
127136
superfences
128137
talla
129138
thibmeu
139+
threeDSCompInd
140+
threeDSMethodData
130141
tracción
142+
transStatus
131143
ttclid
132144
unparseable
133145
upsell

docs/documentation/core-concepts.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ up-to-date list.
184184
| :--- | :--- | :--- |
185185
| `dev.ucp.shopping.discount` | checkout, cart | Discount codes and promotions |
186186
| `dev.ucp.shopping.fulfillment` | checkout | Shipping and delivery options |
187+
| `dev.ucp.shopping.payment_authentication` | checkout | Browser-surface device data collection and 3DS challenges |
187188
| `dev.ucp.shopping.ap2_mandate` | checkout | Non-repudiable authorization for autonomous commerce |
188189
| `dev.ucp.shopping.buyer_consent` | checkout, cart | Explicit consent capture |
189190

docs/specification/examples/platform-tokenizer-payment-handler.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,25 @@ Content-Type: application/json
410410

411411
---
412412

413+
## Runtime Payment Authentication Actions
414+
415+
This handler supports both Action types from the negotiated
416+
[Payment Authentication extension](../payment-authentication.md):
417+
418+
| Action type | Use |
419+
| :---------- | :-- |
420+
| `dev.ucp.payment.device_data_collection` | Collect device/browser data for the selected tokenized instrument. |
421+
| `dev.ucp.payment.three_ds_challenge` | Present a buyer-facing 3DS challenge during payment completion. |
422+
423+
When either step is needed, the Business returns the corresponding Action while
424+
processing the selected instrument. Its `config.payment_instrument_id` identifies
425+
that instrument, from which the Platform resolves this handler and its trust
426+
policy. The Platform processes the Action according to the extension and
427+
retrieves Checkout after `action.done`. The submitted token and instrument remain
428+
unchanged; the Business determines the payment outcome from its provider state.
429+
430+
---
431+
413432
## PSP Integration
414433

415434
### Prerequisites
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
<!--
2+
Copyright 2026 UCP Authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
-->
16+
17+
# Payment Device Data Collection Action
18+
19+
This specification defines the device data collection Action type declared by
20+
the [Payment Authentication extension](../payment-authentication.md):
21+
22+
```text
23+
dev.ucp.payment.device_data_collection
24+
```
25+
26+
It asks the Platform to run a scoped, invisible browser-capable surface associated
27+
with a payment instrument or attempt.
28+
29+
## Purpose and Scope
30+
31+
Device data collection lets a Business, payment handler, PSP, or 3DS provider
32+
collect device or browser data before payment processing continues. UCP does not
33+
carry the collected data. The loaded surface sends provider-specific data directly
34+
to the Business or payment provider through its own integration.
35+
36+
For EMV 3DS, this Action represents only the Platform-facing instruction to
37+
mount the collection surface. UCP does not define how a Business maps ACS method
38+
availability, method timeouts, or collection outcomes into EMVCo state such as
39+
`threeDSCompInd`. If a provider or Business skips collection, including when an
40+
ACS supplies no method URL, the Business does not emit this Action.
41+
42+
## Emission and Gated Effect
43+
44+
A Business **MAY** emit this type from a Create, Update, or Complete Checkout
45+
response after it can associate collection with a payment instrument and
46+
negotiated payment handler. `config.payment_instrument_id` identifies that
47+
instrument.
48+
49+
The Action gates advancement of the associated payment attempt while the
50+
occurrence remains outstanding in the authoritative Checkout. A terminal surface
51+
event starts reconciliation; it does not itself lift the gate or assert that
52+
collection succeeded. If collection is merely an optimization that the Business
53+
will not wait for, the Business **MUST NOT** emit an Action.
54+
55+
## Runtime Shape
56+
57+
The Action is emitted under its type key:
58+
59+
<!-- ucp:example schema=shopping/payment_authentication def=dev.ucp.shopping.checkout extract=$.actions target=$.actions op=read -->
60+
```json
61+
{
62+
"actions": {
63+
"dev.ucp.payment.device_data_collection": [
64+
{
65+
"id": "ddc-1",
66+
"config": {
67+
"payment_instrument_id": "instrument_1",
68+
"url": "https://payments.example.com/ucp/payment/ddc/session_123"
69+
}
70+
}
71+
]
72+
}
73+
}
74+
```
75+
76+
The config shape is defined inline by the
77+
[Payment Authentication extension schema](site:schemas/shopping/payment_authentication.json).
78+
79+
| Field | Type | Required | Notes |
80+
| :---- | :--- | :------- | :---- |
81+
| `payment_instrument_id` | string || ID of the associated instrument in the containing Checkout. |
82+
| `url` | string || Absolute HTTPS URL for the invisible collection surface. |
83+
84+
The Business **SHOULD** provide a Business- or provider-operated wrapper URL that
85+
owns any provider-specific POST, such as posting `threeDSMethodData` to an ACS
86+
method URL. The Platform performs an ordinary navigation to `config.url`.
87+
88+
## Platform Behavior
89+
90+
The Platform **MUST**:
91+
92+
1. validate the URL according to the Payment Authentication contract, the
93+
payment handler and instrument context, and Platform policy;
94+
2. load the URL in an isolated, invisible browser-capable surface;
95+
3. complete the `action.ready` handshake before allowing collection to begin;
96+
4. correlate embedded notifications with both this Action occurrence and the
97+
mounted surface; and
98+
5. unmount the surface after `action.done`, `action.error`, load failure, or
99+
timeout.
100+
101+
Mounting the surface **MUST** follow the shared
102+
[Payment Authentication rendering contract](../payment-authentication.md#surface-rendering-and-notifications)
103+
and [Embedded Protocol security requirements](../embedded-protocol.md#security).
104+
105+
On the web the surface is typically a hidden iframe. A native Platform may use
106+
an isolated webview or equivalent browser surface. It must not be visible to the
107+
Buyer or request Buyer interaction.
108+
109+
The Platform distinguishes only whether its surface finished or could not
110+
continue. It does not determine whether device data was collected successfully,
111+
whether an ACS method timed out, or whether 3DS authentication should proceed.
112+
113+
## Embedded Notifications
114+
115+
After completing the shared
116+
[`action.ready` handshake](../payment-authentication.md#ready-handshake), the
117+
surface sends JSON-RPC 2.0 notifications defined by the
118+
[payment Action embedded contract](../payment-authentication.md#surface-rendering-and-notifications).
119+
120+
### Done
121+
122+
When the Platform-facing collection step is finished, the surface **MUST** send:
123+
124+
<!-- ucp:example schema=transports/jsonrpc def=request op=read -->
125+
```json
126+
{
127+
"jsonrpc": "2.0",
128+
"method": "action.done",
129+
"params": {
130+
"id": "ddc-1"
131+
}
132+
}
133+
```
134+
135+
The surface may send `action.done` when handler-owned logic determines that the
136+
Platform should close the surface. The notification does not reveal whether
137+
collection succeeded, was unavailable, was skipped, or mapped to a particular
138+
provider completion indicator.
139+
140+
### Error
141+
142+
If the surface cannot continue from the Platform-facing transport perspective,
143+
it **MAY** send:
144+
145+
<!-- ucp:example schema=transports/jsonrpc def=request op=read -->
146+
```json
147+
{
148+
"jsonrpc": "2.0",
149+
"method": "action.error",
150+
"params": {
151+
"id": "ddc-1",
152+
"error": {
153+
"ucp": { "version": "{{ ucp_version }}", "status": "error" },
154+
"messages": [
155+
{
156+
"type": "error",
157+
"code": "action_unavailable",
158+
"content": "Device data collection could not start.",
159+
"severity": "recoverable"
160+
}
161+
]
162+
}
163+
}
164+
}
165+
```
166+
167+
Recommended surface-level codes are `action_unavailable` when initialization
168+
fails, `action_expired` when the surface's session expired, and `action_failed`
169+
for another terminal surface error. These are diagnostic codes, not EMV 3DS or
170+
payment outcomes. A provider-domain timeout or unavailable method that the
171+
handler can safely continue past should normally result in `action.done`, with
172+
the Business and provider recording the domain outcome server-side. After either
173+
notification, the Platform follows the shared Payment Authentication
174+
reconciliation contract.
175+
176+
## Deadline and Fallback
177+
178+
[EMV 3-D Secure Protocol and Core Functions v2.3.1.1](https://www.emvco.com/specifications/emv-3-d-secure-protocol-and-core-functions-specification-6/){ target="_blank" }
179+
requires the 3DS Server to set `threeDSCompInd` to `N` when the 3DS Method does
180+
not complete within five seconds (Req 315). That provider-domain timer begins
181+
when the method is invoked and remains owned by the Business and provider; the
182+
Platform **MUST NOT** derive it from the outer surface's load event.
183+
184+
The Platform applies a bounded outer-surface deadline defined by the handler or
185+
Platform policy, measured from navigation and capped by Checkout `expires_at`.
186+
That deadline controls only how long the Platform keeps the UCP surface mounted;
187+
it does not set `threeDSCompInd` or another provider outcome.
188+
189+
If no valid `action.done` or `action.error` arrives before the outer deadline,
190+
the Platform **MUST** unmount the surface, treat the interaction as timed out,
191+
and follow the non-successful surface reconciliation path. It may unmount sooner
192+
after load failure or a valid terminal notification. The Platform **MUST NOT**
193+
remount the same Action type and `id`; an unchanged occurrence follows the
194+
parent Checkout Actions fallback, handoff, and cancellation rules.
195+
196+
## Security
197+
198+
The common [Payment Authentication security requirements](../payment-authentication.md#security-and-data-handling)
199+
apply. In addition:
200+
201+
- The handler's trust policy **MUST** authorize the initial and redirect origins
202+
before the Platform loads them.
203+
- The surface **MUST NOT** receive Platform credentials or access Platform
204+
storage.
205+
- Provider payloads and collected device data **MUST NOT** be copied into the
206+
Action, notification params, Checkout, or payment instrument.
207+
- `action.done` and `action.error` are advisory surface signals. A later
208+
Checkout response, based on Business/provider state, remains authoritative.

0 commit comments

Comments
 (0)