logo NodeSeekbeta

分享下用Grok帮助写的USDT收款程序

基于BSC链的收款系统。

演示:https://buo.us.kg/usdt.php

只需修改两处:
第8行:在 www.bscscan.com 注册,免费申请个KEY,填入第8行。
第9行:改为自己的收款地址

运行会自动生成个SQLite数据库usdt_payments.db储存订单信息,可以修改代码更改数据库路径。充值成功后的结合现有业务逻辑,在175行。

image

image

<?php
header('Content-Type: text/html; charset=utf-8');

// BSC 配置
    //修改此处KEY和收款地址
    const BSC_API_KEY = "KEY";//币安BSC链API KEY
    const WALLET_ADDRESS = "ADDRESS"; //收款地址
    //BSC信息不可更改
    const USDT_CONTRACT = "0x55d398326f99059fF775485246999027B3197955";//币安合约地址,不可更改
    const BSC_API_URL = "https://api.bscscan.com/api?module=account&action=tokentx&contractaddress=%s&address=%s&startblock=0&endblock=99999999&sort=desc&apikey=%s"; //币安BSC链API请求地址



/*
   订单号和金额变量可以从get或者post传递,变量名称见html部分表单,可以删除html表单,使用现有业务的变量传递。
*/


// 设置默认时区为 UTC
date_default_timezone_set('UTC');
// 变量定义
$order_id = isset($_POST['order_id']) ? $_POST['order_id'] : (isset($_GET['order_id']) ? $_GET['order_id'] : '');
$amount = isset($_POST['amount']) ? floatval($_POST['amount']) : (isset($_GET['amount']) ? floatval($_GET['amount']) : 0);
$payment_status = null;


$order_id = date('YmdHis') . mt_rand(1000, 9999);

/**
 * 生成严格的小数补位(首位为0,末位非0)
 */
function generatePadding($digits) {
    if ($digits <= 0) return '';
    
    // 生成格式:0 + (n-1位随机) + 1位非0
    $middle = $digits > 1 
        ? str_pad(mt_rand(0, pow(10, $digits-1)-1), $digits-1, '0', STR_PAD_LEFT)
        : '';
    $last = mt_rand(1, 9);
    
    return '0' . $middle . $last; // 强制首位为0
}

/**
 * 智能金额格式化
 */
function formatDecimal($amount) {
    if (!is_numeric($amount) || $amount == 0) return '';
    
    $parts = explode('.', (string)floatval($amount));
    $intPart = $parts[0];
    $decimal = $parts[1] ?? '';
    
    if (strlen($decimal) >= 4) {
        $decimal = substr($decimal, 0, 4);
    } else {
        $needed = 4 - strlen($decimal);
        $padding = substr(generatePadding($needed), 0, $needed); // 截取所需位数
        $decimal .= $padding;
    }
    
    return $intPart . '.' . $decimal;
}



// 金额变量
$inputAmount = $_POST['amount'] ?? $_GET['amount'] ?? '';
$amount = is_numeric($inputAmount) && $inputAmount != 0 
    ? formatDecimal($inputAmount) 
    : '';
















// 初始化 SQLite 数据库
$db = new SQLite3('usdt_payments.db');
$db->exec("CREATE TABLE IF NOT EXISTS payments (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    order_id TEXT UNIQUE,
    amount REAL,
    wallet_address TEXT,
    tx_hash TEXT,
    status TEXT DEFAULT 'pending',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    processed INTEGER DEFAULT 0
)");

