这里说一下怎么和后端的 webhook
进行交互。这里的 webhook
指的是通过调用 telegram
的 setWebhook
来设置的后台 api webhook
地址,具体可以看 telegram | 数据传递
这里的 mini app
指的是,bot
中打开 open app
的按钮。
那么,通过 open app
如何和 bot
绑定的后端进行交互?
有两个方法。
调用 bot 的 sendMessage 方法
https://api.telegram.org/bot<YOUR_BOT_TOKEN>/sendMessage
,但是,这样就会把 token
暴漏出来,没有任何安全性
直接和后端进行 webhook
发送请求
之前有一种和后台 webhook
的交互方式,就是直接和 bot
聊天,telegram | 前后端 3种 简单的交互案例 ,而在 mini app
中是无法做到这样的。无法调用 tg.sendData
直接发给 telegram
服务器,然后 telegram
服务器转发给后台。
对于,mini app,要时刻记住一点,打开后,它就是一个普通的网页,只不过,如果这个网页是在 telegram 中打开的,可以通过 telegram 的 js 获取相关的数据。
这里举一个例子。
前端:地址是 https://tg.thlm.bond
后端:地址是 https://tgapi.thlm.bond
前端 在 telegram
中打开,可以在 telegram
中获取用户信息发到后端中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 <!DOCTYPE html > <html lang ="zh" > <head > <meta charset ="UTF-8" > <meta name ="viewport" content ="width=device-width, initial-scale=1.0" > <title > Telegram Bot Interface</title > <script src ="https://telegram.org/js/telegram-web-app.js" > </script > <style > body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; background-color : var (--tg-theme-bg-color , #ffffff ); color : var (--tg-theme-text-color , #000000 ); } .container { text-align: center; } .btn { background-color : var (--tg-theme-button-color , #0088cc ); color : var (--tg-theme-button-text-color , #ffffff ); padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer; font-size: 16px; } .btn :hover { opacity : 0.9 ; } #status { margin-top: 20px; padding: 10px; border-radius: 5px; } .success { background-color : #dff0d8 ; color : #3c763d ; } .error { background-color : #f2dede ; color : #a94442 ; } </style > </head > <body > <div class ="container" > <h1 > Telegram Bot Interface</h1 > <button id ="sendInfoBtn" class ="btn" > 点击:发送用户信息</button > <div id ="status" > </div > </div > <script > window .Telegram.WebApp.ready(); const tg = window .Telegram.WebApp; document .documentElement.style.setProperty('--tg-theme-bg-color' , tg.backgroundColor); document .documentElement.style.setProperty('--tg-theme-text-color' , tg.textColor); document .documentElement.style.setProperty('--tg-theme-button-color' , tg.buttonColor); document .documentElement.style.setProperty('--tg-theme-button-text-color' , tg.buttonTextColor); document .getElementById('sendInfoBtn' ).addEventListener('click' , async function ( ) { const statusDiv = document .getElementById('status' ); try { if (!tg.initDataUnsafe || !tg.initDataUnsafe.user) { throw new Error ('无法获取 Telegram 用户信息' ); } const user = tg.initDataUnsafe.user; const response = await fetch('https://tgapi.thlm.bond/info' , { method: 'POST' , headers: { 'Content-Type' : 'application/json' , 'Telegram-Data' : tg.initData }, body: JSON .stringify({ userId: user.id, username: user.username, firstName: user.first_name, lastName: user.last_name, languageCode: user.language_code }) }); const data = await response.json(); if (response.ok) { statusDiv.className = 'success' ; statusDiv.textContent = '信息发送成功!' ; tg.showPopup({ title: '成功' , message: '用户信息已成功发送' , buttons: [{text: '确定' }] }); } else { throw new Error (data.message || '请求失败' ); } } catch (error) { console .error('Error:' , error); statusDiv.className = 'error' ; statusDiv.textContent = '发送失败:' + error.message; tg.showPopup({ title: '错误' , message: error.message, buttons: [{text: '确定' }] }); } }); tg.BackButton.show(); tg.BackButton.onClick(() => { tg.close(); }); tg.expand(); </script > </body > </html >
后端 后端通过 nginx
把 https://tgapi.thlm.bond
的请求都转移到 http://127.0.0.1:8334
上。
这个后端不仅可以接受来自前端的请求,还可以接收用户和 bot
聊天的信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 import loggingfrom datetime import datetimeimport requestsfrom flask import Flask, request, jsonifyfrom flask_cors import CORSapp = Flask(__name__) CORS(app) logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) BOT_TOKEN = 'YOUR_BOT_TOKEN' WEBHOOK_URL = 'https://tgapi.thlm.bond/webhook' def setup_webhook () : """设置 Telegram webhook""" try : delete_url = f'https://api.telegram.org/bot{BOT_TOKEN} /deleteWebhook' delete_response = requests.get(delete_url) logger.info(f"Delete webhook response: {delete_response.json()} " ) set_url = f'https://api.telegram.org/bot{BOT_TOKEN} /setWebhook' set_response = requests.get( set_url, params={ 'url' : WEBHOOK_URL, 'allowed_updates' : ['message' , 'callback_query' ] } ) if set_response.status_code == 200 : result = set_response.json() if result.get('ok' ): logger.info("Webhook set successfully!" ) logger.info(f"Webhook info: {result} " ) else : logger.error(f"Failed to set webhook: {result} " ) else : logger.error(f"Failed to set webhook. Status code: {set_response.status_code} " ) info_url = f'https://api.telegram.org/bot{BOT_TOKEN} /getWebhookInfo' info_response = requests.get(info_url) logger.info(f"Current webhook info: {info_response.json()} " ) except Exception as e: logger.error(f"Error setting up webhook: {str(e)} " ) raise e users_info = {} @app.route('/info', methods=['POST']) def handle_user_info () : """处理从前端发送来的用户信息""" try : user_info = request.json user_id = user_info.get('userId' ) if user_id: users_info[user_id] = { 'info' : user_info, 'timestamp' : datetime.now().isoformat() } logger.info(f"Received user info: {user_info} " ) return jsonify({ 'status' : 'success' , 'message' : 'User information received successfully' }), 200 except Exception as e: logger.error(f"Error processing user info: {str(e)} " ) return jsonify({ 'status' : 'error' , 'message' : str(e) }), 500 @app.route('/webhook', methods=['POST']) def webhook () : """处理来自 Telegram 的 webhook 请求""" try : update = request.json logger.info(f"Received webhook update: {update} " ) if 'message' in update: chat_id = update['message' ]['chat' ]['id' ] user_id = update['message' ]['from' ]['id' ] user_stored_info = users_info.get(str(user_id)) if user_stored_info: response_text = "已收到您的信息!" send_telegram_message(chat_id, response_text) return jsonify({'status' : 'ok' }), 200 except Exception as e: logger.error(f"Error processing webhook: {str(e)} " ) return jsonify({ 'status' : 'error' , 'message' : str(e) }), 500 def send_telegram_message (chat_id, text) : """发送 Telegram 消息的辅助函数""" try : url = f'https://api.telegram.org/bot{BOT_TOKEN} /sendMessage' data = { 'chat_id' : chat_id, 'text' : text } response = requests.post(url, json=data) return response.json() except Exception as e: logger.error(f"Error sending telegram message: {str(e)} " ) return None @app.route('/') def index () : """健康检查端点""" return jsonify({ 'status' : 'ok' , 'timestamp' : datetime.now().isoformat() }) def init_app () : """初始化应用""" try : setup_webhook() logger.info("Application initialized successfully" ) except Exception as e: logger.error(f"Failed to initialize application: {str(e)} " ) raise e if __name__ == '__main__' : init_app() app.run(host='127.0.0.1' , port=8443 )