netfantom / yii2-robokassa
Robokassa Yii2 Framework extension for PHP 8.1
Installs: 10
Dependents: 0
Suggesters: 0
Security: 0
Stars: 3
Watchers: 1
Forks: 0
Open Issues: 0
Type:yii2-extension
Requires
- php: >=8.1
- ext-mbstring: *
- netfantom/robokassa-api: @dev
- yiisoft/yii2: ~2.0.45
Requires (Dev)
- nyholm/psr7: ^1.8
- phpunit/phpunit: ^10.2
- roave/security-advisories: dev-latest
- squizlabs/php_codesniffer: ^3.7
- symfony/http-client: ^6.3
- vimeo/psalm: ^5.12
This package is auto-updated.
Last update: 2025-03-27 12:56:55 UTC
README
Данный компонент предназначен для работы с Робокассой:
- является оберткой вокруг
netFantom/robokassa-api
и полностью исполняет его интерфейсnetFantom\robokassa-api\RobokassaApiInterface
( см. https://github.com/igor-netFantom/robokassa-api ) - выполнен в виде компонента
Yii 2 framework
и расширяет возможности, добавляя удобные методы и виджеты
Для работы требуется PHP 8.1+
Установка с помощью Composer
composer require igor-netfantom/yii2-robokassa:@dev
Подключение компонента
Объектом:
[ // ... 'components' => [ 'robokassa' => [ 'class' => 'netFantom\Yii2Robokassa\Yii2Robokassa', 'robokassaApi' => new \netFantom\RobokassaApi\RobokassaApi( merchantLogin: 'robo-demo', password1: 'password_1', password2: 'password_2', isTest: !YII_ENV_PROD, psr18Client: new \Http\Discovery\Psr18Client(), // необязательно ), ], // ... ], ];
...или массивом:
[ // ... 'components' => [ 'robokassa' => [ 'class' => 'netFantom\Yii2Robokassa\Yii2Robokassa', 'merchantLogin' => 'robo-demo', 'password1' => 'password1', 'password2' => 'password2', 'isTest' => !YII_ENV_PROD, 'psr18Client' =>'Http\Discovery\Psr18Client', // необязательно ], // ... ], ];
Методы
- Переадресация на страницу оплаты счета
- Преобразование параметров платежа в поля формы
- Получение результата оплаты счета от Робокассы из HTTP запроса Yii
- Методы модуля
netFantom/robokassa-api
- 🔗 Получение параметров платежа для передачи в Робокассу
- 🔗 Получение параметров платежа в формате
JSON строки
- 🔗 Получение URL для оплаты счета с указанными параметрами
- 🔗 Отправка второго чека
- 🔗 Получение статуса чека
- 🔗 Отправка СМС
- 🔗 Получение результата оплаты счета от Робокассы
- 🔗 Вспомогательные методы
Переадресация на страницу оплаты счета
/** @var \netFantom\Yii2Robokassa\Yii2Robokassa $robokassa */ $robokassa = Yii::$app->get('robokassa'); /** * @var \models\Invoice $invoice смотрите пример модели счета в разделе ниже * @see https://github.com/igor-netFantom/yii2-robokassa#пример-модели-счета */ /** @var bool $setReturnUrl по умолчанию TRUE {@see \yii\web\User::setReturnUrl()} */ $response = $robokassa->redirectToPaymentUrl($invoice->getInvoiceOptions(), $setReturnUrl); /** @var \yii\web\Response $response */ return $response;
Преобразование параметров платежа в поля формы
Преобразует параметры платежа InvoiceOptions
в скрытые поля формы Html::hiddenInput()
для отправки пользователя на
оплату POST
запросом
/** @var \netFantom\Yii2Robokassa\Yii2Robokassa $robokassa */ $robokassa = Yii::$app->get('robokassa'); /** * @var \models\Invoice $invoice смотрите пример модели счета в разделе ниже * @see https://github.com/igor-netFantom/yii2-robokassa#пример-модели-счета */ echo $robokassa->getHiddenInputsHtml($invoice->getInvoiceOptions());
Получение результата оплаты счета от Робокассы из HTTP запроса Yii
use netFantom\Yii2Robokassa\Yii2Robokassa; use netFantom\RobokassaApi\Results\InvoicePayResult; /** @var \yii\web\Request $request */ $request = Yii::$app->request /** @var InvoicePayResult $invoicePayResult */ $invoicePayResult = Yii2Robokassa::getInvoicePayResultFromYiiWebRequest($request);
Методы модуля netFantom/robokassa-api
Данный компонент является оберткой вокруг netFantom/robokassa-api
и полностью исполняет его интерфейс netFantom\robokassa-api\RobokassaApiInterface
:
( см. https://github.com/igor-netFantom/robokassa-api )
Пример использования компонента
- Пример модели счета
- Примеры действий контроллера для обработки запросов Робокассы
- Примеры представлений для создания счета и отправки пользователя на оплату
Пример модели счета
class InvoiceStatus { public const STATUS_CREATED = 1; public const STATUS_PAYED = 2; public const STATUS_FAILED = 3; }
class PaymentSystem { public const SYSTEM_ROBOKASSA = 1; }
use models\InvoiceStatus; use DateInterval; use DateTimeImmutable; use netFantom\RobokassaApi\Options\InvoiceOptions; use netFantom\RobokassaApi\Params\Option\{Culture, OutSumCurrency, Receipt}; use netFantom\RobokassaApi\Params\Item\{PaymentMethod, PaymentObject}; use netFantom\RobokassaApi\Params\Receipt\{Item, Sno, Tax}; use yii\db\ActiveRecord; class Invoice extends ActiveRecord { public int $id; public string $sum; public int $status_id = InvoiceStatus::STATUS_CREATED; public int $payment_system_id; public int $user_id; public function getInvoiceOptions(): InvoiceOptions { return new InvoiceOptions( outSum: $this->sum, invId: $this->id, description: 'Description', receipt: new Receipt( items: [ new Item( name: "Название товара 1", quantity: 1, sum: 100, tax: Tax::vat10, payment_method: PaymentMethod::full_payment, payment_object: PaymentObject::commodity, ), new Item( name: "Название товара 2", quantity: 3, sum: 450, tax: Tax::vat10, payment_method: PaymentMethod::full_payment, payment_object: PaymentObject::service, cost: 150, nomenclature_code: '04620034587217', ), ], sno: Sno::osn ), expirationDate: (new DateTimeImmutable())->add(new DateInterval('PT48H')), email: 'user@email.com', outSumCurrency: OutSumCurrency::USD, userIP: '127.0.0.1', incCurrLabel: null, userParameters: [ 'user_id' => '123', 'parameter2' => 'parameter2_value', // ... ], encoding: 'utf-8', culture: Culture::ru, ); } //... }
Примеры действий контроллера для обработки запросов Робокассы
use models\{Invoice, InvoiceStatus, PaymentSystem}; use netFantom\Yii2Robokassa\Assets\PopupIframeAsset; use netFantom\Yii2Robokassa\Yii2Robokassa; use Yii; use yii\web\{BadRequestHttpException, Controller, Response}; class PaymentController extends Controller { /** * В случае отказа от исполнения платежа покупатель перенаправляется по данному адресу. * Необходим для того, чтобы продавец мог, например, разблокировать заказанный товар на складе. * * Переход пользователя по данному адресу, строго говоря, не означает окончательного отказа покупателя от оплаты, * нажав кнопку «Назад» в браузере он может вернуться на страницу оплаты Robokassa. * Поэтому в случае блокировки товара на складе под заказ, для его разблокирования желательно проверять * факт отказа от платежа запросом XML-интерфейса получения состояния оплаты счета, используя в запросе * номер счета InvId имеющийся в базе данных магазина/продавца. * @link https://docs.robokassa.ru/pay-interface/ */ public function actionFail(): Response { $invoicePayResult = Yii2Robokassa::getInvoicePayResultFromYiiWebRequest(Yii::$app->request); $invoice = $this->loadInvoice($invoicePayResult->invId); if ($invoice->status_id === InvoiceStatus::STATUS_CREATED) { $invoice->updateAttributes(['status' => InvoiceStatus::STATUS_FAILED]); } return $this->goBack(); } /** * ВАРИАНТ: Загрузка Popup виджета оплаты AJAX запросом */ public function actionInvoiceAjax(): string { $invoice = new Invoice(); $invoice->payment_system_id = PaymentSystem::SYSTEM_ROBOKASSA; $invoice->status_id = InvoiceStatus::STATUS_CREATED; $invoice->user_id = Yii::$app->user->id; if (Yii::$app->request->isAjax && $invoice->load(Yii::$app->request->post()) && $invoice->save()) { return $this->renderAjax('invoice-ajax-response', compact('invoice')); } PopupIframeAsset::register($this->view); return $this->render('invoice-ajax', [ 'invoice' => $invoice, ]); } /** * ВАРИАНТ: Переход на оплату формой с POST запросом */ public function actionInvoiceForm(int $id = null): string { if (isset($id)) { $invoice = $this->loadInvoice($id); if ($invoice->user_id !== Yii::$app->user->id || $invoice->status_id !== InvoiceStatus::STATUS_CREATED) { throw new BadRequestHttpException('Подходящий по условиям счёт не найден'); } return $this->render('invoice-form', compact('invoice')); } $invoice = new Invoice(); $invoice->payment_system_id = PaymentSystem::SYSTEM_ROBOKASSA; $invoice->status_id = InvoiceStatus::STATUS_CREATED; $invoice->user_id = Yii::$app->user->id; if ($invoice->load(Yii::$app->request->post()) && $invoice->save()) { $this->redirect(['payment/invoice-form', 'id' => $invoice->id]); } return $this->render('invoice-create', [ 'invoice' => $invoice, ]); } /** * ВАРИАНТ: Формирование Popup виджета */ public function actionInvoicePopup(int $id = null): string { if (isset($id)) { $invoice = $this->loadInvoice($id); if ($invoice->user_id !== Yii::$app->user->id || $invoice->status_id !== InvoiceStatus::STATUS_CREATED) { throw new BadRequestHttpException('Подходящий по условиям счёт не найден'); } return $this->render('invoice-popup', compact('invoice')); } $invoice = new Invoice(); $invoice->payment_system_id = PaymentSystem::SYSTEM_ROBOKASSA; $invoice->status_id = InvoiceStatus::STATUS_CREATED; $invoice->user_id = Yii::$app->user->id; if ($invoice->load(Yii::$app->request->post()) && $invoice->save()) { $this->redirect(['payment/invoice-popup', 'id' => $invoice->id]); } return $this->render('invoice-create', [ 'invoice' => $invoice, ]); } /** * ResultURL предназначен для получения Вашим сайтом оповещения об успешном платеже в автоматическом режиме. * В случае успешного проведения оплаты Robokassa делает запрос на ResultURL (см. раздел Технические настройки). * Данные всегда передаются в кодировке UTF-8. * * Ваш скрипт, находящийся по ResultURL, обязан проверить равенство полученной контрольной суммы * и контрольной суммы, рассчитанной Вашим скриптом по параметрам, полученным от Robokassa, * а не по локальным данным магазина. * * Если контрольные суммы совпали, то Ваш скрипт должен ответить Robokassa, чтобы мы поняли, * что Ваш скрипт работает правильно и повторное уведомление с нашей стороны не требуется. * Результат должен содержать текст OK и параметр InvId. * Например, для номера счёта 5 должен быть вот такой ответ: OK5. * * Если контрольные суммы не совпали, то полученное оповещение некорректно, и ситуация требует разбора магазином. * @link https://docs.robokassa.ru/pay-interface/ */ public function actionResult(): string { /** @var Yii2Robokassa $robokassa */ $robokassa = Yii::$app->get('robokassa'); $invoicePayResult = Yii2Robokassa::getInvoicePayResultFromYiiWebRequest(Yii::$app->request); if (!$robokassa->checkSignature($invoicePayResult)) { throw new BadRequestHttpException(); } if (!$this->loadInvoice($invoicePayResult->invId)->updateAttributes(['status' => InvoiceStatus::STATUS_PAYED])) { throw new BadRequestHttpException(); } return $invoicePayResult->formatOkAnswer(); } /** * В случае успешного исполнения платежа Покупатель сможет перейти по адресу, * указанному вами в Технических настройках, там же вы указали метод (GET или POST). * * Переход пользователя по данному адресу с корректными параметрами (правильной Контрольной суммой) означает, * что оплата вашего заказа успешно выполнена. * * Однако для дополнительной защиты желательно, чтобы факт оплаты проверялся скриптом, * исполняемым при переходе на SuccessURL, или путем запроса XML-интерфейса получения состояния оплаты счета, * и только при реальном наличии счета с номером InvId в базе данных магазина. * * На самом деле, переход пользователя по ссылке SuccessURL – это формальность, которая нужна только для того, * чтобы пользователь вернулся обратно к Вам и получил информацию о том, что он сделал всё правильно, * и его заказ ждёт его там-то и там-то. Проводить подтверждение оплаты у себя по базе и все остальные действия, * связанные с выдачей покупки, Вам нужно при получении уведомления на ResultUrl, * потому что именно на него Robokassa передаёт подтверждающие данные об оплате в автоматическом режиме * (т. е. в любом случае и без участия пользователя). * @link https://docs.robokassa.ru/pay-interface/ */ public function actionSuccess(): Response|string { $invoicePayResult = Yii2Robokassa::getInvoicePayResultFromYiiWebRequest(Yii::$app->request); $invoice = $this->loadInvoice($invoicePayResult->invId); return $this->render("success", compact('invoice')); } protected function loadInvoice(int $id): Invoice { $invoice = Invoice::find() ->andWhere(['id' => $id]) ->andWhere(['payment_system_id' => PaymentSystem::SYSTEM_ROBOKASSA]) ->one(); if ($invoice === null) { throw new BadRequestHttpException('Подходящий по условиям счёт не найден'); } return $invoice; } }
Примеры представлений для создания счета и отправки пользователя на оплату
ВАРИАНТ: Загрузка Popup виджета оплаты AJAX запросом
Пример представления
invoice-ajax
для действия actionInvoiceAjax
use models\Invoice; use yii\helpers\Html; use yii\helpers\Url; use yii\web\View; use yii\widgets\ActiveForm; /* @var $this View */ /* @var $invoice Invoice */ $url = Url::current(); $this->registerJs( <<<JS $('form').on('beforeSubmit', function(){ var data = $(this).serialize(); $.ajax({ url: '$url', type: 'POST', data: data, success: function(res){ let responsePayForm=$(res).find('#pay-form'); if(responsePayForm.length>0) { $('#pay-form').html(responsePayForm); } else { $('#pay-form').append(res); } }, error: function(){ alert('Error!'); } }); return false; }); JS ); $form = ActiveForm::begin([ 'id' => 'pay-form', 'enableClientValidation' => false, ]); echo $form->field($invoice, 'sum')->textInput(); echo Html::submitButton('Pay', ['class' => 'btn btn-success']); ActiveForm::end();
Пример представления
invoice-ajax-response
для действия actionInvoiceAjax
use models\Invoice; use netFantom\Yii2Robokassa\Widgets\PopupIframeWidget; use netFantom\Yii2Robokassa\Yii2Robokassa; use yii\helpers\Html; use yii\web\View; /* @var $this View */ /* @var $invoice Invoice */ /** @var Yii2Robokassa $robokassa */ $robokassa = Yii::$app->get('robokassa'); PopupIframeWidget::widget([ 'yii2Robokassa' => $robokassa, 'invoiceOptions' => $invoice->getInvoiceOptions(), 'registerAsset' => false, ]); echo Html::encode("Сформирован счет №$invoice->id на сумму $invoice->sum руб. и ждет оплаты"); echo Html::button('оплатить', [ 'onClick' => PopupIframeWidget::SHOW_ROBOKASSA_POPUP_IFRAME_ACTION, 'class' => 'btn btn-primary', ]);
ВАРИАНТ: Переход на оплату формой с POST запросом
Пример представления
invoice-form
для действия actionInvoiceForm
use models\Invoice; use netFantom\Yii2Robokassa\Widgets\PopupIframeWidget; use netFantom\Yii2Robokassa\Yii2Robokassa; use yii\helpers\Html; use yii\web\View; use yii\widgets\ActiveForm; /* @var $this View */ /* @var $invoice Invoice */ /** @var Yii2Robokassa $robokassa */ $robokassa = Yii::$app->get('robokassa'); echo Html::encode("Сформирован счет №$invoice->id на сумму $invoice->sum руб. и ждет оплаты"); $form = ActiveForm::begin([ 'id' => 'pay-form', 'method' => 'POST', 'action' => $robokassa->paymentUrl, ]); echo $robokassa->getHiddenInputsHtml($invoice->getInvoiceOptions()); echo Html::submitButton('оплатить', [ 'onClick' => PopupIframeWidget::SHOW_ROBOKASSA_POPUP_IFRAME_ACTION, 'class' => 'btn btn-primary btn-lg', ]); ActiveForm::end();
ВАРИАНТ: Формирование Popup виджета
Пример представления
invoice-popup
для действия actionInvoicePopup
use models\Invoice; use netFantom\Yii2Robokassa\Widgets\PopupIframeWidget; use netFantom\Yii2Robokassa\Yii2Robokassa; use yii\helpers\Html; use yii\web\View; /* @var $this View */ /* @var $invoice Invoice */ /** @var Yii2Robokassa $robokassa */ $robokassa = Yii::$app->get('robokassa'); PopupIframeWidget::widget([ 'yii2Robokassa' => $robokassa, 'invoiceOptions' => $invoice->getInvoiceOptions(), 'showOnLoad' => true, ]); echo Html::encode("Сформирован счет №$invoice->id на сумму $invoice->sum руб. и ждет оплаты"); echo Html::button('оплатить', [ 'onClick' => PopupIframeWidget::SHOW_ROBOKASSA_POPUP_IFRAME_ACTION, 'class' => 'btn btn-primary btn-lg', ]);
Пример представления
invoice-create
для действий actionInvoicePopup
и actionInvoiceForm
use models\Invoice; use yii\helpers\Html; use yii\web\View; use yii\widgets\ActiveForm; /* @var $this View */ /* @var $invoice Invoice */ $form = ActiveForm::begin(); echo $form->field($invoice, 'sum')->textInput(); echo Html::submitButton('Пополнить баланс', ['class' => 'btn btn-success']); ActiveForm::end();