Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .cspell/custom-words.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Kroger
Lowe's
Macy's
Mastercard
MDES
Paymentech
Paypal
Preorders
Expand Down
6 changes: 6 additions & 0 deletions docs/specification/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -1464,6 +1464,12 @@ Most platform implementations can **avoid PCI-DSS scope** by:
- Forwarding credentials without the ability to use them directly
- Using PSP tokenization payment handlers where raw credentials never pass
through the platform
- Presenting pre-provisioned card network tokens
(`card_number_type: "network_token"`) — network tokens with
cryptograms may qualify for reduced PCI scope compared to handling
FPANs directly; consult current
[PCI DSS guidance](https://www.pcisecuritystandards.org/)
for applicable requirements

#### Business Scope

Expand Down
42 changes: 42 additions & 0 deletions docs/specification/tokenization-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,48 @@ Tokenization handlers transform credentials between source and checkout forms:
Tokenization handlers accept source credentials (e.g., card with FPAN) and
produce checkout credentials (e.g., tokens).

### Pre-Provisioned Credentials

Not all credential flows require a tokenize/detokenize round-trip per
transaction. In some cases, a platform may have acquired credentials in
advance — for example, by provisioning a card network token via the
network's token service — and can present them in place of tokenizing an
FPAN at each transaction. Although no credential transformation occurs,
a payment handler is still required for capability negotiation — the
handler advertises support for this credential type so that platforms and
businesses can discover and agree on its use.

Card network tokens are one such case. When a platform already holds a
network token, it can present the token directly as a `card_credential`
with `card_number_type: "network_token"`:

```json
{
"type": "card",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is also a flow where this obj, even when DPAN / CPAN, could still be wrapped in a payment_handler wrapper. It wouldn't require a de-tokenization call to an out of band API, but would make the object opaque to any intermediate parties.

Can you update the language to be open to that setup as well? I would expect the object definition of the card credential would specify what the object contains.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aligned and truthfully I think thats what would fit the current state of UCP!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep - language is updated to note a payment handler is needed for negotiation. This should leave the door open for handlers that also that wrap credentials for intermediary opacity.

I'm interested to discuss/learn more about pros/cons of wrapping vs. directly passing network tokens (which the schema seems to allow on a complete checkout call) BUT also interested in getting this PR over the finish line before diving into that further ;-)

"card_number_type": "network_token",
"number": "4000000000000002",
"expiry_month": 12,
"expiry_year": 2027,
"cryptogram": "gXc5UCLnM6ckD7pjM1TdPA==",
"eci_value": "07"
}
```

Key differences from the tokenize/detokenize flow:

| Aspect | Tokenize/Detokenize | Pre-Provisioned Credential |
| :----- | :------------------ | :------------------------- |
| Source | Platform holds FPAN | Platform holds network token provisioned in advance |
| Flow | Platform → handler `/tokenize` → token per transaction | Platform presents credential directly |
| Cryptogram | Not applicable | Required — generated by the token service |
| PCI scope | Platform may handle raw PANs | May be reduced — consult current [PCI DSS guidance](https://www.pcisecuritystandards.org/) for applicable scope |

When a handler's `available_instruments` includes
`requires_card_verification: true`, the platform **MUST** provide the
`cryptogram` and `eci_value` fields for network token credentials. See
the [Card Constraints](payment-handler-guide.md#card-constraints) section
in the Payment Handler Guide for details.

### Token Lifecycle

Tokens move through distinct phases. Your handler specification must document
Expand Down
2 changes: 1 addition & 1 deletion source/schemas/shopping/types/card_credential.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://ucp.dev/schemas/shopping/types/card_credential.json",
"title": "Card Credential",
"description": "A card credential containing sensitive payment card details including raw Primary Account Numbers (PANs). This credential type MUST NOT be used for checkout, only with payment handlers that tokenize or encrypt credentials. CRITICAL: Both parties handling CardCredential (sender and receiver) MUST be PCI DSS compliant. Transmission MUST use HTTPS/TLS with strong cipher suites.",
"description": "A card credential containing payment card details. When card_number_type is 'fpan', this contains a raw Primary Account Number (PAN) — both parties MUST be PCI DSS compliant. When card_number_type is 'network_token', this contains a network token with cryptogram and ECI, which may qualify for reduced PCI scope — consult current PCI DSS guidance for applicable requirements. FPAN credentials MUST NOT be used directly for checkout — use payment handlers that tokenize or encrypt credentials. Transmission MUST use HTTPS/TLS with strong cipher suites.",
"allOf": [
{
"$ref": "payment_credential.json"
Expand Down