Hướng dẫn
Xử lý webhook
Sao chép trang
Một trình xử lý webhook hoàn chỉnh. Kiểm tra chữ ký trên nội dung thô, kiểm tra với API, thực hiện một lần và trả lời nhanh.
Lia gửi charge.paid, charge.refunded và reward.paid đến địa chỉ webhook của bạn, được ký bằng bí mật webhook của bạn. Xem Webhooks cho mỗi trường.
#Node.js với Express
Đọc nội dung thô: chữ ký nằm trên các byte chính xác mà Lia đã gửi, vì vậy hãy kiểm tra trước khi phân tích JSON bất kỳ.
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 Workers
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 });
},
};#Quy tắc chung
- Kiểm tra chữ ký, sau đó kiểm tra với API. Một webhook nói rằng điều gì đó đã xảy ra;
GET /charges/:idnói gì'mà đúng bây giờ. - Hành động một lần. Webhooks có thể đến hai lần, và trang của bạn có thể đã gửi trước đó. Hãy ghi nhớ những gì bạn làm với id giao dịch hoặc khóa phần thưởng.
- Trả lời
2xxnhanh chóng. Lia thử webhook hai lần, ngay lập tức, sau đó bỏ qua. Làm công việc chậm sau khi trả lời. - Không'dựa vào webhook riêng. Bắt kịp với
Lia.charges()khi người chơi mở ứng dụng của bạn, do đó một webhook bị bỏ lỡ không bao giờ làm mất một giao dịch. - Lưu ý đến chế độ. Sự kiện kiểm tra đến cùng một địa chỉ: kiểm tra
data.mode. - Bỏ qua các kiểu bạn không'biết, và vẫn trả lời
200.
#Kiểm tra xử lý của bạn
Thử mua hàng như một người kiểm tra (xem Kiểm tra): nó gửi một charge.paid với mode: "test". Để thử trên máy tính của bạn, đặt máy chủ cục bộ của bạn sau một kết nối https và yêu cầu đội Lia chỉ định địa chỉ webhook của bạn đến đó.
Được dịch tự động. Tiếng Anh là nguồn tin cậy. Đọc bằng tiếng Anh