How to convert PAY button to RECEIPT button in Telegram bot after payment completion

I’m working on a Telegram bot that handles payments and everything works fine. But I’m stuck on one thing - I want the PAY button to change into a RECEIPT button after the user completes their payment.

Right now what happens is:

  1. User clicks PAY button and enters card details
  2. Payment goes through successfully
  3. Bot sends confirmation message
  4. PAY button stays the same instead of changing to RECEIPT

I checked the Telegram docs and found this info about receipts:

When an invoice message is sent in chat with the merchant bot, it turns into a Receipt in the UI. Users can open this receipt anytime to view transaction details.

If sent to other chats, the Pay button stays active for multiple payments.

My invoice gets sent to the chat with my bot, so it should become a receipt automatically. But it’s not happening.

I’m using Node.js with webhooks. Here’s my payment handling code:

app.post('/webhook', async (req, res) => {
    try {
        // Handle pre-checkout validation
        if (req.body.pre_checkout_query) {
            // Process with answerPreCheckoutQuery method
            ...
        }

        const msg = req.body.message || req.body.edited_message;

        // Payment completed successfully
        if (msg.successful_payment) {
            // Process successful payment
            // Send confirmation message
            ...
        }

    } catch (error) {
        ...
    }
})

For sending invoices I use:

const apiUrl = `https://api.telegram.org/bot${process.env.BOT_TOKEN}/sendInvoice`;
const result = await axios.post(apiUrl, {
    chat_id: userId,
    title: 'Product Purchase',
    description: 'Purchase description here',
    payload: 'PURCHASE-DATA',
    provider_token: process.env.PAYMENT_TOKEN,
    currency: 'USD',
    prices: JSON.stringify([{
        label: 'Product price',
        amount: 500
    }])
});

I’ve looked at both sendInvoice and answerPreCheckoutQuery methods but can’t find any parameter that would control this button transformation. What am I missing here?

check your webhook response timing - if you’re writing to the database or sending confirmation messages synchronously in the successful_payment handler, that delay might interrupt the receipt conversion. also make sure you’re not accidentally deleting or editing the original invoice message anywhere in your code, that’ll break the transformation completely.

Had this exact problem 6 months ago and wasted hours debugging it. You’re probably sending the invoice to a group chat or your bot isn’t set up as a merchant bot properly. The automatic PAY to RECEIPT thing only works in private chats with bots that have proper merchant status. Check that your bot has payments enabled through BotFather and you’re only sending invoices to private chats. Don’t manually edit or resend the invoice message after payment - that breaks the automatic receipt conversion. The transformation happens right after the successful_payment webhook hits, no extra code needed. Still broken? Create a fresh test bot and see if it happens again. Old bot configs can cause weird payment UI issues.

I’ve hit this exact webhook timing issue before. The receipt transformation happens client-side after Telegram gets payment confirmation. If your successful_payment handler does heavy processing or takes too long to respond, it’ll mess with the UI update. Return status 200 immediately when you get the successful_payment update, then handle any extra processing async. Also check that your provider_token is from a live payment provider, not test - test tokens sometimes cause UI glitches. The button should change automatically within seconds of payment completion without any extra API calls from your bot.