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.
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¤cy=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