Telegram Mini Apps с мгновенной оплатой

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Инструкция, посвящённая созданию Telegram Mini Apps с вызовом окна оплаты без создания дополнительной кнопки для этого.


Mini Apps от Telegram — это веб-сайты, которые телеграм позволяет запускать у себя внутри системы.

Один из вариантов использования Mini Apps — это реализация онлайн магазина: Mini Apps служат визуальным представлением, а оплата происходит через внутреннюю систему Telegram. Одному из способов такой реализации и посвящена эта инструкция.

Как это сделано в примере от Telegram:

Для реализации оплата в Bot API есть два способа:

1. Кнопка оплаты. Библиотеки телеграм позволяют создать кнопку, при нажатии на которую создается и вызывается платежная url‑ссылка.
В документации этот метод значится как sendInvoice().

2. По ссылке. Создается url‑ссылка для оплаты методом createInvoiceLink(), в которой указываются токен платежного провайдера и детали покупки (стоимость, названия и т.д). А после метод openInvoice(url) открывает платежную ссылку, вызвав системное окно оплаты.

Метод createInvoiceLink() вызывается у объекта бота, а openInvoice(url) вызывается в js-коде Mini Apps. В этом и заключается сложность этого метода. Получается, для реализации такого метода нужно по событию в Mini Apps отправлять запрос на создание url‑ссылки для оплаты серверной части с ботом. Там ссылка создастся, вернётся и вызовется из Mini Apps.

Иллюстрированно это выглядит следующим образом.

Иллюстрация оплаты
Иллюстрация оплаты

Приступим к программной реализации.


Для начала — что используется:

  • Python, библиотека Telebot 4.16.1;

  • Код логической части размещен на Yandex Cloud Function, а вызов — через API Gateway;

  • web-сайт для Mini Apps размещен на Netlify.


    Yandex Cloud Function позволяет запускать куски кода при обращении к ним извне. А API Gateway помогает обрабатывать внешние обращения.

1 шаг. Создать web-сайт

Создать сайт, который будет показываться в Mini Apps.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Montserrat', sans-serif;
            font-weight: 200;
        }
    </style>
</head>
<body>
    <p>Привет! Получиолось!!!</p>
</body>
</html>

Простой, пока без внутренней логики сайт. Его нужно захостить. Ссылку на него будем указывать при создании Mini Apps.

2 шаг. Создать телеграм-бота

Создаем через BotFather бота, получаем его токен. Также подключаем к нему платежного провайдера и получаем токен.

/mybots → *Ваш бот* → Payments → *Любой банк* → Test режим → *Проследовать инструкциям от банка*

После этого в разделе Paymnets вашего бота появится платежный токен.
Test — это тестовый режим банка, протестировать оплату — без реальных карт и счетов.
Банк — быстрее всего удалось получить токен у ПСБ и Bank 131.

3 шаг. Логика бота.

Бот будет работать по webhook — то есть не он запрашивает с сервера телеграма последние обновления по переписке, а сервер телеграма будет обращаться к нему, когда поступят новости из чата.

На Yandex Function создаём новую функцию, после выбираем в настройках, что она публичная и язык Python 3.12.

Создаем файл requirements.txt и подключаем библиотеку для бота:

pyTelegramBotAPI==4.16.1

В файле index.handler пишем:

import asyncio, json, os, requests

import telebot
from telebot import types
from telebot.types import LabeledPrice, ShippingOption

provider_token = "ТОКЕН_ПРОВАЙДЕРА_ОПЛАТЫ"
bot = telebot.TeleBot('ТОКЕН_БОТА')

@bot.message_handler(commands = ['start'])
def url(message):
    markup = types.InlineKeyboardMarkup()
    webUrl = types.WebAppInfo("ССЫЛКА_НА_САЙТ")
    web_btn = types.InlineKeyboardButton(text='Название для кнопки', web_app=webUrl)
    markup.add(web_btn)
    bot.send_message(message.from_user.id, "Перейти к Mini Apps", reply_markup = markup)

async def handler(event, context):
    responce = None
    if('X-Custom-Info' in event['headers']):
        responce = bot.create_invoice_link("Покупка","Тестовый","true",provider_token,"rub",[types.LabeledPrice('Покупка',5 * 100)])
        print(responce)
    else:
        data = json.loads(event['body'])
        update = types.Update.de_json(data)
        bot.process_new_updates([update])
        responce = 'ok'
    return {'statusCode': 200, 'body': responce}

Здесь важно, что в обработчике команды start мы создаем Mini Apps через KeyBoard, указав ссылку на наш сайт.

Hidden text
@bot.message_handler(commands = ['start'])
def url(message):
    markup = types.InlineKeyboardMarkup()
    webUrl = types.WebAppInfo("ССЫЛКА_НА_САЙТ")
    web_btn = types.InlineKeyboardButton(text='Название для кнопки', web_app=webUrl)
    markup.add(web_btn)
    bot.send_message(message.from_user.id, "Перейти к оплате", reply_markup = markup)

