用PHP实现ImToken钱包的链上到账通知方案

qbadmin 1.0K 0
本方案基于PHP技术栈,实现ImToken钱包的链上到账实时通知功能,通过对接区块链节点或ImTOKen开放接口,监听以太坊、BSC等主流链上目标钱包地址的交易状态,PHP后端负责处理链上交易回调数据,验证交易签名、地址匹配等合法性,排除无效转账后,通过邮件、短信或Webhook等渠道向用户推送到账通知,保障用户及时掌握资产到账动态,优化链上交易的信息触达效率。

背景与需求

ImToken作为当前主流的多链加密货币钱包,支持以太坊、BSC、Polygon等数十条公链,广泛应用于个人资产管理、项目收款、DApp交互等场景,对于加密项目方来说,实时监控收款地址的到账是自动分发代币、完成用户充值的核心前提;而个人用户或小型工作室也需要及时掌握资产变动,避免手动查询的低效与延迟,由于ImToken本身未提供面向第三方的公开到账回调接口,因此通过区块链浏览器API轮询的方式成为最易实现、成本最低的方案,本文将详细介绍如何用PHP快速搭建这套监听系统,适配中小场景的需求。

核心实现逻辑

ImToken本身作为轻钱包,并未提供面向第三方的公开到账回调接口,因此轮询区块链浏览器API成为最易实现、成本最低的方案——虽然存在秒级延迟,但完全满足中小项目或个人的需求,核心逻辑分为5步:

  1. 选择对应公链的区块链浏览器(如BSC链用BSCscan、以太坊用Etherscan),其提供的公开API可查询地址的所有交易;
  2. 调用API获取目标地址的最新交易记录;
  3. 对比本地存储的最后查询块号,过滤出本次轮询的新交易;
  4. 校验新交易的有效性:确认是转入目标地址、交易成功、排除转出/失败交易;
  5. 触发通知(企业微信、邮件、短信等),完成到账提醒。

准备工作

  1. 环境要求:PHP 7.4+,开启cURL扩展(用于API请求)、BCMath扩展(用于处理链上大数字,避免精度丢失);
  2. API密钥:申请对应区块链浏览器的免费API密钥(如BSCscan免费版支持5次/秒调用,每分钟轮询一次的话,每次仅1次请求,完全不会触发限流);
  3. 示例场景:以BSC链为例(ImToken原生支持BSC链,是中小项目收款的首选公链)。

具体实现步骤

核心监听脚本(PHP示例)

以下是支持BSC链原生币BNB到账通知的简化版脚本,同时兼容扩展为ERC20代币监听:

<?php
// 配置项(建议用.env文件管理,避免硬编码)
$config = [
    'api_key' => '你的BSCscan API密钥',
    'imtoken_address' => '你的ImToken BSC地址',
    'last_block_file' => 'last_block.txt', // 存储上次查询的最后块号
    'notify_type' => 'wechat', // 通知类型:wechat/email/sms
    'notify_webhook' => '你的企业微信机器人Webhook', // 企业微信用
    // 邮件通知配置(如需)
    'smtp_host' => 'smtp.qq.com',
    'smtp_user' => '你的邮箱账号',
    'smtp_pass' => '邮箱授权码',
    'notify_email' => '接收通知的邮箱'
];
// 1. 获取上次查询的最后块号(首次运行需手动设置初始块号,避免返回过多历史交易)
$lastBlock = file_exists($config['last_block_file']) ? (int)file_get_contents($config['last_block_file']) : 0;
// 首次运行提示:建议先访问BSCscan地址页,获取当前最新块号替换$lastBlock为该值
// 2. 调用BSCscan API查询最新交易
$apiUrl = sprintf(
    "https://api.bscscan.com/api?module=account&action=txlist&address=%s&startblock=%d&sort=desc&apikey=%s",
    $config['imtoken_address'], $lastBlock, $config['api_key']
);
$response = file_get_contents($apiUrl);
$data = json_decode($response, true);
// 3. 处理API返回结果
if ($data['status'] !== '1') {
    error_log("API调用失败:" . $data['message']);
    exit;
}
$newTxs = $data['result'];
if (empty($newTxs)) {
    exit("无新交易");
}
// 4. 更新最后块号为本次查询的最新块号
$latestBlock = (int)$newTxs[0]['blockNumber'];
file_put_contents($config['last_block_file'], $latestBlock);
// 5. 遍历新交易,判断有效到账
foreach ($newTxs as $tx) {
    // 有效到账条件:转入目标地址、交易成功(isError=0)、排除转出
    if (
        strtolower($tx['to']) === strtolower($config['imtoken_address']) 
        && $tx['isError'] === '0'
    ) {
        // 转换BNB金额(18位小数)
        $amount = bcdiv($tx['value'], bcpow(10, 18), 18);
        $txHash = $tx['hash'];
        // 触发通知
        sendNotify($config, "BSC到账通知:{$amount} BNB,交易哈希:{$txHash},区块高度:{$tx['blockNumber']}");
    }
}
/**
 * 通知函数(支持企业微信/邮件)
 */
