Обработчики платежной формы ЮKassa
28 сентября 2023Если в платежной форме есть кнопка submit – после нажатия на эту кнопку данные передаются в обработчик. Для WordPress этот процесс немного более сложный – форма должна содержать дополнительные поля и обработчик должен быть сделан особым образом.
Читаем статью – WordPress – получаем данные из формы.
Поскольку при срабатывании события submit формы страница сайта перегружается, лучше разделить обработчик на 2 части.
Обработчик JavaScript
Обработчик JavaScript – срабатывает при нажатии на кнопку подтверждения платежа. Производит валидацию полей, запускает php-обработчик, в зависимости от результата запроса к АПИ Юкасса или перенаправляет пользователя на платежную страницу ЮKassa или выводит на экран ошибку создания платежа.
Если валидация не проходит – вместо запуска php-обработчика, выводим сообщение об ошибке и ждем реакции пользователя. Пользователь исправляет ошибку и снова нажимает кнопку. Процесс повторяется, страница при этом не перегружается.
function vh_payment_submit() {
// ================ Валидация формы
if( !document.getElementById( 'pay-term' ).checked ) {
// чекбокс принятия условий платежа должен быть отмечен
document.querySelector( '#term-error' ).innerHTML = 'Пожалуйста, примите условия платежа';
return;
}
// ================= Валидация формы закончена
// Платежные данные из экранной формы
let paymentData = {
method: 'bank_card',
status: 'new',
amount: '100',
description: 'Здесь описание платежа',
site_url: document.location.href,
}
// вместо кнопки загружается анимированная картинка выполнения процесса
document.getElementById( "payment-button" ).innerHTML = '<img src="' + document.location.origin + '/wp-content/plugins/vh-payment/assets/load.gif">';
const url = "/vh-payment/yookassa-new-payment.php";
let fetch_options = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify( paymentData ), // Тело запроса в JSON-формате
}
fetch( url, fetch_options )
.then( function( response ) {
if ( response.ok ) {
return response.json();
} else {
throw new Error( 'Ошибка при выполнении запроса ' +
'(Err:' + response.status + ')'
);
}
})
.then( function( data ) {
// Запрос вернул данные
if( 'error' in data ) {
document.getElementById( "errors" ).innerHTML =
'<h3>' + data.error + '</h3>' +
'<span>' + data.details + '</span>';
}
if('redirectUrl' in data) {
// перенаправление на страницу платежа
window.location = data.redirectUrl;
}
} )
.catch( function( error ) {
// Обработка ошибок
document.getElementById( "errors" ).innerHTML = '<span>' + error + '</span>';
});
}
Обработчик php
Обработчик php – подключается к API ЮKassa, проверяет существование аккаунта магазина, формирует именованный массив с данными – платеж Юкасса, отправляет ЮKassa запрос и получает ответ, который возвращает в обработчик JavaScript.
<?php
// yookassa-new-payment.php - ajax обработчик экранной платежной формы
//
// Получаем входные данные из js обработчика формы
// vh-payment-form.js
$input = json_decode( file_get_contents( "php://input" ), true );
//
// ====================================================================== Здесь должна быть проверка наличия и корректности входных данных
//
// Считаем что данные пришли и корректны
//
// $_SERVER['DOCUMENT_ROOT'] => D:/Common/WebSerwer/OSPanel-5.3.7/domains/site.ru
$documentroot = $_SERVER['DOCUMENT_ROOT'];
// $wpconfig = $_SERVER['DOCUMENT_ROOT'] . '/wp-config.php';
// Подключение конфигурационного файла WordPress
require( $documentroot . '/wp-config.php' );
$yookassaShopId = get_option( 'yookassa_shop_id' );
$yookassaSecretKey = get_option( 'yookassa_secret_key' );
// Конфигурация
// магазина yookassa - $yookassaId/$yookassaKey
// CloudPayments - $cpId/$cpAPI
require( 'payment-config.php' );
// загрузка SDK yookassa
// $yookassalib = $documentroot . '/vh-payment/yookassa-sdk-php-master/lib/autoload.php';
// путь относительно текущего каталога site.ru\vh-payment\
$yookassalib = 'yookassa-sdk-php-master' . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'autoload.php';
//
// Здесь нужно проверить наличие библиотеки yookassa
//
require( $yookassalib );
use YooKassa\Client;
$yookassaClient = new Client();
// $yookassaClient->setAuth( $yookassaId.'a', $yookassaKey );
$yookassaClient->setAuth( $yookassaShopId, $yookassaSecretKey );
// $error = Array();
$payment = Array();
try {
// Информация о магазине
$response = $yookassaClient->me();
} catch (\Exception $e) {
// Ошибка подключения к магазину yookassa
$payment['error'] = 'Authorization yookassa';
// Ошибка $yookassaId
// -- Login has illegal format. Error code: invalid_credentials. Parameter name: Authorization.
// Ошибка $yookassaKey
// -- Error in shopId or secret key. Check their validity. You can reissue the key in the Merchant Profile. Error code: invalid_credentials.
// $error['details'] = $e->getMessage();
$payment['details'] = $e->getMessage();
die( json_encode( $payment ) );
}
// # подключаемся к базе данных WordPress
$connection = "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME;
try {
$DBH = new PDO( $connection, DB_USER, DB_PASSWORD );
$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
}
catch( PDOException $e ) {
echo "Хьюстон, у нас проблемы.";
// Error log file - https:\\site.ru\vh-payment\PDOErrors.txt
file_put_contents( 'PDOErrors.txt', $e->getMessage(), FILE_APPEND );
$payment['error'] = 'PDO';
$payment['details'] = $e->getMessage();
die( json_encode( $payment ) );
}
// таблица wp_payments
// $table_prefix определен в wp-config.php
$table_name = $table_prefix . 'payments';
$values = array();
foreach( $input as $key => $value ) {
// placeholder’s
$values[] = ':' . $key;
}
// Записывается информация о платеже - статус платежа - 'new'
// INSERT INTO `wp_payments`
// (system, transaction, status, amount, description, recurrent, email, payer, site_url, uniquie)
// values
// (:system, :transaction, :status, :amount, :description, :recurrent, :email, :payer, :site_url, :uniquie)
$sql = "INSERT INTO `" . $table_name . "` (" . join(', ', array_keys( $input )) . ") values (" . join( ', ', $values ) . ")";
$STH = $DBH->prepare( $sql );
$STH->execute( $input );
// получаем id добавленной записи (поле id в таблице БД)
$id = $DBH->lastInsertId();
//
// ========================================================================================================== Здесь создается платеж yooKassa
//
$paymentargs = [
'amount' => array(
'value' => intval( $input['amount'] ),
'currency' => 'RUB',
),
'payment_method_data' => array(
'type' => $input['method'],
),
'confirmation' => array(
'type' => 'redirect',
'return_url' => $input['redirect'] . '?id=' . $id,
),
'capture' => true,
'description' => $input['description'],
'metadata' => array(
'id' => $id,
'uniquie' => $input['uniquie'],
'email' => $input['email'],
'payer' => $input['payer'],
),
'merchant_customer_id' => $input['email'],
];
$paymentargs['save_payment_method'] = false;
if ( $input['recurrent'] == 'y' ) {
// рекуррентный платеж
$paymentargs['save_payment_method'] = true;
}
try {
// Формируется платеж - вернется объект платежа
$response = $yookassaClient->createPayment( $paymentargs, uniqid('', false) );
$sql = "UPDATE `" . $table_name . "` SET `transaction` = '" . $response->id . "', `status` = '" . $response->status . "' WHERE (`id` = '" . $id . "')";
$payment['id'] = $id;
$payment['transaction'] = $response->id;
$payment['redirectUrl'] = $response->getConfirmation()->getConfirmationUrl();
// // Платеж по QR коду
// $json['qrcode'] = '/payment/qrcode.php?url=' . base64_encode( $response->getConfirmation()->getConfirmationData() );
// $json['redirect'] = $response->getConfirmation()->getConfirmationData();
} catch (\Exception $e) {
$sql = "UPDATE `" . $table_name . "` SET `errorinfo` = '" . $e->getMessage() . "', `status` = 'error' WHERE (`id` = '" . $id . "')";
$payment['error'] = 'Payment yookassa';
$payment['details'] = $e->getMessage();
}
$STH = $DBH->prepare($sql);
$STH->execute();
die( json_encode( $payment ) );
Для упрощения некоторые части обработчика (типа валидации входных данных, отработка некоторых ошибок) отсутствуют.
Кроме формирования данных для платежа и запроса в Юкасса этот обработчик помещает платежную информацию в базу данных сайта. Это несколько усложняет скрипт зато дает возможность выводить для пользователя информацию по результатам платежа, вести статистику и собирать данные для дальнейшего использования в плагинах списка плательщиков, проведения компаний по сбору средств и т.д.
Если нет времени и желания разбираться самостоятельно – обращайтесь