Разработка плагина оплаты

Содержание...

Плагины оплаты предназначены для организации процесса оплаты на сайте. Возможность оплаты предоставляется в виде страницы, содержимое которой позволяет покупателю выполнить действия, необходимые для совершения оплаты, например, заполнить форму на специальной странице сайта (интернет-магазина) или перейти на сайт платежной системы.

Во фреймворке Webasyst основа для разработки плагинов оплаты поддерживается на уровне ядра. Фреймворк предоставляет набор методов и определенный формат получения плагинов данных о заказе и обработки обратных запросов со стороны серверов платежных систем. Плагины оплаты реализованы на уровне ядра фреймворка, а не конкретного приложения. Это позволяет использовать функциональность плагинов любым установленным приложениям (например, Shop-Script).

В качестве примера посмотрите исходный код плагина оплаты WebMoney (GitHub-репозиторий).

Исходный код плагинов оплаты находится в директории wa-plugins/payment/. Каждый плагин представляет собой отдельную поддиректорию с реализацией класса, унаследованного от базового класса waPayment и реализующего интерфейсы waIPayment, waIPaymentCapture, waIPaymentRefund, waIPaymentCancel, представляющие собой шаблоны публичных методов payment(), capture(), cancel() и refund() ­для обработки соответствующих типов платежных транзакций (если поддерживаются соответствующей платежной системой; в противном случае они должны возвращать код ошибки).

Наименование поддиректории с файлами плагина является его уникальным идентификатором, который используется в формировании правильного имени класса плагина. Ниже приведен пример таких наименований для некоторого плагина с идентификатором YourPayment:

wa-plugins/payment/yourpayment/lib/yourpaymentPayment.class.php

<?php

class yourpaymentPayment extends waPayment
{

...

}

Помимо основного класса, производного от waPayment, для работы плагина также требуются конфигурационные файлы, которые, как в приложениях и плагинах, размещаются в поддиректории lib/config/ (см. ниже описание конфигурационных файлов плагина оплаты).

В целом процесс разработки плагина оплаты сходен с написанием плагина для приложения, но, в отличие от написания плагина приложения, в случае с плагином оплаты часто достаточно реализовать лишь один или несколько основных методов единственного класса.

Методы

В методах основного класса плагина для получения значений полей настроек плагина, описанных в конфигурационном файле lib/config/settings.php, используйте доступ к приватным полям вида $this->field_name. Вместо field_name указывайте идентификатор поля настроек, значение которого необходимо получить.

payment()

Этот метод формирует основное содержимое страницы, с помощью которой покупатель может ввести данные, необходимые для совершения оплаты (например, реквизиты для выставления банковского счета), либо перейти на защищенную страницу платежной системы. В последнем случае для перехода часто используется форма со скрытыми элементами, содержимое которой отправляется на удаленный сервер при нажатии на кнопку или ссылку.

Следующие методы необходимы, если плагин оплаты предназначен для интеграции с платежной системой, поддерживающей обратные запросы в адрес сайта (интернет-магазина), например, для проверки правильности данных, переданных через платежную форму с сайта и для передачи каких-либо дополнительных данных, например, статуса платежной транзакции, совершенной покупателем на сайте платежной системы.

callbackInit()

Этот метод позволяет извлечь из содержимого либо параметров адреса ответа платежной системы информацию о приложении, которому необходимо передать обработку, а также параметры, указанные в настройках плагина оплаты в этом приложении. В общем виде метод должен иметь следующую логику:

protected function callbackInit($request)
{
    $this->order_id = null; //заменить на логику извлечения номера заказа из параметров запроса
    $this->app_id = null; //аналогично — для получения идентификатора приложения из параметров запроса
    $this->merchant_id = null;//аналогично — для получения идентификатора экземпляра настроек плагина оплаты
    
    return parent::callbackInit($request); //обязательный вызов метода базового класса
}

callbackHandler()

