a primeira plataforma que dá autonomia real aos estabelecimentos

Portal de Integração
PaymentForm

PROCASH · API de Pagamentos v5.8.2 · Documentação para desenvolvedores

"O foco são os estabelecimentos, a prioridade sua rentabilidade, o objetivo a inovação e o pragmatismo."

🔒 PCI SAQ-A ↗ Redirect ⬜ Embutido (iframe) ⇄ S2S 💳 Parcelas 📱 QR 🇦🇷 ARS · Argentina

PaymentForm é o formulário de pagamento hospedado da PROCASH. Seu site nunca vê os dados do cartão: o formulário é servido a partir de um domínio em conformidade com PCI (PCI-compliant). Você só executa duas chamadas server-to-server a partir do seu backend: OrderInitial para criar o pedido e OrderFinal para confirmar o resultado.

⇄

Apenas 2 chamadas S2S

OrderInitial para criar o pedido, OrderFinal para confirmar o resultado. Todo o resto é automático.

🔒

PCI SAQ-A incluído

Seu servidor nunca vê nem processa dados do cartão. O escopo PCI é mínimo por design.

🔀

2 modos de integração

Redirect completo (mais simples) ou iframe embutido com postMessage para uma experiência sem sair do seu site.

💳

Parcelas e QR

Suporte nativo a parcelas (1 a N) com planos financeiros configuráveis por adquirente. Pagamentos por QR dinâmico disponíveis de acordo com a configuração da plataforma.

🇦🇷

Contexto argentino

Moeda ARS (032) · Valores em centavos · CUIT/CUIL como identificador tributário · Fuso horário UTC-3 (Buenos Aires).

Fluxo de pagamento

Como funciona

Diagrama de sequência completo: atores, chamadas e fluxo de dados.

🖥️ Seu siteEC / Backend
⚡ GatewayAPI Core
💳 PaymentFormFormulário hospedado
👤 CompradorBrowser
1
POST /OrderInitial
valor, moeda, MerchantRedirectURL, MerchantNotifyURL
InitialToken + InitialIdentification
+ CustomerRedirectAddress — salve InitialIdentification no seu DB
3 · Redirect 302 → CustomerRedirectAddress?token=…
EC redireciona o browser para o formulário hospedado
4 · Abre o PaymentForm
5 · Formulário obtém configuração (interno)
6 · Insere dados do cartão
7 · Formulário processa o pagamento (interno)
8 · Redirect → MerchantRedirectURL?token=…
9 · Browser retorna ao seu site
10 · POST /OrderFinal (InitialIdentification)
11 · AuthCode, Tickets, valor confirmado
ℹ️
Regra de ouro: O resultado do redirect (passo 8–9) é apenas um sinal de navegação. O resultado real e definitivo sempre é obtido com o OrderFinal (passo 10–11) a partir do seu servidor.
Opções de integração

Modos de integração

O PaymentForm suporta três modos de acordo com o nível de controle de UX e integração que você precisa. Os três mantêm o PCI SAQ-A — o estabelecimento nunca captura os dados do cartão.

↗️

Modo A — Redirect

O browser do comprador sai do seu site e vai para o formulário hospedado. O modo mais simples e rápido de integrar.

✓ PCI SAQ-A Mais fácil
⬜

Modo B — Embutido (iframe completo)

O formulário completo é exibido em um iframe cross-origin dentro da sua página. Comunicação via postMessage.

✓ PCI SAQ-A Melhor UX
EM CONSTRUÇÃO
🧩

Modo C — Hosted Fields

Apenas os campos do cartão (PAN + CVV) vão em um iframe da PROCASH. O lojista monta o resto do formulário — controle máximo de design, sem tocar em CHD.

✓ PCI SAQ-A Controle máximo Projetado · em implementação

Você redireciona o comprador usando o CustomerRedirectAddress retornado pelo OrderInitial. O formulário processa o pagamento e retorna o comprador para a sua MerchantRedirectURL.