function checkPaymentStatus($db, $order_id) {
    $stmt = $db->prepare("SELECT * FROM payments WHERE order_id = :order_id");
    $stmt->bindValue(':order_id', $order_id, SQLITE3_TEXT);
    $result = $stmt->execute()->fetchArray(SQLITE3_ASSOC);
    
    if ($result && $result['status'] === 'pending') {
        $created_at = strtotime($result['created_at'] . ' UTC');
        if ($created_at === false) {
            file_put_contents('payment_error.log', "订单 $order_id 创建时间转换失败: " . $result['created_at'] . "\n", FILE_APPEND);
            return $result;
        }

        $url = sprintf(BSC_API_URL, USDT_CONTRACT, WALLET_ADDRESS, BSC_API_KEY);
        $response = @file_get_contents($url);
        if ($response === false) {
            file_put_contents('payment_error.log', "API 请求失败: $url\n", FILE_APPEND);
            return $result;
        }
        
        $data = json_decode($response, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            file_put_contents('payment_error.log', "JSON 解析失败: " . json_last_error_msg() . "\n", FILE_APPEND);
            return $result;
        }
        
        if ($data['status'] == "1" && !empty($data['result'])) {
            foreach ($data['result'] as $tx) {
                $tx_timestamp = intval($tx['timeStamp']);
                $value = floatval($tx['value']) / 1e18;

                if ($tx_timestamp <= $created_at) {
                    continue;
                }

                if ($tx['to'] === strtolower(WALLET_ADDRESS) && 
                    abs($value - $result['amount']) < 0.01 && 
                    $tx['contractAddress'] === strtolower(USDT_CONTRACT)) {
                    $check_tx = $db->prepare("SELECT COUNT(*) FROM payments WHERE tx_hash = :tx_hash AND order_id != :order_id");
                    $check_tx->bindValue(':tx_hash', $tx['hash'], SQLITE3_TEXT);
                    $check_tx->bindValue(':order_id', $order_id, SQLITE3_TEXT);
                    $tx_exists = $check_tx->execute()->fetchArray(SQLITE3_NUM)[0];
                    
                    if ($tx_exists == 0) {
                        $update = $db->prepare("UPDATE payments SET status = 'completed', tx_hash = :tx_hash WHERE order_id = :order_id AND status = 'pending'");
                        $update->bindValue(':tx_hash', $tx['hash'], SQLITE3_TEXT);
                        $update->bindValue(':order_id', $order_id, SQLITE3_TEXT);
                        $update->execute();

                        $updated = $db->prepare("SELECT * FROM payments WHERE order_id = :order_id");
                        $updated->bindValue(':order_id', $order_id, SQLITE3_TEXT);
                        $result = $updated->execute()->fetchArray(SQLITE3_ASSOC);
                        break;
                    }
                }
            }
        } else {
            file_put_contents('payment_error.log', "API 返回错误: " . $data['message'] . "\n", FILE_APPEND);
        }
    }
    return $result;
}

function handlePaymentSuccess($db, $order_id, $amount, $tx_hash) {

    // 数据库中标记订单为已处理
    $markProcessed = $db->prepare("UPDATE payments SET processed = 1 WHERE order_id = :order_id AND processed = 0");
    $markProcessed->bindValue(':order_id', $order_id, SQLITE3_TEXT);
    $result = $markProcessed->execute();
    if ($db->changes() == 0) {
        file_put_contents('payment_error.log', "订单 $order_id 标记 processed 失败\n", FILE_APPEND);
    }
    
    
    
/*
此处充值成功逻辑,不得包含任何echo或者其它显示
可以对原业务数据库进行update比如支付状态,和跳转、发送邮件通知、短信等等。
*/
    
    
    
    
}




// 处理 AJAX 检查请求
session_start();
if (isset($_POST['ajax_check']) && isset($_POST['order_id'])) {
    header('Content-Type: application/json');
    if (!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) {
        http_response_code(403);
        echo json_encode(['error' => 'Invalid CSRF token']);
        exit;
    }

    $payment_status = checkPaymentStatus($db, $_POST['order_id']);
    if ($payment_status && $payment_status['status'] === 'completed' && $payment_status['processed'] == 0) {
        handlePaymentSuccess($db, $payment_status['order_id'], $payment_status['amount'], $payment_status['tx_hash']);
    }
    echo json_encode($payment_status ?: ['error' => 'No payment found']);
    exit;
}

