SDK для TypeScript
Один файл без зависимостей. Работает в Node.js 18+, Bun, Deno, Next.js (включая edge). Скачайте его в проект:
curl -o src/lib/egn-pay.ts https://pay.egnetwork.ru/sdk/egn-pay.tsТипы в SDK совпадают с OpenAPI. Обновить SDK можно той же командой.
Создать платёж
import { EgnPay, EgnPayError } from "@/lib/egn-pay";
const pay = new EgnPay(process.env.EGN_PAY_KEY!);
try {
const payment = await pay.payments.create({
amount: 49900,
order_id: `order-${order.id}`,
description: "Подписка Pro на 1 месяц",
return_url: "https://example.egnetwork.ru/billing/done",
customer: { email: user.email },
metadata: { user_id: String(user.id) },
});
redirect(payment.payment_url);
} catch (err) {
if (err instanceof EgnPayError && err.code === "order_closed") {
// прошлый платёж по заказу истёк — создайте новый order_id
}
throw err;
}Остальные методы
await pay.payments.retrieve("pay_…");
await pay.payments.findByOrderId("order-1042");
await pay.payments.list({ status: "succeeded", limit: 50 });
await pay.payments.cancel("pay_…");
await pay.payments.refund("pay_…"); // весь остаток
await pay.payments.refund("pay_…", 10000); // 100 ₽
await pay.me(); // проверить ключСетевые ошибки и 5xx у GET и POST /payments повторяются автоматически (до 2 раз). Это безопасно благодаря идемпотентности по order_id. Ошибки API бросаются как EgnPayError с полями status, code, message и details.
Вебхук (Next.js App Router)
// app/api/egn-pay/webhook/route.ts
import { EgnPay } from "@/lib/egn-pay";
export async function POST(req: Request) {
const raw = await req.text();
let event;
try {
event = await EgnPay.webhooks.constructEvent(raw, req.headers.get("x-egn-signature"), process.env.EGN_PAY_WEBHOOK_SECRET!);
} catch {
return new Response("bad signature", { status: 400 });
}
const p = event.data.payment;
switch (event.type) {
case "payment.succeeded":
await orders.markPaid(p.order_id, p.id); // идемпотентно
break;
case "payment.failed":
case "payment.expired":
case "payment.canceled":
await orders.close(p.order_id);
break;
case "payment.refunded":
case "payment.partially_refunded":
await orders.syncRefund(p.order_id, p.refunded_amount);
break;
}
return new Response("ok");
}Страница возврата
// app/billing/done/page.tsx
export default async function Done({ searchParams }: { searchParams: Promise<{ payment_id?: string }> }) {
const { payment_id } = await searchParams;
const payment = payment_id ? await pay.payments.retrieve(payment_id) : null; // не доверяем ?status=
return payment?.status === "succeeded" ? <p>Спасибо!</p> : <p>Оплата не завершена</p>;
}Markdown-версия этой страницы: /docs/sdk.md