moneta-sdk-php v2.0.0

This commit is contained in:
Nikita Ivanaev 2025-02-24 22:31:15 +03:00
commit 7a455450ce
16 changed files with 1443 additions and 0 deletions

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 NKO "MONETA" (LLC)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

157
README.md Normal file
View File

@ -0,0 +1,157 @@
# Moneta SDK PHP
SDK PHP для использования платежных методов [Монета | PayAnyWay](https://moneta.ru/info/d/ru/public/welcome.htm)
[Документация SDK](docs/)
[Документация Монеты](https://docs.moneta.ru/)
## Требования
PHP 8.0 (и выше)
## Установка
### Установка через composer
1. Добавьте строку `"moneta-integrations/moneta-sdk-php": "^2.0"` в список зависимостей вашего проекта в файле composer.json
```
...
"require": {
"moneta-integrations/moneta-sdk-php": "^2.0"
}
...
```
а также разместите следующие скрипты в секции "scripts" файла composer.json. Эти скрипты скопируют каталог конфигурации (config) из пакета moneta-integrations/moneta-sdk-php и разместят его в корне вашего проекта:
```
...
"scripts": {
"moneta-copy-config": [
"php -r \"if(!is_dir('config')){ mkdir('config');}\"",
"php -r \"copy('vendor/moneta-integrations/moneta-sdk-php/config/account.php', 'config/account.php');\"",
"php -r \"copy('vendor/moneta-integrations/moneta-sdk-php/config/url.php', 'config/url.php');\""
]
}
...
```
2. Обновите зависимости проекта. В консоли перейдите в каталог, где лежит composer.json, и выполните команду:
```bash
composer update
```
3. Затем выполните скрипт:
```
composer moneta-copy-config
```
> Обратите внимание, что каталог конфигурации появится в корне вашего проекта. При инициализации объекта MonetaSDK вам потребуется передавать путь до каталога конфигурации, например:
```php
include_once('vendor/autoload.php');
$orderId = 'ORDER_471';
$amount = 123.45;
$description = 'Оплата заказа ORDER_471';
$configPath = 'config';
$mSdk = new Moneta\MonetaSdk($orderId, $amount, $description, $configPath);
$mSdk->getAssistantPaymentLink();
```
4. В коде вашего проекта подключите автозагрузку файлов нашего клиента:
```php
include_once('vendor/autoload.php');
```
### Установка через git
1. Выполните следующую команду:
```git
git clone https://git.pub.moneta.ru/Moneta-Labs/moneta-sdk-php.git
```
2. В коде вашего проекта подключите автозагрузку файлов нашего клиента:
```php
include_once('moneta-sdk-php/autoload.php');
```
## Начало работы
1. В конфигурации SDK укажите свои данные:
1.1. Если вы планируете использовать базовый функционал (выставление ссылок на оплату через Assistant), то заполните только следующие параметры:
`id` --- номер бизнес счета;
`secret` --- код проверки целостности данных;
`demo_mode` --- указать `true`, если вы проводите интеграцию на демо-стенде (demo.moneta.ru).
1.2. Если вы планируете использовать функционал MerchantAPI, то требуется указать дополнительно:
`username` --- логин от личного кабинета [Moneta | PayAnyWay](https://www.payanyway.ru/backoffice/auth/signin);
`password` --- пароль от личного кабинета [Moneta | PayAnyWay](https://www.payanyway.ru/backoffice/auth/signin);
`payment_password` --- платежный пароль.
Полное описание config-файлов можете прочитать в [документации к SDK](/docs/config.md).
2. Пример генерации ссылки на оплату с помощью [MONETA.Assistant](https://www.moneta.ru/doc/MONETA.Assistant.ru.pdf):
```php
include_once('vendor/autoload.php');
$orderId = 'ORDER_471'; // Номер заказа в системе магазина
$amount = 123.45; // Сумма заказа
$mSdk = new Moneta\MonetaSdk($orderId, $amount);
$mSdk->getAssistantPaymentLink(); // Результат: https://demo.moneta.ru/assistant.htm?MNT_ID=96324612&MNT_AMOUNT=123.45&MNT_TRANSACTION_ID=ORDER_471&MNT_CURRENCY_CODE=RUB&MNT_SIGNATURE=93742a04b8b3124779c13a5cfc414784&moneta.locale=ru
```
Когда ссылка будет сгенерирована, нужно направить на неё плательщика..
3. После оплаты на указанный PayURL в настройках счета будет направлено платежное уведомление от Монеты. В вашем обработчике уведомление потребуется сменить статус заказа в системе магазина, а также сформировать ответ для Монеты.
3.1. Ответ без передачи номенклатуры:
```php
include_once('vendor/autoload.php');
$orderId = $_POST['MNT_TRANSACTION_ID']; // Номер заказа, по которому пришло уведомление
$mSdk = new Moneta\MonetaSdk($orderId);
$mSdk->responseToPaymentNotification(); // Результат: SUCCESS
```
В результате для Монеты будет предоставлен минимальный ответ `SUCCESS`. Для платежной системы это будет означать, что система магазина приняла уведомление и изменила статус заказа, после чего в Монете у операции будет присвоен статус "Выполнена".
3.2. Ответ с передачей номенклатуры:
```php
include_once('vendor/autoload.php');
$orderId = $_POST['MNT_TRANSACTION_ID']; // Номер заказа, по которому пришло уведомление
$mSdkReceipt = new Moneta\MonetaSdkReceipt();
// Минимальный набор данных о товаре:
$mSdkReceipt->items = [
[
'name' => 'Тестовый товар 2',
'price' => 123.45,
'quantity' => 1,
]
];
// Минимальный набор данных о плательщике
$mSdkReceipt->customer = [
'email' => 'com@moneta.ru',
];
// Если имеется доставка, то указать ее стоимость:
$mSdkReceipt->delivery = 67.89;
$mSdk = new Moneta\MonetaSdk($orderId);
$mSdk->responseToPaymentNotification($mSdkReceipt); // Результат: ответ в формате xml, см. ниже
```
В результате для Монеты будет сформирован ответ в формате xml с номенклатурой:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<MNT_RESPONSE>
<MNT_ID>12346578</MNT_ID>
<MNT_TRANSACTION_ID>ORDER_471</MNT_TRANSACTION_ID>
<MNT_RESULT_CODE>200</MNT_RESULT_CODE>
<MNT_SIGNATURE>ec134dd3a9d2d0e84597f5bf0eef8a3e</MNT_SIGNATURE>
<MNT_ATTRIBUTES>
<MNT_ATTRIBUTE>
<KEY>INVENTORY</KEY>
<VALUE>[{"name":"Тестовый товар 2","price":123.45,"quantity":1,"vatTag":"1105","pm":"full_payment","po":"commodity"}]</VALUE>
</MNT_ATTRIBUTE>
<MNT_ATTRIBUTE>
<KEY>CUSTOMER</KEY>
<VALUE>com@moneta.ru</VALUE>
</MNT_ATTRIBUTE>
<MNT_ATTRIBUTE>
<KEY>DELIVERY</KEY>
<VALUE>67.89</VALUE>
</MNT_ATTRIBUTE>
</MNT_ATTRIBUTES>
</MNT_RESPONSE>
```
## Документация SDK
В документации описаны методы и примеры их использования:
- #### [Описание config-файлов](docs/config.md);
- #### [Базовые методы](docs/baseMethods.md);
- #### [Обработка http-уведомлений от Монеты](docs/notifications.md);
- #### [Методы MerchantAPI](docs/merchantAPI.md).

21
autoload.php Normal file
View File

@ -0,0 +1,21 @@
<?php
function monetaSdkAutoloader() {
$file_map = array(
'MonetaSdk.php',
'MonetaSdkException.php',
'MonetaSdkReceipt.php',
'MonetaSdkService.php',
'MonetaSdkService.php',
'MonetaSdkSettings.php'
);
$vendorDir = __DIR__ . "/src/";
foreach ($file_map as $one_file) {
$filepath = $vendorDir . $one_file;
require_once($filepath);
}
}
spl_autoload_register('monetaSdkAutoloader');

31
composer.json Normal file
View File

@ -0,0 +1,31 @@
{
"name": "moneta-integrations/moneta-sdk-php",
"description": "PHP SDK of the payment gateway Moneta",
"type": "library",
"license": "MIT",
"homepage": "https://docs.moneta.ru/",
"keywords": [
"moneta",
"payanyway",
"api",
"sdk",
"payment gateway"
],
"authors": [
{
"name": "Moneta",
"email": "tech.support@moneta.ru"
}
],
"version": "2.0.0",
"require": {
"php": ">=8.0.0",
"ext-curl": "*",
"ext-json": "*"
},
"autoload": {
"psr-4": {
"Moneta\\": "src/"
}
}
}

14
config/account.php Normal file
View File

@ -0,0 +1,14 @@
<?php
return [
'id' => 12345,
'secret' => 'qwerty123',
'demo_mode' => false,
'username' => 'payment@moneta.ru',
'password' => 'Qwerty1234',
'payment_password' => '1234qwer',
'locale' => 'ru',
'currency' => 'RUB',
'unit_id' => '',
'limit_ids' => ''
];

9
config/api.php Normal file
View File

@ -0,0 +1,9 @@
<?php
return [
'payment_url' => [
'production' => 'https://service.moneta.ru',
'demo' => 'https://demo.moneta.ru'
],
'urn' => '/services'
];

9
config/url.php Normal file
View File

@ -0,0 +1,9 @@
<?php
return [
'success' => '',
'fail' => '',
'inprogress' => '',
'return' => '',
'iframe_target' => '_parent'
];

36
docs/baseMethods.md Normal file
View File

@ -0,0 +1,36 @@
## Базовые методы Moneta SDK PHP
[Документация Монеты](https://docs.moneta.ru/)
* [Генерация ссылки на оплату с помощью MONETA.Assistant](#Генерация-платежа-assistant)
* [Документация SDK](#Документация)
---
### Генерация ссылки на оплату с помощью MONETA.Assistant<a name="Генерация-платежа-assistant"></a>
[Создание платежа в документации](https://docs.moneta.ru/protocols/#get-/-ASSTNT--payment)
Чтобы сгенерировать ссылку на оплату, нужно создать объект `MonetaSdk`. Он принимает следующие параметры:
1. ID заказа*;
2. Сумма заказа*;
3. Описание заказа.
`*` --- обязательный параметр. Должен быть передан.
Затем вам требуется вызвать метод `getAssistantPaymentLink`. В ответе вам вернется ссылка на оплату, на которую вы должны переадресовать плательщика.
```php
include_once('vendor/autoload.php');
$mSdk = new Moneta\MonetaSdk(uniqid('', true), 123.45);
$paymentLink = $mSdk->getAssistantPaymentLink();
if(!empty($paymentLink)){
header('Location: ' . $paymentLink);
}
```
---
## Документация SDK <a name="Документация"></a>
- #### [Описание config-файлов](config.md);
- #### [Обработка http-уведомлений от Монеты](notifications.md);
- #### [Методы MerchantAPI](merchantAPI.md).

41
docs/config.md Normal file
View File

@ -0,0 +1,41 @@
## Настройки Moneta SDK PHP
Все файлы с настройками лежат по пути `moneta-sdk-new/config/`. Все настройки возвращают ассоциативный массив (ключ - значение).
[Документация Монеты](https://docs.moneta.ru/)
* [Описание account.php](#Описание-account)
* [Описание api.php](#Описание-api)
* [Описание url.php](#Описание-url)
* [Документация SDK](#Документация)
---
1. `account.php` <a name="Описание-account"></a> --- данные от учетной записи:
`id`* --- номер бизнес-счета в системе Монета;
`secret`* --- код проверки целостности данных, указанный в настройках счета в [Монета | PayAnyWay](https://www.payanyway.ru/backoffice/accounts/business);
`demo_mode` --- ставится значение `true`, если тестируете интеграцию на демо-стенде (demo.moneta.ru);
`username`** --- логин от личного кабинета [Монета | PayAnyWay](https://www.payanyway.ru/backoffice/auth/signin);
`password`** --- пароль от личного кабинета [Монета | PayAnyWay](https://www.payanyway.ru/backoffice/auth/signin);
`payment_password`** --- платежный пароль, указанный в настройках счета в [Монета | PayAnyWay](https://www.payanyway.ru/backoffice/accounts/business);
`locale` --- локализация. `ru` -- русская локализация, `en` -- английская. Используется при вызове платежной формы;
`currency` --- валюта. Пока доступно только одно значение -- `RUB`;
`unit_id` --- платежная система по умолчанию. При отображении платежной формы, позволяет выводить первым указанную платежную систему, например, СБП. Доступные значения платежных систем можно найти в разделе "Счета" → "Настройки способа оплаты" → "Разработчику" → "paymentSystem.unitId";
`limit_ids` → ограниченный список платежных систем на платежной форме. Позволяет оставить на платежной форме только указанные платежные системы. Например, только СБП и SberPay.
Параметры, отмеченные `*`, являются обязательными.
Параметры, отмеченные `**`, являются обязательными, если вы планируете использовать методы MerchantAPI.
2. `api.php` <a name="Описание-api"></a> --- системные параметры для MerchantAPI, **изменять их не нужно**:
`payment_url` --- url-ы, на которые шлются запросы;
`urn` --- urn, который используется для запросов при указании в заголовке запроса `username` и `password`;
3. `url.php` <a name="Описание-url"></a> --- адреса на страницы интернет-магазина, куда осуществляется перевод пользователя после обработки формы оплаты заказа:
`success` --- страница магазина, на которой информируется успешный приеме платежа;
`fail` --- страница магазина, где отображается информация о неудачной оплате;
`inprogress` --- страница магазина, где отображается информация о том, что платёж находится в процессе обработки;
`return` --- страница магазина, куда пользователь попадает после завершения оплаты заказа;
`iframe_target` --- одно из значений — `_parent`, `_blank`, `_self_`, , `_top_`, которое используется для настройки окна возврата при интеграции страницы оплаты в iframe. Речь идёт об использовании виджета оплаты заказа вместо полноценной страницы оплаты.
## Документация SDK <a name="Документация"></a>
- #### [Базовые методы](baseMethods.md);
- #### [Обработка http-уведомлений от Монеты](notifications.md);
- #### [Методы MerchantAPI](merchantAPI.md).

144
docs/merchantAPI.md Normal file
View File

@ -0,0 +1,144 @@
## Методы MerchantAPI
[Документация Монеты](https://docs.moneta.ru/)
* [Однофазный платеж](#однофазный-платеж)
* [Двухфазный платеж (операция с холдированием)](#двухфазный-платеж)
* [Подтверждение операции](#подтверждение-операции)
* [Отмена операции](#отмена-операции)
* [Привязка карты (получение токена для рекуррентных платежей)](#привязка-карты)
* [Оплата по рекуррентному токену](#рекуррентный-платеж)
* [Возврат по операции](#возврат)
* [Получить детали операции по ID](#детали-операции-по-id)
* [Документация SDK](#Документация)
---
> **Эти методы доступны только для юридических лиц и ИП. Чтобы узнать, поддерживает ли ваш бизнес-счёт рекуррентные платежи и операции с холдированием, обратитесь в коммерческий отдел: com@payanyway.ru.**
### Однофазный платеж <a name="однофазный-платеж"></a>
[Однофазный платеж в документации](https://docs.moneta.ru/protocols/#post-/-MRCHNT--invoice-request--simple)
Создайте объект `MonetaSdk`, передав номер заказа и сумму, а также по желанию описание. Затем вызовите метод `createInvoice`, будет возвращен номер операции в системе Монета. Данный номер операции требуется передать в метод `getPaymentLink`, тем самым можно получить ссылку на оплату, по которой надо будет перевести плательщика.
```php
include_once('vendor/autoload.php');
$mSdk = new Moneta\MonetaSdk(uniqid('', true), 123.45);
$operationId = $mSdk->createInvoice();
$paymentLink = $mSdk->getPaymentLink($operationId);
if (!empty($paymentLink)) {
header('Location: ' . $paymentLink);
}
```
---
### Двухфазный платеж (операция с холдированием) <a name="двухфазный-платеж"></a>
[Двухфазный платеж в документации](https://docs.moneta.ru/protocols/#post-/-MRCHNT--invoice-request--hold)
Создайте объект `MonetaSdk`, передав номер заказа и сумму, а также по желанию описание. Затем вызовите метод `createInvoice` и передайте в качестве аргумента true, будет возвращен номер операции с холдированием в системе Монета. Данный номер операции требуется передать в метод `getPaymentLink`, тем самым можно получить ссылку на оплату, по которой надо будет перевести плательщика.
```php
include_once('vendor/autoload.php');
$mSdk = new Moneta\MonetaSdk(uniqid('', true), 123.45);
$operationId = $mSdk->createInvoice(true);
$paymentLink = $mSdk->getPaymentLink($operationId);
if (!empty($paymentLink)) {
header('Location: ' . $paymentLink);
}
```
> **При проведении двухфазного платежа(холдирование), нужно подтвердить или отменить операцию.**
---
### Подтверждение операции<a name="подтверждение-операции"></a>
[Подтверждение операции в документации](https://docs.moneta.ru/protocols/#post-/-MRCHNT--confirm-transaction-request)
Чтобы подтвердить операцию нужно создать объект `MonetaSdk`, передать номер заказа и вызвать метод `confirmInvoice`, передав номер операции. В ответе будет возвращен массив с информацией об операции.
```php
include_once('vendor/autoload.php');
$orderId = $_POST['MNT_TRANSACTION_ID'];
$operationId = $_POST['MNT_OPERATION_ID'];
$mSdk = new Moneta\MonetaSdk($transactionId);
$mSdk->confirmInvoice($operationId);
```
---
### Отмена операции<a name="отмена-операции"></a>
[Отмена операции в документации](https://docs.moneta.ru/protocols/#post-/-MRCHNT--cancel-transaction-request)
Чтобы отменить операцию нужно создать объект `MonetaSdk`, передать номер заказа и вызвать метод `confirmInvoice`, передав номер операции. В ответе будет возвращен массив с информацией об операции.
```php
include_once('vendor/autoload.php');
$orderId = $_POST['MNT_TRANSACTION_ID'];
$operationId = $_POST['MNT_OPERATION_ID'];
$mSdk = new Moneta\MonetaSdk($transactionId);
$mSdk->cancelInvoice($operationId);
```
---
### Привязка карты (получение токена для рекуррентных платежей)<a name="привязка-карты"></a>
[Привязка карты в документации](https://docs.moneta.ru/protocols/#post-/-MRCHNT--payment-request--get-token-only)
Для привязки карты создайте объект `MonetaSdk`, передав номер, сумму заказа, и, при необходимости, описание. Затем вызовите метод `createRecurrentInvoice` — он вернёт номер операции в системе Монета.в. Этот номер нужно передать в метод `getPaymentLink`, чтобы получить ссылку для оплаты, по которой надо будет перевести плательщика.
```php
include_once('vendor/autoload.php');
$mSdk = new Moneta\MonetaSdk(uniqid('', true), 456.78);
$operationId = $mSdk->createRecurrentInvoice();
$paymentLink = $mSdk->getPaymentLink($operationId);
if (!empty($paymentLink)) {
header('Location: ' . $paymentLink);
}
```
На платежной форме плательщику потребуется ввести свои карточный данные, а также поставить галочку в чекбоксе "Запомнить карту". После успешной оплаты, на указанный PayURL, указанный в настройках бизнес-счета будет отправлено http-уведомление, в котором будет передан токен для рекуррентных платежей (название параметра в уведомлении: `paymenttoken`). Чтобы проводить рекуррентный платеж без дальнейшего участия плательщика: требуется записать токен в базу данны.___
### Оплата по рекуррентному токену<a name="рекуррентный-платеж"></a>
[Оплата по рекуррентному токену в документации](https://docs.moneta.ru/protocols/#post-/-MRCHNT--payment-request--by-token)
Чтобы привязать карту, создайте объект `MonetaSdk`, передав номер заказа, сумму и, при необходимости, описание. Затем вызовите метод recurringPayment, передав токен плательщика, который получили и сохранили в сценарии "[Привязка карты (получение токена для рекуррентных платежей)](#привязка-карты)". В ответе вы получите массив с информацией об операции.
```php
include_once("moneta-sdk-lib/autoload.php");
$paymentToken = '123456';
$mSdk = new Moneta\MonetaSdk(uniqid('', true), 123.45, 'Оплата за подписку, январь 2025');
$mSdk->recurringPayment($paymentToken);
```
> Обратите внимание: при вызове `recurringPayment` в системе Монеты к переданному номеру заказа добавится "_MONETA" с временной меткой. Например, "6787bc9f456b29.67450389_MONETA1736948895". Это нужно для уникальности номера заказа, иначе операция не создастся. Чтобы получить исходный номер заказа из уведомления, разделите MNT_TRANSACTION_ID с помощью функции `explode`: `explode('_MONETA', $transactionId)[0]`.
---
### Возврат по операции<a name="возврат"></a>
[Возврат по операции в документации (стр. 218)](https://www.moneta.ru/doc/MONETA.MerchantAPI.v2.ru.pdf)
Чтобы выполнить возврат, создайте объект `MonetaSdk`, передав номер, сумму возврата и, при необходимости, описание. Затем вызовите метод refund, передав номер операции из системы Монета. В ответе вы получите массив с информацией о возврате.
```php
include_once("moneta-sdk-lib/autoload.php");
$mSdk = new Moneta\MonetaSdk(uniqid('', true), 123.45, 'Возврат по заказу ' . uniqid('', true));
$operationId = 1234567890;
$mSdk->refund($operationId);
```
---
### Получить детали операции по ID<a name="детали-операции-по-id"></a>
[Возврат по операции в документации (стр. 240)](https://www.moneta.ru/doc/MONETA.MerchantAPI.v2.ru.pdf)
Создайте объект `MonetaSdk`, передав пустой номер заказа. Затем вызовите метод `getOperationDetailsById`, передав номер операции, по которой нужно получить информацию. В ответе вам вернется массив с информацией об операции в системе Монета.
```php
include_once("moneta-sdk-lib/autoload.php");
$mSdk = new Moneta\MonetaSdk('');
$operationId = 1234567890;
$mSdk->getOperationDetailsById($operationId);
```
---
## Документация SDK <a name="Документация"></a>
- #### [Базовые методы](baseMethods.md);
- #### [Описание config-файлов](config.md);
- #### [Обработка http-уведомлений от Монеты](notifications.md);

180
docs/notifications.md Normal file
View File

@ -0,0 +1,180 @@
## Обработка http-уведомлений от Монеты
[Документация Монеты](https://docs.moneta.ru/)
* [Минимальный ответ на платежное уведомление (PayURL)](#Минимальный-ответ-pay-url)
* [Ответ с передачей номенклатуры (PayURL)](#Ответ-с-номенклатурой-pay-url)
* [Ответ на проверочный запрос с передачей номенклатуры (CheckURL)](#Ответ-с-номенклатурой-pay-url)
* [Документация SDK](#Документация)
---
### Минимальный ответ на платежное уведомление (PayURL)<a name="Минимальный-ответ-pay-url"></a>
[Минимальный ответ в документации](https://docs.moneta.ru/payments/payment-notification/)
Чтобы сгенерировать минимальный ответ для платежного уведомления от Монеты, требуется создать объект `MonetaSDK` и передать номер заказа. В результате для Монеты будет предоставлен минимальный ответ `SUCCESS` и на стороне платежной системы статус операции будет изменен на "Выполнена"
```php
include_once('vendor/autoload.php');
$orderId = $_POST['MNT_TRANSACTION_ID'];
$mSdk = new Moneta\MonetaSdk($orderId);
$mSdk->responseToPaymentNotification();
```
---
### Ответ с передачей номенклатуры (PayURL)<a name="Ответ-с-номенклатурой-pay-url"></a>
[Ответ с передачей номенклатуры в документации (раздел "Передача номенклатуры через ответ скрипта Pay URL")](https://docs.moneta.ru/54-fz/module/_index.files/Assistant54FZ.pdf)
Чтобы передать номенклатуру в ответе на платежное уведомление, нужно создать объект `MonetaSdkReceipt` и заполнить переменные объекта:
1. `items`* --- переменная товаров, тип `array`.
В примере ниже показан максимальный и минимальный набор передаваемых параметров товара. Подробное о параметрах и их значениях можно прочитать в [документации раздел "Передача номенклатуры через ответ скрипта Pay URL"](https://docs.moneta.ru/54-fz/module/_index.files/Assistant54FZ.pdf).
> Обратите внимание, что значения `vat` отличаются от того, что написано в документации:
> `none` - без НДС
> `vat0` - НДС по ставке 0%
> `vat10` - НДС чека по ставке 10%
> `vat110` - НДС чека по расчетной ставке 10/110
> `vat20` - НДС чека по ставке 20%
> `vat120` - НДС чека по расчетной ставке 20/120
> `vat5` - 5%
> `vat15` - по расчётной ставке 5%
> `vat7` - 7%
> `vat17` - по расчётной ставке 7
2. `customer`* --- переменная плательщика, тип `array`.
Используется для отправки чека. Параметр `email` --- обязательный
3. `delivery` --- переменная доставки, тип `float`.
Если есть доставка, то указать ее стоимость.
Параметры, отмеченные *, являются обязательными. Их нужно передать при создании объекта MonetaSDKReceipt.
После этого создайте объект `MonetaSDK`, передав номер заказа и сумму. Затем вызовите метод `responseToPaymentNotification`, передайте в него ранее созданный объект `MonetaSdkReceipt`. В результате система Монета получит ответ в формате XML, статус операции изменится на "Выполнена", а в кассовый сервис [kassa.payanyway](https://kassa.payanyway.ru/) будет передана номенклатура для печати чеков.
```php
include_once('vendor/autoload.php');
$mSdkReceipt = new Moneta\MonetaSdkReceipt();
// "Тестовый товар №1" ——— максимальный набор параметров товара
// "Тестовый товар №2" ——— минимальный набор параметров товара
$mSdkReceipt->items = [
[
'name' => 'Тестовый товар №1',
'price' => 123.45,
'quantity' => 1,
'measure' => 'шт',
"paymentMethod" => "full_payment",
"paymentObject" => "commodity",
'vat' => 'none',
'agentInfo' => [
'type' => 'payment_agent',
],
'supplierInfo' => [
'name' => 'Поставщик 1',
'inn' => '1234567890',
'phones' => [
'79995558844',
'79998855221'
]
]
],
[
'name' => 'Тестовый товар №2',
'price' => 999,
'quantity' => 2,
]
];
$mSdkReceipt->customer = [
'email' => 'com@moneta.ru',
'phone' => '74956465848'
];
$mSdkReceipt->delivery = 456.78;
$orderId = $_POST['MNT_TRANSACTION_ID'];
$mSdk = new Moneta\MonetaSdk($orderId);
$mSdk->responseToPaymentNotification($mSdkReceipt);
```
---
### Ответ на проверочный запрос с передачей номенклатуры (CheckURL)<a name="Ответ-с-номенклатурой-check-url"></a>
[Ответ на проверочный запрос с передачей номенклатуры (раздел "Ответ на проверочный запрос (check url - уведомление)")](https://www.payanyway.ru/info/p/ru/public/merchants/cmsspecification.pdf)
Если вы используете кассу БПА ПА (Payanyway) и в настройках счёта указан CheckURL, вам нужно ответить на проверочный запрос, передав номенклатуру. Ответ нужно предоставить до оплаты. Если система магазина не ответит на запрос, пользователь не сможет перейти к оплате.
Чтобы передать номенклатуру в ответе, создайте объект `MonetaSdkReceipt` и заполните его переменные:
1. `items`* --- переменная товаров, тип `array`.
В примере ниже показан максимальный и минимальный набор передаваемых параметров товара. Подробное о параметрах и их значениях можно прочитать в документации в разделе "Ответ на проверочный запрос (check url - уведомление)".
2. `customer`* --- переменная плательщика, тип `array`.
Используется для отправки чека. Параметр `email` --- обязательный
3. `delivery` --- переменная доставки, тип `float`.
Если есть доставка, то указать ее стоимость.
`*` --- обязательная переменная, её нужно заполнить.
После заполнения переменных создайте объект `MonetaSDK`, передав номер заказа и сумму. Затем вызовите метод `responseToCheckRequest`, передав в него ранее созданный объект `MonetaSdkReceipt`. В результате система Монета получит ответ в формате JSON, и пользователь сможет перейти на страницу оплаты.
```php
include_once('vendor/autoload.php');
$mSdkReceipt = new Moneta\MonetaSdkReceipt();
$mSdkReceipt->items = [
[
'name' => 'Тестовый товар №1',
'price' => 123.45,
'quantity' => 1,
'measure' => 'шт',
"paymentMethod" => "full_payment",
"paymentObject" => "commodity",
'vat' => 'none',
'agentInfo' => [
'payingAgent' => [
'operation' => 'Наименование операции банковского платежного агента',
'phones' => [
'79995558844',
'79998855221'
]
],
'supplierInfo' => [
'name' => 'Поставщик 1',
'inn' => '1346',
'phones' => [
'79995558844',
'79998855221'
]
]
]
],
[
'name' => 'Тестовый товар2',
'price' => 999,
'quantity' => 2,
]
];
$mSdkReceipt->customer = [
'name' => 'Иванов Иван Иванович',
'inn' => '1234567890',
'email' => 'com@moneta.ru',
'phone' => '75556664477'
];
$mSdkReceipt->additionalCheckProp = 'Дополнительный реквизит чека';
$mSdkReceipt->additionalUserProps = [
'name' => 'Доп. реквизиты пользователя',
'value' => 'Значение',
];
$mSdkReceipt->delivery = 456.78;
$orderId = $_POST['MNT_TRANSACTION_ID'];
$amount = $_POST['MNT_AMOUNT'];
$mSdk = new Moneta\MonetaSdk($orderId, $amount);
$mSdk->responseToCheckRequest($mSdkReceipt);
```
> **Если вы передаете номенклатуру в ответе на проверочный запрос, то на платежное уведомление можно отдать минимальный ответ в виде SUCCESS ([Пример](#Минимальный-ответ-pay-url))**.
---
## Документация SDK <a name="Документация"></a>
- #### [Описание config-файлов](config.md);
- #### [Базовые методы](baseMethods.md);
- #### [Методы MerchantAPI](merchantAPI.md).

432
src/MonetaSdk.php Normal file
View File

@ -0,0 +1,432 @@
<?php
namespace Moneta;
use Moneta\MonetaSdkService;
use Moneta\MonetaSdkSettings;
use Moneta\MonetaSdkReceipt;
class MonetaSdk {
/**
* Assistant endpoints
*/
const PROD_ENDPOINT = 'https://www.payanyway.ru/assistant.htm?';
const DEMO_ENDPOINT = 'https://demo.moneta.ru/assistant.htm?';
/**
* Exception messages text
*/
const EXCEPTION_MERCHANT_API_NO_TRANSACTION_ID = 'There is no operation number in the response.';
const EXCEPTION_VAR_AMOUNT_EMPTY = 'The amount argument is not passed.';
private
$configPath,
$transactionId,
$amount,
$description;
public function __construct($transactionId, ?float $amount = null, ?string $description = null, ?string $configPath = null) {
$this->configPath = $configPath;
$this->transactionId = $transactionId;
$this->amount = $amount;
$this->description = $description;
}
/**
* @return string
* @throws MonetaSdkException
*/
public function getAssistantPaymentLink() {
if (!isset($this->amount)) {
throw new MonetaSdkException(self::EXCEPTION_VAR_AMOUNT_EMPTY);
}
$httpParams = [
'MNT_ID' => MonetaSdkSettings::getSettings('id', $this->configPath),
'MNT_AMOUNT' => number_format($this->amount, 2, '.', ''),
'MNT_TRANSACTION_ID' => $this->transactionId,
'MNT_CURRENCY_CODE' => 'RUB',
'MNT_DESCRIPTION' => $this->description,
'MNT_SIGNATURE' => MonetaSdkService::createSignature('generateLink', $this->transactionId, $this->configPath, $this->amount),
'MNT_SUCCESS_URL' => MonetaSdkSettings::getSettings('success', $this->configPath),
'MNT_INPROGRESS_URL' => MonetaSdkSettings::getSettings('inprogress', $this->configPath),
'MNT_FAIL_URL' => MonetaSdkSettings::getSettings('fail', $this->configPath),
'MNT_RETURN_URL' => MonetaSdkSettings::getSettings('return', $this->configPath),
'moneta.locale' => MonetaSdkSettings::getSettings('locale', $this->configPath),
'paymentSystem.unitId' => MonetaSdkSettings::getSettings('unit_id', $this->configPath),
'paymentSystem.limitIds' => MonetaSdkSettings::getSettings('limit_ids', $this->configPath),
];
$httpParams = array_diff($httpParams, ['']);
$endpoint = MonetaSdkSettings::getSettings('demo_mode', $this->configPath) ? self::DEMO_ENDPOINT : self::PROD_ENDPOINT;
$paymentLink = $endpoint . http_build_query($httpParams);
return $paymentLink;
}
/**
* @param MonetaSdkReceipt $mSdkR
* @param string $transactionId
* @return string
* @throws MonetaSdkException
*/
public function responseToCheckRequest(MonetaSdkReceipt $mSdkR) {
if (!isset($this->amount)) {
throw new MonetaSdkException(self::EXCEPTION_VAR_AMOUNT_EMPTY);
}
$response = [
'id' => MonetaSdkSettings::getSettings('id', $this->configPath),
'transactionId' => $this->transactionId,
'amount' => number_format($this->amount, 2, '.', ''),
'signature' => MonetaSdkService::createSignature('checkRequest', $this->transactionId, $this->configPath),
'resultCode' => '402',
'receipt' => $mSdkR->getJsonReceipt()
];
header('Content-Type: application/json; charset=utf-8');
echo json_encode($response, JSON_UNESCAPED_UNICODE);
die;
}
/**
* @param MonetaSdkReceipt $mSdkR
* @param string $transactionId
* @return string
* @throws MonetaSdkException
*/
public function responseToPaymentNotification(?MonetaSdkReceipt $mSdkR = null) {
if (isset($mSdkR)) {
$xmlResponse = '<?xml version="1.0" encoding="UTF-8"?>';
$xmlResponse .= '<MNT_RESPONSE>';
$xmlResponse .= ' <MNT_ID>' . MonetaSdkSettings::getSettings('id', $this->configPath) . '</MNT_ID>';
$xmlResponse .= ' <MNT_TRANSACTION_ID>' . $this->transactionId . '</MNT_TRANSACTION_ID>';
$xmlResponse .= ' <MNT_RESULT_CODE>200</MNT_RESULT_CODE>';
$xmlResponse .= ' <MNT_SIGNATURE>' . MonetaSdkService::createSignature('paymentNotification', $this->transactionId, $this->configPath) . '</MNT_SIGNATURE>';
$xmlResponse .= ' <MNT_ATTRIBUTES>';
$xmlResponse .= ' <MNT_ATTRIBUTE>';
$xmlResponse .= ' <KEY>INVENTORY</KEY>';
$xmlResponse .= ' <VALUE>' . $mSdkR->getXmlItems() . '</VALUE>';
$xmlResponse .= ' </MNT_ATTRIBUTE>';
if (isset($mSdkR->customer['email'])) {
$xmlResponse .= ' <MNT_ATTRIBUTE>';
$xmlResponse .= ' <KEY>CUSTOMER</KEY>';
$xmlResponse .= ' <VALUE>' . $mSdkR->customer['email'] . '</VALUE>';
$xmlResponse .= ' </MNT_ATTRIBUTE>';
}
if (isset($mSdkR->customer['phone'])) {
$xmlResponse .= ' <MNT_ATTRIBUTE>';
$xmlResponse .= ' <KEY>PHONE</KEY>';
$xmlResponse .= ' <VALUE>' . $mSdkR->customer['phone'] . '</VALUE>';
$xmlResponse .= ' </MNT_ATTRIBUTE>';
}
if (isset($mSdkR->delivery)) {
$xmlResponse .= ' <MNT_ATTRIBUTE>';
$xmlResponse .= ' <KEY>DELIVERY</KEY>';
$xmlResponse .= ' <VALUE>' . number_format($mSdkR->delivery, 2, '.', '') . '</VALUE>';
$xmlResponse .= ' </MNT_ATTRIBUTE>';
}
$xmlResponse .= ' </MNT_ATTRIBUTES>';
$xmlResponse .= '</MNT_RESPONSE>';
header("Content-type: application/xml");
echo $xmlResponse;
die;
}
echo 'SUCCESS';
die;
}
/**
* @param string $operationId
* @return string
*/
public function getPaymentLink($operationId) {
$endpoint = MonetaSdkSettings::getSettings('demo_mode', $this->configPath) ? self::DEMO_ENDPOINT : self::PROD_ENDPOINT;
$httpParams = [
'operationId' => $operationId,
'moneta.locale' => MonetaSdkSettings::getSettings('locale', $this->configPath),
'paymentSystem.unitId' => MonetaSdkSettings::getSettings('unit_id', $this->configPath),
'paymentSystem.limitIds' => MonetaSdkSettings::getSettings('limit_ids', $this->configPath),
'MNT_SUCCESS_URL' => MonetaSdkSettings::getSettings('success', $this->configPath),
'MNT_INPROGRESS_URL' => MonetaSdkSettings::getSettings('inprogress', $this->configPath),
'MNT_FAIL_URL' => MonetaSdkSettings::getSettings('fail', $this->configPath),
'MNT_RETURN_URL' => MonetaSdkSettings::getSettings('return', $this->configPath),
'MNT_SIGNATURE' => MonetaSdkService::createSignature('generateLink', $this->transactionId, $this->configPath, number_format($this->amount, 2, '.', ''),),
];
$httpParams = array_diff($httpParams, ['']);
$paymentLink = $endpoint . http_build_query($httpParams);
return $paymentLink;
}
/**
* @return int
* @throws MonetaSdkException
*/
public function createInvoice($isTwoPhase = false) {
if (!isset($this->amount)) {
throw new MonetaSdkException(self::EXCEPTION_VAR_AMOUNT_EMPTY);
}
$params = [
'Envelope' => [
'Header' => [
'Security' => [
'UsernameToken' => [
'Username' => MonetaSdkSettings::getSettings('username', $this->configPath),
'Password' => MonetaSdkSettings::getSettings('password', $this->configPath)
]
]
],
'Body' => [
'InvoiceRequest' => [
'payer' => 'card',
'payee' => MonetaSdkSettings::getSettings('id', $this->configPath),
'amount' => number_format($this->amount, 2, '.', ''),
'clientTransaction' => (string) $this->transactionId,
]
]
]
];
if ($isTwoPhase) {
$params['Envelope']['Body']['InvoiceRequest']['operationInfo']['attribute'] = [
[
'key' => 'AUTHORIZEONLY',
'value' => '1'
]
];
}
$response = MonetaSdkService::sendCurl($params, $this->configPath);
if (!isset($response['Envelope']['Body']['InvoiceResponse']['transaction'])) {
throw new MonetaSdkException(self::EXCEPTION_MERCHANT_API_NO_TRANSACTION_ID . " Request result: " . json_encode($response, JSON_UNESCAPED_UNICODE));
}
return $response['Envelope']['Body']['InvoiceResponse']['transaction'];
}
/**
* @param string $operationId
* @return array
*/
public function confirmInvoice($operationId) {
$params = [
'Envelope' => [
'Header' => [
'Security' => [
'UsernameToken' => [
'Username' => MonetaSdkSettings::getSettings('username', $this->configPath),
'Password' => MonetaSdkSettings::getSettings('password', $this->configPath)
]
]
],
'Body' => [
'ConfirmTransactionRequest' => [
'transactionId' => $operationId,
'paymentPassword' => MonetaSdkSettings::getSettings('payment_password', $this->configPath),
]
]
]
];
$response = MonetaSdkService::sendCurl($params, $this->configPath);
return $response['Envelope']['Body'];
}
/**
* @param string $operationId
* @return array
*/
public function cancelInvoice($operationId) {
$params = [
'Envelope' => [
'Header' => [
'Security' => [
'UsernameToken' => [
'Username' => MonetaSdkSettings::getSettings('username', $this->configPath),
'Password' => MonetaSdkSettings::getSettings('password', $this->configPath)
]
]
],
'Body' => [
'CancelTransactionRequest' => [
'transactionId' => $operationId
]
]
]
];
$response = MonetaSdkService::sendCurl($params, $this->configPath);
return $response['Envelope']['Body'];
}
/**
* @return int
* @throws MonetaSdkException
*/
public function createRecurrentInvoice() {
if (!isset($this->amount)) {
throw new MonetaSdkException(self::EXCEPTION_VAR_AMOUNT_EMPTY);
}
$params = [
'Envelope' => [
'Header' => [
'Security' => [
'UsernameToken' => [
'Username' => MonetaSdkSettings::getSettings('username', $this->configPath),
'Password' => MonetaSdkSettings::getSettings('password', $this->configPath)
]
]
],
'Body' => [
'InvoiceRequest' => [
'payer' => 'card',
'payee' => MonetaSdkSettings::getSettings('id', $this->configPath),
'amount' => number_format($this->amount, 2, '.', ''),
'clientTransaction' => (string) $this->transactionId,
'description' => $this->description ?? 'Рекуррентный платеж по заказу №' . $this->transactionId,
'operationInfo' => [
'attribute' => [
[
'key' => 'PAYMENTTOKEN',
'value' => 'request'
]
]
]
]
]
]
];
$response = MonetaSdkService::sendCurl($params, $this->configPath);
if (!isset($response['Envelope']['Body']['InvoiceResponse']['transaction'])) {
throw new MonetaSdkException(self::EXCEPTION_MERCHANT_API_NO_TRANSACTION_ID . " Request result: " . json_encode($response, JSON_UNESCAPED_UNICODE));
}
return $response['Envelope']['Body']['InvoiceResponse']['transaction'];
}
/**
* @param string $token
* @return array
*/
public function recurringPayment($token) {
if (!isset($this->amount)) {
throw new MonetaSdkException(self::EXCEPTION_VAR_AMOUNT_EMPTY);
}
$params = [
'Envelope' => [
'Header' => [
'Security' => [
'UsernameToken' => [
'Username' => MonetaSdkSettings::getSettings('username', $this->configPath),
'Password' => MonetaSdkSettings::getSettings('password', $this->configPath)
]
]
],
'Body' => [
'PaymentRequest' => [
'payer' => 'card',
'payee' => MonetaSdkSettings::getSettings('id', $this->configPath),
'amount' => number_format($this->amount, 2, '.', ''),
'clientTransaction' => (string) $this->transactionId . '_MONETA' . time(),
'description' => $this->description ?? 'Рекуррентный платеж по заказу ' . $this->transactionId,
'operationInfo' => [
'attribute' => [
[
'key' => 'PAYMENTTOKEN',
'value' => $token
]
]
]
]
]
]
];
$response = MonetaSdkService::sendCurl($params, $this->configPath);
return $response['Envelope']['Body'];
}
/**
* @param int $operationId
* @return array
*/
public function refund($operationId) {
if (!isset($this->amount)) {
throw new MonetaSdkException(self::EXCEPTION_VAR_AMOUNT_EMPTY);
}
$params = [
'Envelope' => [
'Header' => [
'Security' => [
'UsernameToken' => [
'Username' => MonetaSdkSettings::getSettings('username', $this->configPath),
'Password' => MonetaSdkSettings::getSettings('password', $this->configPath)
]
]
],
'Body' => [
'RefundRequest' => [
'amount' => number_format($this->amount, 2, '.', ''),
'paymentPassword' => MonetaSdkSettings::getSettings('payment_password', $this->configPath),
'transactionId' => $operationId,
'description' => $this->description ?? 'Возврат по операции ' . $this->transactionId,
'clientTransaction' => (string) $this->transactionId,
]
]
]
];
$response = MonetaSdkService::sendCurl($params, $this->configPath);
return $response['Envelope']['Body'];
}
/**
* @param string $operationId
* @return array
*/
public function getOperationDetailsById($operationId) {
$params = [
'Envelope' => [
'Header' => [
'Security' => [
'UsernameToken' => [
'Username' => MonetaSdkSettings::getSettings('username', $this->configPath),
'Password' => MonetaSdkSettings::getSettings('password', $this->configPath)
]
]
],
'Body' => [
'GetOperationDetailsByIdRequest' => $operationId
]
]
];
$response = MonetaSdkService::sendCurl($params, $this->configPath);
return $response['Envelope']['Body'];
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace Moneta;
class MonetaSdkException extends \Exception {
public function __construct($message, $code = 0, ?Exception $previous = null) {
parent::__construct($message, $code, $previous);
}
public function __toString() {
return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
}
}

167
src/MonetaSdkReceipt.php Normal file
View File

@ -0,0 +1,167 @@
<?php
namespace Moneta;
class MonetaSdkReceipt {
/**
* Exception messages text
*/
const EXCEPTION_REQUIRED_ITEM_PARAM = "This item param is required: ";
const EXCEPTION_REQUIRED_CUSTOMER_PARAM = "This customer param is required: ";
const EXCEPTION_ARRAY_ITEMS_IS_REQUIRED = "The items array is required";
public array $items, $customer, $additionalUserProps;
public string $additionalCheckProp;
public float $delivery;
/**
* @return array
*/
public function getJsonReceipt() {
$receipt = [
'client' => $this->getJsonCustomer(),
'items' => $this->getJsonItems(),
];
if (isset($this->additionalCheckProp)) {
$receipt['additionalCheckProp'] = $this->additionalCheckProp;
}
if (isset($this->additionalUserProps)) {
$receipt['additionalUserProps'] = $this->additionalUserProps;
}
return $receipt;
}
/**
* @return array
* @throws MonetaSdkException
*/
private function getJsonItems() {
$this->checkReceiptParams();
foreach ($this->items as $iteration => $item) {
$receiptItems[] = array_diff([
'name' => $item['name'],
'price' => $item['price'],
'quantity' => $item['quantity'],
'measure' => $item['measure'] ?? '',
'paymentMethod' => $item['paymentMethod'] ?? '',
'paymentObject' => $item['paymentObject'] ?? '',
'vat' => $item['vat'] ?? 'none',
], ['']);
if (isset($item['agentInfo']['payingAgent'])) {
$receiptItems[$iteration]['agentInfo']['payingAgent'] = [
'operation' => $item['agentInfo']['payingAgent']['operation'],
'phones' => $item['agentInfo']['payingAgent']['phones']
];
}
if (isset($item['agentInfo']['supplierInfo'])) {
$receiptItems[$iteration]['agentInfo']['supplierInfo'] = [
'phones' => $item['agentInfo']['supplierInfo']['phones'],
'name' => $item['agentInfo']['supplierInfo']['name'],
'inn' => $item['agentInfo']['supplierInfo']['inn'],
];
}
}
if (isset($this->delivery)) {
$receiptItems[] = [
'name' => 'Доставка',
'price' => $this->delivery,
'quantity' => 1,
'vat' => 'none',
'paymentObject' => 'service'
];
}
return $receiptItems;
}
/**
* @return array
* @throws MonetaSdkException
*/
private function getJsonCustomer() {
$this->checkReceiptParams(false);
$customer = [
'name' => $this->customer['name'] ?? '',
'inn' => $this->customer['inn'] ?? '',
'email' => $this->customer['email'],
'phone' => $this->customer['phone'] ?? '',
];
$customer = array_diff($customer, ['']);
return $customer;
}
/**
* @return array
* @throws MonetaSdkException
*/
public function getXmlItems() {
$this->checkReceiptParams();
foreach ($this->items as $iteration => $item) {
$receiptItems[] = array_diff([
'name' => $item['name'],
'price' => $item['price'],
'quantity' => $item['quantity'],
'vatTag' => MonetaSdkService::getXmlVat($item['vat'] ?? 'none'),
'pm' => $item['paymentMethod'] ?? 'full_payment',
'po' => $item['paymentObject'] ?? 'commodity',
]);
if (isset($item['agentInfo']['type'])) {
$receiptItems[$iteration]['agentInfo']['type'] = $item['agentInfo']['type'];
}
if (isset($item['supplierInfo'])) {
$receiptItems[$iteration]['supplierInfo'] = [
'name' => $item['supplierInfo']['name'],
'inn' => $item['supplierInfo']['inn'],
'phones' => $item['supplierInfo']['phones'],
];
}
}
return json_encode($receiptItems, JSON_UNESCAPED_UNICODE);
}
/**
* @param bool $isItems
* @throws MonetaSdkException
*/
private function checkReceiptParams($isItems = true) {
switch ($isItems) {
case true:
if (!isset($this->items)) {
throw new MonetaSdkException(self::EXCEPTION_ARRAY_ITEMS_IS_REQUIRED);
}
foreach ($this->items as $i) {
if (!isset($i['name'])) {
throw new MonetaSdkException(self::EXCEPTION_REQUIRED_ITEM_PARAM . '"name"');
} else if (!isset($i['price'])) {
throw new MonetaSdkException(self::EXCEPTION_REQUIRED_ITEM_PARAM . '"price"');
} else if (!isset($i['quantity'])) {
throw new MonetaSdkException(self::EXCEPTION_REQUIRED_ITEM_PARAM . '"quantity"');
}
}
break;
case false:
if (!isset($this->customer['email'])) {
throw new MonetaSdkException(self::EXCEPTION_REQUIRED_CUSTOMER_PARAM . '"email"');
}
break;
default:
break;
}
}
}

111
src/MonetaSdkService.php Normal file
View File

@ -0,0 +1,111 @@
<?php
namespace Moneta;
class MonetaSdkService {
/**
* Exception messages text
*/
const EXCEPTION_ERROR_ACTION_NAME = "Wrong action name: ";
/**
* @param string $action
* @param string $transactionId
* @param float|int $amount
* @param string $subscriber
* @return string
* @throws MonetaSdkException
*/
public static function createSignature($action, $transactionId, $configPath, ?float $amount = null,) {
switch ($action) {
case 'generateLink':
return md5(
MonetaSdkSettings::getSettings('id', $configPath) .
$transactionId .
number_format($amount, 2, '.', '') .
MonetaSdkSettings::getSettings('currency', $configPath) .
'' .
0 .
MonetaSdkSettings::getSettings('secret', $configPath)
);
break;
case 'checkRequest':
return md5(
402 .
MonetaSdkSettings::getSettings('id', $configPath) .
$transactionId .
MonetaSdkSettings::getSettings('secret', $configPath)
);
break;
case 'paymentNotification':
return md5(
200 .
MonetaSdkSettings::getSettings('id', $configPath) .
$transactionId .
MonetaSdkSettings::getSettings('secret', $configPath)
);
break;
default:
throw new MonetaSdkException(self::EXCEPTION_ERROR_ACTION_NAME . $action);
break;
}
}
/**
* @param string $jsonVat
* @return string
*/
public static function getXmlVat($jsonVat) {
$xmlVatList = [
'none' => '1105',
'vat0' => '1104',
'vat10' => '1103',
'vat110' => '1107',
'vat20' => '7000',
'vat120' => '7001',
'vat5' => '1108',
'vat7' => '1109',
'vat15' => '1110',
'vat17' => '1111'
];
return isset($xmlVatList[$jsonVat]) ? $xmlVatList[$jsonVat] : '1105';
}
/**
* MerchantAPI query builder
*/
/**
* @return string
*/
private static function getApiUrl($configPath) {
$url = MonetaSdkSettings::getSettings('demo_mode', $configPath) ? MonetaSdkSettings::getSettings('payment_url', $configPath)['demo'] : MonetaSdkSettings::getSettings('payment_url', $configPath)['production'];
$urn = MonetaSdkSettings::getSettings('urn');
return $url . $urn;
}
/**
* @param array $params
* @return string
*/
public static function sendCurl($params, $configPath) {
$ch = curl_init(self::getApiUrl($configPath));
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params, JSON_UNESCAPED_UNICODE));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HEADER, false);
$result = curl_exec($ch);
curl_close($ch);
return json_decode($result, true);
}
}

57
src/MonetaSdkSettings.php Normal file
View File

@ -0,0 +1,57 @@
<?php
namespace Moneta;
class MonetaSdkSettings {
/**
* Config file names
*/
const SETTINGS_ACCOUNT = '/account.php';
const SETTINGS_API = '/api.php';
const SETTINGS_STORAGE = '/storage.php';
const SETTINGS_URL = '/url.php';
/**
* Exception messages text
*/
const EXCEPTION_ERROR_PARAM_NAME = 'There is no such parameter: ';
const EXCEPTION_NO_PARAM_FILE = "Config file not found: ";
/**
* @param null $configPath
* @param @nameParam
* @return array
* @throws MonetaSdkException
*/
public static function getSettings($nameParam, ?string $configPath = null) {
$configPath = $configPath ? $configPath : dirname(__DIR__) . '/config';
$arrayAccountSettings = self::getSettingsFromConfigFiles($configPath . self::SETTINGS_ACCOUNT);
$arrayApiSettings = require dirname(__DIR__) . '/config/api.php';
$arrayUrlSettings = self::getSettingsFromConfigFiles($configPath . self::SETTINGS_URL);
$allSettings = array_merge(
$arrayAccountSettings,
$arrayApiSettings,
$arrayUrlSettings
);
if (!isset($allSettings[$nameParam])) {
throw new MonetaSdkException(self::EXCEPTION_ERROR_PARAM_NAME . $nameParam);
}
return $allSettings[$nameParam];
}
/**
* @param $fileName
* @return array
* @throws MonetaSdkException
*/
private static function getSettingsFromConfigFiles($fileName) {
if (!file_exists($fileName)) {
throw new MonetaSdkException(self::EXCEPTION_NO_PARAM_FILE . $fileName);
}
return require($fileName);
}
}