// 处理订单创建(仅当订单不存在时插入)
if ($amount > 0 && !empty($order_id) && !isset($_POST['ajax_check'])) {
    $check_stmt = $db->prepare("SELECT COUNT(*) FROM payments WHERE order_id = :order_id");
    $check_stmt->bindValue(':order_id', $order_id, SQLITE3_TEXT);
    $exists = $check_stmt->execute()->fetchArray(SQLITE3_NUM)[0];

    if ($exists == 0) {
        $stmt = $db->prepare("INSERT INTO payments (order_id, amount, wallet_address, status, created_at) 
                              VALUES (:order_id, :amount, :wallet_address, 'pending', CURRENT_TIMESTAMP)");
        $stmt->bindValue(':order_id', $order_id, SQLITE3_TEXT);
        $stmt->bindValue(':amount', $amount, SQLITE3_FLOAT);
        $stmt->bindValue(':wallet_address', WALLET_ADDRESS, SQLITE3_TEXT);
        $stmt->execute();
    }

    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}

// 检查支付状态
if (!empty($order_id)) {
    $payment_status = checkPaymentStatus($db, $order_id);
    if ($payment_status && $payment_status['status'] === 'completed' && $payment_status['processed'] == 0) {
        handlePaymentSuccess($db, $payment_status['order_id'], $payment_status['amount'], $payment_status['tx_hash']);
    }
}
?>
<!DOCTYPE html>
<html>
<head>
    <title>USDT 收款系统 (BSC)</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" />
    <style>
        body { font-family: Arial, sans-serif; max-width: 800px; margin: 20px auto; }
        .qr-code { margin: 20px 0; }
        canvas { border: 1px solid #ccc; }
    </style>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/qrcode.min.js"></script>
<style>
    /* 基础重置 */
    body {
        font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
        line-height: 1.5;
        color: #e0e0e0;
        background-color: #;
        max-width: 800px;
        margin: 0 auto;
        padding: 2rem;
        -webkit-font-smoothing: antialiased;
    }


    /* 表单容器 */
    #paymentForm {
        background: #1e293b;
        padding: 2rem;
        border-radius: 12px;
        box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.3);
        margin-bottom: 2rem;
        border: 1px solid #2e3a4e;
    }

    /* 输入框样式 */
    #paymentForm label {
        display: block;
        margin-bottom: 0.75rem;
        font-weight: 500;
        color: #94a3b8;
        font-size: 0.95rem;
    }

    #paymentForm input[type="text"],
    #paymentForm input[type="number"] {
        width: 100%;
        padding: 0.875rem 1rem;
        margin-bottom: 1.5rem;
        border: 1px solid #334155;
        border-radius: 8px;
        font-size: 1rem;
        background-color: #1e293b;
        color: #f8fafc;
        transition: all 0.2s ease;
    }

    #paymentForm input[type="text"]:focus,
    #paymentForm input[type="number"]:focus {
        border-color: #3b82f6;
        outline: none;
        box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2);
    }

    /* 按钮样式 */
    #paymentForm button {
        background: linear-gradient(135deg, #3b82f6, #6366f1);
        color: white;
        border: none;
        padding: 1rem;
        font-size: 1rem;
        font-weight: 600;
        border-radius: 8px;
        cursor: pointer;
        width: 100%;
        transition: all 0.2s ease;
    }

    #paymentForm button:hover {
        transform: translateY(-2px);
        box-shadow: 0 4px 12px -2px rgba(59, 130, 246, 0.4);
    }

    /* 支付信息卡片 */
    .payment-info {
        background: #1e293b;
        padding: 2rem;
        border-radius: 6px;
        box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.3);
        margin-top: 1.5rem;
        border: 1px solid #2e3a4e;
    }

    .payment-info h2 {
        color: #ffffff;
        margin-bottom: 1.5rem;
        font-weight: 600;
        font-size: 1.5rem;
        border-bottom: 1px solid #334155;
        padding-bottom: 0.75rem;
        
    text-align: center;  /* 文字水平居中 */

        
    }

    .payment-info p {
        margin: 1.25rem 0;
        font-size: 1rem;
        color: #e2e8f0;
    }

    /* 金额显示 */
    #amount {
        color: #10b981;
        font-weight: 600;
        font-size: 1.1rem;
    }
    
    .warn {
        color: #10b981;
        font-weight: 400;
        font-size: 1.1rem; 
    }

    /* 状态标签 */
    #status {
        font-weight: 600;
        padding: 0.375rem 0.75rem;
        border-radius: 6px;
        display: inline-block;
        font-size: 0.9rem;
    }

    #status.pending {
        color: #f59e0b;
        background-color: rgba(245, 158, 11, 0.1);
    }

    #status.completed {
        color: #10b981;
        background-color: rgba(16, 185, 129, 0.1);
    }

    /* 二维码容器 */
    /* 二维码容器 - 
        display: flex;
        justify-content: center;
        align-items: center;
            margin: 1.5rem auto;
    居中样式 */
    .qr-code {


        padding: 0.1rem;
        background: #fff;
        border-radius: 6px;
        border: 1px solid #334155;
        width: fit-content; /* 使容器宽度适应内容 */
    }

    /* 确保二维码画布本身也居中 */
    #qrcode {
        display: flex;
        justify-content: center;
    }
    
    .ipaddress {
        color: #3b82f6;
        text-decoration: none;
        font-weight: 500;
        word-break: break-all;
        transition: color 0.2s ease;
    }
    
    /* 复制按钮 */
    .copy-span {
        margin-left: 0.75rem;
        padding: 0.375rem 0.75rem;
        background-color: rgba(59, 130, 246, 0.1);
        color: #3b82f6;
        border: 1px solid rgba(59, 130, 246, 0.3);
        border-radius: 6px;
        cursor: pointer;
        font-size: 0.85rem;
        font-weight: 500;
        transition: all 0.2s ease;
    }

    .copy-span:hover {
        background-color: rgba(59, 130, 246, 0.2);
    }

    /* 交易哈希链接 */
    #txHash a {
        color: #3b82f6;
        text-decoration: none;
        font-weight: 500;
        word-break: break-all;
        transition: color 0.2s ease;
    }

    #txHash a:hover {
        color: #60a5fa;
        text-decoration: underline;
    }

    /* 二维码画布 */
    canvas {
        border: 1px solid #334155;
        border-radius: 8px;
        background: white;
        padding: 8px;
    }

    /* 响应式调整 */
    @media (max-width: 640px) {
        body {
            padding: 1.25rem;
        }
        
        #paymentForm, .payment-info {
            padding: 1.5rem;
        }
        
        h1 {
            font-size: 1.75rem;
            margin-bottom: 2rem;
        }
    }
