Joan eduki nagusira
Certyneo
Garatzailearen dokumentazioa

Webhook sinadura-ekitaldiak jaso denbora errealean

Konfiguratzen baduzu HTTPS helbide bat Certyneo panelean, jasoko duzu HMAC-SHA256 sinatua den POST bat zure gutun-azalera zerbait iristen denean: sinadura, uko, iraungitzea. 8 gertaera onartzen dira, 6 saiakeran berraztertzen da, 8 lerroeko kodea.

< 5s

Eragiketa-denbora ertaineko epea, gertaeraren ondoren

5x

Saiakera huts egin badugu (9 ordu arte)

HMAC-SHA256

Eskari bakoitzaren sinadura algoritmoa

Gertakarien katalogoa

Ondorengo 8 ekitaldiek Certyneo gutun-azal baten bizitza ziklo osoa hartzen dute.

Gertaera-Hori da.
envelope.createdGutun-azal bat sortzen da (UI, API edo txantiloiaren bidez) CRM aldeko erregistro bat sinkronizatzeko erabilgarria sortzean.
envelope.sentGutun-azal hau sinatzaileei bidaltzen zaie (egiten den lehen e-mail-a).
envelope.completedSinatzaile guztiek sinatu dute. eIDAS PDF zigilatua eta bidezko auditoria erabilgarri daude
envelope.declinedSinatzaile batek uko egin dio gutun-azal honi. Uko egiteko arrazoia (sinatzaileak ematen badu) `data.decline_reason`-n dago.
envelope.voidedGutun-azal hau ezabatu egin du emititzaileak sinatu aurretik.
envelope.expiredGutun-azal honen iraungitze-data pasa da sinatu gabe.
recipient.signedSinatzaile batek sinatu du (baina ez guztiek).
recipient.viewedSinatzaile batek sinatu gabe ireki du lotura, eta baliagarria da merkataritza berpizteko.

Karga-formazioa.

Gertaera guztiek JSONren goi mailako patroia partekatzen dute: `event`, `envelope_id`, `occurred_at`, `data`.

{
  "event": "envelope.completed",
  "envelope_id": "env_01HG3K8X9Y2N4P5Q6R7S8T9V0W",
  "occurred_at": "2026-05-27T08:42:13.521Z",
  "data": {
    "title": "Contrat de prestation Acme Corp",
    "status": "completed",
    "created_at": "2026-05-24T14:12:00.000Z",
    "completed_at": "2026-05-27T08:42:13.000Z",
    "signers": [
      {
        "email": "client@acme.example",
        "name": "Alex Client",
        "signed_at": "2026-05-27T08:42:13.000Z",
        "method": "eidas_aes",
        "ip": "203.0.113.42"
      }
    ],
    "proof_pdf_url": "https://certyneo.com/api/envelopes/env_01HG.../proof.pdf"
  }
}

HMAC sinadura gorputz gordinaren gainean kalkulatzen da bidalitako moduan.

HMAC sinadura egiaztatu.

Eskari bakoitza webhook sekretuarekin sinatzen da (sartzean behin bakarrik ikus daiteke, eta gero deskantsatuz enkriptatua).<timestamp>V1=<hex_hmac>Beti egiaztatu sinadura karga prozesatu aurretik. Pauso hau gabe, edonork forjatu dezake gertaera bat eta deitu zure azken puntura.

Node.js / TypeScript

import crypto from "node:crypto";

