Telegram Bot实现带POST请求的外部链接跳转及支付表单模拟
Hey there! Let's tackle your two questions about integrating POST-based payments into your Telegram bot built with PyTelegramBotAPI. I know you're new to HTTP POST/GET concepts, so let's break this down clearly.
Question I: How to Guide Users to a Target URL via POST Request
First off, let's clarify why your current attempts aren't working:
- When you run
requests.post()in your Python code, that's sending a POST request from your server/bot environment, not from the user's browser. That's why the request works but the user never sees the payment page. - Appending parameters to the URL with
urlencode()creates a GET request link, which is why the payment site throws a "wrong request method" error—they explicitly expect POST.
Telegram doesn't support directly sending links that trigger POST requests (all native message links use GET). Here are two reliable workarounds:
1. Create a Middleman Auto-Submit HTML Page
Build a simple HTML page that automatically submits the required POST form as soon as it loads. Host this page on your server, then send the page's URL to users. When they click it, their browser opens the page and immediately redirects them to the payment gateway via POST.
Example HTML template:
<!DOCTYPE html> <html> <body onload="document.getElementById('paymentForm').submit();"> <form id="paymentForm" action="https://securesandbox.webpay.by/" method="post"> <!-- Fill in your dynamic payment fields here --> <input type="hidden" name="wsb_storeid" value="11111111"> <input type="hidden" name="wsb_order_num" value="YOUR-ORDER-NUMBER"> <!-- Add all other required hidden fields --> </form> <p>Redirecting to payment page... If nothing happens, click <button type="submit" form="paymentForm">here</button>.</p> </body> </html>
2. Use Telegram Web Apps
Telegram Bots support Web Apps—mini web pages that load inside the Telegram app. You can host your auto-submit form as a Web App, then send a button to users that opens it. This feels more integrated than a external link.
Example PyTelegramBotAPI code to trigger a Web App:
import telebot from telebot.types import WebAppInfo, KeyboardButton, ReplyKeyboardMarkup bot = telebot.TeleBot("YOUR_BOT_TOKEN") @bot.message_handler(commands=['pay']) def send_payment_button(message): # Link to your hosted auto-submit form web_app_url = "https://your-server.com/payment-auto-submit" web_app = WebAppInfo(url=web_app_url) payment_button = KeyboardButton("Complete Payment", web_app=web_app) markup = ReplyKeyboardMarkup([[payment_button]], resize_keyboard=True) bot.send_message(message.chat.id, "Tap below to pay:", reply_markup=markup) bot.polling()
Question II: Dynamically Generate & Trigger the Required Payment Form in Telegram
Since Telegram can't render and submit HTML forms directly, the solution ties back to the auto-submit page approach—you just need to dynamically populate the form fields for each order.
Step-by-Step Implementation
1. Dynamic HTML Generation
Write a Python function that generates the auto-submit HTML with dynamic values for each payment:
def generate_payment_html(order_num, total, store_id, signature, seed): html_template = """ <!DOCTYPE html> <html> <body onload="document.getElementById('paymentForm').submit();"> <form id="paymentForm" action="https://securesandbox.webpay.by/" method="post"> <input type="hidden" name="*scart" > <input type="hidden" name="wsb_storeid" value="{store_id}"> <input type="hidden" name="wsb_order_num" value="{order_num}"> <input type="hidden" name="wsb_currency_id" value="BYN"> <input type="hidden" name="wsb_version" value="2"> <input type="hidden" name="wsb_seed" value="{seed}"> <input type="hidden" name="wsb_signature" value="{signature}"> <input type="hidden" name="wsb_test" value="1"> <input type="hidden" name="wsb_invoice_item_name[0]" value="Товар 1"> <input type="hidden" name="wsb_invoice_item_quantity[0]" value="2"> <input type="hidden" name="wsb_invoice_item_price[0]" value="10"> <input type="hidden" name="wsb_total" value="{total}"> </form> <p>Redirecting to payment... Click <button type="submit" form="paymentForm">here</button> if stuck.</p> </body> </html> """ return html_template.format( store_id=store_id, order_num=order_num, seed=seed, signature=signature, total=total )
2. Host the Dynamic Page
Use a lightweight web framework like Flask to serve the generated HTML on demand:
from flask import Flask, request, render_string app = Flask(__name__) @app.route('/dynamic-payment') def dynamic_payment_page(): # Fetch dynamic parameters from the request order_num = request.args.get('order_num') total = request.args.get('total') store_id = request.args.get('store_id') signature = request.args.get('signature') seed = request.args.get('seed') # Generate and return the custom HTML payment_html = generate_payment_html(order_num, total, store_id, signature, seed) return render_string(payment_html) if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)
3. Send the Link to Users
Generate a unique URL for each order and send it via your bot:
@bot.message_handler(commands=['checkout']) def start_checkout(message): # Replace with actual order data order_data = { "order_num": "ORDER-12345678", "total": "10", "store_id": "11111111", "signature": "124264917411111111ORDER-123456781BYN10123456", "seed": "1242649174" } # Build the dynamic payment URL payment_url = ( f"https://your-server.com/dynamic-payment?" f"order_num={order_data['order_num']}&" f"total={order_data['total']}&" f"store_id={order_data['store_id']}&" f"signature={order_data['signature']}&" f"seed={order_data['seed']}" ) bot.send_message( message.chat.id, f"Click to complete payment: [Pay Now]({payment_url})", parse_mode='Markdown' )
内容的提问来源于stack exchange,提问作者MikaYeghi

