SplitPay

Webhooklar

API ni so'ramasdan to'lov holati haqida xabarlar

SplitPay kassa to'lovlari haqidagi hodisalarni manzilingizga o'zi yuboradi, shuning uchun GET /v1/charges/{id} ni so'rab turish shart emas. Manzil admin panelda belgilanadi: Kassalar → Webhooklar. U yerda imzo kaliti (bir marta ko'rsatiladi), sinov hodisasi va qo'lda qayta yuborish imkoni bilan yetkazilishlar jurnali ham bor.

Hodisalar

typeQachon
charge.createdTo'lov yaratildi
charge.succeededPul yechildi
charge.failedBank rad etdi
charge.reversedTo'lov bekor qilindi
charge.split_completed / charge.split_failedTaqsimot bajarildi / bajarilmadi
charge.fiscal_registered / charge.fiscal_failedOFD cheki chiqdi / chiqmadi
webhook.testAdmin paneldan sinov hodisasi

So'rov

Manzilingizga JSON tanali POST:

{
  "id": "0f8d3c1e-…",
  "type": "charge.split_completed",
  "createdAt": "2026-09-27T10:00:00.000Z",
  "data": { "object": { "id": "…", "externalId": "order-777", "status": "SUCCEEDED", "split": { "status": "COMPLETED" } } }
}

data.object GET /v1/charges/{id} javobi bilan bir xil formatda. Sarlavhalar: SplitPay-Event-Id, SplitPay-Event-Type va SplitPay-Signature.

Imzoni tekshirish

SplitPay-Signature: t=<unix vaqt>,v1=<imzo>, bu yerda imzo whsec_… kaliti bilan t.tana satridan olingan HMAC-SHA256. JSON ni tahlil qilishdan oldin xom tanani tekshiring va 5 daqiqadan eski hodisalarni rad eting.

import { createHmac, timingSafeEqual } from 'node:crypto';

app.post('/hooks/splitpay', express.text({ type: 'application/json' }), (req, res) => {
  const header = req.header('splitpay-signature') ?? '';
  const { t, v1 } = Object.fromEntries(header.split(',').map((part) => part.split('=')));

  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) {
    return res.sendStatus(400); // hodisa 5 daqiqadan eski
  }

  const expected = createHmac('sha256', process.env.SPLITPAY_WEBHOOK_SECRET)
    .update(`${t}.${req.body}`)
    .digest('hex');

  // doimiy vaqtda solishtirish, imzo vaqt bo'yicha sizib chiqmasligi uchun
  const ok = v1?.length === expected.length && timingSafeEqual(Buffer.from(v1), Buffer.from(expected));
  if (!ok) {
    return res.sendStatus(401);
  }

  const event = JSON.parse(req.body);
  if (event.type === 'charge.split_completed') {
    // event.data.object.externalId buyurtmasi to'landi va taqsimlandi
  }
  res.sendStatus(200);
});

Javob va takrorlar

  • 10 soniya ichida istalgan 2xx kod bilan javob bering; uzoq ishlovni javobdan keyin bajaring.
  • Aks holda yetkazish 1 daq, 5 daq, 15 daq, 1 soat, 3 soat, 6 soat va 12 soatdan keyin takrorlanadi, so'ng xato deb belgilanadi. Uni admin paneldan qayta yuborish mumkin.
  • Bitta hodisa ikki marta kelishi mumkin: takrorlardan himoyalanish uchun id dan foydalaning.
  • Kassa hodisalari tartib bilan yuboriladi, lekin takrorlardan keyin tartib kafolatlanmaydi: createdAt va data.object dagi holatga tayaning.
  • Manzil https bo'lishi va internetdan ochiq bo'lishi kerak.

Ushbu sahifada