Workflows típicos
Receitas práticas pra integrações comuns na PaysClub. Cada workflow tem o fluxo de eventos, código de exemplo e os pontos de atenção.
1. Sincronizar membros com seu banco de dados
Toda vez que um novo membro recebe acesso a um produto, o eventomember.enrolled é disparado. Use isso pra manter seu DB de usuários em sincronia.
import crypto from "crypto";
import express from "express";
const app = express();
app.use(express.raw({ type: "application/json" }));
app.post("/webhooks/paysclub", async (req, res) => {
// 1. Valida assinatura HMAC
const signature = req.headers["x-paysclub-signature"];
const expected = "sha256=" + crypto
.createHmac("sha256", process.env.PAYSCLUB_WEBHOOK_SECRET)
.update(req.body)
.digest("hex");
if (signature !== expected) return res.status(401).send("Invalid signature");
const { event, data } = JSON.parse(req.body.toString());
// 2. Roteia por evento
if (event === "member.enrolled") {
await db.users.upsert({
id: data.buyer_id,
product_ids: { push: data.product_id },
enrolled_at: new Date(),
});
}
if (event === "access.revoked") {
await db.users.update({
where: { id: data.buyer_id },
data: { product_ids: { remove: data.product_id } },
});
}
// 3. Responde 200 RAPIDAMENTE — gateway tem timeout 10s
res.status(200).send("ok");
});order_id + event como chave única pra deduplicar. PaysClub tenta a entrega até 5 vezes com backoff exponencial.2. Vender via API key (sem checkout hospedado)
Para integrações headless onde você quer total controle do UX, crie a sessão de checkout via API e renderize sua própria UI. Use o session_idretornado para gerar o link único de pagamento.
const res = await fetch("https://app.paysclub.com/api/checkout/sessions", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer pk_live_seu_api_key",
},
body: JSON.stringify({
product_id: "550e8400-...",
plan_id: "660e8400-...",
email: "comprador@email.com",
}),
});
const { session_id, session_token } = await res.json();
// Redirect pro checkout com a sessão pré-criada
const checkoutUrl = `https://compra.paysclub.com/checkout/seu-slug?session=${session_id}`;
return Response.redirect(checkoutUrl, 302);3. Processar reembolso programaticamente
Reembolsos podem ser disparados via API quando o cliente entra em contato com seu suporte. O fluxo é assíncrono — você dispara o refund e aguarda o webhook confirmar.
curl -X POST https://app.paysclub.com/api/v1/orders/ORDER_ID/refund \
-H "Authorization: Bearer pk_live_..." \
-H "Content-Type: application/json" \
-d '{ "reason": "Cliente solicitou reembolso por insatisfação" }'
# Resposta imediata (status: pending)
{
"id": "...",
"status": "pending",
"created_at": "2026-04-20T..."
}Após processamento, você recebe o webhook:
{
"event": "refund.requested",
"data": {
"refund_id": "...",
"order_id": "...",
"amount": 97.00,
"reason": "Cliente solicitou reembolso..."
}
}4. Rastrear comissões de afiliados
Quando uma venda vem por link de afiliado, o eventoaffiliate.commission_earned é disparado após confirmação de pagamento. Use pra dashboards externos ou notificações.
{
"event": "affiliate.commission_earned",
"data": {
"affiliate_id": "...",
"order_id": "...",
"product_id": "...",
"commission_amount": 9.70
}
}Boas práticas gerais
✓ Sempre validar HMAC antes de processar payload ✓ Responder 200 em ≤2s (mesmo que processamento seja assíncrono) ✓ Deduplicar por (event_id + order_id) com TTL 24h ✓ Retry assíncrono no SEU lado se DB falhar (não retornar 500) ✓ Logs por correlation_id (order_id) pra debug ✗ Não fazer chamadas síncronas a APIs externas no handler ✗ Não confiar no .data sem revalidar via GET na nossa API ✗ Não fazer trabalho pesado no handler — use queue se >2s