Node.js / Express
// 1. Chamar OrderInitial a partir do seu servidor
const response = await fetch('https://api.procash.dev/OrderInitial', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${API_KEY}`
  },
  body: JSON.stringify({
    OrderInitial: {
      MerchantSystemID: 'SHOP-01',      // requerido
      MerchantCompanyID: '0',          // requerido
      TransactionAmount: 1000000,      // $10.000,00 ARS (em centavos)
      CurrencyCode: '032',            // desejável — se omitido, assume ARS
      ReferenceNumber: 'ORD-2026-0001',
      MerchantRedirectURL: 'https://www.mi-tienda.com.ar/pago/retorno', // opcional
      MerchantNotifyURL: 'https://www.mi-tienda.com.ar/webhooks/pago',   // recomendado
      FacilityNumber: 3,              // opcional — parcelas (1 = à vista)
    }
  })
});
const { OrderInitialResponse: r } = await response.json();

// 2. Verificar se o pedido foi criado corretamente
//    ResponseActions é a fonte de verdade — deve conter "OK"
//    ResponseCode "-1" é o indicador de sucesso neste contrato
if (!r.ResponseActions?.includes('OK') || r.ResponseCode !== '-1') {
  // Pedido rejeitado pela plataforma — não redirecionar
  throw new Error(`OrderInitial fallido: [${r.ResponseActions}] ${r.ResponseMessage}`);
}

// 3. Validar presença dos campos obrigatórios na resposta
if (!r.InitialIdentification || !r.CustomerRedirectAddress) {
  throw new Error('Respuesta incompleta: faltan InitialIdentification o CustomerRedirectAddress');
}

// 4. ⚠️ Salve InitialIdentification no seu DB ANTES de redirecionar
//    É PRIVADO — nunca viaja para o browser
await db.orders.update({ referenceNumber: 'ORD-2026-0001' }, {
  initialIdentification: r.InitialIdentification
});

// 5. Redirecionar o comprador para o formulário — apenas o InitialToken (PÚBLICO) viaja na URL
res.redirect(302, r.CustomerRedirectAddress);

Embuta o formulário na sua página com um iframe usando a mesma URL. Escute os eventos postMessage — os dados do cartão nunca viajam fora do iframe.

📡
Eventos postMessage disponíveis:
paymentform:ready · paymentform:resize · paymentform:submitted · paymentform:error
HTML + JavaScript
<!-- iframe cross-origin — PCI SAQ-A mantenido -->
<iframe
  id="payment-frame"
  src="https://payment.procash.dev/?token=INITIAL_TOKEN_AQUI"
  style="width:100%;border:none;min-height:420px;"
  allow="payment"
></iframe>

<script>
window.addEventListener('message', (e) => {
  // Sempre verificar a origem
  if (e.origin !== 'https://payment.procash.dev') return;

  const { type, result } = e.data;

  if (type === 'paymentform:submitted') {
    if (result === 'approved') {
      // Chamar o seu backend para executar OrderFinal
      confirmOrder(result);
    } else if (result === 'refused') {
      showRefusedMessage();
    }
  }

  if (type === 'paymentform:resize') {
    document.getElementById('payment-frame').style.height = e.data.height + 'px';
  }
});
</script>
🚧
Estado: projetado e em construção (Fase 16). O contrato de integração v1.0.0 está definido e a lógica client-side (embed-fields.ts) está implementada. A infraestrutura de subdomínio cross-origin e a criptografia WASM→JWE estão pendentes. Consulte a equipe da PROCASH sobre a disponibilidade no sandbox.

¿Qué es Hosted Fields?

Em vez de embutir o formulário completo, apenas os campos sensíveis (PAN + CVV) ficam em um iframe cross-origin servido pela PROCASH. Sua página monta o resto do checkout — valor, parcelas, dados do comprador, design — enquanto os dados do cartão nunca tocam seu DOM.

// Sua página (fora do escopo PCI)
SEU FORMULÁRIO
[ Valor: $10.000,00 ARS ]
[ Parcelas: 3 sem juros ]
⬛ IFRAME DA PROCASH (cross-origin · escopo SAQ-D da PROCASH)
[ PAN: ________________ ]
[ CVV: ___ ] [ Venc: __/__ ]
→ WASM criptografa para JWE antes de sair
[ Nome do titular: ________ ]
[ Pagar → ]
↕ postMessage: "ready" · "fieldValidity" · "submit" · "error" · "challenge"

Tiers de hosting disponibles

TierDomínio do iframePara quem
T1 — Compartilhado{tenant}.payment.procash.devPadrão — rápido de integrar (onboarding)
T2 — White-labelpay.tudominio.com (CNAME → PROCASH)Estabelecimentos com branding próprio
T3 — EnterpriseDomínio completamente personalizadoBancos / grandes varejistas (hospedagem regional/on-prem)

Contrato postMessage (eventos del iframe)

EventoDireçãoPayload
paymentform:readyiframe → parent{ mode: 'fields' } — iframe pronto para receber interação
paymentform:fieldValidityiframe → parent{ field: 'pan'|'cvv', valid: bool } — para habilitar/desabilitar o botão
paymentform:resizeiframe → parent{ height: px } — ajustar altura do iframe
paymentform:submitparent → iframe{ token } — trigger de envio a partir do seu botão
paymentform:submittediframe → parent{ result: 'approved'|'refused'|'challenge' }
paymentform:erroriframe → parent{ code, message }
HTML + JavaScript — Hosted Fields (Modelo C)
<!-- Solo el iframe de campos sensibles (cross-origin) -->
<div id="checkout">
  <!-- Tu UI: monto, cuotas, nombre del titular -->
  <p>Total: <strong>$10.000,00 ARS</strong> en 3 cuotas</p>

  <!-- iframe de PROCASH: solo PAN + CVV -->
  <iframe
    id="fields-frame"
    src="https://{tenant}.payment.procash.dev/fields?token=INITIAL_TOKEN"
    style="width:100%;border:none;height:120px;"
    allow="payment"
    sandbox="allow-scripts allow-same-origin"
  ></iframe>

  <!-- Tu propio botón de pago -->
  <input type="text" placeholder="Nombre en la tarjeta" id="cardName">
  <button id="pay-btn" disabled>Pagar</button>
</div>

<script>
const frame = document.getElementById('fields-frame');
const payBtn = document.getElementById('pay-btn');
let panOk = false, cvvOk = false;

// Escutar eventos do iframe
window.addEventListener('message', (e) => {
  if (e.origin !== 'https://{tenant}.payment.procash.dev') return;
  const { type, field, valid, height, result } = e.data;

  if (type === 'paymentform:resize')
    frame.style.height = height + 'px';

  if (type === 'paymentform:fieldValidity') {
    if (field === 'pan') panOk = valid;
    if (field === 'cvv') cvvOk = valid;
    payBtn.disabled = !(panOk && cvvOk);  // habilitar apenas se ambos estiverem OK
  }

  if (type === 'paymentform:submitted' && result === 'approved')
    confirmOrder();  // llamar tu backend → OrderFinal
});

// Seu botão dispara o envio (submit) no iframe
payBtn.addEventListener('click', () => {
  frame.contentWindow.postMessage(
    { type: 'paymentform:submit' },
    'https://{tenant}.payment.procash.dev'
  );
});
</script>
🔒
Segurança: o iframe criptografa PAN + CVV com WASM → JWE antes de saírem do iframe. Sua página nunca vê os dados em texto claro, embora estejam na mesma janela do browser. O sandbox do iframe e o allow-same-origin são configurados pela plataforma para que a comunicação postMessage funcione sem expor o DOM sensível.
Guia de integração

Passo a passo

Siga estes passos para integrar o PaymentForm ao seu backend.

1

OrderInitial (S2S)

Chamada a partir do seu servidor para criar o pedido de pagamento. Nunca a partir do browser.

POST https://api.procash.dev/OrderInitial

Auth: Authorization: Bearer {API_KEY}

Request JSON
{
  "OrderInitial": {
    "MerchantSystemID": "SHOP-01",       // requerido
    "MerchantCompanyID": "0",           // requerido
    "TransactionAmount": 1000000,       // $10.000,00 ARS (em centavos)
    "CurrencyCode": "032",              // desejável — se omitido, assume ARS
    "ReferenceNumber": "ORD-2026-0001", // seu ID interno do pedido
    "MerchantRedirectURL": "https://www.mi-tienda.com.ar/pago/retorno", // opcional
    "MerchantNotifyURL": "https://www.mi-tienda.com.ar/webhooks/pago",   // recomendado
    "FacilityNumber": 3,               // opcional — parcelas (1 = à vista)
    "Products": [
      { "Code": "PLAN-PRO", "Name": "Plan Pro Mensual", "Quantity": 1, "UnitAmount": 1000000 }
    ]
  }
}
Response JSON
{
  "OrderInitialResponse": {
    "ResponseActions": ["OK"],          // ← fonte de verdade
    "ResponseCode": "-1",                 // ← informativo (-1 = OK neste contrato)
    "ResponseMessage": "Orden creada",     // ← informativo
    "InitialToken": "11111111-1111-5111-8111-111111111111",
    "InitialIdentification": "99999999-9999-5999-8999-999999999999",
    "CustomerRedirectAddress": "https://payment.procash.dev/?token=11111111-1111-5111-8111-111111111111",
    "MerchantRedirectURL": "https://www.mi-tienda.com.ar/pago/retorno",
    "TransactionValidThru": "2026-06-04T23:59:59-03:00", // UTC-3 · Buenos Aires
    "Sequence": ""
  }
}
ℹ️
ResponseActions é a fonte de verdade. ResponseCode e ResponseMessage são informativos — estão sempre presentes, mas não devem ser usados como critérios de decisão.
⚠️
Crítico: Salve o InitialIdentification no seu banco de dados associado ao pedido. Ele é PRIVADO — nunca o envie para o browser nem o exponha em URLs.
2

Redirecionar o comprador

Use o CustomerRedirectAddress (já possui o token embutido). Equivale a https://payment.procash.dev/?token={InitialToken}

Express / Node.js
const { OrderInitialResponse: r } = await orderInitial(); // ver Passo 1

// ✅ Apenas redirecionar se ResponseActions contiver "OK" e ResponseCode for "-1"
if (r.ResponseActions?.includes('OK') && r.ResponseCode === '-1'
    && r.InitialIdentification && r.CustomerRedirectAddress) {
  res.redirect(302, r.CustomerRedirectAddress);
} else {
  // Tratar erro — o pedido não foi criado
  res.status(400).json({ error: r.ResponseMessage });
}
3

O formulário processa o pagamento (interno)

O formulário gerencia todo o processamento do pagamento de forma interna — obtém a configuração do pedido, captura os dados do cartão do comprador e processa a transação junto à plataforma. Não requer código da sua parte neste passo.

🔒
Seu site nunca vê nem toca nos dados do cartão. Tudo ocorre no ambiente PCI da PROCASH.
4

Retorno ao seu site

O browser retorna para a sua MerchantRedirectURL. O redirect não inclui o resultado do pagamento — o status sempre é obtido com o OrderFinal (ou OrderStatus) a partir do seu servidor.

URL de retorno (o que chega ao browser)
https://www.mi-tienda.com.ar/pago/retorno
  ?token=11111111-1111-5111-8111-111111111111
  // ← sem status, sem resultado — apenas o token público
  // O resultado real é obtido chamando OrderFinal a partir do seu servidor
⚠️
O redirect não traz o resultado. Nunca presuma aprovado/recusado pelo simples fato de o comprador ter retornado ao seu site. Execute sempre o OrderFinal (S2S) para obter o resultado real. O webhook (MerchantNotifyURL) também o confirma de forma assíncrona.
💡
Sem MerchantRedirectURL: se você omitir este campo no OrderInitial, não haverá redirect. O formulário exibe o resultado diretamente na tela. Nesse caso, use o webhook (MerchantNotifyURL) e/ou o OrderStatus para conhecer o resultado no seu backend.
5

OrderFinal (S2S)

Confirme o resultado a partir do seu servidor usando o InitialIdentification que você salvou no Passo 1.

POST https://api.procash.dev/OrderFinal
Request JSON
{
  "OrderFinal": {
    "InitialIdentification": "99999999-9999-5999-8999-999999999999"
  }
}
Response JSON — Aprovado
{
  "OrderFinalResponse": {
    "ResponseActions": ["OK", "Approve", "Tickets", "Completed"], // ← fonte de verdade
    //  OK        → operação bem-sucedida
    //  Approve   → pagamento aprovado
    //  Tickets   → existem comprovantes para renderizar
    //  Completed → circuito completo: OrderInitial→formulário→OrderFinal executado
    "ResponseCode": "-1",                                      // ← informativo (-1 = aprovado)
    "ResponseMessage": "Aprobado",                               // ← informativo
    "AuthCode": "AUTH123",
    "TransactionAmount": 1000000,
    "CurrencyCode": "032",
    "Tickets": [
      { "Type": "Customer", "Content": "..." },
      { "Type": "Merchant", "Content": "..." }
    ]
  }
}
Response JSON — Recusado
{
  "OrderFinalResponse": {
    "ResponseActions": ["OK", "Refuse", "Completed"], // ← fonte de verdade — pago NO acreditado
    //  OK        → operação processada
    //  Refuse    → recusado pelo emissor
    //  Completed → circuito completo executado (igual que no Approve)
    "ResponseCode": "05",                              // ← informativo, apenas um exemplo — pode ser qualquer código
    "ResponseMessage": "Tarjeta rechazada por el emisor", // ← informativo, apenas um exemplo
    "TransactionAmount": 1000000,
    "CurrencyCode": "032"
  }
}
ℹ️
Lógica de decisão — ResponseActions é sempre um array:

OK → siempre presente junto con Approve o Refuse. Approve → pago aprobado · confirmar y entregar. Refuse → rechazado · no cobrado · notificar al comprador. Completed → circuito completo: el comercio ejecutó OrderFinal y cerró el ciclo de integración. Tickets → hay comprobantes en Tickets[] para renderizar al comprador.

Não use ResponseCode nem ResponseMessage como critérios de decisão. Lógica correta: includes('Approve') para aprovado · includes('Refuse') para recusado · includes('Completed') para circuito encerrado.

📡 Webhook — MerchantNotifyURL

O Core chama sua MerchantNotifyURL de forma assíncrona com o resultado do pagamento. Garante que você receberá o resultado mesmo que o browser não retorne ao seu site.

🔁 Pode chegar mais de uma vez — torne-o idempotente ✓ Use em conjunto com o OrderFinal 📬 Verificar assinatura se estiver disponível
Personalización visual

Look & Feel do formulário

O PaymentForm se adapta completamente ao branding do estabelecimento. Os estilos, o modelo de interface, os produtos e o logotipo são configurados por pedido, diretamente no OrderInitial via AdditionalInformation — sem tocar no código do formulário.

ℹ️
Os estilos viajam em AdditionalInformation[].Name = "PaymentForm.Styles" com o JSON de estilos em Base64. O branding do estabelecimento (nome + logo) vai em Name = "PaymentForm.Company". Ambos são enviados no OrderInitial e o formulário os aplica com prioridade sobre a configuração base.

Modelos de interfaz

É selecionado com FormMode na configuração. Você pode combinar qualquer modelo com qualquer tema de cor.

Capturas — la misma orden en las cuatro combinaciones

Com cartão e com produtos
Com cartão · com produtos
interactive-card · ShowProducts:true
Com cartão sem produtos
Com cartão · sem produtos
interactive-card · ShowProducts:false
Sem cartão com produtos
Sem cartão · com produtos
classic · ShowProducts:true
Sem cartão sem produtos
Sem cartão · sem produtos
classic · ShowProducts:false

Como configurar os estilos a partir do OrderInitial

Os estilos são enviados em AdditionalInformation como JSON em Base64. O formulário os aplica com prioridade sobre qualquer configuração padrão.

⚠️
Importante (Estrutura do JSON): O mecanismo de renderização do formulário suporta apenas três objetos raiz dentro do array de estilos: Background, Text e Form. Qualquer propriedade de personalização de campos ou cartões deve ser configurada dentro desses blocos (por exemplo, use Form.input_color em vez de um objeto Input independente). Objetos raiz legados como Card ou Input não são reconhecidos e serão ignorados.
Passo 1 — Monte o objeto de estilos
// Objeto de estilos (JSON plano antes de codificar)
const stylesArray = [
  { "Background": { "color": "#fcf9fb" } },
  { "Text": { "color": "#130a25" } },
  {
    "Form": {
      "background_color": "#fcf9fb",
      "button_color": "#a47fab",
      "price_color": "#68ac5c",
      "error_color": "#dc2626",
      "border_radius": "10px",
      "max_width": "520px",
      "input_color": "#ffffff",
      "input_innertext_color": "#130a25",
      "input_border_color": "#f3f3f4",
      "form_label": "orden",         // "pedido" | "orden" | "operacion" | "transaction"
      "show_cft": true,
      "show_tea": false,
      "show_interest_rate": true,
      "show_installment_calculation": false,
      "installment_calculation_mode": "simple"
    }
  }
];

const stylesB64 = btoa(JSON.stringify(stylesArray));  // codificar para Base64

// Branding do estabelecimento
const companyB64 = btoa(JSON.stringify({
  "Name": "Tu Comercio",
  "LogoUrl": "https://www.mi-tienda.com.ar/logo.png"   // URL pública — requer acesso a partir do browser do comprador
  // — ou —
  // "LogoUrl": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0i..."  // Data URI — zero requisições externas (recomendado para PCI)
}));

// Exemplo real de Data URI com um ícone SVG (64×64, fundo #004785)
// Você pode gerar o seu com: btoa(svgString) no browser, ou base64.b64encode(svg.encode()).decode() no Python
const iconoBase64 = "data:image/svg+xml;base64," +
  // PNG: ícone + branco sobre fundo #004785 (32×32 px)
  "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAc0lEQVR42u3WWw4AERQDULuzMuvmW+J1S+sRN36nJ0Zm1LnjxgdCYnsRo3HGFG1m4PQhYzK9Y9SfiaWxG1yguWszUDC4QO/cECAzxEBE51lg7I0jQM34Z7D/OyAA9//snrhwFHeyolUoepGi2Ym66Yp2nQBekRDCxivTugAAAABJRU5ErkJggg==";
Paso 2 — Incluirlos en OrderInitial
{
  "OrderInitial": {
    "MerchantSystemID": "SHOP-01",
    "MerchantCompanyID": "0",
    "TransactionAmount": 1000000,
    "CurrencyCode": "032",
    "ReferenceNumber": "ORD-2026-0001",
    "Products": [
      {
        "Code": "PLAN-PRO",
        "Name": "Plan Pro Mensual",
        "Quantity": 1,
        "UnitAmount": 1000000,
        "ImageUrl": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAc0lEQVR42u3WWw4AERQDULuzMuvmW+J1S+sRN36nJ0Zm1LnjxgdCYnsRo3HGFG1m4PQhYzK9Y9SfiaWxG1yguWszUDC4QO/cECAzxEBE51lg7I0jQM34Z7D/OyAA9//snrhwFHeyolUoepGi2Ym66Yp2nQBekRDCxivTugAAAABJRU5ErkJggg=="
        // ↑ PNG real 32×32 px — ícone + branco sobre fundo #004785 — 172 bytes / 232 chars base64
      }
    ],
    "AdditionalInformation": [
      {
        "Name": "PaymentForm.Styles",
        "Value": "<stylesB64>"   // resultado de btoa(JSON.stringify(stylesArray))
      },
      {
        "Name": "PaymentForm.Company",
        "Value": "<companyB64>"  // resultado de btoa(JSON.stringify(companyObj))
      }
    ]
  }
}

Tokens de estilo disponíveis

TokenObjetoDescriçãoExemplo
colorBackgroundCor de fundo da página#fcf9fb · #0f172a
colorTextCor dos textos principais del card#130a25 · #ffffff
background_colorFormCor de fundo do card do formulário#fcf9fb · #ffffff
button_colorFormCor do botão "Pagar"#a47fab · #004785
price_colorFormCor do valor total#68ac5c · #22c55e
error_colorFormCor das mensagens de erro de validação#dc2626 · #fb7185
input_colorFormCor de fundo dos campos de texto#ffffff · #f8fafc
input_innertext_colorFormCor do texto digitado nos campos#130a25 · #0f172a
input_border_colorFormCor da borda dos campos de texto#f3f3f4 · #e2e8f0
border_radiusFormArredondamento do card do formulário10px · 0
max_widthFormLargura máxima do formulário520px
form_labelFormTítulo do formulárioorden · pedido · operacion · transaction
show_cftFormHabilita/Desabilita a exibição do Custo Financiero Total (CFT) no seletor de parcelastrue · false
show_teaFormHabilita/Desabilita a exibição da Taxa Efetiva Anual (TEA) no seletor de parcelastrue · false
show_interest_rateFormHabilita/Desabilita a exibição da Taxa Nominal Anual (TNA) no seletor de parcelastrue · false
show_installment_calculationFormSe for true, calcula o valor de cada parcela aplicando os juros do plano em vez de uma divisão direta simplestrue · false
installment_calculation_modeFormFórmula para calcular a parcela com juros: simple (direto), french_tna (Francés TNA), french_tea (Francés TEA), cft (Francés CFT)simple · french_tna · french_tea · cft
header_alignFormAlinhamento horizontal do cabeçalho do pedidoleft · center · right
header_fontFormFamília tipográfica do cabeçalho do pedidoOutfit, sans-serif
header_sizeFormTamanho da fonte do cabeçalho do pedido14px · 0.875rem
header_colorFormCor do texto do cabeçalho do pedido#475569
button_alignFormAlinhamento e estiramento do botão de pagamentoflex-start · center · flex-end · stretch
button_widthFormLargura explícita do botão de pagamento200px · 100%
button_paddingFormEspaçamento interno (padding) do botão de pagamento12px 24px
button_font_sizeFormTamanho da fonte do botão de pagamento16px
button_icon_urlFormURL do ícone personalizado para substituir o cadeado padrãohttps://example.com/shield.png
amount_fontFormFamília tipográfica do valor do pagamentoInter, sans-serif
amount_font_sizeFormTamanho da fonte do valor do pagamento24px · 1.5rem
amount_colorFormCor do texto do valor do pagamento#16a34a
💡
Nota de Configuração: As seguintes propriedades correspondem à configuração padrão do Tenant (estabelecimento/plataforma). No entanto, você pode substituí-las dinamicamente para cada transação enviando-as no JSON de estilos (PaymentForm.Styles) dentro do bloco "Form" (ex: Styles[].Form.form_mode). Se não forem enviadas, a plataforma aplicará os valores pré-configurados para a sua conta ou os valores padrão do formulário.

Configuração do formulário

CampoTipoDefaultDescrição
FormModestringclassicclassic — formulario tradicional · interactive-card — tarjeta 3D interactiva (premium)
ShowProductsbooleantrueMostra ou oculta o detalhe dos produtos. Se false, o formulário fica mais compacto.
AllowInstallmentsbooleantrueHabilita o seletor de parcelas. Os planos disponíveis são determinados pelo BIN do cartão.
AllowAmountEditbooleanfalsePermite que o comprador modifique o valor antes de pagar.
ProductLayoutstringlistlist — vertical · grid — grade de 2 colunas · compact — sem imagens, ideal para carrinhos grandes
Localestringes-ARIdioma e formato. es-AR · en-US · pt-BR. Altera rótulos, formatos de data e moeda.
🖼️
Imagens de produtos: o campo ImageUrl em Products[] aceita URL pública ou Data URI base64. Quando base64 é usado, a imagem não gera requisições de rede externas — conformidade estrita com o PCI. As imagens também podem vir no Products[] retornado pelo Core.
Visualização — Data URI renderizado no browser
Ícone do produto
32×32 · PNG · 172 bytes
Ícone
Plan Pro Mensual
SKU: PLAN-PRO · x1
$10.000
A string enviada em ImageUrl:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAc0lEQVR42u3WWw4AERQDULuzMuvmW+J1S+sRN36nJ0Zm1LnjxgdCYnsRo... (232 caracteres · PNG 32×32 px)
Formato: data:<mime>;base64,<dados> — RFC 2397. O cabeçalho iVBORw0KGgo sempre identifica um PNG (bytes mágicos \x89PNG). Suporta image/png, image/jpeg, image/webp, image/svg+xml.
Como gerar o Data URI?
// Browser (JS)
const
reader =
new
FileReader();
reader.onload = e =>
console.log
(e.target.result);
reader.readAsDataURL(imageFile);
# Python
import
base64
with
open
("logo.png", "rb") as f:
  b64 = base64.b64encode(f.read()).decode()
uri = f"data:image/png;base64,{b64}"
# Node.js
const fs = require('fs');
const b64 = fs.readFileSync('logo.png')
  .toString('base64');
const uri = `data:image/png;base64,${b64}`;
Sandbox & Testing

Dados de teste

Use estes cartões e cenários no ambiente sandbox da PROCASH.

Cartões de teste

Número do cartão Bandeira CVV Vencimento Resultado
4111 1111 1111 1111 Visa 123 12/28 ✅ Aprovada
4000 0000 0000 0002 Visa 123 12/28 ❌ Recusada
5555 5555 5555 4444 Mastercard 123 12/28 ✅ Aprovada
5105 1051 0510 5100 Mastercard 123 12/28 ❌ Recusada

ResponseActions — valores possíveis

ResponseActions é um array — sempre pode conter múltiplos valores ao mesmo tempo. OK e Completed sempre acompanham Approve ou Refuse quando o circuito está completo.

ResponseActions (array) ResponseCode Significado
["OK", "Approve", "Completed"] -1 ✅ Pagamento aprovado · circuito fechado
["OK", "Approve", "Tickets", "Completed"] -1 ✅ Aprovado + comprovantes disponíveis
["OK", "Refuse", "Completed"] 05 (ej.) ❌ Recusado — o código é informativo e pode variar
⚠️ Os valores de ResponseCode são apenas exemplos. Existe uma grande variedade de códigos possíveis de acordo com o emissor e a plataforma. A fonte de verdade é sempre a action Refuse ou Error em ResponseActions — esse é o indicador real de que o pagamento não foi aprovado, independentemente do código.
💡
Lógica de código correta:
actions.includes('Approve') → aprovado, creditar.
actions.includes('Refuse') → recusado, não cobrado.
actions.includes('Completed') → o estabelecimento executou o OrderFinal e fechou o ciclo.
actions.includes('Tickets') → renderizar Tickets[] para o comprador.

Pagamento NÃO aprovado: includes('Refuse') ou includes('Error') são os únicos indicadores reais de recusa. ResponseCode e ResponseMessage são informativos e podem variar — nunca os use como critérios de decisão.

Cenários de teste

Cenários configuráveis no sandbox — consulte a equipe da PROCASH para ativá-los.

baseline
Fluxo padrão aprovado sem fricção
refused-response
Resposta recusada pelo emissor
3ds-frictionless
3DS sem challenge — aprovação automática
3ds-snap-challenge
3DS com challenge interativo
high-risk
Transação de alto risco — revisão adicional

Métodos de pago en sandbox

MétodoDisponível no sandboxNotas
💳 Cartão de crédito (parcelas) ✅ Sí Visa, Mastercard, Amex · hasta 12 cuotas según plan del BIN
💳 Cartão de débito ✅ Sí Apenas 1 parcela · PIN não requerido no canal CNP
📱 QR dinâmico ⚡ De acordo com config. Requer habilitação na plataforma · consulte a equipe da PROCASH
🏦 Transferência / CVU ⚡ De acordo com config. Disponível se o plano incluir · o formulário mostra o CVU de destino

Endpoints Sandbox

S2S https://api.procash.dev · Gateway / API Core
WEB https://payment.procash.dev · PaymentForm (formulário hospedado)
API Reference

Referência rápida

Campos principais da requisição OrderInitial.

Campo Tipo Obrigatório Descrição
MerchantSystemID string ✅ Sí Identificador do sistema merchant (lojista)
MerchantCompanyID string ✅ Sí ID da empresa
MerchantBranch string Não se aplica Não é utilizado na integração web CNP. A plataforma o resolve por meio da configuração do estabelecimento.
MerchantPOSID string Não se aplica Não é utilizado na integração web CNP. A plataforma o resolve por meio da configuração do estabelecimento.
TransactionAmount integer ✅ Sí Valor em centavos (ex: 1000000 = $10.000,00 ARS)
CurrencyCode string ⚡ Desejável ISO 4217 — 032 = ARS (Pesos argentinos). Se omitido, a plataforma assume a moeda do país do estabelecimento. Recomenda-se enviá-lo sempre.
ReferenceNumber string ✅ Sí Seu ID interno do pedido (para reconciliação)
MerchantRedirectURL string Opcional URL para a qual o comprador retorna após o pagamento. Se omitida, não há redirect: o formulário exibe diretamente o resultado final (aprovado / recusado) sem sair da página do formulário.
MerchantNotifyURL string ⚡ Recom. Webhook — o Core notifica o resultado de forma assíncrona
Products array Opcional Detalhe dos produtos para exibir no formulário
FacilityNumber integer Opcional Quantidade de parcelas (1 = à vista, 3/6/12… = parcelas). Requer plano financeiro habilitado para o BIN.
TaxIdentification string Opcional Identificador tributário do comprador — CUIT/CUIL para a Argentina (ex: 20-12345678-9)

Valores em ARS — formato

O campo TransactionAmount vai em centavos (sem vírgula decimal). Use o ponto como separador de milhares e a vírgula para decimais ao exibi-lo ao usuário.

Valor para o usuárioTransactionAmountNota
$1.000,00 ARS100000Mil pesos
$5.000,00 ARS500000Cinco mil pesos
$10.000,00 ARS1000000Dez mil pesos
$50.000,00 ARS5000000Cinquenta mil pesos
$100.000,00 ARS10000000Cem mil pesos

💡 Para converter: TransactionAmount = Math.round(valorPesos * 100)

Flujo resumido

1️⃣
OrderInitial
Tu server → Gateway
Obtenha token + ID
2️⃣
Redirect
Browser → PaymentForm
Comprador insere o cartão
3️⃣
Retorno
Browser → sua MerchantRedirectURL
+ webhook assíncrono
4️⃣
OrderFinal
Tu server → Gateway
Confirme o resultado real
✅
Dúvidas? Entre em contato com a equipe de integração da PROCASH. Mencione o número do contrato PROCASH Payments API v5.8.2 na sua consulta.
Elementos opcionais do OrderInitial

Seller · Payer · Customer · Shipping

O OrderInitial aceita quatro objetos opcionais que enriquecem a transação com dados das partes envolvidas. Todos são opcionais — incluí-los permite maior rastreabilidade, análise antifraude e conformidade regulatória.

ℹ️
Payer vs Customer: se o Payer não estiver presente, a plataforma usará os dados de Customer como pagador. Na maioria dos casos de e-commerce, eles são a mesma pessoa — basta enviar Customer.

Dados do comprador/cliente. É o objeto mais comum no e-commerce. Se o Payer não for enviado, estes dados serão usados também como pagador.

CampoTipoDescrição
FirstNamestringPrimeiro nome
LastNamestringSobrenome
MiddleNamestringNome(s) do meio
EmailstringE-mail do cliente
PhonestringNúmero de telefone
DocumentTypeenumCI · PAS · ACCOUNT_NUMBER · CONTRACT · OTHER
DocumentNumberstringNúmero do documento
TaxIdentificationTypestringTipo de identificador tributário — na Argentina: CUIT ou CUIL
TaxIdentificationstringNúmero do CUIT/CUIL ou outro identificador tributário
AddressStreetstringRua
AddressNumberstringNúmero
AddressInternalstringAndar, apto, unidade
AddressSuburbstringBairro
CitystringCidade
StatestringEstado
CountrystringPaís
ZipCodestringCódigo postal
NotifyURLstringURL de notificação específica para o cliente
Exemplo — Customer no OrderInitial (Argentina)
{
  "OrderInitial": {
    "MerchantSystemID": "SHOP-01",
    "MerchantCompanyID": "0",
    "TransactionAmount": 1000000,
    "CurrencyCode": "032",
    "ReferenceNumber": "ORD-2026-0001",
    "Customer": {
      "FirstName": "María",
      "LastName": "González",
      "Email": "maria.gonzalez@email.com",
      "Phone": "1123456789",
      "DocumentType": "CI",
      "DocumentNumber": "12345678",
      "TaxIdentificationType": "CUIL",
      "TaxIdentification": "27-12345678-3",
      "AddressStreet": "Av. Corrientes",
      "AddressNumber": "1234",
      "AddressInternal": "Piso 3 Dpto B",
      "City": "Buenos Aires",
      "State": "CABA",
      "Country": "AR",
      "ZipCode": "C1043"
    }
  }
}

Dados do pagador — a pessoa que efetua o pagamento com o seu cartão. Mesmo schema de Customer. Necessário apenas quando o pagador é diferente do comprador (ex: alguém que paga em nome de outra pessoa).

CampoTipoDescrição
FirstNamestringPrimeiro nome del pagador
LastNamestringSobrenome del pagador
EmailstringE-mail do pagador
PhonestringTelefone do pagador
DocumentTypeenumCI · PAS · ACCOUNT_NUMBER · CONTRACT · OTHER
DocumentNumberstringNúmero do documento del pagador
TaxIdentificationTypestringTipo de identificador tributário — na Argentina: CUIT ou CUIL
TaxIdentificationstringNúmero do CUIT/CUIL do pagador
AddressStreet · AddressNumber · City · State · Country · ZipCodestringEndereço completo do pagador
NotifyURLstringURL de notificação específica para o pagador
💡
Na maioria dos casos de e-commerce, o comprador e o pagador são a mesma pessoa — envie apenas Customer e omita Payer. A plataforma usará Customer como pagador automaticamente.

Dados do vendedor. Útil em modelos de marketplace ou quando o estabelecimento precisa identificar o vendedor específico dentro da plataforma.

CampoTipoDescrição
FirstNamestringNome do vendedor
LastNamestringSobrenome del vendedor
EmailstringE-mail do vendedor
DocumentTypeenumCI · PAS · ACCOUNT_NUMBER · CONTRACT · OTHER
DocumentNumberstringNúmero do documento del vendedor
TaxIdentificationTypestringTipo de identificador tributário — na Argentina: CUIT
TaxIdentificationstringCUIT do vendedor
IdentificationstringIdentificador interno do vendedor na plataforma
IdentificationTypeenumTipo de identificador: CI · PAS · ACCOUNT_NUMBER · CONTRACT · OTHER
AddressStreet · AddressNumber · City · State · CountrystringEndereço do vendedor
Exemplo — Seller no OrderInitial (marketplace)
{
  "OrderInitial": {
    // ... campos base ...
    "Seller": {
      "Identification": "SELLER-0042",
      "IdentificationType": "CONTRACT",
      "FirstName": "Distribuidora",
      "LastName": "Sur S.A.",
      "TaxIdentificationType": "CUIT",
      "TaxIdentification": "30-71234567-8",
      "Email": "ventas@distribuidorasur.com.ar"
    }
  }
}

Endereço de entrega do pedido. Independente do endereço de cobrança do comprador. Necessário quando o envio físico faz parte do fluxo.

CampoTipoMaxDescrição
FirstNamestring100Nome do destinatário
LastNamestring100Sobrenome del destinatario
Address1string255Endereço principal (rua e número)
Address2string255Complemento (piso, dpto, unidad)
Citystring100Cidade de entrega
StateProvincestring100Estado
Countrystring50País (ej: AR)
ZipCodestring20Código postal
PhoneNumberstring50Telefone de contato para a entrega
Emailstring255E-mail de contato para notificações de envio
Exemplo — Shipping no OrderInitial
{
  "OrderInitial": {
    // ... campos base + Customer ...
    "Shipping": {
      "FirstName": "María",
      "LastName": "González",
      "Address1": "Av. Corrientes 1234",
      "Address2": "Piso 3 Dpto B",
      "City": "Buenos Aires",
      "StateProvince": "CABA",
      "Country": "AR",
      "ZipCode": "C1043",
      "PhoneNumber": "1123456789",
      "Email": "maria.gonzalez@email.com"
    }
  }
}

Ejemplo completo — todos los objetos

OrderInitial com Customer + Shipping (caso de e-commerce típico na Argentina)
{
  "OrderInitial": {
    "MerchantSystemID": "SHOP-01",
    "MerchantCompanyID": "0",
    "TransactionAmount": 1000000,       // $10.000,00 ARS
    "CurrencyCode": "032",
    "ReferenceNumber": "ORD-2026-0001",
    "FacilityNumber": 3,               // 3 parcelas
    "MerchantRedirectURL": "https://www.mi-tienda.com.ar/pago/retorno",
    "MerchantNotifyURL": "https://www.mi-tienda.com.ar/webhooks/pago",
    "Products": [
      { "Code": "PROD-001", "Name": "Zapatillas Running", "Quantity": 1, "UnitAmount": 1000000 }
    ],
    "Customer": {              // comprador = pagador (caso mais comum)
      "FirstName": "María",
      "LastName": "González",
      "Email": "maria.gonzalez@email.com",
      "Phone": "1123456789",
      "DocumentType": "CI",
      "DocumentNumber": "12345678",
      "TaxIdentificationType": "CUIL",
      "TaxIdentification": "27-12345678-3"
    },
    "Shipping": {             // endereço de entrega (pode ser diferente do de Customer)
      "FirstName": "María",
      "LastName": "González",
      "Address1": "Av. Corrientes 1234",
      "Address2": "Piso 3 Dpto B",
      "City": "Buenos Aires",
      "StateProvince": "CABA",
      "Country": "AR",
      "ZipCode": "C1043",
      "PhoneNumber": "1123456789",
      "Email": "maria.gonzalez@email.com"
    }
    // Seller apenas se for marketplace — Payer apenas se for diferente de Customer
  }
}