Extensão de mandatos AP2¶
Visão geral¶
A extensão AP2 Mandates permite a troca segura de intenções do usuário e autorizações usando Credenciais Digitais Verificáveis. Ele estende o capacidade padrão do Shopping Service Checkout para oferecer suporte ao Protocolo AP2.
Quando esta capacidade é negociada e ativa, ela transforma um padrão sessão de checkout em um contrato vinculado criptograficamente:
- As empresas DEVEM incorporar uma assinatura criptográfica na finalização da compra respostas, provando que os termos (preço, itens de linha) são autênticos.
- Plataformas DEVEM fornecer provas assinadas criptograficamente (Mandatos)
durante a operação
complete, comprovando que o usuário autorizou explicitamente a estado de checkout específico e transferência de fundos.
Security Binding: Depois que esta extensão for negociada no recurso intersecção, a sessão será Segurança Bloqueada. Nenhuma das partes poderá voltar a um fluxo de checkout padrão (desprotegido).

Projeto¶
Todos os campos específicos do AP2 estão aninhados em um objeto ap2 nas solicitações e
respostas. Este projeto fornece:
- Modularidade do esquema — O esquema de checkout básico permanece limpo; AP2 adiciona um campo contendo todos os seus dados.
- Canonização consistente — Uma regra: excluir
ap2do negócio cálculo de assinatura. Os campos AP2 futuros são tratados automaticamente. - Coexistência de extensões — Várias extensões de segurança podem coexistir sem colisões de namespace.
- Sinal de capacidade — A presença do objeto
ap2indica claramente AP2 está ativo.
Descoberta e Negociação¶
Esta extensão segue o protocolo de negociação padrão do BCP. Está ativado somente quando aparece na Interseção de capacidade de ambos os negócios e a plataforma.
Anúncio do perfil da empresa¶
As empresas declaram apoio adicionando br.dev.bcp.shopping.ap2_mandate aos seus
Lista capabilities em /.well-known/ucp.
Exemplo de perfil comercial:json
{
"ucp": {
"version": "2026-07-14",
"services": {},
"capabilities": {
"br.dev.bcp.shopping.checkout": [
{
"version": "2026-07-14",
"spec": "https://bcp.dev.br/2026-07-14/specification/checkout",
"schema": "https://bcp.dev.br/2026-07-14/schemas/shopping/checkout.json"
}
],
"br.dev.bcp.shopping.ap2_mandate": [
{
"version": "2026-07-14",
"spec": "https://bcp.dev.br/2026-07-14/specification/ap2-mandates",
"schema": "https://bcp.dev.br/2026-07-14/schemas/shopping/ap2_mandate.json",
"extends": "br.dev.bcp.shopping.checkout",
"config": {
"vp_formats_supported": {
"dc+sd-jwt": { }
}
}
}
]
},
"payment_handlers": {}
}
}### Anúncio do perfil da plataforma
As plataformas declaram apoio em seu perfil. Se a plataforma estiver operando sob
modelo de provedor de plataforma confiável, a plataforma DEVE fornecer pelo menos um
digite a matriz keys de nível superior em seu perfil.
Ativação e bloqueio de sessão¶
- A plataforma anuncia seu URI de perfil (mecanismo específico de transporte).
- A empresa busca o perfil e calcula a interseção.
- Se
br.dev.bcp.shopping.ap2_mandateestiver presente na intersecção:- O negócio DEVE incluir
ap2.merchant_authorizationem todos respostas de checkout. - A empresa NÃO DEVE aceitar uma solicitação
complete_checkoutque não possuiap2.checkout_mandate. - A plataforma DEVE verificar a assinatura da empresa antes de apresentar o checkout para o usuário.
- O negócio DEVE incluir
Requisitos-chave de assinatura¶
Para utilizar esta extensão, uma chave de assinatura pública DEVE estar disponível para o empresa para verificar a assinatura do mandato.
- Fluxo do Provedor da Plataforma: Chave fornecida no
keysdo perfil da plataforma. - Fluxo de credencial do usuário: Chave vinculada à credencial de pagamento digital.
Se uma chave pública não puder ser resolvida ou se a assinatura for inválida, a empresa DEVE retornar um erro.
Requisitos criptográficos¶
Esta extensão usa as primitivas criptográficas definidas no Especificação de Assinaturas de mensagens:
- Algoritmo: de acordo com a regra de assinatura JWT do Checkout do AP2 — o AP2 v0.2 requer
ECDSA (
ES256/ES384/ES512); veja a nota abaixo. - Canonização: JCS (RFC 8785)
- Formato chave: JWK (RFC 7517)
- Chave Descoberta:
keys[]em/.well-known/ucp(consulte Descoberta de chave)
Consulte Assinaturas de mensagens para formato e rotação de chaves.
Nota (requisito de algoritmo). AP2 vincula a Mandação de Pagamento ao Finalização de compra via
hash(checkout_jwt); a propriedade de segurança subjacente é imprevisibilidade por sessão dos bytes assinados - qual é o único do BCP Checkout por sessãoidfornece estruturalmente. AP2 v0.2 é internamente inconsistente sobre como exigir isso:specification.mddeclara um regra de classe de algoritmo (apenas não determinística, por exemplo, ECDSA), enquanto o Considerações de segurança e privacidade estabelecem uma regra de entropia satisfeita por qualquer algoritmo com entropia de carga útil suficiente. AP2 #268 trilhas convergindo para a formulação da entropia. Siga pela AP2 para regra autoritária; sob a leitura de entropia, um JWT de checkout BCP pode ser assinado com qualquer algoritmo (incluindo Ed25519), deixando uma chave servir a ambos Assinatura de mandato AP2 e Web Bot Auth.
Autorização Comercial¶
As empresas DEVEM incorporar sua assinatura no corpo da resposta de checkout em
ap2.merchant_authorization usando formato JWS Detached Content
(RFC 7515 Apêndice F).
Resposta de checkout com assinatura incorporada:json
{
"ucp": { ... },
"id": "chk_abc123",
"status": "ready_for_complete",
"currency": "USD",
"line_items": [ ... ],
"totals": [ ... ],
"links": [ ... ],
"ap2": {
"merchant_authorization": "eyJhbGciOiJFUzI1NiIsImtpZCI6Im1lcmNoYW50XzIwMjUifQ..<signature>"
}
}O valor merchant_authorization é um JWS com payload desanexado no formato
<header>..<signature>. O ponto duplo (..) indica que a carga útil está
transmitido separadamente (como o próprio corpo do checkout).
Reivindicações de cabeçalho JWS:
| Reivindicação | Tipo | Obrigatório | Descrição |
|---|---|---|---|
alg |
corda | Sim | Algoritmo de assinatura aceito pelo AP2 (ex. ES256) |
kid |
corda | Sim | ID da chave referenciando o keys do negócio |
Cálculo de assinatura:
A assinatura DEVE abranger tanto o cabeçalho JWS quanto a carga útil do checkout. Isto
evita ataques de substituição de algoritmo onde um invasor modifica o alg
reivindicação sem invalidar a assinatura.```text
sign_checkout(checkout, private_key, kid, alg="ES256"):
// Extract payload (checkout minus ap2)
payload = checkout without "ap2" field
// Canonicalize using JCS (RFC 8785)
canonical_bytes = jcs_canonicalize(payload)
// Create protected header
header = {"alg": alg, "kid": kid}
encoded_header = base64url_encode(json_encode(header))
// Sign header + payload per JWS
signing_input = encoded_header + "." + base64url_encode(canonical_bytes)
signature = sign(signing_input, private_key, alg)
// Return detached JWS (header..signature, no payload)
checkout.ap2.merchant_authorization = encoded_header + ".." + base64url_encode(signature)
return checkout
```### Estrutura do Mandato
Os mandatos são credenciais SD-JWT com Key Binding (+kb). A plataforma
DEVE produzir dois artefatos de mandato distintos:
| Mandato | Colocação BCP | Finalidade |
|---|---|---|
| checkout_mandate | ap2.checkout_mandate |
Prova vinculada aos termos de checkout protege os negócios |
| mandato_pagamento | payment.instruments[*].credential.token |
Comprovante vinculado à autorização de pagamento protege fundos |
O mandato de checkout DEVE conter a resposta de checkout completa, incluindo o
Campo ap2.merchant_authorization. Isso cria uma ligação criptográfica aninhada
onde a assinatura da plataforma cobre a assinatura da empresa.
Limite de especificação: Esta extensão define onde os mandatos são colocados nas solicitações e respostas do BCP. A estrutura de credenciais do mandato (reivindicações, divulgação seletiva, vinculação de chave) é definida pelo Especificação do Protocolo AP2.
Canonização¶
Todas as cargas JSON DEVEM ser canonizadas usando Canonização JSON Esquema (JCS) de acordo com RFC 8785.
Por que JCS para Mandatos? As assinaturas de solicitação BCP usam Content-Digest (bruto
bytes) sem canonização — a solicitação é assinada e verificada
imediatamente pela mesma conexão HTTP. Os mandatos são diferentes:
- Durabilidade — Os mandatos são armazenados como prova do consentimento do usuário. Eles podem ser recuperados e verificados dias ou meses depois.
- Transmissão entre sistemas — Os mandatos passam por vários sistemas (plataforma → negócio → PSP → rede de cartões) que pode serializar novamente o JSON.
- Reprodutibilidade — Qualquer parte deve reconstruir os bytes assinados exatos do conteúdo JSON lógico, independentemente das diferenças de serialização.
JCS garante que JSON semanticamente idêntico produza saída idêntica em bytes, tornando as assinaturas reproduzíveis entre implementações e tempo.
Regra Específica do AP2: Ao calcular o merchant_authorization do negócio
assinatura, exclua totalmente o campo ap2. Isso garante futuros campos AP2
são tratados automaticamente.
O Fluxo do Mandato¶
Uma vez negociada a capacidade br.dev.bcp.shopping.ap2_mandate, a sessão
está bloqueado no fluxo a seguir. Ambas as partes DEVEM seguir estas etapas para
garantir a integridade criptográfica; qualquer tentativa de ignorar essas etapas ou enviar
uma solicitação de conclusão sem mandatos DEVE resultar em uma falha de sessão.
Etapa 1: Criação e assinatura do checkout¶
A plataforma inicia a sessão. O negócio retorna o objeto Checkout
com ap2.merchant_authorization embutido no corpo da resposta.
Checkout extended with AP2 mandate support.
| Name | Type | Required | Description |
|---|---|---|---|
| ucp | any | Yes | UCP metadata for checkout responses. |
| id | string | Yes | Unique identifier of the checkout session. |
| line_items | Array[object] | Yes | List of line items being checked out. |
| buyer | object | No | Representation of the buyer. |
| context | object | No | Provisional buyer signals for relevance and localization—not authoritative data. Businesses SHOULD use these values when verified inputs (e.g., shipping address) are absent, and MAY ignore or down-rank them if inconsistent with higher-confidence signals (authenticated account, risk detection) or regulatory constraints (export controls). Eligibility and policy enforcement MUST occur at checkout time using binding transaction data. Context SHOULD be non-identifying and can be disclosed progressively—coarse signals early, finer resolution as the session progresses. Higher-resolution data (shipping address, billing address) supersedes context. |
| signals | object | No | Environment data provided by the platform to support authorization and abuse prevention. Values MUST NOT be buyer-asserted claims — platforms provide signals based on direct observation or independently verifiable third-party attestations. All signal keys MUST use reverse-domain naming to ensure provenance and prevent collisions when multiple extensions contribute to the shared namespace. |
| attribution | object | No | Platform-emitted referral and conversion-event context — campaign identifiers, click IDs, source/medium markers, etc. The same parameters platforms communicate via URL query parameters in browser-based flows. |
| status | string | Yes | Checkout state indicating the current phase and required action. See Checkout Status lifecycle documentation for state transition details. Enum: incomplete, requires_escalation, ready_for_complete, complete_in_progress, completed, canceled |
| currency | string | Yes | ISO 4217 currency code reflecting the merchant's market determination. Derived from address, context, and geo IP—buyers provide signals, merchants determine currency. |
| totals | Array[Total] | Yes | Different cart totals. |
| messages | Array[object] | No | List of messages with error and info about the checkout session state. |
| links | Array[object] | Yes | Links to be displayed by the platform (Privacy Policy, TOS). Mandatory for legal compliance. |
| expires_at | string | No | RFC 3339 expiry timestamp. Default TTL is 6 hours from creation if not sent. |
| continue_url | string | No | URL for checkout handoff and session recovery. MUST be provided when status is requires_escalation. See specification for format and availability requirements. |
| payment | object | No | Payment configuration containing handlers. |
| order | object | No | Details about an order created for this checkout session. |
| ap2 | any | No |
Exemplo de resposta:json
{
"ucp": { ... },
"id": "chk_abc123",
"status": "ready_for_complete",
"currency": "USD",
"line_items": [
{
"id": "li_1",
"item": {"id": "item_123", "title": "Widget", "price": 2500},
"quantity": 2,
"totals": [
{"type": "subtotal", "amount": 5000},
{"type": "total", "amount": 5000}
]
}
],
"totals": [
{"type": "subtotal", "amount": 5000},
{"type": "tax", "amount": 400},
{"type": "total", "amount": 5400}
],
"links": [ ... ],
"ap2": {
"merchant_authorization": "eyJhbGciOiJFUzI1NiIsImtpZCI6Im1lcmNoYW50XzIwMjUifQ..<signature>"
}
}A plataforma DEVE verificar a assinatura:```text
verify_merchant_authorization(checkout, merchant_profile):
// Parse detached JWS (header..signature)
jws = checkout.ap2.merchant_authorization
[encoded_header, empty, encoded_signature] = jws.split(".")
// Decode and validate header
header = json_decode(base64url_decode(encoded_header))
assert header.alg in ap2_accepted_algorithms // ES256/ES384/ES512 per AP2 v0.2
// Reconstruct signed payload (checkout minus ap2)
payload = checkout without "ap2" field
canonical_bytes = jcs_canonicalize(payload)
// Reconstruct signing input (header + payload)
signing_input = encoded_header + "." + base64url_encode(canonical_bytes)
// Get business's public key and verify
public_key = get_key_by_kid(merchant_profile.keys, header.kid)
return verify(encoded_signature, signing_input, public_key, header.alg)
```### Etapa 2: Consentimento do usuário e geração de mandato
Quando o usuário confirma a compra, a plataforma DEVE facilitar a geração de mandatos verificáveis criptograficamente.
Opção 1: Provedor de plataforma confiável¶
Um provedor de plataforma confiável atua em nome do usuário para gerar o credenciais de mandato. O provedor da plataforma DEVE garantir que os mandatos não são criados sem o consentimento explícito do usuário de fontes confiáveis e determinísticas canais.
Mediante consentimento do usuário, a plataforma assina os mandatos usando seu servidor chave. A empresa confia que a assinatura da plataforma implica o consentimento do usuário.
Opção 2: credencial de pagamento digital¶
Neste modelo, o usuário possui um VDC emitido por uma fonte confiável para a empresa (por exemplo: uma credencial de pagamento digital emitida por um banco ou rede).
A plataforma solicita uma apresentação através de um protocolo como OpenID4VP. O usuário A Wallet (ou equivalente) processa a solicitação e assina os mandatos usando o chave privada associada à sua credencial de pagamento.
A empresa confia no Emissor da Credencial (Banco) e verifica a Chave do usuário Assinatura de ligação (+kb).
Etapa 3: Envio (complete_checkout)¶
Uma vez gerados os mandatos, a plataforma os submete no preenchimento solicitar:
AP2 extension data including checkout mandate.
| Name | Type | Required | Description |
|---|---|---|---|
| checkout_mandate | string | No | SD-JWT+kb proving user authorized this checkout. |
| { | |||
| "payment": { | |||
| "instruments": [ | |||
| { | |||
| "id": "instr_1", | |||
| "handler_id": "gpay_1234", | |||
| "type": "card", | |||
| "selected": true, | |||
| "display": { | |||
| "description": "Visa •••• 1234" | |||
| }, | |||
| "billing_address": { | |||
| "street_address": "123 Main St", | |||
| "address_locality": "Anytown", | |||
| "address_region": "CA", | |||
| "address_country": "US", | |||
| "postal_code": "12345" | |||
| }, | |||
| "credential": { | |||
| "type": "PAYMENT_GATEWAY", | |||
| "token": "examplePaymentMethodToken" | |||
| } | |||
| } | |||
| ] | |||
| }, | |||
| "ap2": { | |||
| "checkout_mandate": "eyJhbGciOiJFUzI1NiIsInR5cCI6InZjK3NkLWp3dCJ9..." // The User-Signed SD-JWT+kb / platform provider signed SD-JWT / delegated SD-JWT-KB | |||
| } | |||
| } | |||
``*ap2.checkout_mandate`: O mandato de checkout SD-JWT+kb contendo o |
|||
checkout completo (com ap2.merchant_authorization) |
|||
* payment.instruments[*].credential.token: Contém a ordem de pagamento (token composto) |
Verificação e processamento¶
Verificação comercial¶
Ao receber a solicitação complete, a empresa DEVE:
- Aplicar Negociação: Se o AP2 foi negociado, rejeite a solicitação com
Código de erro
mandate_requiredseap2.checkout_mandateestiver faltando.
Verificação de mandato (conforme especificação AP2):
- Verificar Mandato: Decodifique e verifique a assinatura SD-JWT, ligação de chave, e expiração de acordo com o Especificação do Protocolo AP2.
- Extrair Checkout Incorporado: Extraia o objeto checkout do reivindicações de mandato verificadas.
Verificação BCP:
-
Verifique a autorização comercial: Confirme
ap2.merchant_authorizationno checkout incorporado está a assinatura válida da própria empresa:```text jws = embedded_checkout.ap2.merchant_authorization [encoded_header, _, encoded_signature] = jws.split(".") header = json_decode(base64url_decode(encoded_header))payload = embedded_checkout without "ap2" field signing_input = encoded_header + "." + base64url_encode(jcs_canonicalize(payload))
my_key = get_key_by_kid(my_keys, header.kid) verify(encoded_signature, signing_input, my_key, header.alg) ```2. Verificar a correspondência dos termos: Confirme se os termos de checkout incorporados correspondem aos estado atual da sessão (id, totais, itens de linha).
Verificação PSP¶
A empresa passa o token (objeto composto) para seu Pagamento
Manipulador / PSP. O PSP verifica o payment_mandate conforme o
Especificação do Protocolo AP2,
incluindo validação de assinatura, expiração e correlação com o
check-out.
Esquema¶
Autorização comercial¶
JWS Detached Content signature (RFC 7515 Appendix F) over the checkout response body (excluding ap2 field). Format: <base64url-header>..<base64url-signature>. The header MUST contain 'alg' (ES256/ES384/ES512) and 'kid' claims. The signature covers both the header and JCS-canonicalized checkout payload.
Pattern: ^[A-Za-z0-9_-]+\.\.[A-Za-z0-9_-]+$
Resposta de check-out do AP2¶
O objeto ap2 incluído nas respostas de checkout.
AP2 extension data including merchant authorization.
| Name | Type | Required | Description |
|---|---|---|---|
| merchant_authorization | string | No | Merchant's signature proving checkout terms are authentic. |
Mandato de check-out¶
SD-JWT+kb credential in ap2.checkout_mandate. Proving user authorization for the checkout. Contains the full checkout including ap2.merchant_authorization.
Pattern: ^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]*\.[A-Za-z0-9_-]+(~[A-Za-z0-9_-]+)*$
Solicitação completa de AP2¶
O objeto ap2 incluído nas solicitações de checkout COMPLETE.
AP2 extension data including checkout mandate.
| Name | Type | Required | Description |
|---|---|---|---|
| checkout_mandate | string | No | SD-JWT+kb proving user authorized this checkout. |
Códigos de erro¶
Error codes specific to AP2 mandate verification.
Enum: mandate_required, agent_missing_key, mandate_invalid_signature, mandate_expired, mandate_scope_mismatch, merchant_authorization_invalid, merchant_authorization_missing
| Código de erro | Descrição |
|---|---|
mandate_required |
AP2 foi negociado, mas falta ap2.checkout_mandate na solicitação. |
agent_missing_key |
O perfil da plataforma não possui uma entrada keys válida. |
mandate_invalid_signature |
A assinatura do mandato não pode ser verificada. |
mandate_expired |
O carimbo de data/hora do mandato exp passou. |
mandate_scope_mismatch |
O mandato está vinculado a uma verificação diferente. |
merchant_authorization_invalid |
A assinatura da autorização comercial não pôde ser verificada. |
merchant_authorization_missing |
A resposta de checkout omite ap2.merchant_authorization. |