В этом методе описывается алгоритм обработки обратных запросов, полученных от платежной системы. Такие запросы должны направляться по URL вида http://yourdomain.ru/payments.php/[plugin_id]/. Для передачи плагину оплаты дополнительных параметров от платежной системы допускается использование параметров адресной строки, обычно доступных в виде элементов массива $_GET. Устоявшейся практикой является использование переменной transaction_result со следующими значениями:

  • result: обратный вызов платежной системы
  • success либо failure: возврат (редирект) покупателя на сайт после успешной либо неудачной попытки оплаты

Пример URL, по которому должен выполняться обратный вызов платежной системой: http://yourdomain.ru/payments.php/[plugin_id]/?transaction_result=result

Основное назначение метода — вызвать обработчик приложения для обработки транзакции:

$this->execAppCallback($state, $transaction_data)

В качестве $state нужно указать статус транзакции с помощью одной из констант системного класса waPayment: CALLBACK_PAYMENT, CALLBACK_REFUND, CALLBACK_CONFIRMATION, CALLBACK_CAPTURE, CALLBACK_DECLINE, CALLBACK_CANCEL, CALLBACK_CHARGEBACK, например:

$result = $this->execAppCallback(self::CALLBACK_PAYMENT, $transaction_data);

В случае, если в ходе обработки колбека платёж был зарегистрирован как полученный, в массиве, возвращаемом методом execAppCallback(), будет содержаться значение true с ключом 'result'.

Вызов обработчика приложения следует выполнять только после выполнения проверки корректности/валидности полученных данных с использованием контрольной суммы, подписи и т. п. Использование непроверенных данных может привести к нарушению целостности данных о платежах клиентов!

Метод callbackHandler может после обработки вызова от платежной системы либо выполнить перенаправление покупателя на указанный URL, либо отобразить страницу, сформированную указанным шаблоном. Для этого метод должен вернуть массив значений, соответствующих нужному способу взаимодействия с покупателем:

  • Перенаправление:
    return [
        'redirect' => 'URL', //укажите требуемый URL, на который нужно перенаправить покупателя
    ];
  • Отображение страницы:
    return [
        'header' => [], //массив необязательных HTTP-заголовков, которые будут добавлены к ответу сервера с помощью метода addHeader() класса waResponse
        'template' => 'path/to/template.html', //необязательный путь к шаблону формируемой страницы; по умолчанию используется путь wa-system/webasyst/templates/actions/payments/Payments.html
        'some_var' => 'some_value', //произвольная переменная для использования в шаблоне
    ];

formalizeData()

Метод formalizeData() полезно использовать для приведения содержимого запроса, полученного от платежной системы, в формат, пригодный для хранения в базе данных интернет-магазина.

image ($order_data)

Реализуйте этот метод в основном классе плагина, если он поддерживает оплату по QR-коду.

Параметры
  • $order_data: Экземпляр класса waOrder с информацией о заказе, для которого требуется оплата.

Метод должен вернуть массив со следующими ключами (либо для любого из них, либо для обоих):

  • image_url: Абсолютный URL изображения с QR-кодом.
  • image_data_url: Данные для отображения QR-кода в формате «data URL».

Конфигурационные файлы

plugin.php

Файл plugin.php является главным конфигурационным файлом плагина оплаты и предназначен для хранения базовой информации о плагине: названия, описания, версии и т. д. Формат файла:

<?php
    
return [
    'name'        => ...,
    'description' => ...,
    'icon'        => ...,
    'logo'        => ...,
    'vendor'      => ...,
    'version'     => ...,
    'type'        => ...,
];

Описания полей

  • name: наименование плагина; если в файле локализации плагина есть строка с ключом, совпадающим с указанным названием, то название будет локализовано автоматически;
  • description: описание плагина; если в файле локализации плагина есть строка с ключом, совпадающим с указанным описание, то описание будет локализовано автоматически;
  • icon: путь к файлу иконки плагина относительно директории с файлами плагина, например: img/webmoney16.png (указан путь к иконке стандартного размера 16х16 пикселей);
  • logo: путь к файлу логотипа плагина относительно директории с файлами плагина, например: img/webmoney.png (указан путь к логотипу стандартного размера для плагина оплаты — 60х32 пикселя);
  • vendor: числовой идентификатор разработчика, его необходимо скопировать из своего аккаунта разработчика в Центре заказчика Webasyst;
  • version: строковое обозначение версии плагина, например: '1.0.0';
  • type: тип плагина оплаты: одна из констант системного класса waPayment: TYPE_CARD (прием оплаты банковской картой непосредственно на собственном сайте), TYPE_ONLINE (прием оплаты на сайте платежной системы) или TYPE_MANUAL (обработка платежей вручную администратором сайта), например: waPayment::TYPE_ONLINE.

