Метод answerPreCheckoutQuery

Метод для подтверждения или отклонения предварительного платежного запроса пользователя перед завершением оплаты.

Описание

После того как пользователь подтвердил свои платежные и транспортные данные, Bot API отправляет окончательное подтверждение в виде Update с полем pre_checkout_query. Используйте этот метод для ответа на такие предварительные платежные запросы. При успешном выполнении возвращается True. Примечание: Bot API должен получить ответ в течение 10 секунд после отправки предварительного платежного запроса.

Параметр Тип Обязательный Описание
pre_checkout_query_id String Да Уникальный идентификатор запроса, на который нужно ответить
ok Boolean Да Укажите True, если все в порядке (товары доступны и т.д.) и бот готов продолжить оформление заказа. Используйте False, если есть какие-либо проблемы.
error_message String Опционально Обязателен, если ok равен False. Сообщение об ошибке в удобочитаемой форме, объясняющее причину невозможности продолжить оформление заказа (например, "Извините, пока вы заполняли платежные данные, кто-то только что купил последнюю нашу удивительную черную футболку. Пожалуйста, выберите другой цвет или изделие!"). Telegram покажет это сообщение пользователю.

Примеры

php

<?php

// Токен вашего бота
$botToken = 'YOUR_BOT_TOKEN';

// ID предварительного запроса на оплату из обновления
$preCheckoutQueryId = $_POST['pre_checkout_query_id'] ?? ''; // В реальном коде получайте из Update

// Статус проверки (true - всё хорошо, false - есть проблемы)
$ok = true;

// Сообщение об ошибке (только если $ok = false)
$errorMessage = '';

// Если есть проблемы с заказом
// $ok = false;
// $errorMessage = 'Извините, товар закончился. Пожалуйста, выберите другой товар.';

// Подготовка данных для запроса
$data = [
    'pre_checkout_query_id' => $preCheckoutQueryId,
    'ok' => $ok
];

// Добавляем сообщение об ошибке только если статус false
if (!$ok && !empty($errorMessage)) {
    $data['error_message'] = $errorMessage;
}

// Отправка запроса к Telegram Bot API
$url = "https://api.telegram.org/bot{$botToken}/answerPreCheckoutQuery";

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json'
]);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

// Обработка ответа
if ($httpCode === 200) {
    $result = json_decode($response, true);
    
    if ($result['ok'] === true) {
        // Успешный ответ на pre-checkout запрос
        echo "Pre-checkout query answered successfully.\n";
        
        // Здесь можно обновить статус заказа в вашей базе данных
        // и подготовить данные для отправки счёта
        
    } else {
        echo "Error: " . $result['description'] . "\n";
    }
} else {
    echo "HTTP Error: " . $httpCode . "\n";
}

// Альтернативный вариант с использованием file_get_contents
/*
$context = stream_context_create([
    'http' => [
        'method' => 'POST',
        'header' => 'Content-Type: application/json',
        'content' => json_encode($data)
    ]
]);

$response = file_get_contents($url, false, $context);
$result = json_decode($response, true);

if ($result['ok'] === true) {
    echo "Success!\n";
} else {
    echo "Error: " . $result['description'] . "\n";
}
*/

// Пример обработки в вебхуке
/*
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $update = json_decode(file_get_contents('php://input'), true);
    
    if (isset($update['pre_checkout_query'])) {
        $preCheckoutQuery = $update['pre_checkout_query'];
        $preCheckoutQueryId = $preCheckoutQuery['id'];
        $userId = $preCheckoutQuery['from']['id'];
        $orderInfo = $preCheckoutQuery['order_info'] ?? [];
        $totalAmount = $preCheckoutQuery['total_amount'];
        $currency = $preCheckoutQuery['currency'];
        $invoicePayload = $preCheckoutQuery['invoice_payload'];
        
        // Проверяем доступность товара и другие условия
        $isAvailable = checkProductAvailability($invoicePayload);
        
        if ($isAvailable) {
            // Всё хорошо, подтверждаем оплату
            answerPreCheckoutQuery($preCheckoutQueryId, true);
            
            // Помечаем заказ как ожидающий оплаты
            updateOrderStatus($invoicePayload, 'pending_payment');
        } else {
            // Товар недоступен, отказываем в оплате
            answerPreCheckoutQuery($preCheckoutQueryId, false, 
                'Извините, товар временно отсутствует на складе.');
        }
    }
}

function answerPreCheckoutQuery($queryId, $ok, $errorMessage = '') {
    global $botToken;
    
    $data = [
        'pre_checkout_query_id' => $queryId,
        'ok' => $ok
    ];
    
    if (!$ok && !empty($errorMessage)) {
        $data['error_message'] = $errorMessage;
    }
    
    $url = "https://api.telegram.org/bot{$botToken}/answerPreCheckoutQuery";
    
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => json_encode($data),
        CURLOPT_HTTPHEADER => ['Content-Type: application/json']
    ]);
    
    curl_exec($ch);
    curl_close($ch);
}
*/

?>

python

import asyncio
from telegram import Bot, Update
from telegram.ext import Application, PreCheckoutQueryHandler

# Инициализация бота
bot = Bot(token="YOUR_BOT_TOKEN")

# Пример обработки pre-checkout запроса
async def handle_pre_checkout_query(update: Update, context):
    query = update.pre_checkout_query
    
    # Проверяем возможность обработки платежа
    if is_payment_valid(query):
        # Подтверждаем успешную проверку
        await query.answer(ok=True)
    else:
        # Отклоняем с сообщением об ошибке
        await query.answer(
            ok=False,
            error_message="Извините, товар временно недоступен. Пожалуйста, попробуйте позже."
        )

# Вспомогательная функция для проверки платежа
def is_payment_valid(query):
    # Здесь должна быть ваша логика проверки:
    # - Доступность товара
    # - Корректность суммы
    # - Проверка пользователя и т.д.
    
    # Пример простой проверки
    if query.total_amount > 0:
        return True
    return False

# Пример использования в обработчике
async def main():
    # Создаем приложение
    application = Application.builder().token("YOUR_BOT_TOKEN").build()
    
    # Регистрируем обработчик pre-checkout запросов
    application.add_handler(PreCheckoutQueryHandler(handle_pre_checkout_query))
    
    # Запускаем бота
    await application.initialize()
    await application.start()
    await application.updater.start_polling()

# Альтернативный вариант - прямой вызов API
async def answer_pre_checkout_query_directly():
    # Прямой вызов метода answer_pre_checkout_query
    result = await bot.answer_pre_checkout_query(
        pre_checkout_query_id="UNIQUE_QUERY_ID",
        ok=True
    )
    
    # Или с ошибкой
    result = await bot.answer_pre_checkout_query(
        pre_checkout_query_id="UNIQUE_QUERY_ID",
        ok=False,
        error_message="Товар закончился на складе"
    )
    
    return result

# Запуск примера
if __name__ == "__main__":
    asyncio.run(main())

История изменений

  • API 3.0. Добавлен метод answerPreCheckoutQuery

Дополнительно

  • Update - Объект Update представляет входящее событие в Telegram Bot API, содержащее информацию о сообщениях, запросах, изменениях статуса участников и других действиях, связанных с ботом.
Комментарии