node-telegram-bot-api icon indicating copy to clipboard operation
node-telegram-bot-api copied to clipboard

How to create SendInvoice

Open dotnrx opened this issue 7 years ago • 18 comments

Hello, I need the full example of bot.sendInvoice, examples from core.telegram and so on are not understandable for me. If you worked with bot.sendInvoice or with all functions of Invoice, pls send me examples. Thanks

dotnrx avatar Apr 11 '18 19:04 dotnrx

Is simple :)

First go to BotFather and follow instruction to link Stripe account (/mybots > bot > payments). Then you have a test token and production token, for testing use test token (to avoid pay yourself, lol).

Then use this code:

bot.onText(/pay/i, function (message) {
	var iKeys = [];
	iKeys.push([{
		text: "2 €",
		callback_data: "pay:2.00"
	},{
		text: "10 €",
		callback_data: "pay:10.00"
	}]);

	bot.sendMessage(message.chat.id, "Select an amount to pay", {
		parse_mode: 'HTML',
		disable_web_page_preview: true,
		reply_markup: {
			inline_keyboard: iKeys
		}
	});
});

bot.on('callback_query', function (message) {
	var StripeToken = "xxx";
	var func = text.split(":")[0];
	var param = text.split(":")[1];
	if (func == "pay") {
		var payload = player_id + Date.now() + param;	// you can use your own payload
		var prices = [{
			label: "Donation",
			amount: parseInt(param.replace(".", ""))	// if you have a decimal price with . instead of ,
		}];
		bot.sendInvoice(message.from.id, "Donation", "Donation of " + param + "€", payload, StripeToken, "pay", "EUR", prices);	// send invoice button to user
		// remember to save payload and user data in db, it will be useful later
		// usually i save Payload and Status = WAIT
	}
});

bot.on('message', function (message) {
	if (message.successful_payment != undefined) {
		var savedPayload = "yyy";	// get from db
		var savedStatus = "zzz";	// get from db, this should be "WAIT"
		if ((savedPayload != message.successful_payment.invoice_payload) || (savedStatus != "WAIT")) {	// match saved data to payment data received
			bot.sendMessage(message.chat.id, "Payment verification failed");
			return;
		}
		
		// payment successfull
		bot.sendMessage(message.chat.id, "Payment complete!");
	}
});

If you need further info please answer ;)

sidelux avatar Apr 13 '18 07:04 sidelux

Oh thank you very much, but why we should use "payload","provider_data" and "start_parameter" what is the sense of them?

dotnrx avatar Apr 14 '18 20:04 dotnrx

  1. For check reason: if a user send manual payload and not match with your, transaction will fail.
  2. For history reason: if you save all payloads you can later use as you need (statistics, etc.).

sidelux avatar Apr 14 '18 20:04 sidelux

do you know, how to change the text in the inline button of the invoice? For example, now it's "Pay 1000 UZS", but I need "Make a payment". And how to get the users phone? Because there are not enough functions in node-telegram-bot-api in sendInvoice

dotnrx avatar Apr 15 '18 12:04 dotnrx

I don't think you can do it, cause a bad user can replace text with fake description and trick people. I'm not totally sure but... maybe at 90%.

sidelux avatar Apr 15 '18 12:04 sidelux

oh okay, thank you very much for your help

dotnrx avatar Apr 15 '18 12:04 dotnrx

I have a problem, I'm already desperate. When i tried to pay in test mode with stripe he shows me "timeout" and never confirm the pay, why is this problem happening? Any ideas?

albertohortabtc avatar Aug 21 '19 09:08 albertohortabtc

@AHGsystems Maybe you have not enabled payments in Botfather? Anyway check in Stripe Dashboard, there is a calls history that you can use for debugging.

sidelux avatar Aug 21 '19 09:08 sidelux

I am new and I am desperate, I can't find a way to process the payment, it simply answers me with a "timeout". This is my code //-------------------------------------------------------------

const TelegramBot = require('node-telegram-bot-api'); const token = 'yyyyyyyyyyyyyyy:xxxxxxxxxxxxxxxx';

const bot = new TelegramBot(token, {polling: true});

bot.onText(/pay/i, function (message) { var iKeys = []; iKeys.push([{ text: "2 €", callback_data: "pay:2.00" },{ text: "10 €", callback_data: "pay:10.00" }]);

bot.sendMessage(message.chat.id, "Select an amount to pay", {
    parse_mode: 'HTML',
    disable_web_page_preview: true,
    reply_markup: {
        inline_keyboard: iKeys
    }
});

}); bot.on('callback_query', function (message) { var StripeToken = "-------------:TEST:-----------------";

        var payload = "12345" + Date.now() + "pay";// you can use your own payload
        var prices = [{
            label: "Donation",
            amount: parseInt("1000")	// if you have a decimal price with . instead of ,
        }];
        bot.sendInvoice(message.from.id, "Donation", "Donation of " + "pay"+ "€", payload, StripeToken, "pay", "EUR", prices);	// send invoice button to user
        // remember to save payload and user data in db, it will be useful later
        // usually i save Payload and Status = WAIT

});

