Pagamentos
Intenções de pagamento e idempotência
Uma intenção de pagamento define imutativamente os termos econômicos da transação antes que o usuário interaja com o widget. Isso impede que um cliente malicioso altere o valor, a conta de destino ou o conceito de transferência no frontend.
Parâmetros para criar uma intenção de pagamento (POST /payments/?action=create)
1. Modelo padrão para comerciantes (Beneficiário próprio)
Neste modelo, o comerciante define todos os dados de cobrança:
| Campo | Tipo | Obrigatório | Descrição e regras |
|---|---|---|---|
amount_minor |
Inteiro | Sim | Quantidade em unidades menores (centavos). Por exemplo, 1500 representa 15,00 EUR. |
currency |
String de texto | Sim | Código de moeda ISO 4217 de 3 letras. Atualmente EUR. |
beneficiary |
Objeto de Dados JSON | Sim | Dados da conta de destino: name (proprietário, de 1 a 140 caracteres de texto) e iban (IBAN válida sem espaços, com dígito verificador validado). Suporta apenas essas duas chaves. |
reference |
String de texto | Sim | Descrição do pagamento visível no extrato bancário (máximo 140 caracteres de texto). |
customer_reference |
String de texto | Sim | Identificador interno do seu pedido ou cliente (1 a 128 caracteres de texto: letras, números, ., _, :, -; deve começar com uma letra ou número). |
allowed_origin |
String de texto | Sim | A fonte exata HTTPS que irá incorporar o widget (por exemplo, https://tienda.example.com), sem caminho. |
allowed_institution_codes |
Array | Não | Lista de códigos de entidade permitidos (por exemplo, ["santander-es", "bbva-es"]). Se omitido, qualquer entidade no catálogo é permitida. |
locale |
String de texto | Não | A linguagem da interface do widget. Apenas essão aceitos nesta versão; qualquer outro valor retorna 422 invalid_locale. |
expected_mode |
String de texto | Não | mock ou live. Verifica que você está chamando o ambiente esperado; não muda de ambiente. Se não corresponder, 409 payment_mode_mismatch. |
O corpo é uma lista branca estrita: enviar um campo que não está nessa tabela retorna 422 invalid_request, assim como omitir um obrigatório. O cabeçalho Content-Type: application/json é obrigatório (415 json_required) e o corpo é limitado a 32 KB.
2. Modelo com perfil gerenciado (Doações/Demonstrações)
Para casos regulados ou demonstrações públicas como cruz_roja_demo, o servidor impõe as regras financeiras e define as contas-alvo oficiais:
| Campo | Tipo | Obrigatório | Descrição e regras |
|---|---|---|---|
profile |
String de texto | Sim | Identificador de perfil (por exemplo, cruz_roja_demo). |
institution_code |
String de texto | Sim | Código de entidade selecionado pelo usuário (de profile-institutions). |
amount_minor |
Inteiro | Sim | Valor limitado pelas regras do perfil (por exemplo, de 1 a 100 centavos). |
customer_reference |
String de texto | Sim | A própria referência de auditoria do seu sistema. |
allowed_origin |
String de texto | Sim | Widget HTTPS fonte. |
locale |
String de texto | Não | Linguagem de widgets (es). |
expected_mode |
String de texto | Não | Modo esperado (mock ou live). |
Quando profileé especificado, o servidor automaticamente atribui o beneficiário oficial e o conceito correspondente. Não envie beneficiary ou reference em solicitações com perfil gerenciado.
Regra da Idempotency-Key
O cabeçalho Idempotency-Key é necessário em qualquer requisição para criar uma intenção de pagamento. Ele deve conter entre 16 e 128 caracteres de texto ASCII visível, sem espaços (por exemplo, uma UUID v4). Seu escopo é exclusivo para a empresa autenticada:
- Mesma chave de idempotência e mesmo corpo: retorna a intenção original criada anteriormente junto com
idempotent_replay: true. Nenhuma nova cobrança é gerada e a ordem bancária não é duplicada. - Mesma chave de idempotência e corpo diferente: a API responde imediatamente com HTTP
409 Conflict. - Mesma chave de idempotência em outra empresa: pertence a outro espaço de idempotência completamente isolado.
Se uma solicitação para criar uma intenção de pagamento sofrer uma queda de rede ou tempo limite excedido (timeout), tente novamente com exatamente o mesmo cabeçalho Idempotency-Key e o mesmo corpo. Não gere uma nova chave em caso de falha transitória.
Persistência e ciclo de vida
- Persistência prévia: A intenção é registrada no banco de dados antes de retornar a resposta ou interagir com qualquer conector bancário.
- Token de widget efêmero: O token de resposta (
payment.widget.token) tem validade de tempo curto (geralmente de 15 a 30 minutos) e só pode ser usado a partir doallowed_origindeclarado. - Bloqueio de Concorrência: O sistema implementa controle otimista e leases para evitar que duas chamadas simultâneas autorizem ou modifiquem a mesma intenção.
Códigos de Erro Comuns
| HTTP | Código | Causa | Ação recomendada |
|---|---|---|---|
400 |
idempotency_key_required |
O cabeçalho Idempotency-Key está ausente ou está formatado incorretamente. |
Gerar uma chave válida de entre 16 e 128 caracteres de texto ASCII visível, sem espaços. |
409 |
idempotency_conflict |
A chave foi reutilizada com diferentes detalhes de pagamento. | Gerar uma nova chave para diferentes pagamentos ou reutilizar exatamente o mesmo corpo da requisição. |
409 |
payment_mode_mismatch |
expected_mode não corresponde ao modo do ambiente que você está chamando. |
Verifique se você está mirando no sandbox ou na produção; o modo é definido pela implantação, não pela chamada. |
401 |
invalid_api_key |
O cabeçalho X-API-Keyestá ausente, seu formato é inválido, ou a chave de acesso não existe ou está inativa. |
Revise o código de acesso. Nunca o inclua no frontend. |
403 |
payments_not_allowed |
A chave API não tem o produto PAYMENTS ativado. |
Entre em contato com Wealth Reader suporte para ativar os pagamentos na sua conta. |
403 |
payment_profile_not_allowed |
O perfil gerenciado não está ativado para sua empresa. | Solicite o registro da conta de perfil de Wealth Reader. |
429 |
api_limit_reached |
A credencial atingiu o limite cumulativo de chamadas. | Não é resolvido tentando novamente ou esperando: não há janela nem reset automático. Solicite estender o limite. |
415 |
json_required |
O cabeçalho Content-Type: application/jsonestá faltando. |
Envie o corpo como JSON. |
422 |
invalid_request |
Um campo obrigatório está faltando ou um campo não reconhecido foi enviado. | Confira a tabela de parâmetros: o corpo é uma lista branca rígida. |
422 |
invalid_institution |
A entidade selecionada está indisponível ou inválida. | Veja GET /payments/entities/ para códigos válidos. |
422 |
invalid_amount |
O valor é menor que o mínimo (€0,01) ou não é um inteiro. | Verifique se você está enviando um inteiro em cents (amount_minor). |
Próximo passo
Continue com Status, consultas periódicas de status e reconciliação.