</style>
</head>
<body>

<?php if (!isset($payment_status['amount']) || !$payment_status['amount']): ?>
    
    <form method="POST" id="paymentForm">

        <input type="hidden" name="order_id" value="<?php echo htmlspecialchars($order_id); ?>" placeholder="请输入订单号">
        <label>支付金额 (USDT):</label><?php //echo $amount > 0 ? $amount : ''; ?>
<input type="number" name="amount" style="box-sizing: border-box; max-width: 100%; -webkit-appearance: none;" step="0.000001" min="0.000001" 
       value="" placeholder="0.1" required>
        <input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?? ''; ?>">
        <button type="submit">显示支付信息</button>
    </form>
    
 <?php endif; ?>


    <?php if (!empty($order_id) &&               $amount                 &&  $payment_status): ?>
        <div class="payment-info">
            <h2>支付详情</h2>
            <!--p>订单: <span id="orderId"><?php echo htmlspecialchars($order_id); ?></span></p-->
            <p>BCS链: <span class="ipaddress">BNB Smart Chain(BEP20)</span></p>
            <p>金额: <span id="amount"><?php echo $payment_status['amount']; ?></span> USDT <span class="warn">(注意:金额必须精确)</span></p>
            <p>收款地址: <span class="ipaddress"><?php echo WALLET_ADDRESS; ?></span>
            <span class="copy-span" onclick="copyToClipboard('<?php echo WALLET_ADDRESS; ?>', this)">点击复制</span>
            </p>

            <div id="qrcode" class="qr-code"></div>
            <p>状态: <span id="status"><?php echo $payment_status['status']; ?></span></p>
            <p id="txHash" style="display: <?php echo $payment_status['status'] === 'completed' ? 'block' : 'none'; ?>">
                交易哈希: <a href="https://bscscan.com/tx/<?php echo $payment_status['tx_hash']; ?>" target="_blank"><?php echo $payment_status['tx_hash']; ?></a>
            </p>
        </div>
    <?php endif; ?>

    <script>
    function generateQR(text, elementId) {
        new QRCode(document.getElementById(elementId), {
            text: text,
            width: 150,
            height: 150,
            colorDark: "#000000",
            colorLight: "#ffffff",
            correctLevel: QRCode.CorrectLevel.H
        });
    }

    function startAutoCheck(orderId) {
        if (!orderId) return;

        const statusElement = document.getElementById('status');
        const txHashElement = document.getElementById('txHash');
        let checkInterval = null;

        const checkStatus = () => {
            console.log('检查状态,订单ID:', orderId);
            fetch(window.location.href, {
                method: 'POST',
                headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                body: 'ajax_check=1&order_id=' + orderId + '&csrf_token=<?php echo $_SESSION['csrf_token'] ?? ''; ?>'
            })
            .then(response => response.json())
            .then(data => {
                console.log('返回数据:', data);
                if (data && data.status === 'completed') {
                    statusElement.textContent = 'completed';
                    txHashElement.style.display = 'block';
                    txHashElement.innerHTML = `交易哈希: <a href="https://bscscan.com/tx/${data.tx_hash}" target="_blank">${data.tx_hash}</a>`;
                    if (checkInterval !== null) {
                        console.log('停止定时器,checkInterval:', checkInterval);
                        clearInterval(checkInterval);
                        checkInterval = null;
                    }
                }
            })
            .catch(error => console.error('检查状态失败:', error));
        };

        if (statusElement.textContent === 'pending' && checkInterval === null) {
            console.log('启动定时器,订单ID:', orderId);
            checkInterval = setInterval(checkStatus, 10000);
            checkStatus();
        }
    }