settings.php

Файл settings.php используется для автоматического формирования интерфейса настроек плагина оплаты в бекенде приложения, которое использует такой плагин. См. подробное описание файла настроек плагина.

requirements.php

Файл requirements.php используется для указания дополнительных системных требований, специфичных для работы конкретного плагина (например, наличие дополнительных расширений или отдельных параметров конфигурации PHP, установленных приложений Webasyst). См. подробное описание правил оформления системных требований продукта.

guide.php

Файл guide.php используется для того, чтобы предоставить пользователю в интерфейсе настроек плагина возможность скопировать некоторые параметры, чтобы сохранить их в настройках аккаунта продавца на сайте платежной системы, например: URL для обновления статусов заказов, идентификатор экземпляра настроек плагина, название используемой кодировки символов или метода отправки данных.

Файл guide.php должен представлять собой PHP-файл с массивом параметров для каждого такого поля в настройках плагина оплаты, как показано в примере:

<?php
    
return [
    [
        'title'       => '',
        'description' => '',
        'value'       => '',
    ],
    [
        'title'       => '',
        'description' => '',
        'value'       => '',
    ],
    ...
];

Каждый подмассив соответствует одному из полей. Его элементы имеют следующие значения:

  • title — название поля
  • description — необязательное описание поля
  • value — текст, который необходимо отображать пользователю. В тексте допускается использовать специальные переменные, которые будут автоматически заменены на актуальные значения:

    %RELAY_URL%: URL для обработки callback-вызовов от платежной системы

    %HTTP_RELAY_URL%: URL для обработки callback-вызовов от платежной системы с принудительным использованием только протокола http://

    %HTTPS_RELAY_URL%: URL для обработки callback-вызовов от платежной системы с принудительным использованием только протокола https:// (в этом случае на доменном имени, где установлен фреймворк Webasyst, должно быть доступно отображение сайта по протоколу https://)

    %APP_ID%: идентификатор приложения, использующего плагин оплаты

    %MERCHANT_ID%: идентификатор экземпляра настроек плагина для данного приложения

Пример файла guide.php:

<?php
    
return [
    [
        'title'       => 'URL для уведомления об успешной оплате',
        'description' => '',
        'value'       => '%HTTPS_RELAY_URL%',
    ],
    [
        'title'       => 'URL для уведомления об отклоненных транзакциях',
        'description' => '',
        'value'       => '%HTTPS_RELAY_URL%?transaction_result=failure',
    ],
    [
        'title'       => 'Кодировка, используемая при отправке данных',
        'description' => 'Укажите при настройке нового протокола подключения к платежной системе',
        'value'       => 'UTF-8',
    ],
];

Отображение дополнительных элементов управления во фронтенде

Плагин оплаты может предлагать пользователю фронтенда дополнительные элементы управления, в том числе нестандартные. Для этого в классе плагина необходимо реализовать публичный метод customFields(). Этот метод должен вернуть массив элементов управления в виде подмассивов, содержащих параметры нужных элементов. Через аргумент $order можно использовать информацию о заказе для формирования списка дополнительных полей и их значений. Пример реализации этого метода:

public function customFields(waOrder $order)
{
    return [
        'field1' => [
            'value'        => $default_field_value, //значение по умолчанию, если необходимо
            'title'        => _wp('First field name'),
            'control_type' => waHtmlControl::INPUT,
        ],
        'field2' => [
            'value'        => $default_field_value, //значение по умолчанию, если необходимо
            'title'        => _wp('Second field name'),
            'control_type' => 'MyPaymentPluginControl', //идентификатор пользовательского элемента управления
        ],
        //...
    ];
}

