PesaBridge
ሰነዶች/በሥራ ላይ ማስኬድ/Webhooks

በሥራ ላይ ማስኬድ

Webhooks

Signed, retried event deliveries: endpoints, event types, verification in four languages, testing and replay.

6 ደቂቃ ንባብ

የገንቢዎች መመሪያዎች በእንግሊዝኛ የተጻፉት ኮዱ፣ የመስኮች ስሞች እና የስህተት መልዕክቶች ከAPI ጋር በትክክል እንዲዛመዱ ነው።

በዚህ ገጽ ላይ
  1. Endpoints
  2. Event types
  3. What a delivery looks like
  4. Verify every delivery
  5. Retries and duplicates
  6. Test and replay

Endpoints

Create one or more endpoints with POST /partner/webhooks/endpoints (name, url, events as a comma-separated list or *, and mode). Each gets its own signing secret, shown once at creation. Update, delete and list them with the /partner/webhooks/endpoint… calls, or in the console.

Event types

EventSent when
charge.createdA prompt-to-pay charge was created.
charge.completedThe customer approved and the money moved.
charge.declinedThe customer declined the prompt.
charge.expiredThe prompt expired unanswered.
checkout.completedA hosted checkout session was paid.
c2b.confirmationA customer paid your till or pay bill directly.

What a delivery looks like

HeaderValue
X-PesaBridge-EventThe event type, e.g. charge.completed.
X-PesaBridge-SignatureHex HMAC-SHA256 of the raw request body, keyed with the endpoint's signing secret.
X-PesaBridge-TimestampUnix time the delivery was signed.
X-PesaBridge-Signature-V2t=<timestamp>,v1=<hex HMAC-SHA256 of "<timestamp>.<raw body>">: replay-resistant.
X-PesaBridge-DeliveryDelivery id: log it, and use it to ignore duplicates.

Verify every delivery

Compute the HMAC over the exact bytes you received, before parsing JSON, and compare in constant time. Prefer V2 and reject timestamps older than five minutes.

Node.js
import crypto from "node:crypto";
// Express: app.post("/webhook", express.raw({ type: "application/json" }), handler)
function verified(req, secret) {
  const [t, v1] = (req.get("X-PesaBridge-Signature-V2") || "").split(",").map((p) => p.split("=")[1]);
  if (!t || Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
  const want = crypto.createHmac("sha256", secret).update(`${t}.${req.body}`).digest("hex");
  return v1?.length === want.length && crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(want));
}
Python
import hmac, hashlib, time

def verified(raw_body: bytes, headers, secret: str) -> bool:
    parts = dict(p.split("=", 1) for p in headers.get("X-PesaBridge-Signature-V2", "").split(",") if "=" in p)
    t, v1 = parts.get("t"), parts.get("v1", "")
    if not t or abs(time.time() - int(t)) > 300:
        return False
    want = hmac.new(secret.encode(), f"{t}.".encode() + raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(v1, want)
PHP
<?php
$raw = file_get_contents("php://input");
parse_str(str_replace(",", "&", $_SERVER["HTTP_X_PESABRIDGE_SIGNATURE_V2"] ?? ""), $sig);
$ok = isset($sig["t"], $sig["v1"]) && abs(time() - (int)$sig["t"]) <= 300
   && hash_equals(hash_hmac("sha256", $sig["t"] . "." . $raw, getenv("PB_WHSEC")), $sig["v1"]);
http_response_code($ok ? 200 : 401);
Go
package webhook

import ("crypto/hmac"; "crypto/sha256"; "encoding/hex")

// Verified checks the V1 signature: hex HMAC-SHA256 of the raw body.
func Verified(raw []byte, sig, secret string) bool {
    m := hmac.New(sha256.New, []byte(secret))
    m.Write(raw)
    return hmac.Equal([]byte(hex.EncodeToString(m.Sum(nil))), []byte(sig))
}

Retries and duplicates

Answer with any 2xx within 10 seconds. Anything else, or a timeout, is retried with exponential back-off (1, 2, 4, 8 and 16 minutes, up to 6 attempts), after which the delivery is marked failed. Because of retries, the same event can arrive twice: make your handler idempotent on X-PesaBridge-Delivery or on charge_ref.

We only deliver to public HTTPS addresses. Private and internal network addresses are refused.

Test and replay

  • POST /partner/webhooks/test sends a test event to an endpoint.
  • GET /partner/webhooks/deliveries lists recent deliveries with their status code and attempts.
  • POST /partner/webhooks/resend replays a delivery after you fix your handler.
  • The Echo receiver (GET /partner/echo/url) captures and auto-verifies deliveries with no server of your own.

መሐንዲሶቻችን የማገናኘት ጥያቄዎችን ይመልሳሉ። የጥያቄውን ማጣቀሻ ይላኩልን፣ ትክክለኛውን ጥሪ እናገኛለን።

ድጋፍን ያግኙ