Avisos a tu sistema

Cuando cambia un cobro, te pegamos un POST https en la URL del panel. Respondé 2xx. Si no, lo reintentamos.

Qué te llega

POST https://tudominio.com/webhooks/tiki

Content-Type: application/json
X-Tiki-Event: payment.approved
X-Tiki-Timestamp: 1710000000
X-Tiki-Signature: sha256=3f1c…

{
  "event": "payment.approved",
  "cobro_id": 12,
  "codigo": "TKI1-AB12CD34",
  "estado": "PAGADA",
  "monto": "15000.00",
  "monto_cobrado": "15000.00",
  "transaccion_id": 88
}
$raw = file_get_contents('php://input');
$ts = isset($_SERVER['HTTP_X_TIKI_TIMESTAMP']) ? $_SERVER['HTTP_X_TIKI_TIMESTAMP'] : '';
$hdr = isset($_SERVER['HTTP_X_TIKI_SIGNATURE']) ? $_SERVER['HTTP_X_TIKI_SIGNATURE'] : '';
$sig = (strpos($hdr, 'sha256=') === 0) ? substr($hdr, 7) : $hdr;
$calc = hash_hmac('sha256', $ts . '.' . $raw, $secret);
if (!hash_equals($calc, $sig)) {
  header('HTTP/1.1 401');
  exit;
}
$data = json_decode($raw, true);
header('HTTP/1.1 200');
// $data['event'], $data['cobro_id'], $data['estado']
const crypto = require('crypto');

function ok(raw, ts, header, secret) {
  const sig = String(header || '').replace(/^sha256=/, '');
  const calc = crypto.createHmac('sha256', secret)
    .update(ts + '.' + raw)
    .digest('hex');
  return crypto.timingSafeEqual(Buffer.from(calc), Buffer.from(sig));
}

// Express
app.post('/webhooks/tiki', express.raw({ type: 'application/json' }), (req, res) => {
  const raw = req.body.toString('utf8');
  if (!ok(raw, req.get('X-Tiki-Timestamp'), req.get('X-Tiki-Signature'), secret)) {
    return res.status(401).end();
  }
  const data = JSON.parse(raw);
  res.status(200).end();
});
HTTP/1.1 200 OK

(vacío alcanza)

Eventos

EventoCuándoestado en el cuerpo
payment.createdCreaste el cobroPENDIENTE
payment.pendingEstá en procesoPENDIENTE / EN_PROCESO
payment.approvedSe acreditóPAGADA
payment.partially_paidPago parcialPAGADA_PARCIALMENTE
payment.rejectedNo se acreditó o vencióCANCELADO
payment.refundedDevolviste todoDEVUELTA
payment.partially_refundedDevolviste una parteDEVUELTA_PARCIALMENTE

La firma es HMAC-SHA256 de timestamp + '.' + body con la clave del panel. La URL tiene que ser https.