├── README.md ├── .gitattributes ├── bot ├── keyboards.py ├── main.py └── handlers.py └── site ├── style.css ├── index.html └── app.js /README.md: -------------------------------------------------------------------------------- 1 | # Web_App 2 | Код из видео https://youtu.be/O1ZRJXKBa4U 3 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /bot/keyboards.py: -------------------------------------------------------------------------------- 1 | from aiogram.types import WebAppInfo 2 | from aiogram import types 3 | 4 | web_app = WebAppInfo(url='site_url') 5 | 6 | keyboard = types.ReplyKeyboardMarkup( 7 | keyboard=[ 8 | [types.KeyboardButton(text='Site', web_app=web_app)] 9 | ], 10 | resize_keyboard=True 11 | ) 12 | -------------------------------------------------------------------------------- /bot/main.py: -------------------------------------------------------------------------------- 1 | from aiogram import Bot, Dispatcher 2 | 3 | import asyncio 4 | 5 | bot = Bot(token='token') 6 | dp = Dispatcher(bot=bot) 7 | 8 | async def main(): 9 | from handlers import dp 10 | try: 11 | await dp.start_polling() 12 | finally: 13 | await bot.session.close() 14 | 15 | if __name__ == "__main__": 16 | try: 17 | asyncio.run(main()) 18 | except (KeyboardInterrupt, SystemExit): 19 | print('Bot stopped!') 20 | -------------------------------------------------------------------------------- /site/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-size: 18px; 5 | color: var(--tg-theme-text-color); 6 | background: var(--tg-theme-bg-color); 7 | } 8 | 9 | .container { 10 | max-width: 390px; 11 | } 12 | 13 | .inner { 14 | display: grid; 15 | grid-template-columns: 1fr 1fr; 16 | grid-template-rows: 200px 200px 200px; 17 | } 18 | 19 | .img { 20 | width: 150px; 21 | } 22 | 23 | .item { 24 | text-align: center; 25 | } 26 | 27 | .btn { 28 | display: inline-block; 29 | padding: 10px 20px; 30 | border: none; 31 | background: rgb(248, 168, 24); 32 | border-radius: 10px; 33 | color: #fff; 34 | text-transform: uppercase; 35 | font-weight: 700; 36 | 37 | transition: background .2s linear; 38 | } 39 | 40 | .btn:hover { 41 | background: lightgreen; 42 | } 43 | 44 | .usercard { 45 | text-align: center; 46 | } 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /site/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 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 | -------------------------------------------------------------------------------- /bot/handlers.py: -------------------------------------------------------------------------------- 1 | from main import bot, dp 2 | from keyboards import keyboard 3 | from aiogram import types 4 | from aiogram.dispatcher.filters import Command 5 | 6 | @dp.message_handler(Command('start')) 7 | async def start(message: types.Message): 8 | await bot.send_message(message.chat.id, 'Тестируем WebApp!', 9 | reply_markup=keyboard) 10 | 11 | PRICE = { 12 | '1': [types.LabeledPrice(label='Item1', amount=100000)], 13 | '2': [types.LabeledPrice(label='Item2', amount=200000)], 14 | '3': [types.LabeledPrice(label='Item3', amount=300000)], 15 | '4': [types.LabeledPrice(label='Item4', amount=400000)], 16 | '5': [types.LabeledPrice(label='Item5', amount=500000)], 17 | '6': [types.LabeledPrice(label='Item6', amount=600000)] 18 | } 19 | 20 | @dp.message_handler(content_types='web_app_data') 21 | async def buy_process(web_app_message): 22 | await bot.send_invoice(web_app_message.chat.id, 23 | title='Laptop', 24 | description='Description', 25 | provider_token='pay_token', 26 | currency='rub', 27 | need_email=True, 28 | prices=PRICE[f'{web_app_message.web_app_data.data}'], 29 | start_parameter='example', 30 | payload='some_invoice') 31 | 32 | @dp.pre_checkout_query_handler(lambda query: True) 33 | async def pre_checkout_process(pre_checkout: types.PreCheckoutQuery): 34 | await bot.answer_pre_checkout_query(pre_checkout.id, ok=True) 35 | 36 | @dp.message_handler(content_types=types.ContentType.SUCCESSFUL_PAYMENT) 37 | async def successful_payment(message: types.Message): 38 | await bot.send_message(message.chat.id, 'Платеж прошел успешно!') 39 | -------------------------------------------------------------------------------- /site/app.js: -------------------------------------------------------------------------------- 1 | let tg = window.Telegram.WebApp; 2 | 3 | tg.expand(); 4 | 5 | tg.MainButton.textColor = '#FFFFFF'; 6 | tg.MainButton.color = '#2cab37'; 7 | 8 | let item = ""; 9 | 10 | let btn1 = document.getElementById("btn1"); 11 | let btn2 = document.getElementById("btn2"); 12 | let btn3 = document.getElementById("btn3"); 13 | let btn4 = document.getElementById("btn4"); 14 | let btn5 = document.getElementById("btn5"); 15 | let btn6 = document.getElementById("btn6"); 16 | 17 | btn1.addEventListener("click", function(){ 18 | if (tg.MainButton.isVisible) { 19 | tg.MainButton.hide(); 20 | } 21 | else { 22 | tg.MainButton.setText("Вы выбрали товар 1!"); 23 | item = "1"; 24 | tg.MainButton.show(); 25 | } 26 | }); 27 | 28 | btn2.addEventListener("click", function(){ 29 | if (tg.MainButton.isVisible) { 30 | tg.MainButton.hide(); 31 | } 32 | else { 33 | tg.MainButton.setText("Вы выбрали товар 2!"); 34 | item = "2"; 35 | tg.MainButton.show(); 36 | } 37 | }); 38 | 39 | btn3.addEventListener("click", function(){ 40 | if (tg.MainButton.isVisible) { 41 | tg.MainButton.hide(); 42 | } 43 | else { 44 | tg.MainButton.setText("Вы выбрали товар 3!"); 45 | item = "3"; 46 | tg.MainButton.show(); 47 | } 48 | }); 49 | 50 | btn4.addEventListener("click", function(){ 51 | if (tg.MainButton.isVisible) { 52 | tg.MainButton.hide(); 53 | } 54 | else { 55 | tg.MainButton.setText("Вы выбрали товар 4!"); 56 | item = "4"; 57 | tg.MainButton.show(); 58 | } 59 | }); 60 | 61 | btn5.addEventListener("click", function(){ 62 | if (tg.MainButton.isVisible) { 63 | tg.MainButton.hide(); 64 | } 65 | else { 66 | tg.MainButton.setText("Вы выбрали товар 5!"); 67 | item = "5"; 68 | tg.MainButton.show(); 69 | } 70 | }); 71 | 72 | btn6.addEventListener("click", function(){ 73 | if (tg.MainButton.isVisible) { 74 | tg.MainButton.hide(); 75 | } 76 | else { 77 | tg.MainButton.setText("Вы выбрали товар 6!"); 78 | item = "6"; 79 | tg.MainButton.show(); 80 | } 81 | }); 82 | 83 | 84 | Telegram.WebApp.onEvent("mainButtonClicked", function(){ 85 | tg.sendData(item); 86 | }); 87 | 88 | 89 | let usercard = document.getElementById("usercard"); 90 | 91 | let p = document.createElement("p"); 92 | 93 | p.innerText = `${tg.initDataUnsafe.user.first_name} 94 | ${tg.initDataUnsafe.user.last_name}`; 95 | 96 | usercard.appendChild(p); 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | --------------------------------------------------------------------------------