export function verifyCertyneoSignature(
  rawBody: string,
  signatureHeader: string,
  secret: string,
): boolean {
  // Header format: t=<timestamp>,v1=<hex_hmac>
  const parts = Object.fromEntries(
    signatureHeader.split(",").map((p) => p.split("=")),
  );
  const ts = parts.t;
  const sig = parts.v1;
  if (!ts || !sig) return false;

  // Reject events older than 5 minutes (replay protection).
  const age = Math.abs(Date.now() / 1000 - Number(ts));
  if (age > 300) return false;

  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${ts}.${rawBody}`)
    .digest("hex");

  // timingSafeEqual to mitigate timing attacks.
  return crypto.timingSafeEqual(
    Buffer.from(expected, "hex"),
    Buffer.from(sig, "hex"),
  );
}

Python

import hashlib
import hmac
import time


def verify_certyneo_signature(
    raw_body: bytes, signature_header: str, secret: str
) -> bool:
    """Verify a Certyneo webhook signature.

    Header format: `t=<timestamp>,v1=<hex_hmac>`
    Rejects events older than 5 minutes (replay protection).
    """
    parts = dict(p.split("=") for p in signature_header.split(","))
    ts = parts.get("t")
    sig = parts.get("v1")
    if not ts or not sig:
        return False

    if abs(time.time() - int(ts)) > 300:
        return False

    expected = hmac.new(
        secret.encode("utf-8"),
        f"{ts}.{raw_body.decode('utf-8')}".encode("utf-8"),
        hashlib.sha256,
    ).hexdigest()

    return hmac.compare_digest(expected, sig)

Ohizko akats bat

Ez erabili `===` edo `==` sinadura espero eta jasotakoa alderatzeko. Erabili denbora-segurtasun funtzioa (`crypto.timingSafeEqual` Node-n, `hmac.compare_digest` Python-en). Bestela, bi sinaduren arteko konparazioaren denbora-desberdintasunak sekretuak paziente erasotzaile bati pixkanaka-pixkanaka agerian uzten dizkio (timing attack).

Berriz saiatzeko politika

Zure helburuak HTTP 2xx (timeout, 5xx, connection refused) baino erantzun gehiago ematen badu, erantzuna erantzuna izango da: "Eskalatzaileen segurtasun-segurtasun-sistema".

Saiakera bat.Denbora-tarte batDenbora igaro da.
#100
#2+ 1 min1 min
#3+ 5 min6 min
#4+ 30 min36 min
#5+ 2 h2h 36
#6+ 6 h8h 36

Porrot egindako ekitaldi bat eskuz bidali nahi baduzu, webhook-eko panelak botoi bat eskaintzen du porrot egindako entrega bakoitzeko, porrotaren ondoren 7 egunetan zehar erabilgarri.

Egiazko gutun-azal bat bidali gabe probatzea.

Webhooks-ek urrutiko helbide bat eta gertaera mota bat onartzen ditu, eta benetakoaren antzera sinatutako karga fikziozko bat POSTatzen du.

# Trigger a test webhook to your endpoint
curl -X POST https://api.certyneo.com/v1/webhooks/test \
  -H "Authorization: Bearer $CERTYNEO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"event": "envelope.completed", "url": "https://your.app/webhooks/certyneo"}'

6 ohitura jarraitu behar dira

  • HMAC sinadura egiaztatu gorputzaren irakurketa baino lehen.
  • Prozesatu behin bakarrik IDak gordez. Berriz ere ekitaldi bera egin daiteke.
  • HTTP 200 erantzun 5 segundotan, eta gero prozesatu asinkronikoki. Bestela, denbora-galera izango duzu eta berriro saiatze gisa kontatuko da.
  • Gorputz gordina erregistratu + sinadura osoa debugatu HMAC egiaztapenak askotan huts egiten du BOM edo espazio zuri ikusezin batean.
  • "Hondatu" gertaeren atzealdeko "dead-letter" bat konektatu eta eskuz bidali zure zerbitzukoek gertakariak jasotzeko.
  • 5 minutuko atzerapena onartu `t=` eta harreraren artean, eta atzera bota, berriro ikustea eragozteko.

Aurrera egin behar dugu.

Prest zuen sistemak konektatzeko?

Sortzeko kontua dohainik 2 minutuan webhook konfigurazioa Starter planarekin dago eskuragarri (dohainik, 5 gutun-azal/hilean).