Telegram Bot Payment Processing Gets Stuck During Stripe Test Transaction

I’m working on a Node.js Telegram bot that downloads video content from social media posts. Everything works fine but I want to add a payment system where users need to pay after using the service a few times.

I implemented Stripe payments using Telegram’s invoice feature. The bot sends an invoice and users can enter their card details, but when they click the final pay button, it just keeps loading forever and eventually times out. I’m using Stripe in test mode since my account isn’t verified yet.

I tried both the regular invoice method and the invoice link approach but got the same timeout issue. I think maybe I need to set up some kind of webhook to handle the payment completion, but I’m not sure how to connect that with Telegram’s API.

Currently I’m using ngrok for local development and the standard webhook setup for receiving messages. Here’s my payment code:

const server = express();
const serverPort = 8000;

const telegramToken = process.env.BOT_TOKEN;
server.use(bodyParser.json());

// Message handler endpoint
server.post(`/webhook${telegramToken}`, async (req, res) => {
  const { message } = req.body;

  if (message && message.text) {
    const userId = message.chat.id;
    const userMessage = message.text;

    // Send payment request after user hits usage limit
    const paymentResult = await createPaymentInvoice(
      userId,
      "Pro Access",
      "Get unlimited access to video downloads.",
      "pro_access_payment",
      process.env.STRIPE_PROVIDER_TOKEN,
      "payment",
      "USD",
      [{ label: "Pro Access", amount: 1500 }],
    );

    console.log(JSON.stringify(paymentResult, null, 2));
  }

  res.status(200).end();
});

async function createPaymentInvoice(
  userId,
  invoiceTitle,
  invoiceDescription,
  invoicePayload,
  stripeToken,
  parameterStart,
  currencyCode,
  priceList,
) {
  const telegramApiUrl = `https://api.telegram.org/bot${telegramToken}/sendInvoice`;

  const paymentData = {
    chat_id: userId,
    title: invoiceTitle,
    description: invoiceDescription,
    payload: invoicePayload,
    provider_token: stripeToken,
    start_parameter: parameterStart,
    currency: currencyCode,
    prices: priceList,
  };

  try {
    const apiResponse = await fetch(telegramApiUrl, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(paymentData),
    });

    const responseData = await apiResponse.json();
    return responseData;
  } catch (err) {
    console.error("Invoice sending failed:", err);
    return err.message;
  }
}

I’ve searched everywhere but can’t find clear documentation about whether I need to configure anything special in Stripe or if there’s a specific webhook setup required for Telegram payments. Any help would be appreciated!

You’re missing the payment handlers completely. You need to handle pre_checkout_query and successful_payment updates from Telegram. If you don’t answer the pre_checkout_query, the payment will hang forever. Add those handlers to your webhook endpoint and it’ll work fine, even in test mode.

The timeout happens because your webhook isn’t handling payment updates from Telegram properly. I hit this exact same issue building a similar bot last year. Telegram sends payment events as separate update types, not regular messages. You need to modify your webhook to check for req.body.pre_checkout_query and respond with answerPreCheckoutQuery within 10 seconds - otherwise the payment hangs forever. Also handle req.body.message.successful_payment to confirm completion. Your current code only processes req.body.message.text, which is why payments never finish. Stripe test mode works great with Telegram once you add these handlers - no extra Stripe webhook config needed.

Your webhook’s only catching regular messages, but Telegram sends payment updates as completely different event types. When someone hits pay, Telegram fires a pre_checkout_query - you’ve got 10 seconds to respond with answerPreCheckoutQuery or the payment times out. After payment goes through, you’ll get a successful_payment update. You need to modify your webhook to check for req.body.pre_checkout_query and req.body.message.successful_payment alongside regular messages. Stripe test mode works fine with Telegram, but if you don’t handle these payment events, users will just stare at that loading spinner forever.