bot.on('message', function (message) {
    if (message.successful_payment != undefined) {
        var savedPayload = "12345" + Date.now() + "pay";	// get from db
        var savedStatus = "WAIT";	// get from db, this should be "WAIT"
        if ((savedPayload != message.successful_payment.invoice_payload) || (savedStatus != "WAIT")) {	// match saved data to payment data received
            bot.sendMessage(message.chat.id, "Payment verification failed");
            return;
        }

        // payment successfull
        bot.sendMessage(message.chat.id, "Payment complete!");
    }
});

albertohortabtc avatar Sep 18 '19 03:09 albertohortabtc

@AHGsystems Have you enabled Payments with Botfather? Anyway try to put some logs everywhere to find where it stops.

sidelux avatar Sep 18 '19 06:09 sidelux

BOTTELEGRAM

YES, I have enabled and connected the TEST stripe payment

albertohortabtc avatar Sep 18 '19 15:09 albertohortabtc

Hello Sidelux. I have the very same problem as AHGsystems. I have connected a Stripe TEST account to my Telegram bot. When fired, the Stripe bot runs, asks me my (fake) credit card data (any of the ones suggested in https://stripe.com/docs/testing#cards) but it times out. The Stripe dashboard reports no traffic. Should I try a real world payment? (If so, what is test mode for?) Thank you for your help

rcecinati avatar Nov 16 '19 16:11 rcecinati

I am having the same issue. Does anyone find a solution ?

2-towns avatar Apr 14 '20 00:04 2-towns

do you answer the pre_checkout_query during press pay button

lixiaoming502 avatar Jul 12 '20 16:07 lixiaoming502

do you answer the pre_checkout_query during press pay button

I have this fault. why don't answer the pre_checkout_query during press pay button ? do anyone know ?

I am using telegram TEST payment ....

ghost avatar Aug 27 '21 06:08 ghost

do you answer the pre_checkout_query during press pay button

can i have an example?

Vo0oX avatar Sep 03 '22 11:09 Vo0oX

Is simple :)

First go to BotFather and follow instruction to link Stripe account (/mybots > bot > payments). Then you have a test token and production token, for testing use test token (to avoid pay yourself, lol).

Then use this code:

bot.onText(/pay/i, function (message) {
	var iKeys = [];
	iKeys.push([{
		text: "2 €",
		callback_data: "pay:2.00"
	},{
		text: "10 €",
		callback_data: "pay:10.00"
	}]);

	bot.sendMessage(message.chat.id, "Select an amount to pay", {
		parse_mode: 'HTML',
		disable_web_page_preview: true,
		reply_markup: {
			inline_keyboard: iKeys
		}
	});
});

bot.on('callback_query', function (message) {
	var StripeToken = "xxx";
	var func = text.split(":")[0];
	var param = text.split(":")[1];
	if (func == "pay") {
		var payload = player_id + Date.now() + param;	// you can use your own payload
		var prices = [{
			label: "Donation",
			amount: parseInt(param.replace(".", ""))	// if you have a decimal price with . instead of ,
		}];
		bot.sendInvoice(message.from.id, "Donation", "Donation of " + param + "€", payload, StripeToken, "pay", "EUR", prices);	// send invoice button to user
		// remember to save payload and user data in db, it will be useful later
		// usually i save Payload and Status = WAIT
	}
});

bot.on('message', function (message) {
	if (message.successful_payment != undefined) {
		var savedPayload = "yyy";	// get from db
		var savedStatus = "zzz";	// get from db, this should be "WAIT"
		if ((savedPayload != message.successful_payment.invoice_payload) || (savedStatus != "WAIT")) {	// match saved data to payment data received
			bot.sendMessage(message.chat.id, "Payment verification failed");
			return;
		}
		
		// payment successfull
		bot.sendMessage(message.chat.id, "Payment complete!");
	}
});

If you need further info please answer ;)


Quite unfortunate , I got an exception raised:

Unhandled rejection Error: ETELEGRAM: 400 Bad Request: can't parse prices JSON object

Alternatively, I use RESTFUL API method instead :

Method: GET

const sendInvoice = async (chatId, product, description, payload, currency, price) => { 
    // https://core.telegram.org/bots/payments#supported-currencies
    const url = `https://api.telegram.org/bot${BOT_oken}/sendInvoice`;
    const response = await axios.get(url, {
        params: {
            chat_id: chatId,
            title: product,
            description: description,
            payload: payload,
            provider_token: YOUR_payment_token,
            currency: currency,
            prices: JSON.stringify([
                {
                    label: product,
                    amount: price,
                },
            ]),
        }
    });

    console.log(response.data);
};

ctkqiang avatar Jul 22 '23 10:07 ctkqiang