Skip to content

Commit d16d385

Browse files
authored
Merge pull request python-telegram-bot#658 from jeffffc/paymentbot_example_and_fixes
Add PaymentBot Example, Bugfixes on payment methods
2 parents da8a3ce + c7ed87d commit d16d385

File tree

2 files changed

+148
-2
lines changed

2 files changed

+148
-2
lines changed

examples/paymentbot.py

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
#
4+
# Basic example for a bot that can receive payment from user.
5+
# This program is dedicated to the public domain under the CC0 license.
6+
7+
from telegram import (LabeledPrice, ShippingOption)
8+
from telegram.ext import (Updater, CommandHandler, MessageHandler,
9+
Filters, PreCheckoutQueryHandler, ShippingQueryHandler)
10+
import logging
11+
12+
# Enable logging
13+
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)
14+
15+
logger = logging.getLogger(__name__)
16+
17+
18+
def error(bot, update, error):
19+
logger.warn('Update "%s" caused error "%s"' % (update, error))
20+
21+
22+
def start_callback(bot, update):
23+
msg = "Use /shipping to get an invoice for shipping-payment, "
24+
msg += "or /noshipping for an invoice without shipping."
25+
update.message.reply_text(msg)
26+
27+
28+
def start_with_shipping_callback(bot, update):
29+
chat_id = update.message.chat_id
30+
title = "Payment Example"
31+
description = "Payment Example using python-telegram-bot"
32+
# select a payload just for you to recognize its the donation from your bot
33+
payload = "Custom-Payload"
34+
# get your provider_token at @botfather, see https://core.telegram.org/bots/payments#getting-a-token
35+
provider_token = "PROVIDER_TOKEN"
36+
start_parameter = "test-payment"
37+
currency = "USD"
38+
# price in dollars
39+
price = 1
40+
# price * 100 so as to include 2 d.p.
41+
# check https://core.telegram.org/bots/payments#supported-currencies for more details
42+
prices = [LabeledPrice("Test", price * 100)]
43+
44+
# optionally pass need_name=True, need_phone_number=True,
45+
# need_email=True, need_shipping_address=True, is_flexible=True
46+
bot.sendInvoice(chat_id, title, description, payload,
47+
provider_token, start_parameter, currency, prices,
48+
need_name=True, need_phone_number=True,
49+
need_email=True, need_shipping_address=True, is_flexible=True)
50+
51+
52+
def start_without_shipping_callback(bot, update):
53+
chat_id = update.message.chat_id
54+
title = "Payment Example"
55+
description = "Payment Example using python-telegram-bot"
56+
# select a payload just for you to recognize its the donation from your bot
57+
payload = "Custom-Payload"
58+
# get your provider_token at @botfather, see https://core.telegram.org/bots/payments#getting-a-token
59+
provider_token = "PROVIDER_TOKEN"
60+
start_parameter = "test-payment"
61+
currency = "USD"
62+
# price in dollars
63+
price = 1
64+
# price * 100 so as to include 2 d.p.
65+
prices = [LabeledPrice("Test", price * 100)]
66+
67+
# optionally pass need_name=True, need_phone_number=True,
68+
# need_email=True, need_shipping_address=True, is_flexible=True
69+
bot.sendInvoice(chat_id, title, description, payload,
70+
provider_token, start_parameter, currency, prices)
71+
72+
73+
def shipping_callback(bot, update):
74+
query = update.shipping_query
75+
# check the payload, is this from your bot?
76+
if query.invoice_payload != 'Custom-Payload':
77+
# answer False pre_checkout_query
78+
bot.answerShippingQuery(shipping_query_id=query.id, ok=False,
79+
error_message="Something went wrong...")
80+
return
81+
else:
82+
options = list()
83+
# a single LabeledPrice
84+
options.append(ShippingOption('1', 'Shipping Option A', [LabeledPrice('A', 100)]))
85+
# an array of LabeledPrice objects
86+
price_list = [LabeledPrice('B1', 150), LabeledPrice('B2', 200)]
87+
options.append(ShippingOption('2', 'Shipping Option B', price_list))
88+
bot.answerShippingQuery(shipping_query_id=query.id, ok=True,
89+
shipping_options=options)
90+
91+
92+
# after (optional) shipping, it's the pre-checkout
93+
def precheckout_callback(bot, update):
94+
query = update.pre_checkout_query
95+
# check the payload, is this from your bot?
96+
if query.invoice_payload != 'Custom-Payload':
97+
# answer False pre_checkout_query
98+
bot.answerPreCheckoutQuery(pre_checkout_query_id=query.id, ok=False,
99+
error_message="Something went wrong...")
100+
else:
101+
bot.answerPreCheckoutQuery(pre_checkout_query_id=query.id, ok=True)
102+
103+
104+
# finally, after contacting to the payment provider...
105+
def successful_payment_callback(bot, update):
106+
# do something after successful receive of payment?
107+
update.message.reply_text("Thank you for your payment!")
108+
109+
110+
def main():
111+
# Create the EventHandler and pass it your bot's token.
112+
updater = Updater(token="BOT_TOKEN")
113+
114+
# Get the dispatcher to register handlers
115+
dp = updater.dispatcher
116+
117+
# simple start function
118+
dp.add_handler(CommandHandler("start", start_callback))
119+
120+
# Add command handler to start the payment invoice
121+
dp.add_handler(CommandHandler("shipping", start_with_shipping_callback))
122+
dp.add_handler(CommandHandler("noshipping", start_without_shipping_callback))
123+
124+
# Optional handler if your product requires shipping
125+
dp.add_handler(ShippingQueryHandler(shipping_callback))
126+
127+
# Pre-checkout handler to final check
128+
dp.add_handler(PreCheckoutQueryHandler(precheckout_callback))
129+
130+
# Success! Notify your user!
131+
dp.add_handler(MessageHandler(Filters.successful_payment, successful_payment_callback))
132+
133+
# log all errors
134+
dp.add_error_handler(error)
135+
136+
# Start the Bot
137+
updater.start_polling()
138+
139+
# Run the bot until you press Ctrl-C or the process receives SIGINT,
140+
# SIGTERM or SIGABRT. This should be used most of the time, since
141+
# start_polling() is non-blocking and will stop the bot gracefully.
142+
updater.idle()
143+
144+
145+
if __name__ == '__main__':
146+
main()

telegram/bot.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1975,7 +1975,7 @@ def answer_shipping_query(self,
19751975
data = {'shipping_query_id': shipping_query_id, 'ok': ok}
19761976

19771977
if ok is True:
1978-
data['shipping_options'] = shipping_options
1978+
data['shipping_options'] = [option.to_dict() for option in shipping_options]
19791979
if error_message is not None:
19801980
data['error_message'] = error_message
19811981

@@ -2009,7 +2009,7 @@ def answer_pre_checkout_query(self, pre_checkout_query_id, ok,
20092009
20102010
"""
20112011

2012-
if not (ok ^ (error_message is None)):
2012+
if not (ok ^ (error_message is not None)):
20132013
raise TelegramError(
20142014
'answerPreCheckoutQuery: If ok is True, there should '
20152015
'not be error_message; if ok is False, error_message '

0 commit comments

Comments
 (0)