الدروس
معالجة الـ webhooks
نسخ الصفحة
معالجة ويب هوك كاملة. تحقق من التوقيع في الجسم الأصلي، وتحقق مع API، واتخذ إجراء واحد، ورد بسرعة.
يُرسل Lia charge.paid, charge.refunded و reward.paid إلى عنوان ويب هوك الخاص بك، موقعة بسر ويب هوك الخاص بك. انظر الويب هوكس لكل مجال.
#Node.js مع إكسبريس
اقرأ الجسم بحالة خام: التوقيع على البايتات الدقيقة Lia المرسلة، لذلك تحقق قبل أي تحليل JSON.
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 العمال
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 });
},
};#قواعد عامة
- تحقق من التوقيع، ثم تحقق مع API. يقول الويب هوك شيئًا حدث؛
GET /charges/:idتقول ما'الواقع الآن. - اعمل مرة واحدة. يمكن أن تصل الويب هوكس مرتين، وقد تم تسليم صفحتك بالفعل. قم بتحديد ما تفعله على معرف الدفع أو مفتاح المكافأة.
- إجابة
2xxبسرعة. يحاول Lia مُعدَّل الويب مرتين، مباشرة، ثم يستسلم. قم بعمل بطيء بعد الإجابة. - لا'لا تعتمد فقط على الـ webhooks. اللحاق بالركب
Lia.charges()عندما يفتح اللاعب تطبيقك، لذلك لا يفقد بيعًا أبدًا بسبب ويب هوك مفقود. - انتبه للوضع. تصل الأحداث التجريبية إلى نفس العنوان: تحقق من
data.mode. - تجاهل الأنواع التي لا'لأنك تعرف والإجابة, ويرد على
200.
#اختبار معالجك
قم بشراء تجريبية كمُختبر (انظر الاختبار): يرسل رمزًا حقيقيًا مُوقَّعًا charge.paid مع mode: "test". لتجربته على جهازك، ضع خادمك المحلي خلف جسر HTTPS واطلب من فريق Lia توجيه عنوان ويب هوك الخاص بك إليه.
تم الترجمة تلقائيًا. الإنجليزية هي مصدر الحقيقة. اقرأ باللغة الإنجليزية