You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Telegram sendInvoice调用失败:Stripe测试交易遇预检查超时错误

问题修复与支付成功逻辑实现

一、解决“bot precheckout timeout”错误

这个错误的核心原因是未在10秒内响应Telegram的pre_checkout_query请求。Telegram要求收到该请求后,必须调用answerPreCheckoutQuery接口完成确认,否则会触发超时。你的代码仅发送了消息,未执行关键的确认步骤,修改如下:

if(req.body.pre_checkout_query?.id){
    // 必须先调用该接口确认,否则会触发超时
    await axios.post(`${TELEGRAM_API}/answerPreCheckoutQuery`, {
        pre_checkout_query_id: req.body.pre_checkout_query.id,
        ok: true // 设为true允许支付,设为false则拒绝支付
    });

    // 执行保存到sqlite的逻辑
    console.log("保存预支付信息到sqlite", req.body);
    // 补充你的sqlite插入代码,例如:
    // db.run('INSERT INTO pre_payments (username, chat_id, amount) VALUES (?, ?, ?)', 
    //        [req.body.pre_checkout_query.from.username, req.body.pre_checkout_query.from.id, 4000]);

    await axios.post(`${TELEGRAM_API}/sendMessage`, {
        chat_id: req.body.pre_checkout_query?.from.id,
        text: "正在确认支付,请稍候...",
    });
}

二、完善支付成功后的处理逻辑

支付完成后,Telegram会发送successful_payment类型的消息,你需要监听该事件来完成后续业务逻辑(如标记订单完成、发送最终通知等),补充到webhook处理逻辑中:

app.post(URI, async (req, res) => {
    console.log(req.body);
    let text = "", chatId = "", userObjectForTable = {}; 

    // 处理普通消息
    if(req.body.message?.chat?.id && req.body.message?.text){
        chatId = req.body.message.chat.id;
        text = req.body.message.text;
        await axios.post(`${TELEGRAM_API}/sendMessage`, {
            chat_id: chatId,
            text: text,
        });
    }

    // 处理支付指令
    if (text === "/pay") {
        const message = await axios.post(`${TELEGRAM_API}/sendInvoice`, {
            chat_id: chatId,
            title: `FinnessinPips`,
            description: invoiceDescription,
            payload: "Invoice for payment",
            provider_token: BOTTOKEN,
            currency: "USD",
            prices: [{ label: "服务费用", amount: 4000 }], // 建议修改label为更清晰的描述
            start_parameter: "payment-finnessinpips" // 可选,用于区分不同支付场景
        });
        userObjectForTable = {
            date: new Date(message.data.result.date),
            username: message.data.result.from.username
        };
    }

    // 处理预支付查询
    if(req.body.pre_checkout_query?.id){
        try {
            await axios.post(`${TELEGRAM_API}/answerPreCheckoutQuery`, {
                pre_checkout_query_id: req.body.pre_checkout_query.id,
                ok: true
            });
        } catch (err) {
            console.error("响应预支付查询失败:", err);
        }

        console.log("保存预支付信息到sqlite", req.body);
        // 补充sqlite插入逻辑

        await axios.post(`${TELEGRAM_API}/sendMessage`, {
            chat_id: req.body.pre_checkout_query.from.id,
            text: "正在确认支付,请稍候...",
        });
    }

    // 处理支付成功事件(支付完成后Telegram会推送该事件)
    if(req.body.message?.successful_payment){
        const payment = req.body.message.successful_payment;
        const chatId = req.body.message.chat.id;

        // 保存支付成功记录到sqlite
        console.log("保存支付成功记录到sqlite", payment);
        // 示例sqlite插入逻辑:
        // db.run('INSERT INTO successful_payments (username, chat_id, total_amount, currency) VALUES (?, ?, ?, ?)',
        //        [req.body.message.from.username, chatId, payment.total_amount, payment.currency]);

        // 发送最终支付成功通知
        await axios.post(`${TELEGRAM_API}/sendMessage`, {
            chat_id: chatId,
            text: `✅ 支付成功!\n金额:${payment.total_amount / 100} ${payment.currency}\n订单标识:${payment.invoice_payload}`,
        });

        // 这里可添加专属链接生成、内容推送等后续逻辑
    }

    return res.sendStatus(200); // 返回200告知Telegram已成功接收请求
});

三、额外注意事项

  • 超时排查:确保服务器能在10秒内完成answerPreCheckoutQuery调用;本地测试需用ngrok等工具暴露公网地址,保证Telegram能正常回调。
  • 测试信用卡:使用Stripe官方测试卡(如4242 4242 4242 4242,过期日期选未来任意月份,CVV填任意3位),确保测试环境配置正确。
  • 错误捕获:用try-catch包裹所有异步API调用,避免因接口调用失败导致webhook响应超时。

内容的提问来源于stack exchange,提问作者The Coder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 09:15:31