pythontelegram-bottelegram-api

How to see an actual raw HTTP request of sendInvoice going to the Telegram Bot API on Python?


Example of my code:

import json
from telegram import Bot, Update, LabeledPrice
from telegram.ext import ContextTypes


PAYMENT_SYSTEM_TOKEN = '000000000000000'
INVOICE_PAYLOAD = 'Payload-Testing'
MATERIAL_CODES = {"202409TESTPURCHASE": ["TEST Purchase",
                                         "Checking the functioning of the payment system.",
                                         100,
                                         "https://www.python.org",
                                         "https://www.python.org/static/img/python-logo.png",
                                         "python-logo.png",
                                         ],
                  }


async def catch_callback_codes(update: Update, context: ContextTypes.DEFAULT_TYPE):
    tguser, name, lastname, username = (update.effective_user.id,
                                        update.effective_user.first_name,
                                        update.effective_user.last_name,
                                        update.effective_user.username)
    code_m = str(context.user_data['user_code'])
    title = f'{MATERIAL_CODES[code_m][0]}'
    description = f'{MATERIAL_CODES[code_m][1]}'
    label = f'Material of {code_m.upper()}'  # Turn into uppercase for a pretty view.
    amount = int(MATERIAL_CODES[code_m][2])
    currency = 'USD'
    
    if context.user_data.get('phone'):  # String of exactly 11 numeric characters.
        payment_params = {"receipt": {"phone": context.user_data['phone'],  # In string format.
                                      "items": [{"description": label,  # Up to 128 characters max.
                                                 "quantity": "1.00",
                                                 "amount": {"value": f'{amount:.2f}',  # In string format.
                                                            "currency": currency,  # In string format.
                                                            },
                                                 "vat_code": 1,
                                                 },
                                                ],
                                      },
                          }
    else:
        payment_params = {"receipt": {"email": context.user_data['email'],  # In string format.
                                      "items": [{"description": label,  # Up to 128 characters max.
                                                 "quantity": "1.00",
                                                 "amount": {"value": f'{amount:.2f}',  # In string format.
                                                            "currency": currency,  # In string format.
                                                            },
                                                 "vat_code": 1,
                                                 },
                                                ],
                                      },
                          }

    provider_data = json.dumps(payment_params)
    # print(f'provider_data {type(provider_data)}: {provider_data}')  # DEBUGGING
    # https://core.telegram.org/bots/api#sendinvoice
    await context.bot.send_invoice(tguser,  # chat_id, required.
                                   title,  # title, required.
                                   description,  # description, required.
                                   INVOICE_PAYLOAD,  # payload, required.
                                   PAYMENT_SYSTEM_TOKEN,  # provider_token, optional.
                                   currency,  # currency, required.
                                   [LabeledPrice(label, amount * 100)],  # prices, required.
                                   need_name=False,  # Optional.
                                   need_phone_number=False,  # Optional.
                                   send_phone_number_to_provider=False,  # Optional.
                                   need_email=False,  # Optional.
                                   send_email_to_provider=False,  # Optional.
                                   provider_data=provider_data,  # Optional.
                                   need_shipping_address=False,  # Optional.
                                   reply_to_message_id=update.effective_message.id)

The issue is that the Payment System I have a contract with gets an incorrect string in provider_data for some reason. They ask me to send the raw HTTP request of sendInvoice so we can debug it.

Tried the module logging with the level of DEBUG, didn't help:

import logging

logging.basicConfig(filename='debugging.log',
                    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
                    encoding='utf-8',
                    level=logging.DEBUG,
                    )

It was giving me these lines, not raw requests:

2024-09-14 13:58:53,713 - telegram.ext.ExtBot - DEBUG - Calling Bot API endpoint `sendInvoice` with parameters `{'chat_id': 0000000, 'title': 'TEST Python The Language', 'description': 'Python is a high-level, general-purpose programming language.', 'payload': 'Payload-Testing', 'provider_token': '00000000000000', 'currency': 'USD', 'prices': [LabeledPrice(amount=11100, label='Testing of 19910220PYTHON')], 'provider_data': '{"amount": {"value": "111.00", "currency": "USD"}, "receipt": {"customer": {"email": "123@123"}, "items": [{"description": "Testing of 19910220PYTHON", "amount": {"value": "111.00", "currency": "USD"}, "vat_code": 1, "quantity": "1"}]}}', 'need_name': False, 'need_phone_number': False, 'need_email': False, 'need_shipping_address': False, 'send_phone_number_to_provider': False, 'send_email_to_provider': False, 'reply_parameters': ReplyParameters(message_id=4655)}`
2024-09-14 13:58:53,720 - httpcore.http11 - DEBUG - send_request_headers.started request=<Request [b'POST']>
2024-09-14 13:58:53,721 - httpcore.http11 - DEBUG - send_request_headers.complete
2024-09-14 13:58:53,721 - httpcore.http11 - DEBUG - send_request_body.started request=<Request [b'POST']>
2024-09-14 13:58:53,722 - httpcore.http11 - DEBUG - send_request_body.complete

