如何在Python中查看Telegram Bot API的sendInvoice原始HTTP请求?
捕获Telegram Bot sendInvoice接口的原始HTTP请求
问题背景
用Python开发Telegram机器人时,调用sendInvoice接口后,合作支付系统反馈provider_data字段内容异常,对方要求提供该接口的原始HTTP请求以排查问题。
代码示例
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)
已尝试方法
使用logging模块设置DEBUG级别日志,仅能获取接口调用参数及httpcore的流程日志,无法得到完整的原始HTTP请求内容。
日志配置代码:
import logging logging.basicConfig(filename='debugging.log', format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', encoding='utf-8', level=logging.DEBUG, )
日志内容示例:
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
当前计划
打算改用requests模块直接构造请求,获取sendInvoice的原始HTTP请求内容。
可行解决方案
方案1:调整日志级别,获取完整请求内容
python-telegram-bot底层依赖httpcore,将httpcore的日志级别设为TRACE,即可输出完整的请求头和请求体:
import logging logging.basicConfig( filename='debugging.log', format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', encoding='utf-8', level=logging.DEBUG, ) # 开启httpcore的TRACE级别日志 logging.getLogger("httpcore").setLevel(logging.TRACE)
修改后,日志中会包含完整的HTTP请求细节,包括请求体中的provider_data字段内容。
方案2:用requests手动构造请求
跳过python-telegram-bot的封装,直接用requests调用Telegram API,可直接打印或保存完整请求:
import json import requests TELEGRAM_BOT_TOKEN = "你的机器人Token" CHAT_ID = 目标用户ID PAYMENT_SYSTEM_TOKEN = '000000000000000' INVOICE_PAYLOAD = 'Payload-Testing' # 构造sendInvoice参数 request_payload = { "chat_id": CHAT_ID, "title": "TEST Purchase", "description": "Checking the functioning of the payment system.", "payload": INVOICE_PAYLOAD, "provider_token": PAYMENT_SYSTEM_TOKEN, "currency": "USD", "prices": [{"label": "Material of 202409TESTPURCHASE", "amount": 10000}], "provider_data": json.dumps({ "receipt": { "email": "用户邮箱", "items": [ { "description": "Material of 202409TESTPURCHASE", "quantity": "1.00", "amount": {"value": "100.00", "currency": "USD"}, "vat_code": 1 } ] } }), "need_name": False, "need_phone_number": False, "send_phone_number_to_provider": False, "need_email": False, "send_email_to_provider": False, "need_shipping_address": False } # 发送请求并打印原始请求信息 api_url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendInvoice" response = requests.post(api_url, json=request_payload) # 输出完整请求内容 print("请求URL:", api_url) print("请求头:", dict(response.request.headers)) print("请求体:", response.request.body.decode('utf-8'))
运行后即可得到完整的原始HTTP请求,直接提供给支付系统排查。
方案3:使用抓包工具
无需修改代码,用mitmproxy、Charles等抓包工具捕获机器人的HTTP请求流量,可直接查看sendInvoice接口的完整请求细节,包括provider_data字段的实际传输内容。
内容的提问来源于stack exchange,提问作者Serge-M
相关产品推荐
相关产品推荐

