
Приветствую сообщество.
Бот Telegram @wallet недавно предоставил API для приема платежей в сторонних Telegram ботах. Из крипто валют поддерживаются BTC, TON, USDT.
Необходимо зарегистрироваться на сайте, предоставить сведения о подключаемом к API боте, пройти процедуру идентификации (биометрия для физических лиц), дождаться одобрения заявки и назначения размера комиссии для ваших платежей. У меня процедура заняла чуть более суток.
После одобрения заявки получаете доступ в личный кабинет, где нужно сгенерировать ключ для доступа к API WalletPay.
После этого можно приступать к продажам. Покупателю нужно предоставить ссылку для оплаты через WalletPay товаров/услуг вашего бота. Код для получения этой ссылки может быть таким.
import requests def get_pay_link(): headers = { 'Wpay-Store-Api-Key': 'YOUR-API-KEY', 'Content-Type': 'application/json', 'Accept': 'application/json', } payload = { 'amount': { 'currencyCode': 'USD', # выставляем счет в долларах США 'amount': '1.00', }, 'description': 'Goods and service.', 'externalId': 'XXX-YYY-ZZZ', # ID счета на оплату в вашем боте 'timeoutSeconds': 60 * 60 * 24, # время действия счета в секундах 'customerTelegramUserId': '999666999', # ID аккаунта Telegram покупателя 'returnUrl': 'https://t.me/mybot', # после успешной оплаты направить покупателя в наш бот 'failReturnUrl': 'https://t.me/wallet', # при отсутствии оплаты оставить покупателя в @wallet } response = requests.post( "https://pay.wallet.tg/wpay/store-api/v1/order", json=payload, headers=headers, timeout=10 ) data = response.json() if (response.status_code != 200) or (data['status'] not in ["SUCCESS", "ALREADY"]): logging.warning("# code: %s json: %s", response.status_code, data) return '' return data['data']['payLink']
Счет можно выставлять в долларах США, евро или рублях. Пересчет в BTC, TON, USDT будет выполнен по курсу WalletPay.
Для подтверждения факта оплаты счета, WalletPay предоставляет две опции:
периодический опрос состояния счета с вашей стороны.
POST-запрос на указанный вами в личном кабинете
httpsадрес (webhook в терминах WalletPay).
Я использовал второй вариант. Код обработчика вебхука может быть таким.
from flask import Flask, request app = Flask(__name__) @app.route('/tgwallet/ipn', methods=['POST']) def ipn_tgwallet(): for event in request.get_json(): if event["type"] == "ORDER_PAID": data = event["payload"] print("Оплачен счет N {} на сумму {} {}. Оплата {} {}.".format( data["externalId"], # ID счета в вашем боте, который мы указывали при создании ссылки для оплаты data["orderAmount"]["amount"], # Сумма счета, указанная при создании ссылки для оплаты data["orderAmount"]["currencyCode"], # Валюта счета data["selectedPaymentOption"]["amount"]["amount"], # Сколько оплатил покупатель data["selectedPaymentOption"]["amount"]["currencyCode"] # В какой криптовалюте )) # нужно всегда возвращать код 200, чтобы WalletPay не делал повторных вызовов вебхука return 'OK'
Прежде чем передавать оплаченный товар или услугу, нужно убедиться, что вызов вебхука пришел из WalletPay, а не от злоумышленников, жаждущих заполучить наш товар бесплатно.
Для этого WalletPay предлагает две опции:
проверка принадлежности IP вызова к пулу IP адресов WalletPay;
проверка хеша, вычисленного на основе данных вызова вебхука и вашего ключа API.
Список IP адресов WalletPay можно найти в документации, а для проверки хеша можно использовать следующий код.
import base64, hashlib, hmac ENCODING = 'utf-8' def is_valid(flask_request): text = '.'.join([ flask_request.method, # 'POST' flask_request.path, # нужно использовать часть адреса без имени домена, '/tgwallet/ipn' в нашем случае flask_request.headers.get('WalletPay-Timestamp'), base64.b64encode(flask_request.get_data()).decode(ENCODING), ]) signature = base64.b64encode(hmac.new( bytes('YOUR-API-KEY', ENCODING), msg=bytes(text, ENCODING), digestmod=hashlib.sha256 ).digest()) return flask_request.headers.get('Walletpay-Signature') == signature.decode(ENCODING)
Затем использовать функцию is_valid для проверки в обработчике вебхука.
Спасибо за внимание.
