跳转到主要内容

简介

通常,当您向 API 端点发出请求时,您期望获得近乎即时的响应。但是,某些请求可能需要较长时间处理,这可能导致超时错误。为了防止超时错误,会返回一个待处理响应。由于您的记录需要更新为请求的最终状态,您需要:
  1. 请求更新(通常称为轮询),或
  2. 使用 Webhook URL 监听事件。
实用提示
我们建议您使用 Webhook 为客户提供价值,而不是使用回调或轮询。使用回调时,我们无法控制客户端发生的情况。您也无法控制。如果客户设备上的网络连接失败或较弱,或者设备在交易后关闭,回调可能会失败。

轮询 vs Webhooks

轮询需要定期发出 GET 请求以获取请求的最终状态。例如,当您为客户分配充值地址时,您需要不断请求与该地址关联的交易,直到找到一个。 使用 Webhooks,资源服务器(在本例中为 Blockradar)会在您请求的状态发生变化时向您的服务器发送更新。请求状态的变化称为事件。您通常会在称为 Webhook URL 的 POST 端点上监听这些事件。 下表突出显示了轮询和 Webhooks 之间的一些差异:
轮询Webhooks
更新方式手动自动
速率限制
受扩展影响

创建 Webhook URL

Webhook URL 只是资源服务器发送更新的 POST 端点。该 URL 需要解析 JSON 请求并返回 200 OK
// Using Express
app.post("/my/webhook/url", function(req, res) {
    // Retrieve the request's body
    const event = req.body;
    // Do something with event
    res.send(200);
});
当您的 Webhook URL 收到事件时,需要解析并确认事件。确认事件意味着在 HTTP 头中返回 200 OK。如果响应头中没有 200 OK,我们将在接下来的 2 小时 35 分钟内持续发送事件:
  • 我们将尝试发送 5 次 Webhook,每次尝试之间的延迟递增,从 5 分钟开始并以指数方式增加到 80 分钟。这 5 次尝试的总持续时间约为 2 小时 35 分钟。
避免长时间运行的任务
如果您的 Webhook 函数中有长时间运行的任务,您应该在执行长时间运行的任务之前确认事件。长时间运行的任务会导致请求超时和服务器自动返回错误响应。没有 200 OK 响应,我们将按上述方式重试。

本地测试 Webhooks

在开发过程中,您可以在测试主钱包环境中将 Webhook URL 配置为本地地址,例如 http://localhost127.0.0.1 要将本地服务器暴露到互联网以进行测试,请考虑使用 ngrokwebhook.site 等工具。这些工具允许您查看 Webhook 载荷的样子,并在将应用程序部署到正式环境之前在本地模拟 Webhook 事件。 使用这些工具,您可以确保 Webhook 集成正常工作,并在进入生产环境之前在受控的本地环境中处理任何问题。

重新发送交易 Webhook

如果由于某些原因您没有收到交易 Webhook 且退避时间已过,我们提供了一个 API 供您重新发送交易 Webhook
谨慎使用!
这可能导致处理已完成的交易,请确保在使用此端点时进行适当的验证。
curl --request POST \
  --url https://api.blockradar.co/v1/wallets/{walletId}/transactions/webhooks/resend \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: <api-key>' \
  --data '{
  "id": "TRANSACTION_ID"
}'

验证事件来源

由于您的 Webhook URL 是公开可用的,您需要验证事件是否来自 Blockradar 而不是恶意攻击者。有两种方法可以确保 Webhook URL 的事件来自 Blockradar:
  1. 签名验证(推荐)

签名验证

从 Blockradar 发送的事件带有 x-blockradar-signature 头。此头的值是使用您的密钥对事件载荷进行 HMAC SHA512 签名的结果。应在处理事件之前验证头签名:
const crypto = require('crypto');
const apiKey = process.env.WALLET_API_KEY;
// Using Express
app.post("/my/webhook/url", function(req, res) {
    //validate event
    const hash = crypto.createHmac('sha512', apiKey).update(JSON.stringify(req.body)).digest('hex');
    if (hash == req.headers['x-blockradar-signature']) {
    // Retrieve the request's body
    const event = req.body;
    // Do something with event
    }
    res.send(200);
});

上线检查清单