Также здесь важны еще эти строчки:

if('X-Custom-Info' in event['headers']):
        responce = bot.create_invoice_link("Покупка","Тестовый","true",provider_token,"rub",[types.LabeledPrice('Покупка',5 * 100)])
        print(responce)

К запросу из Mini Apps к нашей Yandex Function мы будем добавлять дополнительный заголовок, и его существование означает, что нужно сделать и вернуть url‑ссылку оплаты.

Это мы здесь и делаем — проверяем наличие заголовка и с помощью метода create_invoice_link() создаем ссылку, указав следующие параметры:

Название, описание, параметр под свои нужды, токен провайдера оплаты, валюта, массив объектов LabeledPrice — цены на товары

5 шаг. Добавить логику на сайт

После создания бота, сайта и Mini Apps нам нужно дописать логику, отправляющую запрос на сайт для создания url‑ссылки оплаты и после — для её открытия.

Для открытия url‑ссылки оплаты используется ранее названный метод — openInvoice(url), нужно подключить на сайт скрипт телеграма:

<script src="https://telegram.org/js/telegram-web-app.js"></script>

Теперь на сайте можно использовать Telegram Mini Apps API.

Mini Apps включает в себя:

  • CSS-стиль адаптивный под тему, выбранную в Telegram;

  • Элементы — кнопки, popup, alert;

  • Методы для взаимодействия.

 const tg = window.Telegram.WebApp;

Так мы получаем объект Mini Apps для вызова методов и создания элементов.

tg.MainButton.show();
        tg.MainButton.setText("Оплатить");
        tg.MainButton.onClick(() => {
            console.log("start");
            var xhr = new XMLHttpRequest();
            xhr.open("POST", url, true);
            xhr.setRequestHeader("Content-Type", "application/json");
            xhr.setRequestHeader("X-Custom-Info", "getOpenInvoiceUrl");
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4 && xhr.status === 200) {
                    tg.openInvoice(xhr.responseText);
                }
            };
            xhr.send();
        });

Здесь создаем кнопку снизу для оплаты и обрабатываем ее нажатие. Внутри мы будем отправлять запрос к Yandex Function для получения url‑ссылки на оплату и после вызываем её.

Также здесь:
url — ваша ссылка на API Yandex Function.
data — данные json для отправки. Планируется, что вы отправляете данные для создания url‑ссылки оплаты.

В итоге код сайта выглядит следующим образом:

Hidden text

6

6 шаг. Настройка API Gateway

Последним шагом нужно настроить API, по которому будет вызываться Yandex Function. Для этого в разделе API Gateway создаем новое API и в добавляем в него конфигурацию:

openapi: 3.0.0
info:
  title: Sample API
  version: 1.0.0
servers:
- url:'здесь будет ссылка на api автоматически'
x-yc-apigateway:
  cors:
    origin: '*'
    methods: '*'
    allowedHeaders: '*'
paths:
   /'название для запроса - обычно имя функции':
    post:
      x-yc-apigateway-integration:
        type: cloud-functions
        function_id: 'доменное имя функции, находится в ее настройках'
      operationId: 'название функции'

Здесь настроили пути обращения к функции, а также раздел с cors, который, обращаясь из Mini Apps js, сначала отправляет options-запрос, проверяя, можно ли вообще посылать post-запрос. По умолчанию его нет в конфигурационном файле. Последним надо из-за особенностей построения бота настроить WebHook. Инструкция для этого есть от Яндекса — ссылка.

В итоге получается следующее:


На этом всё. Telegram Mini Apps — довольно интересный инструмент, а реализация бота с помощью Yandex Cloud Fucntion — пусть не самый простой, но очень эффективный и удобный способ.

Источник: https://habr.com/ru/articles/796793/


Интересные статьи

Интересные статьи

В последнее время на Хабре несколько раз всплывала тема загрузки видео из VK для дальнейшего просмотра оффлайн. Я решил подойти к этому вопросу немного с другой стороны, и решить вопрос с помощью теле...
Если вы изучали информатику, основы программирования или архитектуру операционных систем, это имя должно быть вам хорошо знакомо. Автор популярных учебников, ставших бестселлерами во многих страна...
Привет! Меня зовут Боровков Евгений и я предприниматель. В этой статье я расскажу про свой pet-проект. Или как я решил проблему вечного поиска информации прямо в уютном Телеграммчике.
В предыдущих хабрапостах мы поделились open source инструментом для сравнительного анализа метагеномных данных и рассказали об открытых проектах, которыми занимается наша лаборатория мультиагентных си...
Компания MINISFORUM не так давно выпустила новый миниатюрный ПК, который при своих небольших размерах обеспечивает неплохую производительность. Интерес в этой системе вызывает прежде в...