В качестве значения параметра 'control_type' можно указать строковый идентификатор пользовательского элемента управления (который может представлять из себя любой фрагмент HTML- и JavaScript-кода).

Для реализации пользовательского элемента управления необходимо следующее:

  1. Добавьте в класс плагина публичный метод, возвращающий строку HTML-кода пользовательского элемента.
  2. В начале метода customFields() выполните вызов следующего вида:

    $this->registerControl('MyPaymentPluginControl', [$this, 'myPaymentPluginControl']);

    В этом примере 'MyPaymentPluginControl' в качестве первого аргумента метода registerControl() является идентификатором пользовательского элемента управления, а 'myPaymentPluginControl' — именем метода, в котором реализован этот элемент управления.

Идентификатор пользовательского элемента управления и метод для его реализации могут именованы произвольно.

Передача информации о налоговых ставках

Значения налоговых ставок доступны только том в случае, если приложение, использующее плагин оплаты, передает эти данные. Величина налога передается в процентах: значение 18 означает, что налоговая ставка составляет 18%.

Элементы заказа

Налоговая ставка передается для каждого элемента заказа. Элементы заказа в методе payment() доступны в виде поля waOrder->items экземпляра класса waOrder, который содержит формализованную информацию о заказе.

Каждый элемент заказа представляет собой ассоциативный массив. Запись массива с ключом 'tax_rate' содержит значение налоговой ставки в виде числа или null. Значение 0 означает нулевую налоговую ставку. Значение null означает, что элемент заказа не облагается налогом. Если записи с таким ключом в массиве нет, то приложение, использующее плагин оплаты, не поддерживает передачу данных о налоговых ставках.

Необязательное положительное значение записи 'tax_included' в элементе заказа обозначает, что размер налога включен в стоимость этого элемента заказа.

Доставка

Информация о доставке не содержится в элементах заказа, ее нужно извлекать отдельно. Значение налоговой ставки для стоимости доставки доступно в поле waOrder->shipping_tax_rate. Признак включения размера налога в стоимость доставки — в поле waOrder->shipping_tax_included.

Если сервис фискализации принимает информацию о доставке как часть массива заказа, то подготовить эту информацию можно подобным образом:

$item = [
    'quantity'     => 1,
    'name'         => $order->shipping_name,
    'amount'       => $order->shipping,
    'tax_rate'     => $order->shipping_tax_rate,
    'tax_included' => ($order->shipping_tax_included !== null) ? $order->shipping_tax_included : true,
];

Примеры реализации

В плагине «Яндекс.Деньги» получение налоговых ставок реализовано в методе getReceiptData(waOrder $order).

Советы

Различные полезные URL для настройки интеграции между вашим сайтом и платежной системой, можно получить в PHP-коде плагина следующим образом:

Значения переменных, используемых в файле guide.php:

  • %RELAY_URL%
    $this->getRelayUrl();
  • %HTTP_RELAY_URL%
    $this->getRelayUrl(false);
  • %HTTPS_RELAY_URL%
    $this->getRelayUrl(true);

URL для возврата клиента с сайта платежной системы:

$this->getAdapter()->getBackUrl($type, $data);

В качестве $type укажите тип действия в виде одной из констант системного класса waAppPayment: URL_SUCCESS (успешная оплата), URL_DECLINE (отмена платежа), URL_FAIL (неудачная попытка оплаты), URL_CHECKOUT (возврат на страницу оформления заказа), URL_PRINTFORM (отображение печатной формы). В качестве $data нужно передать массив с данными транзакции. Пример:

$return_url = $this->getAdapter()->getBackUrl(waAppPayment::URL_SUCCESS, $transaction_data);
В приложении, использующем плагин оплаты, должна иметься поддержка типа URL возврата покупателя, указанного вами при вызове метода getBackUrl().

Контроллеры и экшены

Плагин оплаты может иметь собственные контроллеры для обработки запросов от пользователей. Контроллеры плагина должны быть унаследованы от одного из следующих базовых классов:

  • waJsonActions
  • waJsonController
  • waLongActionController
  • waSystemPluginActions
  • waSystemPluginAction

