Перейти к содержимому

Библиотеки Standard Webhooks

Наши вебхуки следуют Standard Webhooks — открытой спецификации с официальными библиотеками. Проверяйте подпись ими; не пишите свою проверку.

Язык Пакет Установка
Node standardwebhooks npm install standardwebhooks
PHP standard-webhooks/standard-webhooks composer require standard-webhooks/standard-webhooks
Python standardwebhooks pip install standardwebhooks
Go libraries/go go get github.com/standard-webhooks/standard-webhooks/libraries

В репозитории есть и библиотеки для Java, C#, Ruby, Rust и Elixir.

Передайте библиотеке секрет эндпоинта как есть, whsec_…: библиотеки сами разбирают префикс. Дайте ей сырое тело и заголовки запроса — она проверит подпись и отклонит время, которое расходится больше чем на 5 минут.

examples/node/webhooks/receive.mjs
// Receive webhooks: verify each one with the Standard Webhooks library, act on it once.
import { createServer } from "node:http";
import { Webhook } from "standardwebhooks";
const webhook = new Webhook(process.env.WEBHOOK_SECRET); // whsec_…, answered once by PUT /v1/webhook-endpoint
const handled = new Set(); // webhook-id of the events acted on; keep this in your database
const versions = new Map(); // the highest version applied, per payment, refund or payout
createServer((req, res) => {
const chunks = [];
req.on("data", (chunk) => chunks.push(chunk));
req.on("end", () => {
let event;
try {
// The exact bytes received, before any JSON parsing; the timestamp must be within 5 minutes.
event = webhook.verify(Buffer.concat(chunks).toString("utf8"), req.headers);
} catch {
res.writeHead(400).end();
return;
}
if (!handled.has(req.headers["webhook-id"])) {
handled.add(req.headers["webhook-id"]);
apply(event);
}
res.writeHead(204).end(); // answer 2xx within 15 seconds; do slow work after answering
});
}).listen(Number(process.env.PORT ?? 8080));
function apply(event) {
const [subject, version] = {
"payment.status_changed": [event.payment_id, event.payment_version],
"refund.status_changed": [event.refund_id, event.refund_version],
"payout.status_changed": [event.payout_id, event.payout_version],
}[event.type] ?? [event.event_id, 0];
// Events may come late or twice: an older version than the one applied changes nothing.
if ((versions.get(subject) ?? 0) > version) return;
versions.set(subject, version);
console.log(`verified ${event.type} ${subject} v${version} ${event.status ?? ""}`);
}

Подробнее: приём вебхуков.