Integração de API de pagamento cripto: cobranças, assinaturas e webhooks
Um guia prático para desenvolvedores: uma requisição assinada para criar a cobrança, um endpoint de webhook para receber o status e os detalhes de segurança que tornam tudo confiável.

Uma integração de API de pagamento cripto precisa de duas peças: uma requisição do lado do servidor que cria uma cobrança (invoice) para cada pedido e devolve uma URL de checkout, e um endpoint de webhook que recebe atualizações de status assinadas quando o pagamento é detectado e confirmado na blockchain. Com o mistKET, as duas são HTTPS e JSON simples, assinados com HMAC-SHA256 — sem precisar de SDK.
Este guia percorre o fluxo completo com código e depois cobre os detalhes de segurança e confiabilidade que separam uma demo de um sistema em produção.
A arquitetura de uma API de pagamento cripto em uma imagem
Toda integração de API de pagamento cripto segue o mesmo ciclo de cinco etapas:
- Pedido criado — seu backend chama
POST /api/v1/invoicescom valor, moeda, ID do pedido e URL de callback. - Redirecionamento — você envia o cliente para a
checkout_urlretornada. - Pagamento — o cliente escolhe uma rede e paga na página hospedada; a cotação fica travada durante a validade da cobrança.
- Webhook — o mistKET faz um POST de
invoice.paid,invoice.confirmedou de um evento de exceção para a sua URL de callback. - Entrega — você verifica a assinatura, marca o pedido como pago e entrega.
Sua API key, sua API secret e sua webhook secret são emitidas no painel do lojista depois que sua conta é aprovada. A referência completa fica no painel, na seção API.
Etapa 1: assine e envie a requisição da cobrança
Toda requisição à API leva três cabeçalhos. A assinatura é o HMAC-SHA256 em hexadecimal da string {timestamp}.{raw body} usando sua API secret:
POST /api/v1/invoices
X-Api-Key: mp_live_…
X-Api-Timestamp: 1760000000
X-Api-Signature: hex(hmac_sha256("{ts}.{body}", secret))
{
"amount": "184.50",
"currency": "USD",
"order_id": "2041",
"callback_url": "https://yourstore.com/webhooks/mistket"
} Uma versão mínima em PHP fica assim:
$body = json_encode([
'amount' => '184.50', 'currency' => 'USD',
'order_id' => '2041',
'callback_url' => 'https://yourstore.com/webhooks/mistket',
]);
$ts = (string) time();
$sig = hash_hmac('sha256', $ts . '.' . $body, $apiSecret);
// envie $body com X-Api-Key, X-Api-Timestamp, X-Api-Signature Assine exatamente os bytes que você envia. Recodificar o JSON depois de assinar (espaçamento ou ordem de chaves diferentes) é a causa número um de erros de assinatura.
Etapa 2: redirecione para o checkout hospedado
Uma chamada bem-sucedida retorna 201 Created com o UUID da cobrança, seu status (new) e uma checkout_url. Salve o UUID junto com o pedido e redirecione o cliente. A página hospedada mostra o valor exato, um QR code, uma contagem regressiva e o status ao vivo, e funciona no celular. O cliente escolhe a rede ali — USDT na TRON, BNB Smart Chain, Ethereum ou Arbitrum, além de TRX, BNB e ETH — a menos que você fixe a rede na chamada da API.
Além de criar cobranças, a API permite listar, consultar e cancelar cobranças, o que é útil quando um carrinho muda ou um pedido é abandonado.
Etapa 3: receba e verifique os webhooks de pagamento cripto
Quando o status muda, o mistKET faz um POST com JSON para a sua URL de callback com estes cabeçalhos:
| Cabeçalho | Função |
|---|---|
X-Mistket-Event | Nome do evento, ex.: invoice.confirmed |
X-Mistket-Timestamp | Horário Unix usado na assinatura |
X-Mistket-Signature | sha256= + HMAC-SHA256 de {timestamp}.{raw body} com sua webhook secret |
X-Mistket-Delivery | ID da entrega, útil para logs |
Verificação em PHP:
$raw = file_get_contents('php://input');
$ts = $_SERVER['HTTP_X_MISTKET_TIMESTAMP'] ?? '';
$got = $_SERVER['HTTP_X_MISTKET_SIGNATURE'] ?? '';
$exp = 'sha256=' . hash_hmac('sha256', $ts . '.' . $raw, $webhookSecret);
if (!hash_equals($exp, $got) || abs(time() - (int) $ts) > 300) {
http_response_code(401); exit;
}
$event = json_decode($raw, true); Use uma comparação em tempo constante (hash_equals no PHP, hmac.compare_digest no Python, crypto.timingSafeEqual no Node.js) e rejeite timestamps antigos para bloquear ataques de repetição. Para entender o fundamento, veja a RFC 2104 (HMAC).
Exemplo de payload de webhook
Um pagamento confirmado chega como um documento JSON compacto. Os campos que você mais vai usar são o evento, o ID do pedido, o status e os valores esperado e recebido:
POST https://yourstore.com/webhooks/mistket
X-Mistket-Event: invoice.confirmed
X-Mistket-Signature: sha256=…
{ "event": "invoice.confirmed", "data": {
"order_id": "2041", "status": "confirmed",
"pay_amount": "184.5", "paid_amount": "184.5",
"pay_currency": "USDT", "network": "TRC20" } } Salve pay_currency e network junto com o pedido. Eles ajudam na contabilidade e em conversas com o suporte mais tarde.
Verificação em Node.js e Python
A mesma checagem em outras duas linguagens populares:
// Node.js (Express com express.raw nesta rota)
const exp = 'sha256=' + crypto.createHmac('sha256', secret)
.update(ts + '.' + rawBody).digest('hex');
const ok = crypto.timingSafeEqual(Buffer.from(exp), Buffer.from(sig));
# Python
exp = 'sha256=' + hmac.new(secret.encode(), f'{ts}.{raw}'.encode(),
hashlib.sha256).hexdigest()
ok = hmac.compare_digest(exp, sig) Nos dois casos, garanta que você está lendo o corpo bruto da requisição. Muitos frameworks fazem o parse do JSON automaticamente; depois de parseado e serializado de novo, os bytes não batem mais com a assinatura.
Testando localmente
Webhooks precisam de uma URL HTTPS pública, então um notebook local não consegue recebê-los diretamente. Há duas opções práticas: publicar cedo o handler em um servidor de homologação ou expor temporariamente sua porta local com uma ferramenta de túnel. Crie cobranças pequenas apontando para o callback de homologação e confira os logs de entrega no painel do lojista para ver exatamente o que foi enviado e o que seu servidor respondeu.
Tente disparar cada tipo de evento pelo menos uma vez durante os testes: paid, confirmed, underpaid e expired. Quando cada ramo do seu handler tiver rodado com um webhook real, sobra muito pouco para te surpreender em produção, e você saberá exatamente como ficam os logs de entrega quando algo der errado.
Etapa 4: trate cada status
O payload do webhook inclui o ID do pedido, o status, o valor esperado (pay_amount), o valor recebido (paid_amount), a moeda e a rede. Associe cada evento a uma ação:
| Evento | Significado | Ação típica |
|---|---|---|
invoice.paid | Transferência detectada, confirmações pendentes | Mostrar "pagamento recebido, confirmando" |
invoice.confirmed | Confirmações necessárias atingidas | Marcar como pago e entregar |
invoice.underpaid | Abaixo da sua tolerância | Aguardar complemento ou falar com o cliente |
invoice.overpaid | Mais do que o esperado | Entregar; decidir o que fazer com a diferença |
invoice.expired | Nenhum pagamento válido no prazo | Liberar estoque, manter o pedido não pago |
Tolerância de pagamento a menor, pagamentos parciais que somam o total e pagamentos atrasados dentro de um período de carência são tratados pelo mistKET; seu código só reage ao resultado final.
Confiabilidade: reenvios e idempotência
Se o seu endpoint estiver fora do ar ou retornar erro, os webhooks são reenviados com back-off por horas. Ou seja, às vezes você vai receber o mesmo evento duas vezes. Deixe seu handler idempotente pelo ID do pedido:
- Responda rápido com um 2xx e processe o trabalho pesado em uma fila.
- Antes de entregar, verifique se o pedido já está marcado como pago.
- Registre o ID da entrega e o evento para rastrear problemas; o painel também mostra os logs de entrega dos webhooks.
Checklist de segurança
Uma integração de API de pagamento cripto lida com dinheiro, então trate-a como qualquer outro código de pagamento:
- Mantenha a API secret e a webhook secret só no servidor — nunca no front-end nem em apps móveis.
- Restrinja o acesso à API com a lista de IPs permitidos do painel.
- Rejeite requisições fora de uma janela curta de timestamp.
- Configure a expiração das cobranças de acordo com sua lógica de reserva de estoque.
- Trate valores como strings ou decimais, nunca como floats.
Próximos passos
Essa é a integração completa de uma API de pagamento cripto: uma requisição assinada, um webhook verificado e um mapa de status. Para a visão não técnica do mesmo fluxo, leia como aceitar pagamentos em cripto no seu site. Está criando um bot em vez de um site? Veja como aceitar pagamentos cripto em um bot do Telegram. Peça suas chaves de API no Telegram @mistnetwork, confira o exemplo na seção para desenvolvedores e gerencie as chaves no login do lojista.