function copyToClipboard(text, element) {
  const input = document.createElement('input');
  input.value = text;
  document.body.appendChild(input);
  input.select();
  document.execCommand('copy');
  document.body.removeChild(input);
  
  const originalText = element.innerText;
  element.innerText = '已复制';
  setTimeout(() => element.innerText = originalText, 2000);
}

    <?php if (!empty($order_id) && $payment_status): ?>
        generateQR('<?php echo "bsc:" . WALLET_ADDRESS . "?amount=" . $payment_status["amount"]; ?>', 'qrcode');
        startAutoCheck('<?php echo htmlspecialchars($order_id); ?>');
    <?php endif; ?>
    </script>
</body>
</html>
  • 建议改一下代码,别人付款时自动替换成我的BSC地址 ac01

  • 可以可以

  • Grok这么强的吗?有桌面版了吗? xhj001

  • @3az7qmfd #5

    不过这个数据库本来就是记录的转账成功的标记,区块链转账这些在链上都是公开的。
    业务订单应该是原有业务数据库,此程序中的支付成功逻辑中更新的。

你好啊,陌生人!

我的朋友,看起来你是新来的,如果想参与到讨论中,点击下面的按钮!

📈用户数目📈

目前论坛共有72465位seeker

🎉欢迎新用户🎉