В данном примере рассматривается процесс формирования скрытой формы на оплату с автоматическим перенаправлением, исходя из предоставленных параметров. При открытии страницы с данным кодом плательщик будет перенаправлен на страницу оплаты для завершения транзакции.
1 2 3 4 5 6 7 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 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
<!DOCTYPE html> <html lang="ru"> <head> <meta charset="utf-8" /> <title>Форма оплаты</title> </head> <body> <h1>Идёт перенаправление на оплату...</h1> <div id="paymentFormContainer"></div> <script> // Ссылка формы оплаты Paykeeper const url = 'https://xxxxxxxx.server.paykeeper.ru/create'; // Данные клиента let name = 'Иванов Иван Иванович'; let email = 'mail@example.com'; let phone = '+79630000000'; // Номер заказа const orderId = 9999; // Массив товаров в заказе const basket = [ { name: 'Тортилья, 20 см, 756 г', count: '5', price: '381.00' } ]; // Собираем массив товаров для paykeeper // https://docs.paykeeper.ru/onlain-kassa-54-fz/tovary-v-cheke-54-fz-full/ let total = 0; const prods = []; for (let i = 0; i < basket.length; i++) { const row = basket[i]; prods.push({ name: row.name, price: row.price, quantity: row.count, sum: parseFloat(row.price) * parseInt(row.count), tax: 'none', item_type: 'goods' }); total += parseFloat(row.price) * parseInt(row.count); } // Доставка prods.push({ name: 'Доставка', price: 300, quantity: 1, sum: 300, tax: 'none', item_type: 'service' }); total += 300; // Необязательные данные для чека const receiptProps = { agent: { // агент type: 'other', phones: ['+74012965000'], operation: 'Наименование операции платёжного агента или субагента', inn: '39006320200', name: 'ООО ОПЕРАТОР АГЕНТ', }, supplier: { // поставщик phones: ['+74012965055'], inn: '39006320245', name: 'ООО ПОСТАВЩИК', }, client: { // плательщик identity: 'ООО ПЛАТЕЛЬШИК', inn: '39006320245', }, }; // Формируем массив данных для полей формы оплаты const fields = [ { name: 'sum', value: total }, { name: 'clientid', value: name }, { name: 'orderid', value: orderId }, { name: 'client_email', value: email }, { name: 'client_phone', value: phone }, { name: 'cart', value: JSON.stringify(prods) }, { name: 'receipt_properties', value: JSON.stringify(receiptProps) }, { name: 'service_name', value: 'Оплата заказа № ' + orderId }, { name: 'lang', value: 'ru' } ]; // Функция создания и отправки скрытой формы оплаты function createAndSubmitPaymentForm(url, fields) { const form = document.createElement('form'); form.method = 'POST'; form.action = url; fields.forEach(field => { const input = document.createElement('input'); input.type = 'hidden'; input.name = field.name; input.value = field.value; form.appendChild(input); }); document.getElementById('paymentFormContainer').appendChild(form); form.submit(); // Автоматически отправляем форму } // Вызываем функцию для создания и отправки формы window.onload = createAndSubmitPaymentForm(url, fields); </script> </body> </html> |
После открытия страницы пользователь будет направлен на страницу оплаты.
Тот же пример с использованием библиотеки jQuery:
1 2 3 4 5 6 7 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 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
<!DOCTYPE html> <html lang="ru"> <head> <meta charset="utf-8" /> <title>Форма оплаты</title> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> </head> <body> <h1>Идёт перенаправление на оплату...</h1> <div id="paymentFormContainer"></div> <script> // Ссылка формы оплаты Paykeeper const url = 'https://tr-cms-dev.server.paykeeper.ru/create'; // Данные клиента let name = 'Иванов Иван Иванович'; let email = 'mail@example.com'; let phone = '+79630000000'; // Номер заказа const orderId = 9999; // Массив товаров в заказе const basket = [ { name: 'Тортилья, 20 см, 756 г', count: '5', price: '381.00' } ]; // Собираем массив товаров для paykeeper // https://docs.paykeeper.ru/onlain-kassa-54-fz/tovary-v-cheke-54-fz-full/ let total = 0; const prods = []; basket.forEach(row => { prods.push({ name: row.name, price: row.price, quantity: row.count, sum: parseFloat(row.price) * parseInt(row.count), tax: 'none', item_type: 'goods' }); total += parseFloat(row.price) * parseInt(row.count); }); // Доставка prods.push({ name: 'Доставка', price: 300, quantity: 1, sum: 300, tax: 'none', item_type: 'service' }); total += 300; // Необязательные данные для чека const receiptProps = { agent: { // агент type: 'other', phones: ['+74012965000'], operation: 'Наименование операции платёжного агента или субагента', inn: '39006320200', name: 'ООО ОПЕРАТОР АГЕНТ', }, supplier: { // поставщик phones: ['+74012965055'], inn: '39006320245', name: 'ООО ПОСТАВЩИК', }, client: { // плательщик identity: 'ООО ПЛАТЕЛЬШИК', inn: '39006320245', }, }; // Формируем массив данных для скрытой формы оплаты const fields = [ { name: 'sum', value: total }, { name: 'clientid', value: name }, { name: 'orderid', value: orderId }, { name: 'client_email', value: email }, { name: 'client_phone', value: phone }, { name: 'cart', value: JSON.stringify(prods) }, { name: 'receipt_properties', value: JSON.stringify(receiptProps) }, { name: 'service_name', value: 'Оплата заказа № ' + orderId }, { name: 'lang', value: 'ru' } ]; // Функция создания и отправки скрытой формы оплаты function createAndSubmitPaymentForm(url, fields) { const $form = $('<form>', { method: 'POST', action: url }); fields.forEach(field => { $('<input>', { type: 'hidden', name: field.name, value: field.value }).appendTo($form); }); $('#paymentFormContainer').append($form); $form.submit(); // Автоматически отправляем форму } // Вызываем функцию для создания и отправки формы $(document).ready(function () { createAndSubmitPaymentForm(url, fields); }); </script> </body> </html> |
На языке JavaScript периодический опрос статуса счёта можно реализовать следующим образом:
1 2 3 4 5 6 7 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 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Проверка статуса оплаты</title> </head> <body> <h1>Проверка статуса оплаты</h1> <div id="statusMessage">Проверяем статус...</div> <script> // Номер счёта для проверки const invoiceId = "20140402085214805"; // URL для запроса. // На стороне сервера должен быть реализован скрипт опроса данных счёта // https://docs.paykeeper.ru/dokumentatsiya-json-api/scheta/#3.1 const endpoint = `/check_payment_status?id={invoiceId}`; // Лимит попыток const maxAttempts = 10; // Интервал опроса (в миллисекундах) const pollInterval = 10000; let attemptCount = 0; // Счётчик попыток let polling; // Ссылка на таймер // Функция проверки статуса оплаты function checkPaymentStatus() { fetch(endpoint) .then(response => { if (!response.ok) { throw new Error(`Ошибка HTTP: ${response.status}`); } return response.json(); }) .then(data => { // Проверяем ответ if (data.result) { // Обработка ошибки, если счёт не найден updateStatusMessage(`Ошибка: ${data.msg}`); stopPolling(); } else if (data.id) { const status = data.status; // Логика обработки статусов if (['created', 'sent'].includes(status)) { updateStatusMessage("Счёт в процессе оплаты..."); } else if (status === 'paid') { updateStatusMessage("Счёт успешно оплачен."); stopPolling(); } else if (status === 'expired') { updateStatusMessage("Срок действия счёта истёк."); stopPolling(); } else { console.log("Неизвестный статус:", status); } } else { console.error("Некорректный формат ответа от сервера."); } }) .catch(error => { console.error("Ошибка запроса:", error); }); } // Функция обновления статуса на странице function updateStatusMessage(message) { const statusDiv = document.getElementById("statusMessage"); statusDiv.textContent = message; } // Функция остановки опроса function stopPolling() { if (polling) { clearInterval(polling); polling = null; } } // Функция начала опроса function startPolling() { polling = setInterval(() => { attemptCount++; if (attemptCount > maxAttempts) { updateStatusMessage("Лимит попыток исчерпан. Проверьте статус позже."); stopPolling(); } else { console.log(`Попытка №${attemptCount}`); checkPaymentStatus(); } }, pollInterval); } // Начинаем опрос при загрузке страницы document.addEventListener("DOMContentLoaded", () => { updateStatusMessage("Начинаем проверку статуса..."); startPolling(); }); </script> </body> </html> |
Полный перечень параметров в ответе на запрос получения данных счёта можно посмотреть здесь.
Тот же пример с использованием библиотеки jQuery:
1 2 3 4 5 6 7 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 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Проверка статуса оплаты</title> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> </head> <body> <h1>Проверка статуса оплаты</h1> <div id="statusMessage">Проверяем статус...</div> <script> $(document).ready(function () { // Номер счёта для проверки const invoiceId = "20140402085214805"; // URL для запроса. // На стороне сервера должен быть реализован скрипт опроса данных счёта // https://docs.paykeeper.ru/dokumentatsiya-json-api/scheta/#3.1 const endpoint = `/check_payment_status?id={invoiceId}`; // Лимит попыток const maxAttempts = 10; // Интервал опроса (в миллисекундах) const pollInterval = 10000; let attemptCount = 0; // Счётчик попыток let polling; // Ссылка на таймер // Функция проверки статуса оплаты function checkPaymentStatus() { $.ajax({ url: endpoint, method: "GET", dataType: "json", success: function (data) { // Проверяем ответ if (data.result) { // Обработка ошибки, если счёт не найден updateStatusMessage(`Ошибка: ${data.msg}`); stopPolling(); } else if (data.id) { const status = data.status; // Логика обработки статусов if (['created', 'sent'].includes(status)) { updateStatusMessage("Счёт в процессе оплаты..."); } else if (status === 'paid') { updateStatusMessage("Счёт успешно оплачен."); stopPolling(); } else if (status === 'expired') { updateStatusMessage("Срок действия счёта истёк."); stopPolling(); } else { console.log("Неизвестный статус:", status); } } else { console.error("Некорректный формат ответа от сервера."); } }, error: function (jqXHR, textStatus, errorThrown) { console.error(`Ошибка запроса: {textStatus}`, errorThrown); } }); } // Функция обновления статуса на странице function updateStatusMessage(message) { $("#statusMessage").text(message); } // Функция остановки опроса function stopPolling() { if (polling) { clearInterval(polling); polling = null; } } // Функция начала опроса function startPolling() { polling = setInterval(function () { attemptCount++; if (attemptCount > maxAttempts) { updateStatusMessage("Лимит попыток исчерпан. Проверьте статус позже."); stopPolling(); } else { console.log(`Попытка №${attemptCount}`); checkPaymentStatus(); } }, pollInterval); } // Начинаем опрос при загрузке страницы updateStatusMessage("Начинаем проверку статуса..."); startPolling(); }); </script> </body> </html> |
Пример серверного скрипта на PHP с запросом получения данных счёта, к которому обращается JavaScript (jQuery):
1 2 3 4 5 6 7 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 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
<?php // Данные для авторизации $server = 'https://xxxxxxxx.server.paykeeper.ru'; $uri = '/info/invoice/byid/'; $user = 'admin'; $password = 'xxxxxxxx'; $base64 = base64_encode("$user:$password"); header('Content-Type: application/json'); // Проверяем наличие параметра id счёта при запросе от JavaScript (jQuery) if (!isset($_GET['id']) || empty($_GET['id'])) { http_response_code(400); echo json_encode(['error' => 'Параметр id обязателен.']); exit; } // Получаем id из GET-запроса $invoiceId = htmlspecialchars($_GET['id']); try { // Инициализация cURL $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $server . $uri . "?id=" . urlencode($invoiceId)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: Basic ' . $base64 ]); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $response = curl_exec($ch); // Проверяем ошибки if (curl_errno($ch)) { throw new Exception('Ошибка запроса: ' . curl_error($ch)); } // Получаем HTTP-код ответа $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode === 200) { $data = json_decode($response, true); // Если формат ответа корректный if (json_last_error() === JSON_ERROR_NONE) { echo json_encode($data); } else { throw new Exception('Некорректный JSON в ответе: ' . json_last_error_msg()); } } else { throw new Exception('API вернул код ошибки: ' . $httpCode); } } catch (Exception $e) { // Обрабатываем ошибки и возвращаем ответ с кодом 500 http_response_code(500); echo json_encode(['error' => $e->getMessage()]); } |
Менеджер перезвонит вам и расскажет про детали подключения