现在您已成功创建 Webhook URL,以下是确保您获得良好体验的一些方法:
  • Blockradar 控制面板的主钱包上添加 Webhook URL
  • 确保您的 Webhook URL 是公开可用的(localhost URL 无法接收事件)
  • 如果使用 .htaccess,请记住在 URL 末尾添加尾部 /
  • 测试您的 Webhook 以确保您获取 JSON 主体并返回 200 OK HTTP 响应
  • 如果您的 Webhook 函数有长时间运行的任务,您应该首先通过返回 200 OK 确认收到 Webhook,然后再继续长时间运行的任务
  • 如果我们没有从您的 Webhook 收到 200 OK HTTP 响应,我们会将其标记为失败尝试
  • 我们将尝试发送 5 次 Webhook,每次尝试之间的延迟递增,从 5 分钟开始并以指数方式增加到 80 分钟。这 5 次尝试的总持续时间约为 2 小时 35 分钟。

事件类型

以下是我们目前触发的事件。随着我们在未来接入更多操作,我们会将更多事件添加到此列表中。

事件示例

以下是一些最常见事件的 Webhook 载荷示例:
{
    "event": "deposit.success",
    "data": {
        "id": "6d2f9646-cae4-48a5-8bfe-1f9379868d4f",
        "reference": "LSk5RLfSrR",
        "senderAddress": "0x2455eC6700092991Ce0782365A89d5Cd89c8Fa22",
        "recipientAddress": "0xe1037B45b48390285e5067424053fa35c478296b",
        "amount": "10.0",
        "amountPaid": "10.0",
        "fee": null,
        "currency": "USD",
        "blockNumber": 6928760,
        "blockHash": "0x5f2e0ed782752b9559e7a3d89c0fb9f6706e4866e74ba7a434cf933bb3f02a2b",
        "hash": "0x94c733496df59c15e5a489f20374096bba31166a8e149ceea4d410e3e5821357",
        "confirmations": 6,
        "confirmed": true,
        "gasPrice": "1201381238",
        "gasUsed": "62159",
        "gasFee": "0.000074676656372842",
        "status": "SUCCESS",
        "type": "DEPOSIT",
        "note": null,
        "amlScreening": {
            "provider": "ofac",
            "status": "success",
            "message": "Address is not sanctioned"
        },
        "network": "testnet",
        "chainId": 11155111,
        "metadata": {
            "user_id": 1
        },
        "createdAt": "2024-10-23T11:19:58.451Z",
        "updatedAt": "2024-10-23T11:19:58.451Z",
        "asset": {
            "id": "fe04a28c-c615-4e41-8eda-f84c862864f5",
            "name": "USDC Coin",
            "symbol": "USDC",
            "decimals": 6,
            "address": "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
            "standard": "ERC20",
            "isActive": true,
            "logoUrl": "https://res.cloudinary.com/blockradar/image/upload/v1716800083/crypto-assets/usd-coin-usdc-logo_fs9mhv.png",
            "network": "testnet",
            "createdAt": "2024-05-14T11:53:33.682Z",
            "updatedAt": "2024-06-14T22:32:12.589Z"
        },
        "address": {
            "id": "0a69c48a-6c6f-422c-bd6a-70de3306a3ac",
            "address": "0xe1037B45b48390285e5067424053fa35c478296b",
            "name": "Customer 1",
            "isActive": true,
            "type": "INTERNAL",
            "derivationPath": "m/44'/60'/0'/0/87",
            "metadata": {
                "user_id": 1
            },
            "network": "testnet",
            "createdAt": "2024-10-23T11:13:40.446Z",
            "updatedAt": "2024-10-23T11:13:40.446Z"
        },
        "blockchain": {
            "id": "85ffc132-3972-4c9e-99a5-5cf0ccb688bf",
            "name": "ethereum",
            "symbol": "eth",
            "slug": "ethereum",
            "derivationPath": "m/44'/60'/0'/0",
            "isEvmCompatible": true,
            "logoUrl": "https://res.cloudinary.com/blockradar/image/upload/v1716800081/crypto-assets/ethereum-eth-logo_idraq2.png",
            "isActive": true,
            "tokenStandard": "ERC20",
            "createdAt": "2024-05-14T11:53:33.095Z",
            "updatedAt": "2024-06-14T22:32:11.983Z"
        },
        "wallet": {
            "id": "d236a191-c1d4-423c-a439-54ce6542ca41",
            "name": "Ethereum Master Wallet",
            "description": "This is ethereum testnet master wallet",
            "address": "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a",
            "derivationPath": "m/44'/60'/0'/0/0",
            "isActive": true,
            "status": "ACTIVE",
            "network": "testnet",
            "createdAt": "2024-08-22T09:48:56.322Z",
            "updatedAt": "2024-10-23T10:52:34.332Z"
        },
        "beneficiary": null
    }
}


祝您开发愉快!