Создание способа оплаты через модуль¶
Способ оплаты — это группа нескольких PHP- и TPL-файлов, а также записи в таблице payment_processors
.
Поля таблицы payment_processors¶
processor (string) — поле с названием способа оплаты. Для всех языков будет отображаться одинаково, но лучше заполнять его латинскими символами.
processor_script (string) — название PHP-файла, в котором описана логика работы процессора нового способа оплаты.
Примечание
Укажите только название файла, например, foo_bar.php. Указывать директории или другие символы не нужно. По умолчанию этот файл запускается из директории app/payments. А если название модуля указать в поле addon в таблице
payment_processors
, то файл будет запускаться из директории app/addons/{$addon_name}/payments, где $addon_name - название модуля.processor_template (string) — это относительный путь без первого слэша (/) к TPL-файлу шаблона, который отображается для покупателя, создающего заказ. Путь должен быть относителен директории design/themes/{$theme_name}/templates. Например:
views/orders/components/payments/cc.tpl
.Если способу оплаты нужен разработанный с нуля шаблон, укажите к нему путь в модуле. Например, вот так выглядит путь к шаблону модуля PayPal:
addons/paypal/views/orders/components/payments/paypal_express.tpl
.В директории design/themes/responsive/templates/views/orders/components/payments находятся шаблоны темы responsive. Используйте их в качестве основы или примера, указав путь к шаблону в поле processor_template.
admin_template (string) — это название TPL-файла шаблона, который появляется при создании и редактировании способа оплаты в отдельной вкладке. Этот шаблон содержит поля и формы, где администраторы указывают параметры способа оплаты, например, токены и т.п.
Примечание
Укажите название TPL-файла без директории и других символов. Например: foo_processor_template.tpl. По умолчанию этот файл запускается из директории design/backend/templates/views/payments/components/cc_processors.
Если способ оплаты добавлен модулем, и поле addon в таблице
payment_processors
заполнено корректно, файл будет запускаться из директории design/backend/templates/addons/{$addon_name}/views/payments/components/cc_processors; где{$addon_name}
— название модуля.callback (ENUM(‘Y’,’N’)) — определяет, как сработает оплата заказа:
Y — способ оплаты отправит запрос на сервер, где обрабатывается заказ, без перенаправления покупателя на этот сервер. Например, так можно сделать с помощью cURL.
Подсказка
Так работают PayPal Pro и Authorize.Net.
N — покупателя, который оставляет заказ, перенаправит на сторону сервера, где обрабатывается заказ, чтобы совершить оплату.
Подсказка
Так работают способы оплаты DPS PX Access и Player.
type (ENUM(‘P’,’C’,’B’)) — определяет, где именно появится шаблон, указанный в поле processor_template.
P (Payment gateway - Платёжный шлюз) — шаблон появится в секции “Способы оплаты” на странице оформления заказа.
Подсказка
Страница оформления заказа находится здесь:
dispatch=checkout.checkout
.C (Checkout - Оформление заказа) — шаблон появится в качестве кнопки оплаты в корзине.
Подсказка
Корзина находится здесь:
dispatch=checkout.cart
.B (Both - Оба) — шаблон появится в обоих местах.
- addon (string) — идентификатор модуля, добавляющего способ оплаты (например,
paypal
). Если модуль выключен или не установлен, тогда способы оплаты, использующие этот модуль, не появятся на витрине, а при создании нового способа оплаты, этот процессор не будет доступен.
- addon (string) — идентификатор модуля, добавляющего способ оплаты (например,
Скрипт обработки платежей¶
Используем в качестве примера скрипт процессора с типом callback = "N"
.
Логическое ядро способа оплаты — PHP-файл, указанный в поле processor_script в таблице payment_processors
. Это обычный скрипт, подключенный через директиву include
. После этого подключения выполняется содержимое файла.
Этот файл используют в двух разных сценариях, поэтому он включает в себя алгоритм с логическим разветвлением, которое позволяет запускать только часть скрипта, в зависимости от контекста (т.е. от того, зачем он запущен).
В следующем примере скрипт находится в директории app/addons/sample_payment/payments. Назовем его sample_payment_processor.php и добавим минимально необходимый для работы скрипта код:
<?php
// app/addons/sample_payment/payments/sample_payment_processor.php — директория файла.
// Запрещаем обращение к скрипту напрямую, он должен быть включен через директиву "include". Константа "BOOTSTRAP" объявляется во время запуска.
defined('BOOTSTRAP') or die('Access denied');
// Есть два разных сценария для запуска скрипта.
if (defined('PAYMENT_NOTIFICATION')) {
/**
* Получение и обработка ответа от сторонних
* платежных сервисов и систем оплаты.
*/
} else {
/**
* Запуск необходимой для принятия платежей логики,
* после того как клиент нажмет кнопку "Создать заказ".
*/
}
Рассмотрим оба возможных сценария использования скрипта.
Запуск логики, необходимой для принятия платежа, после нажатия кнопки “Оформить зака甶
Скрипт подключается после того, как создается заказ (т.е. после создания записи о заказе в таблице orders
). Вот типичные задачи, которые выполняет скрипт в контексте этого сценария:
- Проверка данных, введенных покупателем при создании заказа. Например, проверка срока действия банковской карты, указанной покупателем.
- Смена статуса заказа на Неудавшийся, если данные не прошли проверку.
- Сбор и подготовка данных к отправке на сервер сторонней платёжной системы.
- Сбор одноразовых токенов и ключей доступа от платёжных систем.
- Создание URL, на которую будет перенаправлен клиент после того, как будут произведены необходимые действия на сайте платёжной системы.
- Перенаправление покупателя на сайт платёжной системы, чтобы подтвержить платёж и/или дополнить предоставленные данные.
Процессы, которые происходят до и после выполнения скрипта обработки платежей¶
Покупатели выбирают способ оплаты и нажимают на кнопку “Создать заказ”. Это отправляет POST-запрос к
index.php?dispatch=checkout.place_order
.Выполняется контроллер
checkout.place_order
, обращаясь к функцииfn_checkout_place_order()
. Помимо других аргументов, эта функция принимает массив$_REQUEST
. Если функция находит элемент с ключомpayment_info
в массиве$_REQUEST['payment_info']
, то она копирует значение этого элемента в массив$cart
с таким же ключом$cart['payment_info']
. Это позволяет скрипту работать с данными, введенными клиентами во время выбора способа оплаты. Поля для этих данных указываются в шаблоне processor_template.После этого функция проводит проверки, необходимые перед созданием заказа, и создает заказ со статусом Незавершенный по умолчанию. Этот статус обозначается буквой
N
в базе данных.Процесс оплаты начинается с вызова функции
fn_start_payment()
. Во время работы функции объявляются следующие переменные, которые потом можно использовать в скрипте способа оплаты:$order_id (integer) — уникальный идентификатор созданного заказа.
$order_info (array) — подробная информация о заказе.
Подсказка
Эта информация возвращается функцией
fn_get_order_info()
.$processor_data (array) — информация о способе оплаты.
Подсказка
Эта информация возвращается функцией
fn_get_processor_data()
.
- После скрипт обработки платежей подключается и выполняется директивой
include
. В скрипте должна объявляться переменная
$pp_response
, которая позже используется в функцииfn_start_payment()
и передается в обращении к функцииfn_finish_payment()
.
- После скрипт обработки платежей подключается и выполняется директивой
Получение и обработка ответа от сторонних сервисов и платёжных систем¶
В этом сценарии скрипт обрабатывает HTTP-запрос, отправленный платёжной системой. Например, запрос на возвращение клиента на сайт магазина либо другие запросы, отправленные сервером платёжной системы.
Контроллер payment_notification (с параметром callback = "N"
) как раз принимает такие запросы. Два из них — обязательные GET параметры:
- mode (string) — цель запроса, описанная в свободной форме. Значение этого параметра будет в переменной
$mode
в скрипте обработки платежей. Значения могут быть такими: success, error, redirect, и т.д. - payment (string) — название исполняемого файла скрипта оплаты. В названии не нужно указывать расширение .php, например, можно указать sample_payment_processor.
Процессы, происходящие при выполнении контроллера payment_notification:
- Объявляется константа
PAYMENT_NOTIFICATION
; её значение —true
. Это позволяет провести различие между двумя сценариями выполнения алгоритма. - Проверяется, активен ли способ оплаты, использующий платежный процессор, переданный в параметре GET.
- Скрипт обработки платежей включается с помощью директивы
include
.
Пример скрипта обработки платежей¶
Создадим скрипт обработки платежа с параметрами callback = "N"
и type = "P"
. Он будет перенаправлять покупателя на сервер платёжной системы, и способ оплаты появится в секции Способы оплаты на странице оформления заказа.
Начнем с создания файла sample_payment_processor.php в директории app/addons/sample_payment/payments и добавим минимальный необходимый код для его работы:
<?php
// Запрещаем прямой доступ к скрипту, потому что он должен быть включен директивой "include".
defined('BOOTSTRAP') or die('Access denied');
// Два различных контекста выполнения скрипта
if (defined('PAYMENT_NOTIFICATION')) {
/**
* Получение и обработка ответа от сторонних
* платежных сервисов и систем оплаты.
*
* Доступные переменные:
* @var string $mode цель запроса
*/
} else {
/**
* Запуск необходимой для принятия платежей логики,
* после того как клиент нажмет кнопку "Создать заказ".
*
* Доступные переменные:
*
* @var array $order_info Полная информация о заказе
* @var array $processor_data Информация о обработчике платежа
*/
}
Например, добавим следующий код:
<?php
// Запрещаем прямой доступ к скрипту, потому что он должен быть включен директивой "include".
defined('BOOTSTRAP') or die('Access denied');
// Два различных контекста выполнения скрипта
if (defined('PAYMENT_NOTIFICATION')) {
fn_print_r("Обработка платежа");
} else {
fn_print_r("Отправка данных");
}
Теперь, если на странице оформления заказа выбрать способ оплаты с этим скриптом обработки платежей и нажать “Создать заказ”, мы увидим распечатанные сообщения “Обработка платежа”, а после — “Отправка данных”. Можно также использовать код любого способа оплаты из директории app/payments как пример.
Добавляем описание для процессора способа оплаты¶
Можно добавить описание к процессору способа оплаты, которое появится в поле Processor, когда создаете способ оплаты на странице Администрирование → Способы оплаты.
Описание процессора обработки платежей — это динамически формирующаяся языковая переменная в таблице
language_values
.
Название языковой переменной — processor_description_{$processor_script}; где {$processor_script}
— это значение поля processor_script в таблице payment_processors
без указания расширения .php.
Например, если значением processor_script будет foo_bar_processor.php, то название языковой переменной будет таким: processor_description_foo_bar_processor.
После добавления этой языковой переменной с описанием процессора способа оплаты в таблицу language_values
описание процессора foo_bar_processor появится в Панели администратора.
Значения языковых переменных можно редактировать следующими тремя способами: * в Панели администратора на странице Тексты и языки → Редактировать тексты;
- SQL-запросом к таблице
language_values
во время установки модуля; - через миграцию.
Режим IFRAME для процессора платежей¶
Некоторые процессоры позволяют взаимодействовать с платёжными шлюзами с помощью встроенной iframe страницы. При использовании iframe покупателю не нужно покидать сайт магазина.
Примечание
Посмотрите на Skrill QuickCheckout (skrill_qc.php) и Skrill eWallet (skrill_ewallet.php) в app/payments — эти процессоры поддерживают iframe mode. Есть также пример такого модуля на GitHub.
Для работы в режиме iframe платежный процессор должен иметь параметр iframe_mode
со значением Y
.
Вот пример:
<input
type="hidden"
name="payment_data[processor_params][iframe_mode]"
value="Y"
/>
При выборе оплаты через iframe на странице оформления заказа, кнопка Создать заказ и процессоры в файле checkout.post.php не работают. Из-за этого также покупатель не сможет подписаться на рассылку на этой странице.
Обычно для идентификации заказа используется order_id
, но так как в этом случае он ещё не создан, то ему присваивается случайное одноразовое число. Таким образом из константы TIME
и user_id
генерируется “одноразовый” номер заказа.
- Платежный шлюз в iframe загружается через режим
process_payment
контроллера checkout.php, где скрипт процессора подключается с помощью директивыinclude
. - Скрипт обработки платежей отправляет всю необходимую информацию платежному шлюзу, включая одноразовый номер заказа и идентификатор сессии.
- Как только получено уведомление об оплате от шлюза, заказ размещается, и информация о заказе извлекается из сеанса.
- После получения уведомления об оплате нужно выбрать следующие действия:
- разместить заказ вручную;
- связать одноразовый номер заказа с
order_id
;
Вот такие записи будут добавлены в таблицу order_data
, когда будет получено уведомление payment_notification
:
order_id | тип | данные |
---|---|---|
Идентификатор созданного заказа | S | Константа TIME |
Идентификатор созданного заказа | Е | Одноразовый номер заказа |