Hide navigation sidebar
Hide table of contents sidebar
PTB has undergone significant changes in v20. Please read the documentation carefully and also check out the transition guide in the wiki.
Back to top
Toggle table of contents sidebar

# `paymentbot.py`

      1#!/usr/bin/env python
      2# pylint: disable=unused-argument
      3# This program is dedicated to the public domain under the CC0 license.
      4
      5"""Basic example for a bot that can receive payment from user."""
      6
      7import logging
      8
      9from telegram import LabeledPrice, ShippingOption, Update
     10from telegram.ext import (
     11    Application,
     12    CommandHandler,
     13    ContextTypes,
     14    MessageHandler,
     15    PreCheckoutQueryHandler,
     16    ShippingQueryHandler,
     17    filters,
     18)
     19
     20# Enable logging
     21logging.basicConfig(
     22    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
     23)
     24# set higher logging level for httpx to avoid all GET and POST requests being logged
     25logging.getLogger("httpx").setLevel(logging.WARNING)
     26
     27logger = logging.getLogger(__name__)
     28
     29PAYMENT_PROVIDER_TOKEN = "PAYMENT_PROVIDER_TOKEN"
     30
     31
     32async def start_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
     33    """Displays info on how to use the bot."""
     34    msg = (
     35        "Use /shipping to get an invoice for shipping-payment, or /noshipping for an "
     36        "invoice without shipping."
     37    )
     38
     39    await update.message.reply_text(msg)
     40
     41
     42async def start_with_shipping_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
     43    """Sends an invoice with shipping-payment."""
     44    chat_id = update.message.chat_id
     45    title = "Payment Example"
     46    description = "Payment Example using python-telegram-bot"
     47    # select a payload just for you to recognize its the donation from your bot
     48    payload = "Custom-Payload"
     49    # In order to get a provider_token see https://core.telegram.org/bots/payments#getting-a-token
     50    currency = "USD"
     51    # price in dollars
     52    price = 1
     53    # price * 100 so as to include 2 decimal points
     54    # check https://core.telegram.org/bots/payments#supported-currencies for more details
     55    prices = [LabeledPrice("Test", price * 100)]
     56
     57    # optionally pass need_name=True, need_phone_number=True,
     58    # need_email=True, need_shipping_address=True, is_flexible=True
     59    await context.bot.send_invoice(
     60        chat_id,
     61        title,
     62        description,
     63        payload,
     64        PAYMENT_PROVIDER_TOKEN,
     65        currency,
     66        prices,
     67        need_name=True,
     68        need_phone_number=True,
     69        need_email=True,
     70        need_shipping_address=True,
     71        is_flexible=True,
     72    )
     73
     74
     75async def start_without_shipping_callback(
     76    update: Update, context: ContextTypes.DEFAULT_TYPE
     77) -> None:
     78    """Sends an invoice without shipping-payment."""
     79    chat_id = update.message.chat_id
     80    title = "Payment Example"
     81    description = "Payment Example using python-telegram-bot"
     82    # select a payload just for you to recognize its the donation from your bot
     83    payload = "Custom-Payload"
     84    # In order to get a provider_token see https://core.telegram.org/bots/payments#getting-a-token
     85    currency = "USD"
     86    # price in dollars
     87    price = 1
     88    # price * 100 so as to include 2 decimal points
     89    prices = [LabeledPrice("Test", price * 100)]
     90
     91    # optionally pass need_name=True, need_phone_number=True,
     92    # need_email=True, need_shipping_address=True, is_flexible=True
     93    await context.bot.send_invoice(
     94        chat_id, title, description, payload, PAYMENT_PROVIDER_TOKEN, currency, prices
     95    )
     96
     97
     98async def shipping_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
     99    """Answers the ShippingQuery with ShippingOptions"""
    100    query = update.shipping_query
    101    # check the payload, is this from your bot?
    102    if query.invoice_payload != "Custom-Payload":
    103        # answer False pre_checkout_query
    104        await query.answer(ok=False, error_message="Something went wrong...")
    105        return
    106
    107    # First option has a single LabeledPrice
    108    options = [ShippingOption("1", "Shipping Option A", [LabeledPrice("A", 100)])]
    109    # second option has an array of LabeledPrice objects
    110    price_list = [LabeledPrice("B1", 150), LabeledPrice("B2", 200)]
    111    options.append(ShippingOption("2", "Shipping Option B", price_list))
    112    await query.answer(ok=True, shipping_options=options)
    113
    114
    115# after (optional) shipping, it's the pre-checkout
    116async def precheckout_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    117    """Answers the PreQecheckoutQuery"""
    118    query = update.pre_checkout_query
    119    # check the payload, is this from your bot?
    120    if query.invoice_payload != "Custom-Payload":
    121        # answer False pre_checkout_query
    122        await query.answer(ok=False, error_message="Something went wrong...")
    123    else:
    124        await query.answer(ok=True)
    125
    126
    127# finally, after contacting the payment provider...
    128async def successful_payment_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    129    """Confirms the successful payment."""
    130    # do something after successfully receiving payment?
    131    await update.message.reply_text("Thank you for your payment!")
    132
    133
    134def main() -> None:
    135    """Run the bot."""
    136    # Create the Application and pass it your bot's token.
    137    application = Application.builder().token("TOKEN").build()
    138
    139    # simple start function
    140    application.add_handler(CommandHandler("start", start_callback))
    141
    142    # Add command handler to start the payment invoice
    143    application.add_handler(CommandHandler("shipping", start_with_shipping_callback))
    144    application.add_handler(CommandHandler("noshipping", start_without_shipping_callback))
    145
    146    # Optional handler if your product requires shipping
    147    application.add_handler(ShippingQueryHandler(shipping_callback))
    148
    149    # Pre-checkout handler to final check
    150    application.add_handler(PreCheckoutQueryHandler(precheckout_callback))
    151
    152    # Success! Notify your user!
    153    application.add_handler(
    154        MessageHandler(filters.SUCCESSFUL_PAYMENT, successful_payment_callback)
    155    )
    156
    157    # Run the bot until the user presses Ctrl-C
    158    application.run_polling(allowed_updates=Update.ALL_TYPES)
    159
    160
    161if __name__ == "__main__":
    162    main()