Integração Host-to-Host
Quick Reference
Host-to-Host (H2H) é integração por API direta: seu backend chama a A55 com dados do cartão e do pedido. Você mantém controle total sobre novas tentativas, idempotência e tratamento de erros.
Por que H2H (comparação)
| Critério | H2H | SDK | Checkout Page |
|---|---|---|---|
| Segurança dos dados | Você gerencia o transporte | A55 protege via SDK | A55 gerencia tudo |
| Nível de controle | Total | Parcial | Mínimo |
| Tratamento dos dados do cartão | Seu servidor | SDK no navegador | Hospedado pela A55 |
| Gestão do 3DS | Você trata o redirecionamento | O SDK trata | A A55 trata |
| Ideal para | Equipes com controle total do servidor | Mercado médio | Low-code / no-code |
Quando usar
- Você tem infraestrutura para manipular dados de cartão com segurança (transporte HTTPS, sem armazenamento local).
- Você precisa de controle máximo no lado do servidor sobre o ciclo de vida da cobrança.
- Você implementará redirecionamentos 3DS quando a API retornar
pendingeurl_3ds.
Campos de cartão (corpo da requisição)
| Campo | Descrição |
|---|---|
card_name | Nome do portador conforme impresso no cartão |
card_number | Primary Account Number (PAN) |
card_expiry_month | Mês de validade (1–12) |
card_expiry_year | Ano de validade (quatro dígitos) |
card_cvv | Card verification value |
Fluxo técnico
Integração passo a passo
Obter um token de acesso
- cURL
- Python
- Node.js
- Go
- Java
- PHP
curl -s -X POST "https://a55-auth.auth.us-east-1.amazoncognito.com/oauth2/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials&client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET"
import os, requests
resp = requests.post(
"https://a55-auth.auth.us-east-1.amazoncognito.com/oauth2/token",
data={"grant_type": "client_credentials",
"client_id": os.environ["CLIENT_ID"],
"client_secret": os.environ["CLIENT_SECRET"]},
headers={"Content-Type": "application/x-www-form-urlencoded"},
)
access_token = resp.json()["access_token"]
const resp = await fetch(
"https://a55-auth.auth.us-east-1.amazoncognito.com/oauth2/token",
{
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: "grant_type=client_credentials"
+ "&client_id=" + process.env.CLIENT_ID
+ "&client_secret=" + process.env.CLIENT_SECRET,
}
);
const { access_token } = await resp.json();
data := url.Values{
"grant_type": {"client_credentials"},
"client_id": {os.Getenv("CLIENT_ID")},
"client_secret": {os.Getenv("CLIENT_SECRET")},
}
resp, _ := http.PostForm(
"https://a55-auth.auth.us-east-1.amazoncognito.com/oauth2/token", data)
defer resp.Body.Close()
var tok struct{ AccessToken string `json:"access_token"` }
json.NewDecoder(resp.Body).Decode(&tok)
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://a55-auth.auth.us-east-1.amazoncognito.com/oauth2/token"))
.header("Content-Type", "application/x-www-form-urlencoded")
.POST(HttpRequest.BodyPublishers.ofString(
"grant_type=client_credentials&client_id=" + CLIENT_ID
+ "&client_secret=" + CLIENT_SECRET))
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
String accessToken = new JSONObject(resp.body()).getString("access_token");
$ch = curl_init("https://a55-auth.auth.us-east-1.amazoncognito.com/oauth2/token");
curl_setopt_array($ch, [
CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["Content-Type: application/x-www-form-urlencoded"],
CURLOPT_POSTFIELDS => http_build_query([
"grant_type" => "client_credentials",
"client_id" => getenv("CLIENT_ID"),
"client_secret" => getenv("CLIENT_SECRET"),
]),
]);
$token = json_decode(curl_exec($ch))->access_token;
Montar e enviar a cobrança
POST https://core-manager.a55.tech/api/v1/bank/wallet/charge/
- cURL
- Python
- Node.js
- Go
- Java
- PHP
curl -sS -X POST 'https://core-manager.a55.tech/api/v1/bank/wallet/charge/' \
-H 'Authorization: Bearer $ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: ord_001' \
-d '{
"wallet_uuid": "00000000-0000-4000-8000-000000000001",
"merchant_id": "merchant_123",
"payer_name": "Jane Doe",
"payer_email": "jane@example.com",
"payer_cell_phone": "+5511999999999",
"payer_tax_id": "12345678901",
"items": [{"name": "Order", "quantity": 1, "value": 10000}],
"payer_address": {"street": "Av. Paulista 1000", "city": "São Paulo", "state": "SP", "zip_code": "01310100", "country": "BR"},
"currency": "BRL",
"installment_value": 10000,
"installment_count": 1,
"due_date": "2026-12-31",
"description": "H2H charge",
"type_charge": "credit_card",
"card_name": "JANE DOE",
"card_number": "4111111111111111",
"card_expiry_month": 12,
"card_expiry_year": 2030,
"card_cvv": "123",
"reference_external_id": "ord_001",
"threeds_authentication": false,
"webhook_url": "https://merchant.example/webhooks/a55",
"redirect_url": "https://merchant.example/return"
}'
import os, requests
r = requests.post(
"https://core-manager.a55.tech/api/v1/bank/wallet/charge/",
headers={
"Authorization": f"Bearer {os.environ['ACCESS_TOKEN']}",
"Content-Type": "application/json",
},
json={
"wallet_uuid": "00000000-0000-4000-8000-000000000001",
"merchant_id": "merchant_123",
"payer_name": "Jane Doe", "payer_email": "jane@example.com",
"payer_tax_id": "12345678901",
"currency": "BRL", "installment_value": 10000, "installment_count": 1,
"type_charge": "credit_card",
"card_name": "JANE DOE", "card_number": "4111111111111111",
"card_expiry_month": 12, "card_expiry_year": 2030, "card_cvv": "123",
"reference_external_id": "ord_001",
"threeds_authentication": False,
"webhook_url": "https://merchant.example/webhooks/a55",
},
timeout=60,
)
print(r.status_code, r.json())
const res = await fetch(
"https://core-manager.a55.tech/api/v1/bank/wallet/charge/",
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.ACCESS_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
wallet_uuid: "00000000-0000-4000-8000-000000000001",
merchant_id: "merchant_123",
payer_name: "Jane Doe", payer_email: "jane@example.com",
payer_tax_id: "12345678901",
currency: "BRL", installment_value: 10000, installment_count: 1,
type_charge: "credit_card",
card_name: "JANE DOE", card_number: "4111111111111111",
card_expiry_month: 12, card_expiry_year: 2030, card_cvv: "123",
reference_external_id: "ord_001",
threeds_authentication: false,
webhook_url: "https://merchant.example/webhooks/a55",
}),
}
);
console.log(await res.json());
payload := map[string]interface{}{
"wallet_uuid": "00000000-0000-4000-8000-000000000001",
"type_charge": "credit_card",
"card_name": "JANE DOE", "card_number": "4111111111111111",
"card_expiry_month": 12, "card_expiry_year": 2030, "card_cvv": "123",
"currency": "BRL", "installment_value": 10000, "installment_count": 1,
"reference_external_id": "ord_001",
"threeds_authentication": false,
"webhook_url": "https://merchant.example/webhooks/a55",
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST",
"https://core-manager.a55.tech/api/v1/bank/wallet/charge/", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("ACCESS_TOKEN"))
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
io.Copy(os.Stdout, resp.Body)
String json = """
{"wallet_uuid":"00000000-0000-4000-8000-000000000001",
"type_charge":"credit_card","card_name":"JANE DOE",
"card_number":"4111111111111111","card_expiry_month":12,
"card_expiry_year":2030,"card_cvv":"123",
"currency":"BRL","installment_value":10000,"installment_count":1,
"reference_external_id":"ord_001","threeds_authentication":false,
"webhook_url":"https://merchant.example/webhooks/a55"}
""";
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://core-manager.a55.tech/api/v1/bank/wallet/charge/"))
.header("Authorization", "Bearer " + System.getenv("ACCESS_TOKEN"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(json)).build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());
$payload = [
"wallet_uuid" => "00000000-0000-4000-8000-000000000001",
"type_charge" => "credit_card",
"card_name" => "JANE DOE", "card_number" => "4111111111111111",
"card_expiry_month" => 12, "card_expiry_year" => 2030, "card_cvv" => "123",
"currency" => "BRL", "installment_value" => 10000, "installment_count" => 1,
"reference_external_id" => "ord_001", "threeds_authentication" => false,
"webhook_url" => "https://merchant.example/webhooks/a55",
];
$ch = curl_init("https://core-manager.a55.tech/api/v1/bank/wallet/charge/");
curl_setopt_array($ch, [
CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("ACCESS_TOKEN"),
"Content-Type: application/json",
"Idempotency-Key: ord_001"],
CURLOPT_POSTFIELDS => json_encode($payload),
]);
echo curl_exec($ch);
Tratar a resposta
- Confirmado
- 3DS pendente
- Erro
{
"uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "confirmed",
"reference_external_id": "ord_001"
}
{
"uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "pending",
"url_3ds": "https://confirmacion.a55.tech/charge/a1b2c3d4...",
"reference_external_id": "ord_001"
}
Redirecione o comprador para url_3ds. Consulte 3D Secure para o tratamento do desafio.
{
"uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "error",
"message": [{"message": "Declined or validation failed"}],
"code": "CARD_DECLINED"
}
Tratar o redirecionamento 3DS (se pendente)
Se a resposta incluir url_3ds, redirecione o comprador e escute o evento de conclusão:
window.addEventListener('message', function (event) {
if (event.data?.event === '3ds-auth-complete') {
const chargeUuid = event.data.chargeUuid;
// Fetch charge status and update your UI
}
});
Confirmar via webhook
Configure webhook_url para receber atualizações de status assíncronas mesmo se o comprador fechar o navegador.
{
"charge_uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "paid",
"transaction_reference": "txn_ref_001"
}
Testar com cartões de sandbox
| Card Number | Brand | Scenario | Expected Status |
|---|---|---|---|
4111 1111 1111 1111 | Visa | Pagamento bem-sucedido | confirmed |
5500 0000 0000 0004 | Mastercard | Pagamento bem-sucedido | confirmed |
4000 0000 0000 0002 | Visa | Cartão recusado | declined |
4000 0000 0000 0101 | Visa | Desafio 3DS necessário | confirmed |
4000 0000 0000 0069 | Visa | Erro de processamento | error |
5105 1051 0510 5100 | Mastercard | Saldo insuficiente | declined |
Quer taxas de aprovação mais altas?
Visa Data Only envia dados enriquecidos da transação para os emissores pelas trilhas do 3DS — sem redirecionamento de desafio. O piloto da Square com mais de 6 milhões de transações mostrou ganho de até +646 pontos-base na aprovação.
Se você já envia device_info para 3DS, já tem os dados. Basta definir data_only: true em vez de threeds_authentication: true.
Trade-off: não há transferência de responsabilidade por fraude (o lojista assume o risco). Para alto volume e baixo risco na América Latina, o ganho de aprovação costuma superar o custo de fraude.