Всем привет!
Еще совсем немного времени осталось до момента, когда статье о порядке подключения платежной системы к сайту на базе плагина WP-Recall исполнится пять лет. И хотя прежнее платежное API плагина позволило реализовать подключение к нескольким десяткам платежных систем, но все же имело ряд недостатков, которые не позволяли использовать в полной мере возможности, что предлагало API платежной системой.
Рад сообщить, что с версии 16.24 плагина WP-Recall, платежный функционал плагина был доработан и способен предложить более гибкий подход к реализации платежных форм и подключения к платежным системам. Данный функционал активно использует API произвольных полей плагина WP-Recall и без его знания работать с данным мануалом будет затруднительно.
В этой статье мы рассмотрим порядок реализации подключения к платежной системе.
Создаем свой класс
Как вам, скорее всего, известно, подключение к какой-либо платежной системе оформляется в виде дополнения к плагину WP-Recall, поэтому создаем папку дополнения и в файле index.php начинаем реализовывать свой класс, в котором будем описывать настройки нашего подключения и логику его работы. Работу можно начать с универсального шаблона:
class My_Gateway extends Rcl_Gateway_Core { function __construct() { //регистрационные данные подключения parent::__construct( array( 'request' => 'mymoney-request', //get- или post-параметр, по которому будем отлавливать запрос от платежной системы 'name' => 'MYMoney', //наименование платежной системы 'submit' => __( 'Payment via MYMoney' ), //надпись на окончательной кнопке оплаты 'icon' => rcl_addon_url( 'icon.jpg', __FILE__ ) //url до иконки платежной системы в папке дополнения ) ); } //указание опций подключения function get_options() { } //создание платежной формы function get_form( $data ) { } //обработка платежа function result( $process ) { } //проверка платежа и перенаправление //на страницы fail или successfull function success( $process ) { } }
Теперь опишем каждый метод по порядку.
Метод get_options()
Данный метод должен возвращать массив опций необходимых для дальнейшего использования при создании платежной формы и во время процедуры обработки запросов от платежной системы. Перечень необходимых опций напрямую зависит от API платежной системы, но могут присутствовать опции позволяющие, например, кастомизировать платежную форму, сменить наименование платежной системы или загрузить другую иконку для использования. Содержимое массива отдельной опции формируется согласно правил описанных в статье Подробно о произвольных полях WP-Recall. Пример метода с примерным содержимым массива опций:
function get_options() { return array( array( 'type' => 'text', 'slug' => 'mm_public_key', 'title' => __( 'Public Key' ) ), array( 'type' => 'password', 'slug' => 'mm_private_key', 'title' => __( 'Private Key' ) ), array( 'type' => 'select', 'slug' => 'mm_mode', 'title' => __( 'Режим работы' ), 'values' => array( __( 'Рабочий'), __( 'Тестовый') ) ) ); }
Каждую указанную через данный метод опцию можно получить с помощью функции
rcl_get_commerce_option('option_key', $defaultValue = false);
Метод get_form()
В этом методе создается платежная форма. По сути, необходимо сформировать массив полей формы и передать их во вспомогательный метод родительского класса - construct_form(). Массив полей платежной формы создается на основе текущего API платежной системы и установленных опций, заданных в методе get_options(). Как правило, массив полей формы состоит только из скрытых полей, поэтому поля в массиве могут указываться в виде ключ => значение, но если возникнет необходимость добавить поле другого типа, то его данные необходимо будет указывать как массив произвольного поля WP-Recall. Вот как может выглядеть создание платежной формы:
function get_form( $data ) { $fields = array( 'amount' => $data->pay_summ, 'currency' => $data->currency, 'description' => $data->description, 'order_id' => $data->pay_id, 'customer' => $data->user_id, 'public_key' => rcl_get_commerce_option( 'mm_private_key' ), 'mode' => rcl_get_commerce_option( 'mm_mode', 0 ), 'result_url' => get_permalink( $data->page_result ), 'success_url' => get_permalink( $data->page_success ), 'custom_field_baggage' => $data->baggage_data, 'custom_field_pay_type' => $data->pay_type ); return parent::construct_form( [ 'action' => 'https://www.payment-system-domen.com/checkout', 'fields' => $fields ] ); }
Метод get_form() принимает объект с параметрами платежа, которые потребуется использовать при создании формы:
- pay_summ - сумма платежа (обязательно к передаче)
- currency - валюта
- description - описание текущего платежа
- pay_type - тип платежа (обязательно к передаче)
- pay_id - внутренний идентификатор платежа (обязательно к передаче)
- user_id - идентификатор пользователя (обязательно к передаче)
- baggage_data - строка с произвольными данными платежа (обязательно к передаче)
- page_result - идентификатор страницы RESULT
- page_success - идентификатор страницы SUCCESS
- page_fail - идентификатор страницы FAIL
- page_successfully - идентификатор страницы успешного платежа
Некоторые из указанных данных обязательны к передаче на сторону платежной системы, после чего они должны быть возвращены платежной системой для обработки после совершения оплаты.
Если API платежной системы не позволяет возвратить хотя бы один из обязательных параметров, значит настроить полноценное взаимодействие с данной платежной системой не выйдет.
Некоторые параметры указанные нами в опциях на стороне сайта мы получаем с помощью функции rcl_get_commerce_option();
Сформированный массив полей необходимо будет передать в метод construct_form(), данный метод принимает массив параметров, необходимый для создания формы:
array( 'action', //параметр action тега form - url 'method', //параметр method тега форм - post или get 'fields', //массив с данными полей формы 'onclick', //указание атрибута onclick для кнопки отправки 'submit', //надпись на кнопке отправки );
Метод result()
Если форма была создана верно и платежная система приняла данные с нее без ошибок, то, как правило, после успешно оплаты, платежная система посылает уведомление с данными успешного платежа на обработку на стороне магазина. Метод result() должен содержать логику обработки такого уведомления. В этом методе, как правило, содержится сравнение данных платежа, проверка цифровой подписи и запись данных платежа в БД.
Для фиксации платежа в БД сайта необходимо обязательно принять перечень обязательных параметров, описанных выше, проверить по идентификатору платежа его наличие и в случае его отсутствия создать новый платеж, передав в метод insert_payment() массив с этими данными. Логика может быть реализована следующим образом:
function result( $data ) { //принимаем данные переданные платежной системой $pay_id = $_REQUEST['order_id']; $user_id = $_REQUEST['customer']; $pay_summ = $_REQUEST['amount']; $pay_type = $_REQUEST['custom_field_pay_type']; $baggage_data = $_REQUEST['custom_field_baggage_data']; //проверяем наличие платежа по идентификатору if ( ! parent::get_payment( $pay_id ) ) { //создаем новый платеж, передав массив с обязательными параметрами parent::insert_payment( array( 'pay_id' => $pay_id, 'pay_summ' => $pay_summ, 'user_id' => $user_id, 'pay_type' => $pay_type, 'baggage_data' => $baggage_data ) ); } //завершаем выполнение скрипта в любом случае echo "OK"; exit(); }
Метод result() принимает объект с данными, которые могут потребоваться при фиксации платежа.
Метод success()
Необязательный для применения метод, но может быть полезен, если платежная система позволяет перенаправлять пользователя на страницу успешной оплаты на сайте после успешного платежа, для этого на стороне платежной системы надо указать URL страницы SUCCESS. Если пользователь будет перенаправлен на эту страницу, то будет вызван метод success() и отработает логика внутри него. Как правило, внутри данного метода проверяется наличие платежа по переданному идентификатору и если его нет, то выводим соответствующее уведомление, если же все в порядке, то перенаправляем пользователя на страницу успешного платежа. Метод может выглядеть следующим образом:
function success( $data ) { //принимаем от платежной системы идентификатор платежа $pay_id = $_REQUEST['order_id']; //проверяем наличие платежа if ( parent::get_payment( $pay_id ) ) { wp_redirect( get_permalink( $data->page_successfully ) ); exit; } else { wp_die( 'Платеж не найден в базе данных!' ); } }
Итак, все необходимые для реализации методы были описаны, весь класс будет выглядеть так:
class My_Gateway extends Rcl_Gateway_Core { function __construct() { //регистрационные данные подключения parent::__construct( array( 'request' => 'mymoney-request', //get- или post-параметр, по которому будем отлавливать запрос от платежной системы 'name' => 'MYMoney', //наименование платежной системы 'submit' => __( 'Payment via MYMoney' ), //надпись на окончательной кнопке оплаты 'icon' => rcl_addon_url( 'icon.jpg', __FILE__ ) //url до иконки платежной системы в папке дополнения ) ); } //указание опций подключения function get_options() { return array( array( 'type' => 'text', 'slug' => 'mm_public_key', 'title' => __( 'Public Key' ) ), array( 'type' => 'password', 'slug' => 'mm_private_key', 'title' => __( 'Private Key' ) ), array( 'type' => 'select', 'slug' => 'mm_mode', 'title' => __( 'Режим работы' ), 'values' => array( __( 'Рабочий' ), __( 'Тестовый' ) ) ) ); } //создание платежной формы function get_form( $data ) { $fields = array( 'amount' => $data->pay_summ, 'currency' => $data->currency, 'description' => $data->description, 'order_id' => $data->pay_id, 'customer' => $data->user_id, 'public_key' => rcl_get_commerce_option( 'mm_private_key' ), 'mode' => rcl_get_commerce_option( 'mm_mode', 0 ), 'result_url' => get_permalink( $data->page_result ), 'success_url' => get_permalink( $data->page_success ), 'custom_field_baggage' => $data->baggage_data, 'custom_field_pay_type' => $data->pay_type ); return parent::construct_form( [ 'action' => 'https://www.payment-system-domen.com/checkout', 'fields' => $fields ] ); } //обработка платежа function result( $data ) { //принимаем данные переданные платежной системой $pay_id = $_REQUEST['order_id']; $user_id = $_REQUEST['customer']; $pay_summ = $_REQUEST['amount']; $pay_type = $_REQUEST['custom_field_pay_type']; $baggage_data = $_REQUEST['custom_field_baggage_data']; //проверяем наличие платежа по идентификатору if ( ! parent::get_payment( $pay_id ) ) { //создаем новый платеж, передав массив с обязательными параметрами parent::insert_payment( array( 'pay_id' => $pay_id, 'pay_summ' => $pay_summ, 'user_id' => $user_id, 'pay_type' => $pay_type, 'baggage_data' => $baggage_data ) ); } //завершаем выполнение скрипта в любом случае echo "OK"; exit(); } //проверка платежа и перенаправление //на страницы fail или successfull function success( $data ) { //принимаем от платежной системы идентификатор платежа $pay_id = $_REQUEST['order_id']; //проверяем наличие платежа if ( parent::get_payment( $pay_id ) ) { wp_redirect( get_permalink( $data->page_successfully ) ); exit; } else { wp_die( 'Платеж не найден в базе данных!' ); } } }
Нам останется только зарегистрировать наше подключение в системе WP-Recall. Делается это следующим образом:
add_action( 'rcl_payments_gateway_init', 'rcl_add_mymoney_gateway' ); function rcl_add_mymoney_gateway() { //указываем идентификатор платежной системы и //наименование созданного класса с логикой обработки платежа rcl_gateway_register( 'mymoney', 'My_Gateway' ); }
В принципе, этих действий достаточно, чтобы создать подключение к любой платежной системе или агрегатору, но API платежной системы зачастую позволяет получать дополнительные параметры, которые будут влиять на поведение платежной системы после перехода пользователя на ее страницу. Например, мы можем указать в платежной форме явно платежную систему, которая будет предложена пользователю сразу, без необходимости выбора из перечня на стороне платежной системы. Платежное API плагина WP-Recall позволяет учитывать эти возможности и строить платежные формы с их учетом.
Добавление динамических полей в платежную форму
Например, мы знаем, что платежный агрегатор может предложить три способа оплаты:
- 'cards' - банковские карты
- 'mobile' - мобильные платежи
- 'bitcoin' - криптовалюты
и если через платежную форму передать один из этих параметров, то на странице платежной системы пользователь сразу увидит нужный вариант оплаты.
Мы можем предложить выбор нужного варианта оплаты на нашем сайте, дополнив платежную форму соответствующим полем:
$fields = array( [ 'type' => 'radio', 'slug' => 'payment_case', 'title' => __( 'Выберите способ оплаты' ), 'values' => [ 'cards' => __( 'Банковские карты' ), 'mobile' => __( 'Мобильные платежи' ), 'bitcoin' => __( 'Криптовалюты' ) ] ], 'amount' => $data->pay_summ, 'currency' => $data->currency, 'description' => $data->description, 'order_id' => $data->pay_id, 'customer' => $data->user_id, 'public_key' => rcl_get_commerce_option( 'mm_private_key' ), 'mode' => rcl_get_commerce_option( 'mm_mode', 0 ), 'result_url' => get_permalink( $data->page_result ), 'success_url' => get_permalink( $data->page_success ), 'custom_field_baggage' => $data->baggage_data, 'custom_field_pay_type' => $data->pay_type );
Теперь пользователь может выбрать способ оплаты еще на сайте, а платежная система получить параметр payment_case с указанием определенного способа оплаты и сразу предложить пользователю перейти к оплате этим способом.
Подобным образом, мы можем строить сложные формы, передавая платежной системе нужные параметры динамически.
Но очень часто, платежная система предлагает строить цифровую подпись с учетом всех передаваемых параметров, а это значит, что у нас не выйдет передать динамически формируемый параметр, значение которого зависит от выбора пользователя, в алгоритм формирования цифровой подписи. Специально для подобных случаев, у нас есть возможность строить предварительные платежные формы, где пользователь будет выбирать параметры, которые затем будут участвовать в построении цифровой подписи для окончательной платежной формы.
Такие параметры необходимо передавать в специальном методе - get_pre_form_fields(); Это может выглядеть так:
function get_pre_form_fields( $data ) { return [ [ 'type' => 'radio', 'slug' => 'payment_case', 'title' => __( 'Выберите способ оплаты' ), 'values' => [ 'cards' => __( 'Банковские карты' ), 'mobile' => __( 'Мобильные платежи' ), 'bitcoin' => __( 'Криптовалюты' ) ] ], [ 'type' => 'select', 'slug' => 'return_url', 'title' => __( 'Страница возврата' ), 'values' => [ '' => __( 'По-умолчанию' ), 'https://domen.com/page' => __( 'Текущая страница' ), 'user_office' => __( 'В личный кабинет' ) ] ] ]; }
Если мы передадим массив полей через метод get_pre_form_fields(), то кнопка оплаты через нашу платежную систему не будет сразу перенаправлять пользователя на платежную систему, а вызовет предварительную форму с этими полями. Указав нужные параметры в этой форме пользователь вызовет уже конечную форму, в алгоритм формирования которой будут переданы данные с этих полей, а именно в методе get_form() мы сможем получить их из массива $_POST и использовать для формирования цифровой подписи или других целей.
Примером такой формы может послужить форма пополнения баланса, в ней мы можем динамически указать сумму платежа и нужное подключение для оплаты, а уже после этих действий мы получаем готовую кнопку на оплату.
В конце, после реализации нашего класса, мы можем оформить наш код в дополнение к плагину WP-Recall и начинать распространять его. Порядок оформления дополнения подробно описан в статье.
Конечно, данный мануал предполагает хотя бы небольшой опыт в реализации подключений к платежным системам, понимания логики их реализации и может вызвать трудности у новичков. Не стесняйтесь задавать вопросы, буду рад ответить на них. При необходимости создавайте тему на форуме, если требуется более глубокое изучение вашей проблемы.
Комментариев (0)