Now I'm switching to the module requests for the same task.


Solution

  • The module requests helped, indeed.

    First you need to know your chat_id. Send something in your private chat with your bot and then call the API using the method getUpdates:

    https://api.telegram.org/botBOT_TOKEN/getUpdates
    

    Paste that URL into your browser to get a pretty output, like this:

    {
      "ok": true,
      "result": [
        {
          "update_id": 867982244,
          "message": {
            "message_id": 4649,
            "from": {
              "id": 00000000,
              "is_bot": false,
              "first_name": "XXXXXX",
              "last_name": "XXXXXX",
              "username": "XXXXXX",
              "language_code": "en",
              "is_premium": true
            },
            "chat": {
              "id": 00000000,  # ←—— Grab this ID for your future API calls.
              "first_name": "XXXXX",
              "last_name": "XXXXX",
              "username": "XXXXX",
              "type": "private"
            },
            "date": 1726300803,
            "text": "XXXXXXXX"
          }
        }
      ]
    }
    

    Then make a POST request:

    import json
    import requests
    
    
    # https://core.telegram.org/bots/api#sendinvoice
    TG_API = 'https://api.telegram.org'
    bot_token = f'bot{BOT_TOKEN}'
    method = 'sendInvoice'
    
    chat_id = 00000000  # Private chat with you.
    label = f'TEST Label'
    amount = 100
    currency = 'USD'
    prices = [{"label": label,
               "amount": amount * 100}]
    
    pers_data = 'test@test.com'
    payment_params = {"amount": {"value": f'{amount:.2f}',  # In string format.
                                 "currency": currency,  # In string format.
                                 },
                      "receipt": {"customer": {"email": pers_data,  # In string format.
                                               },
                                  "items": [{"description": label,  # Up to 128 characters max.
                                             "amount": {"value": f'{amount:.2f}',  # In string format.
                                                        "currency": currency,  # In string format.
                                                        },
                                             "vat_code": 1,
                                             "quantity": "1",
                                             },
                                            ],
                                  },
                      }
    provider_data = json.dumps(payment_params)
    
    params = {"chat_id": chat_id,
              "title": "Testing of sendInvoice",
              "description": "Testing of sendInvoice",
              "payload": INVOICE_PAYLOAD,
              "provider_token": PAYMENT_SYSTEM_TOKEN,  # Optional.
              "currency": currency,
              "prices": json.dumps(prices),
              "need_name": False,  # Optional.
              "need_phone_number": False,  # Optional.
              "send_phone_number_to_provider": False,  # Optional.
              "need_email": False,  # Optional.
              "send_email_to_provider": False,  # Optional.
              "provider_data": provider_data,  # Optional.
              "need_shipping_address": False,  # Optional.
              }
    
    url = f'{TG_API}/{bot_token}/{method}'
    
    response = requests.post(url, params=params)
    print(f'\nURL: {url}')
    print(f'request.url: {response.request.url}')
    print(f'API Response: {response.text}')
    
    
    

    Now I'm getting raw HTTP requests of sendInvoice. Example:

    https://api.telegram.org/botBOT_TOKEN/sendInvoice?chat_id=00000000&title=TEST+Python+The+Language&description=Python+is+a+high-level%2C+general-purpose+programming+language.&payload=Payload-Testing&provider_token=00000000000000&currency=USD&prices=%5B%7B%22label%22%3A+%22Material+of+19910220PYTHON%22%2C+%22amount%22%3A+11100%7D%5D&need_name=False&need_phone_number=False&send_phone_number_to_provider=False&need_email=False&send_email_to_provider=False&provider_data=%7B%22amount%22%3A+%7B%22value%22%3A+%22111.00%22%2C+%22currency%22%3A+%22USD%22%7D%2C+%22receipt%22%3A+%7B%22customer%22%3A+%7B%22email%22%3A+%22test%40test.com%22%7D%2C+%22items%22%3A+%5B%7B%22description%22%3A+%22Material+of+19910220PYTHON%22%2C+%22amount%22%3A+%7B%22value%22%3A+%22111.00%22%2C+%22currency%22%3A+%22USD%22%7D%2C+%22vat_code%22%3A+1%2C+%22quantity%22%3A+%221%22%7D%5D%7D%7D&need_shipping_address=False
    

    If you need to decode them, this code will help:

    url = 'ENCODED_URL'
    print(f'Decoded URL: {requests.utils.unquote(url)}')
    

    Or use any URL decoder online. I like this one: https://www.urldecoder.org