VKX Pay
Você cobra em reais; quem paga escolhe a cripto. O valor do lojista e a taxa da VKX saem na mesma transação on-chain — ou as duas acontecem, ou nenhuma. Sem custódia em momento algum.
Começar
Antes do código: crie a conta em /pay/painel com sua conta Google e cadastre um endereço de carteira por rede. É a única configuração que existe.
npm install @vkx/pay
Criar a cobrança
No seu servidor — a chave secreta nunca vai para o navegador.
const { createPaymentIntent } = require('@vkx/pay');
const payment = await createPaymentIntent({
apiKey: process.env.VKX_PAY_SECRET_KEY, // sk_vkxpay_...
amount: '199.90', // reais, string
orderId: pedido.id, // o id no SEU sistema
});
// payment.checkoutUrl → mande o pagador para cá
// (botão no site, link no WhatsApp, QR no balcão)
Parâmetros
| Campo | Obrigatório | Descrição |
|---|---|---|
apiKey | sim | Sua chave secreta sk_vkxpay_... |
amount | sim | Valor em reais, como string: '199.90' |
orderId | não | Id do pedido no seu sistema — volta no webhook |
metadata | não | Objeto livre, guardado com a cobrança |
expiresInSeconds | não | Validade da cobrança (padrão 1800, entre 120 e 86400) |
Receber a confirmação
Quando a blockchain confirma, a VKX chama sua URL. Use o corpo cru da requisição — antes de qualquer JSON.parse do framework.
const { constructWebhookEvent } = require('@vkx/pay');
app.post('/webhooks/vkx', express.raw({ type: 'application/json' }), (req, res) => {
const event = constructWebhookEvent({
secret: process.env.VKX_PAY_WEBHOOK_SECRET, // whsec_...
body: req.body,
signature: req.headers['x-vkx-signature'],
});
if (event.event === 'payment.completed') {
liberarPedido(event.data.orderId);
}
res.sendStatus(200);
});
A assinatura chega como t=<unix>,v1=<hmac>, um HMAC-SHA256 de "<t>.<corpo>". O SDK recusa corpo adulterado, segredo errado e requisição antiga (mais de 5 minutos).
Corpo do evento
{
"event": "payment.completed",
"createdAt": "2026-08-15T18:30:44.603Z",
"data": {
"paymentIntentId": "pay_c-M_7otXmizP",
"orderId": "PEDIDO-123",
"amount": "199.90",
"currency": "BRL",
"network": "bsc",
"txHash": "0x…",
"payer": "0x…",
"confirmedAt": "2026-08-15T18:31:02.114Z"
}
}
Eventos: payment.completed e payment.expired. Responda 2xx; a VKX repete a entrega com espera crescente (1min, 5min, 30min, 2h, 6h, 12h, 24h) até desistir.
Estados de uma cobrança
| Estado | Significa |
|---|---|
OPEN | Criada, esperando pagamento |
PENDING | Transação vista na blockchain, aguardando confirmações |
PAID | Confirmada — o webhook foi disparado |
EXPIRED | Venceu sem pagamento |
CANCELED | Cancelada por você antes do pagamento |
REFUNDED_EXTERNAL | Devolvida por fora e registrada no histórico |
Redes e moedas
| Rede | Moedas | Confirmações |
|---|---|---|
| BNB Chain | USDT, USDC, USD1, BNB | 3 |
| Polygon | USDT, USDC, POL | 30 |
| Base | USDC, ETH | 12 |
| Solana | USDC, SOL | finalizada |
Moedas nativas são opcionais — você liga no painel se quiser aceitá-las. A cotação em reais é congelada durante o checkout (cerca de 5 minutos em stablecoin, menos em moeda nativa, que oscila mais).
Endpoints REST
Se você não usa Node.js, fale direto com a API. Base: https://api.vkxtech.com.br
| Método | Rota | O que faz |
|---|---|---|
POST | /pay/v1/payment-intents | Cria a cobrança |
GET | /pay/v1/payment-intents/:id | Consulta status e pagamentos |
POST | /pay/v1/payment-intents/:id/cancel | Cancela antes do pagamento |
POST | /pay/v1/payment-intents/:id/refunded-external | Registra devolução feita por fora |
PUT | /pay/v1/wallets | Define onde receber em cada rede |
POST | /pay/v1/webhook-endpoints | Cadastra a URL do webhook |
GET | /pay/v1/me | Resumo de vendas (aceita chave de leitura) |
curl -X POST https://api.vkxtech.com.br/pay/v1/payment-intents \
-H "Authorization: Bearer sk_vkxpay_..." \
-H "Content-Type: application/json" \
-d '{"amount":"199.90","orderId":"PEDIDO-123"}'
Outras linguagens
O pacote npm é conveniência, não requisito. O VKX Pay é uma API REST com JSON: qualquer linguagem que faça uma requisição HTTP integra — PHP, Python, Ruby, Go, Java, C#, Elixir, o que você usar.
São só duas operações: criar a cobrança (uma requisição autenticada) e validar o webhook (um HMAC-SHA256, que toda linguagem tem na biblioteca padrão).
Python
import requests, hmac, hashlib, time
# criar a cobrança
r = requests.post(
"https://api.vkxtech.com.br/pay/v1/payment-intents",
headers={"Authorization": f"Bearer {VKX_PAY_SECRET_KEY}"},
json={"amount": "199.90", "orderId": pedido_id},
).json()
checkout_url = r["checkoutUrl"]
# validar o webhook
def valido(corpo_cru: bytes, header: str, segredo: str) -> bool:
partes = dict(p.split("=", 1) for p in header.split(","))
t = int(partes["t"])
if abs(time.time() - t) > 300:
return False
esperado = hmac.new(segredo.encode(),
f"{t}.".encode() + corpo_cru,
hashlib.sha256).hexdigest()
return hmac.compare_digest(esperado, partes["v1"])
Go
body, _ := json.Marshal(map[string]string{"amount": "199.90", "orderId": pedidoID})
req, _ := http.NewRequest("POST", apiBase+"/pay/v1/payment-intents", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("VKX_PAY_SECRET_KEY"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
Qualquer coisa que rode cURL
curl -X POST https://api.vkxtech.com.br/pay/v1/payment-intents \
-H "Authorization: Bearer $VKX_PAY_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"amount":"199.90","orderId":"PEDIDO-123"}'
WordPress
WordPress é PHP, então a integração usa wp_remote_post — sem plugin e sem dependência externa. Cole no functions.php do seu tema (ou num plugin próprio):
<?php
function vkx_criar_cobranca($valor, $pedido_id) {
$resposta = wp_remote_post('https://api.vkxtech.com.br/pay/v1/payment-intents', [
'headers' => [
'Authorization' => 'Bearer ' . VKX_PAY_SECRET_KEY,
'Content-Type' => 'application/json',
],
'body' => wp_json_encode([
'amount' => $valor, // '199.90'
'orderId' => $pedido_id,
]),
'timeout' => 20,
]);
if (is_wp_error($resposta)) return null;
$dados = json_decode(wp_remote_retrieve_body($resposta), true);
return $dados['checkoutUrl'] ?? null; // redirecione o comprador para cá
}
// Webhook: registre uma rota REST e valide a assinatura
add_action('rest_api_init', function () {
register_rest_route('vkx/v1', '/webhook', [
'methods' => 'POST',
'permission_callback' => '__return_true',
'callback' => function (WP_REST_Request $req) {
$corpo = $req->get_body(); // corpo CRU
$header = $req->get_header('x-vkx-signature');
parse_str(str_replace(',', '&', $header), $p); // t=...,v1=...
if (abs(time() - (int) $p['t']) > 300) return new WP_REST_Response('velho', 400);
$esperado = hash_hmac('sha256', $p['t'] . '.' . $corpo, VKX_PAY_WEBHOOK_SECRET);
if (!hash_equals($esperado, $p['v1'])) return new WP_REST_Response('invalido', 400);
$evento = json_decode($corpo, true);
if ($evento['event'] === 'payment.completed') {
// marque o pedido como pago: $evento['data']['orderId']
}
return new WP_REST_Response('ok', 200);
},
]);
});
Em WooCommerce, chame vkx_criar_cobranca() no seu gateway e redirecione para a checkoutUrl; no webhook, use $order->payment_complete().
React / Next.js
A chave secreta nunca vai para o browser. Crie a cobrança no servidor e devolva só a URL do checkout.
// app/api/pagar/route.ts (Next.js App Router)
import { createPaymentIntent } from '@vkx/pay';
export async function POST(req: Request) {
const { orderId, total } = await req.json();
const payment = await createPaymentIntent({
apiKey: process.env.VKX_PAY_SECRET_KEY!,
amount: total,
orderId,
});
return Response.json({ checkoutUrl: payment.checkoutUrl });
}
// componente do cliente
async function pagar() {
const r = await fetch('/api/pagar', {
method: 'POST',
body: JSON.stringify({ orderId: pedido.id, total: '199.90' }),
}).then((r) => r.json());
window.location.assign(r.checkoutUrl);
}
Chaves de API
| Chave | Pode | Onde usar |
|---|---|---|
sk_vkxpay_… | Criar cobranças, configurar a conta | Só no seu servidor |
rk_vkxpay_… | Somente leitura: consultar vendas | Painéis e aplicativos |
whsec_… | Validar a assinatura do webhook | Só no seu servidor |
Cada chave aparece uma única vez ao ser criada — guardamos apenas um hash. Perdeu? Gere outra e revogue a anterior no painel.
Painel no celular
Gere uma chave rk_ no painel e use no aplicativo VKX Wallet para acompanhar as vendas do celular. Como ela é somente leitura, não cria cobrança nem move fundos, mesmo que o aparelho se perca.
curl https://api.vkxtech.com.br/pay/v1/me \
-H "Authorization: Bearer rk_vkxpay_..."
A resposta traz volume do dia, volume total, número de vendas, ticket médio, movimentação por rede e as últimas cobranças.