Бот-витрина магазина с оплатой в TON
Эта страница переведе на сообществом на русский язык, но нуждается в улучшениях. Если вы хотите принять участие в переводе свяжитесь с @alexgton.
В этой статье мы расскажем о том, как принимать платежи в боте Telegram.
📖 Чему вы научитесь
В этой статье вы узнаете, как:
- создать Telegram-бота с помощью Python + Aiogram
- работать с публичным API TON (TON Center)
- работать с базой данных SQlite
И наконец: как принимать платежи в Telegram-боте, используя знания из предыдущих шагов.
📚 Прежде чем мы начнем
Убедитесь, что у вас установлена последняя версия Python и установлены следующие пакеты:
- aiogram
- requests
- sqlite3
🚀 Давайте начнем!
Мы будем действовать по нижеприведенному порядку:
- Работа с базой данных SQlite
- Работа с публичным API TON (TON Center)
- Создание Telegram-бота с помощью Python + Aiogram
- Получаем прибыль!
Давайте создадим следующие четыре файла в директории нашего проекта:
telegram-bot
├── config.json
├── main.py
├── api.py
└── db.py
Конфигурация
В config.json
мы сохраним токен нашего бота и наш публичный ключ TON API.
{
"BOT_TOKEN": "Your bot token",
"MAINNET_API_TOKEN": "Your mainnet api token",
"TESTNET_API_TOKEN": "Your testnet api token",
"MAINNET_WALLET": "Your mainnet wallet",
"TESTNET_WALLET": "Your testnet wallet",
"WORK_MODE": "testnet"
}
В config.json
мы решаем, какую сеть мы будем использовать: testnet
или mainnet
.
База данных
Создаем базу данных
В этом примере используется локальная база данных Sqlite.
Создайте db.py
.
Чтобы начать работу с базой данных, нам нужно импортировать модуль sqlite3 и несколько модулей для работы со временем.
import sqlite3
import datetime
import pytz
Sqlite3
-модуль для работы с базой данных sqlitedatetime
- модуль для работы со временемpytz
- модуль для работы с часовыми поясами
Далее нам нужно создать соединение с базой данных и курсор для работы с ней:
locCon = sqlite3.connect('local.db', check_same_thread=False)
cur = locCon.cursor()
Если база данных не существует, она будет создана автоматически.
Теперь мы можем создать таблицы. У нас их две.
Транзакции:
CREATE TABLE transactions (
source VARCHAR (48) NOT NULL,
hash VARCHAR (50) UNIQUE
NOT NULL,
value INTEGER NOT NULL,
comment VARCHAR (50)
);
source
- адрес кошелька плательщикаhash
- хэш транзакцииvalue
- значение транзакцииcomment
- комментарий к транзакции
Пользователи:
CREATE TABLE users (
id INTEGER UNIQUE
NOT NULL,
username VARCHAR (33),
first_name VARCHAR (300),
wallet VARCHAR (50) DEFAULT none
);
id
- ID пользователя Telegramusername
- имя пользователя Telegramfirst_name
- имя пользователя Telegramwallet
- адрес кошелька пользователя
В таблице users
мы храним пользователей :) их Telegram ID, @логин,
имя и кошелек. Кошелек добавляется в базу данных при первом
успешном платеже.
В таблице transactions
хранятся проверенные транзакции.
Чтобы проверить транзакцию, нам нужны хеш, источник, значение и комментарий.
Чтобы создать эти таблицы, нам нужно выполнить следующую функцию:
cur.execute('''CREATE TABLE IF NOT EXISTS transactions (
source VARCHAR (48) NOT NULL,
hash VARCHAR (50) UNIQUE
NOT NULL,
value INTEGER NOT NULL,
comment VARCHAR (50)
)''')
locCon.commit()
cur.execute('''CREATE TABLE IF NOT EXISTS users (
id INTEGER UNIQUE
NOT NULL,
username VARCHAR (33),
first_name VARCHAR (300),
wallet VARCHAR (50) DEFAULT none
)''')
locCon.commit()
Этот код создаст таблицы, если они еще не созданы.
Работа с базой данных
Давайте проанализируем ситуацию. Пользователь совершил транзакцию. Как ее подтвердить? Как сделать так, чтобы одна и та же транзакция не была подтверждена дважды?
В транзакциях есть body_hash, с помощью которого мы можем легко понять, есть ли транзакция в базе данных или нет.
Мы добавляем транзакции в базу данных, в которых мы уверены. Функция check_transaction
проверяет, есть ли найденная транзакция в базе данных или нет.
add_v_transaction
добавляет транзакцию в таблицу транзакций.
def add_v_transaction(source, hash, value, comment):
cur.execute("INSERT INTO transactions (source, hash, value, comment) VALUES (?, ?, ?, ?)",
(source, hash, value, comment))
locCon.commit()
def check_transaction(hash):
cur.execute(f"SELECT hash FROM transactions WHERE hash = '{hash}'")
result = cur.fetchone()
if result:
return True
return False
check_user
проверяет, есть ли пользователь в базе данных, и добавляет его, если нет.
def check_user(user_id, username, first_name):
cur.execute(f"SELECT id FROM users WHERE id = '{user_id}'")
result = cur.fetchone()
if not result:
cur.execute("INSERT INTO users (id, username, first_name) VALUES (?, ?, ?)",
(user_id, username, first_name))
locCon.commit()
return False
return True
Пользователь может сохранить кошелек в таблице. Он добавляется при первой успешной покупке. Функция v_wallet
проверяет, есть ли у пользователя связанный с ним кошелек. Если есть, то возвращает его. Если нет, то добавляет.
def v_wallet(user_id, wallet):
cur.execute(f"SELECT wallet FROM users WHERE id = '{user_id}'")
result = cur.fetchone()
if result[0] == "none":
cur.execute(
f"UPDATE users SET wallet = '{wallet}' WHERE id = '{user_id}'")
locCon.commit()
return True
else:
return result[0]
get_user_wallet
просто возвращает кошелек пользователя.
def get_user_wallet(user_id):
cur.execute(f"SELECT wallet FROM users WHERE id = '{user_id}'")
result = cur.fetchone()
return result[0]
get_user_payments
возвращает список платежей пользователя.
Эта функция проверяет, есть ли у пользователя кошелек. Если есть, то она возвращает список платежей.
def get_user_payments(user_id):
wallet = get_user_wallet(user_id)
if wallet == "none":
return "You have no wallet"
else:
cur.execute(f"SELECT * FROM transactions WHERE source = '{wallet}'")
result = cur.fetchall()
tdict = {}
tlist = []
try:
for transaction in result:
tdict = {
"value": transaction[2],
"comment": transaction[3],
}
tlist.append(tdict)
return tlist
except:
return False
API
У нас есть возможность взаимодействовать с блокчейном, используя сторонние API, предоставляемые некоторыми участниками сети. С помощью этих сервисов разработчики могут пропустить этап запуска собственного узла и настройки API.