LiaРазработчики

Руководства

Полный обработчик вебхука. Проверьте подпись в исходном теле, проверьте с помощью API, действуйте один раз, и отвечайте быстро.

Lia отправляет charge.paid, charge.refunded и reward.paid на ваш адрес вебхука, подписанного вашим секретом вебхука. См. Вебхуки для каждого поля.

#Node.js с Express

Прочтите тело в исходном виде: подпись находится над точными байтами Lia, которые были отправлены, поэтому проверьте ее до любого JSON парсинга.

webhook.js
import express from "express";
import { createHmac, timingSafeEqual } from "node:crypto";
import { lia } from "./lia.js";

const app = express();

function verified(rawBody, header, secret) {
  const parts = Object.fromEntries((header ?? "").split(",").map((part) => part.split("=")));
  const t = Number(parts.t);
  if (!t || !parts.v1 || Math.abs(Date.now() / 1000 - t) > 300) return null;
  const expected = Buffer.from(createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex"));
  const given = Buffer.from(parts.v1);
  if (expected.length !== given.length || !timingSafeEqual(expected, given)) return null;
  return JSON.parse(rawBody);
}

app.post("/lia/webhook", express.raw({ type: "application/json" }), async (req, res) => {
  const event = verified(req.body.toString("utf8"), req.get("Lia-Signature"), process.env.LIA_WEBHOOK_SECRET);
  if (!event) return res.status(400).end();

  // Answer first; do the work after.
  res.status(200).end();

  if (event.type === "charge.paid") {
    // A nudge: check with Lia, then grant once per charge.
    const { charge } = await lia("GET", `/charges/${event.data.id}`);
    if (charge.status !== "paid") return;
    await db.grantOnce(charge.id, charge.playerId, () => grant(charge.playerId, charge.productId));
    await lia("POST", `/charges/${charge.id}/deliver`);
  }

  if (event.type === "charge.refunded") {
    await db.takeBack(event.data.id); // if you'd already given it
  }

  if (event.type === "reward.paid") {
    await db.noteReward(event.data.key, event.data.playerId, event.data.amount);
  }
});

#Cloudflare Работники

worker.js
async function verified(request, secret) {
  const rawBody = await request.text();
  const parts = Object.fromEntries((request.headers.get("Lia-Signature") ?? "").split(",").map((part) => part.split("=")));
  const t = Number(parts.t);
  if (!t || !parts.v1 || Math.abs(Date.now() / 1000 - t) > 300) return null;
  const key = await crypto.subtle.importKey("raw", new TextEncoder().encode(secret), { name: "HMAC", hash: "SHA-256" }, false, ["verify"]);
  const signature = new Uint8Array(parts.v1.match(/../g).map((byte) => parseInt(byte, 16)));
  const ok = await crypto.subtle.verify("HMAC", key, signature, new TextEncoder().encode(`${t}.${rawBody}`));
  return ok ? JSON.parse(rawBody) : null;
}

export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url);
    if (request.method === "POST" && url.pathname === "/lia/webhook") {
      const event = await verified(request, env.LIA_WEBHOOK_SECRET);
      if (!event) return new Response(null, { status: 400 });
      ctx.waitUntil(handle(event, env)); // the work, after answering
      return new Response(null, { status: 200 });
    }
    return new Response("Not found", { status: 404 });
  },
};

#Правила thumb

  • Проверьте подпись, а затем проверьте с API. Вебхук говорит, что что-то произошло; GET /charges/:id говорит, что'это правда сейчас.
  • Действуйте один раз. Вебхуки могут прийти дважды, и ваша страница уже могла их доставить. Учитывайте, что вы делаете по идентификатору платежа или ключу вознаграждения.
  • Ответ 2xx быстро. Lia пытается вебхук дважды, сразу, а затем сдается. Делайте медленную работу после ответа.
  • Дон'не полагаться только на вебхуки. Догоните Lia.charges() когда игрок открывает ваше приложение, поэтому пропущенный вебхук никогда не теряет продажу.
  • Обратите внимание на режим. Тестовые события приходят по одному адресу: проверьте data.mode.
  • Игнорируйте типы, которые вы не'не знать, и все еще отвечать 200.

#Тестирование вашего обработчика

Сделайте тестовую покупку как тестировщик (см. Тестирование): отправляет реальный, подтвержденный charge.paid с mode: "test". Чтобы протестировать это на своем компьютере, разместите локальный сервер за туннелем https и попросите команду Lia указать ваш webhook-адрес туда.

Автоматически переведено. Английский — источник истины. Читать на английском

Введите, чтобы искать по каждой странице, методу и точке окончания.