服务器参考
网络钩子
复制页面
Lia会在支付或退款时以及奖励支付时通知你的服务器,并用你的webhook密钥进行签名。发送的内容、如何检查签名以及重试的工作方式。
#设置一个
给Lia团队一个你服务器的https地址,并保留webhook签名密钥(whsec_…)与您的密钥一起提供。Lia 然后发送一个 POST 当你的应用中发生某些事情时,它就会出现。
一个网络钩子是一个 推动,不是真相:在采取行动之前,请先与API核实(例如,对于一次收费, GET /charges/:id)。而且不要'仅依赖网络钩子;您的页面也可以告诉您的服务器(参见 出售物品).
#什么'的发送
POST /lia/webhook
Content-Type: application/json
Lia-Signature: t=1761998400,v1=5f2c8a…
{
"type": "charge.paid",
"app": "your-app",
"at": 1761998400123,
"data": {
"id": "ch_9b1f4c2e7a0d5b8f3e6a1c4d",
"playerId": "p_3f9c0a6d1b2e4f5a6b7c",
"productId": "extra-lives",
"amount": 5,
"status": "paid",
"mode": "live",
"createdAt": 1761998400000,
"deliveredAt": null,
"refundedAt": null
}
}| 字段 | 类型 | |
|---|---|---|
type | 字符串 | 发生了什么(如下)。 |
app | 字符串 | 您的应用程序 ID。 |
at | 数字 | 当它被发送时,以 1970. 以来的毫秒数表示 |
data | 对象 | 它's 关于。 |
#类型
| 类型 | 何时 | data |
|---|---|---|
charge.paid | 有人在Lia上付款'的付款表格,在测试或正式环境中。 | 的 收费,带有 status: "paid" |
charge.refunded | 您已退款。 | 费用,以及 status: "refunded" |
reward.paid | 您从您的资金池中支付了奖励,在测试或上线状态下。 | { key, playerId, amount, reason, mode } |
检查 data.mode (或充值's mode)因此测试事件永远不会授予任何真实的东西。可能会添加更多类型:忽略您不熟悉的类型。'不要知道并回答 200.
#检查签名
每个网络钩子都有一个 Lia-Signature 标题, t=<seconds>,v1=<signature>。签名是HMAC SHA-256,的十六进制,是秒数、点和原始正文的组合,使用你的整个网络钩子密钥(包括 whsec_):
v1 = hex(HMAC_SHA256(key = "whsec_…", message = t + "." + rawBody))将其与原始身体内容精确对比,就像它到达时一样,在解析之前,拒绝几分钟以上的网络钩子。
import { createHmac, timingSafeEqual } from "node:crypto";
export function liaWebhook(rawBody, header, secret, toleranceSeconds = 300) {
const parts = Object.fromEntries((header ?? "").split(",").map((part) => part.split("=")));
const t = Number(parts.t);
if (!t || !parts.v1) return null;
if (Math.abs(Date.now() / 1000 - t) > toleranceSeconds) 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);
}export async function liaWebhook(request, secret, toleranceSeconds = 300) {
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) > toleranceSeconds) 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;
}处理网络钩子 有一个完整的处理程序。
#回答和重试
- 用任何
2xx状态,快速。在回答后进行缓慢的工作。 - 如果你的服务器没有't 回答
2xx或可以't 被到达),Lia会立即再试一次。之后,webhook不会'再次发送。 - 因此webhooks可能会被错过,也可能重复到达。请确保您的处理程序可以安全地运行两次(根据charge id或reward key进行键控),并有另一种方式来追上进度,例如
Lia.charges()当玩家打开你的应用时。
#您的密钥
您的网络钩子密钥在您的密钥重新生成时会更改。将其保留在您的服务器上,与您的密钥放在一起。
自动翻译。英语是真实来源。 阅读英文