如何通过tonapi.io Webhook正确获取交易状态?
如何通过tonapi.io Webhook正确获取交易状态?
我来帮你拆解下你遇到的问题,其实核心是对TON API的参数格式和鉴权规则理解有偏差,咱们一步步解决:
一、核心问题:account_id格式不匹配
你收到的「illegal base32 data」错误,本质是因为TON API的账户ID参数要求的是base64url格式(无填充),但webhook返回的是带0:前缀的十六进制格式。之前你尝试转base64url可能步骤有误,再加上鉴权的小问题,导致报错混淆了。
二、正确转换account_id的步骤
给你写个靠谱的转换工具函数(以JavaScript为例),一步到位把webhook里的account_id转成TON API需要的格式:
function convertTonAccountIdToBase64url(accountId) { // 先校验格式:必须带0:前缀 if (!accountId.startsWith('0:')) { throw new Error('Invalid TON account format (missing "0:" prefix)'); } // 去掉0:前缀,取纯十六进制部分 const hexRaw = accountId.slice(2); // 十六进制转字节数组 const byteArray = new Uint8Array(hexRaw.length / 2); for (let i = 0; i < hexRaw.length; i += 2) { byteArray[i / 2] = parseInt(hexRaw.slice(i, i + 2), 16); } // 字节数组转base64再转base64url(替换特殊字符+去掉填充) const base64 = btoa(String.fromCharCode(...byteArray)); return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''); }
三、401未授权问题的排查方向
你已经加了Bearer头,但还是报401,大概率是这几个细节没注意:
- API Key格式问题:检查你的key有没有多余的空格、换行符(比如复制时带了末尾空格,或者从.env文件读取时带了换行),建议用
trim()处理:const authHeader = `Bearer ${process.env.TON_API_KEY.trim()}`; - 鉴权头格式错误:必须严格是
Bearer(后面跟一个空格)+ API Key,不能少空格,也不能多写其他字符。 - API Key权限问题:去TON API的控制台看看你的key是否有效,有没有被禁用,或者是否有权限访问你调用的交易查询端点。
四、优化后的完整webhook处理代码
我把你的handler函数做了优化,加入了正确的格式转换、鉴权处理,还加了最佳实践的签名验证注释:
import { checkTransactionStatus } from "../utils/ton.js"; // 新增:account_id格式转换工具函数 function convertTonAccountIdToBase64url(accountId) { if (!accountId.startsWith('0:')) { throw new Error('Invalid TON account format (missing "0:" prefix)'); } const hexRaw = accountId.slice(2); const byteArray = new Uint8Array(hexRaw.length / 2); for (let i = 0; i < hexRaw.length; i += 2) { byteArray[i / 2] = parseInt(hexRaw.slice(i, i + 2), 16); } const base64 = btoa(String.fromCharCode(...byteArray)); return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''); } export default async function handler(req, res) { if (req.method !== "POST") { return res.status(405).json({ error: "Method not allowed" }); } try { const { tx_hash, account_id } = req.body; if (!tx_hash || !account_id) { return res.status(400).json({ error: "Invalid request body: missing tx_hash or account_id" }); } // 【最佳实践】验证webhook签名,防止恶意请求 // 你需要从TON API控制台获取webhook secret,然后验证X-TON-Signature头 // const signature = req.headers['x-ton-signature']; // const isValid = verifyWebhookSignature(JSON.stringify(req.body), signature, process.env.TON_WEBHOOK_SECRET); // if (!isValid) return res.status(403).json({ error: "Invalid webhook signature" }); // 1. 转换account_id为TON API要求的格式 const formattedAccountId = convertTonAccountIdToBase64url(account_id); // 2. 确保鉴权头格式正确 const authHeader = `Bearer ${process.env.TON_API_KEY.trim()}`; // 3. 调用TON API获取交易状态 const status = await checkTransactionStatus(tx_hash, formattedAccountId, authHeader); return res.status(200).json({ status, transaction: tx_hash, account: formattedAccountId }); } catch (error) { console.error("Webhook handler error:", error); return res.status(500).json({ error: "Internal server error", details: error.message }); } }
五、额外避坑提示
- tx_hash无需转换:webhook里的交易哈希是直接可用的十六进制格式,直接传给TON API即可。
- 错误信息的误导性:有时候TON API的错误信息会不准,比如base32错误可能其实是你调用的端点参数名写错了(比如用了
account_id而端点要求account),一定要核对官方文档的参数名。 - 签名验证必做:不要忽略webhook签名验证,否则可能收到恶意伪造的交易通知。
备注:内容来源于stack exchange,提问作者Robert Grey
相关产品推荐
相关产品推荐

