Botão de pagamento em cripto para sites
Como adicionar um botão «Pagar com cripto» a um site: por que o botão não pode chamar a API de pagamentos diretamente, o padrão de três passos, código funcional de front-end e servidor, e o que proteger.

Um botão «Pagar com cripto» é fácil de adicionar, mas não pode ser um trecho para copiar e colar: criar um pagamento exige sua chave de API secreta, que nunca deve chegar ao navegador. O botão precisa, portanto, falar com o seu próprio servidor, que cria o pagamento e devolve o endereço da página de pagamento. Este guia mostra esse padrão com código funcional e os pontos que o mantêm seguro.
Por que ainda não há um botão para copiar e colar
Muitos provedores de pagamento oferecem um botão ou widget incorporável. A Qvard ainda não tem botão sem código: os links de pagamento estão em desenvolvimento. O checkout incorporado já está pronto para o seu site. Os SDKs estão prontos. Hoje a integração é pela API, e a API se autentica com uma chave secreta no cabeçalho Authorization: Bearer.
Essa chave pode criar pagamentos do seu projeto, então deve ficar no seu servidor. Um botão que levasse a chave em código de front-end a entregaria a cada visitante. Não é uma limitação a contornar; é o motivo de o padrão abaixo ter uma etapa no servidor.
O padrão: botão, seu endpoint, página de pagamento
Três passos formam um botão que funciona:
- O botão envia uma requisição a um endpoint do seu servidor, dizendo o que o visitante quer comprar (um produto, um plano), não quanto custa.
- Seu endpoint busca o preço, cria seu próprio registro de pedido e chama a Qvard: um
POSTparahttps://api.qvard.com/api/v1/paymentcom a chave no cabeçalhoAuthorization: Bearere um JSON com o número do pedido comoide o valor comopriceem dólares americanos. A resposta é201com umredirectUrl. - O navegador é redirecionado para esse
redirectUrl, a página de pagamento hospedada da Qvard, onde o visitante escolhe um ativo e uma rede e paga de uma carteira.
Nada secreto toca a página, e a própria página de pagamento é hospedada pela Qvard, então você não constrói um checkout cripto.
O front-end: um botão e um redirecionamento
O botão precisa de cerca de quinze linhas. Ele se desativa enquanto a requisição roda, envia o identificador do produto e, em caso de sucesso, leva o navegador ao endereço devolvido. Em caso de falha, volta a ficar ativo e mostra uma mensagem, para o visitante tentar de novo.
Tenha em mente uma regra: o navegador envia o que é comprado, nunca quanto. Se o valor viesse da página, qualquer um poderia abrir as ferramentas de desenvolvedor e transformar um plano de 49 dólares em um pagamento de um dólar.
<button id="pay-crypto" data-product="pro-plan">Pay with crypto</button>
<script>
document.getElementById('pay-crypto').addEventListener('click', async (event) => {
const button = event.currentTarget;
button.disabled = true;
try {
// Send only WHAT is being bought; the server decides the price.
const res = await fetch('/api/crypto-checkout', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ product: button.dataset.product })
});
if (!res.ok) throw new Error('checkout failed');
const { redirectUrl } = await res.json();
window.location.assign(redirectUrl); // the Qvard hosted payment page
} catch (e) {
button.disabled = false;
alert('Could not start the payment. Please try again.');
}
});
</script>O servidor: preço, pedido, pagamento
O endpoint do exemplo faz quatro coisas:
- Busca o preço em uma tabela no servidor e rejeita produtos desconhecidos.
- Cria o seu pedido e usa o número dele como
iddo pagamento. É assim que o webhook depois encontra o pedido. - Chama a Qvard e devolve ao navegador apenas o
redirectUrl. Uma resposta400(«Error validation», com uma mensagem por campo) significa que o corpo estava errado; um401significa que a chave está errada. Nenhum dos dois deve ser repetido sem mudança. - É seguro repetir. Enviar o mesmo
idpara o mesmo método de pagamento devolve o pagamento existente, então um visitante que clica duas vezes não cria dois.
Adicione limitação de taxa ao endpoint para que ninguém consiga criar milhares de pedidos sem pagar, e exija usuário logado ou captcha se o seu produto precisar.
import express from 'express';
import crypto from 'node:crypto';
const app = express();
const PRICES_USD = { 'pro-plan': 49 }; // prices live on the server, never in the browser
app.post('/api/crypto-checkout', express.json(), async (req, res) => {
const price = PRICES_USD[req.body.product];
if (!price) return res.sendStatus(400);
const orderId = await db.orders.create({ product: req.body.product, amountUsd: price }); // your own order number
const response = await fetch('https://api.qvard.com/api/v1/payment', {
method: 'POST',
headers: { Authorization: 'Bearer ' + process.env.QVARD_API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ id: String(orderId), price })
});
if (response.status !== 201) return res.sendStatus(502);
const { redirectUrl } = await response.json();
res.json({ redirectUrl });
});Depois do clique: o webhook decide
Redirecionar o visitante para a página de pagamento inicia o pagamento; não o conclui. Quando o pagamento é concluído, a Qvard chama a callback URL salva no seu projeto com o seu id e o estado completed. Só então conceda o acesso ou marque o pedido como pago. O endpoint deve responder exatamente HTTP 200 e ser seguro se executar duas vezes; veja como proteger webhooks de pagamentos em cripto.
Ainda não há URLs de retorno após o pagamento, então o visitante volta ao seu site por conta própria. Dê a ele uma página que mostre o estado real do pedido e se atualize enquanto espera, não uma página de agradecimento que presume sucesso.
Preços fixos, valores variáveis e o que vem a seguir
- Preços fixos (planos, produtos) são o caso fácil: a tabela do servidor os guarda.
- Valores variáveis (doações, recargas) precisam de validação no servidor: um mínimo, um máximo e uma checagem numérica. Um valor abaixo do mínimo do método de pagamento escolhido é rejeitado com um
400. - Vários botões compartilham o mesmo endpoint; só muda o identificador do produto.
O passo a passo completo está em como aceitar pagamentos em cripto em um site, e a API em API de pagamentos em cripto para desenvolvedores. Uma fatura de demonstração mostra a página para onde o botão leva; as condições comerciais estão na página de preços.
FAQ
Posso colocar a chave de API da Qvard no código do botão?
Não. A chave pode criar pagamentos do seu projeto e deve ficar no seu servidor. O botão deve chamar o seu próprio endpoint, que chama a Qvard.
Existe um widget incorporável ou um botão sem código?
Sim, o checkout incorporado já é um widget pronto para o seu site. Botão sem código ainda não há: os links de pagamento estão em desenvolvimento. Os SDKs estão prontos. Hoje a integração usa a API com um pequeno endpoint no servidor.
De onde deve vir o preço?
Do seu servidor, nunca do navegador. O botão envia apenas o que é comprado, e o servidor decide o preço em dólares americanos.
Como sei que o cliente pagou?
Pelo webhook que a Qvard envia quando o pagamento é concluído. O visitante voltar ao seu site não é prova de pagamento.