Обращение к собственным контроллерам плагина можно использовать, например, на странице настроек.

Если обработка запроса выполняется контроллером в бекенде, то перед этой обработкой автоматически проверяются права доступа пользователя бекенда.

Готовый URL для выполнения запроса к собственному контроллеру удобно получать с помощью метода основного класса плагина getInteractionUrl($action = 'default', $module = 'backend').

Файлы HTML-шаблонов экшенов должны размещаться в директории templates/actions/[module]/[Module][Action].html.

Произвольные PHP-классы плагина

Для подключения произвольных классов плагина с использованием системного механизма автозагрузки файлы классов должны размещаться в директории lib/classes/ и именоваться по правилу payment[Plugin_id][Class_name].class.php. Имена классов в таких файлах должны именоваться по правилу payment[Plugin_id][Class_name]. Здесь [Plugin_id] — идентификатор плагина, [Class_name] — произвольная часть имени класса на усмотрение разработчика.

База данных

Общие настройки плагина

Общие для всех приложений настройки плагина можно хранить в таблице wa_app_settings. Сохранять и читать такие значения можно с помощью методов:

  • setGeneralSettings($name, $value)
  • getGeneralSettings($name = null, $default = '')

Такие настройки сохраняются в таблицу со значениями поля app_id в формате webasyst.payment.[id]. Здесь [id] — это идентификатор плагина.

В качестве идентификаторов настроек нельзя использовать некоторые зарезервированные значения:

  • update_time — используется механизмом метаобновлений;
  • sync_time — используется механизмом выполнения задач по расписанию;
  • sync_success_time — используется механизмом выполнения задач по расписанию;
  • sync_failure_time — используется механизмом выполнения задач по расписанию.

Собственные таблицы плагина

Именовать таблицы плагина оплаты нужно с использованием префикса wa_payment_%plugin_id%.

Описывать структуру таблиц нужно в файле lib/config/db.php, как и для приложений и плагинов для них.

Для работы с собственной таблицей в плагине можно использовать класс waSystemPluginModel — дочерний класс waModel. В этом случае можно не оформлять самостоятельные классы моделей для каждой из таблиц плагина. С помощью метода setPlugin(waSystemPlugin $plugin, $table = null) этого класса удобно получить экземпляр waModel с указанием имени таблицы и сразу работать с данными в этой таблице.

Но если вам нужны собственные методы, которых нет в waModel, то этот способ не подойдёт — в этом случае нужно оформлять собственные классы моделей. Свои классы можно наследовать и от waSystemPluginModel.

В основном классе плагина есть метод getModel($table = null). Если в него передать имя таблицы, то он вернёт экземпляр класса для этой таблицы — если такой класс модели есть в плагине — или экземпляр waSystemPluginModel для указанной таблицы. В качестве имени таблицы нужно передать только часть имени после обязательного префикса.

Если имя таблицы не передавать, то метод вернёт экземпляр класса для той таблицы плагина, имя которой совпадает с обязательным префиксом плагина. Такая ситуация возможна, например, когда плагин оплаты использует только одну таблицу в базе данных.

Хранение данных в файлах

Плагины оплаты могут хранить собственные данные в директории wa-data/. Для работы с такими файлами можно использовать новые методы основного класса:

  • getDataPath($path = null, $public = false, $create = true) — получение пути к файлам;
  • getDataUrl($path = null, $absolute = false) — получение URL файлов.

Параметры конфигурационных файлов

  • Описание поддержки функциональности приложением в файле плагина app.php:
    • rights — требуемый вид прав пользователя для взаимодействия с плагином через его контроллеры. Если поле пустое или отсутствует, то требуются административные права к приложению. Для приложения shop необходим идентификатор прав доступа settings, который даёт пользователю доступ к настройкам приложения и плагинов оплаты.
  • Описания адресов (URL) для callback-уведомлений плагинов оплаты размещаются в файле guide.php.

Метаобновления

Файлы метаобновлений должны размещаться в директории lib/updates/.