function sendNotify($config, $content) {
    switch ($config['notify_type']) {
        case 'wechat':
            $postData = json_encode([
                'msgtype' => 'text',
                'text' => ['content' => $content]
            ]);
            $ch = curl_init($config['notify_webhook']);
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
            curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
            curl_exec($ch);
            curl_close($ch);
            break;
        case 'email':
            // 需先安装PHPMailer:composer require phpmailer/phpmailer
            require 'vendor/autoload.php';
            $mail = new PHPMailer\PHPMailer\PHPMailer();
            $mail->isSMTP();
            $mail->Host = $config['smtp_host'];
            $mail->SMTPAuth = true;
            $mail->Username = $config['smtp_user'];
            $mail->Password = $config['smtp_pass'];
            $mail->SMTPSecure = 'tls';
            $mail->Port = 587;
            $mail->setFrom($config['smtp_user'], '链上到账通知');
            $mail->addAddress($config['notify_email']);
            $mail->isHTML(true);
            $mail->Subject = 'BSC到账提醒';
            $mail->Body = nl2br($content);
            $mail->send();
            break;
    }
}
?>

定时运行脚本

为了持续监听,需用定时任务每分钟执行一次脚本,避免遗漏交易:

  • Linux环境:编辑crontab(crontab -e),添加规则(自动清理7天前日志):
    */1 * * * * /usr/bin/php /你的脚本路径/tx_notify.php >> /var/log/tx_notify.log 2>&1 && find /var/log/tx_notify.log -mtime +7 -delete
  • 生产环境优化:搭配supervisor守护进程,避免脚本意外中断,配置示例:
    [program:tx_notify]
    command=/usr/bin/php /你的脚本路径/tx_notify.php
    autostart=true
    autorestart=true
    stderr_logfile=/var/log/tx_notify.err.log
    stdout_logfile=/var/log/tx_notify.out.log

进阶优化与扩展

  1. 支持ERC20/BEP20代币:将API的action参数改为tokentx,添加contractaddress参数指定代币合约地址(如USDT合约地址),解析交易时根据代币小数位数(如USDT为6位)转换金额,即可监听各类代币到账。
  2. 实时监听替代轮询:轮询存在1分钟延迟,可改用WebSocket订阅实现秒级通知,通过web3.php库接入Infura或BSC节点的WebSocket接口,监听链上交易事件,延迟可降至秒级。
  3. 交易确认数校验:为避免链上回滚导致的无效通知,需等待交易达到一定确认数后再通知(BSC建议12个,以太坊建议12个),脚本中添加逻辑对比当前块号与交易块号,计算确认数后触发通知。
  4. 多链支持:切换Etherscan(以太坊)、PolygonScan(Polygon)、Solscan(Solana)等API,仅需替换域名和API密钥,即可实现跨链监听。

注意事项

  1. API安全:不要硬编码API密钥,推荐用vlucas/phpdotenv加载.env文件,或服务器环境变量存储,避免代码泄露;同时将.env加入.gitignore,禁止提交到公共仓库。
  2. 调用频率:免费API有调用限制,轮询间隔建议设为1分钟,若需更高频率可升级付费API,或合并多地址查询减少调用次数。
  3. 地址大小写:区块链地址不区分大小写,但统一转小写后对比可避免匹配失败,代码中已实现该逻辑,无需额外调整。

通过这套方案,开发者可低成本搭建稳定的链上到账监听系统,适配中小项目的收款监控需求,部署简单、维护方便,还可结合数据库实现交易统计、对账等扩展功能,进一步提升实用性。

标签: #钱包 #USDT #ImToken