moneta-sdk-php v2.0.0
This commit is contained in:
commit
7a455450ce
21
LICENSE
Normal file
21
LICENSE
Normal 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
157
README.md
Normal 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
21
autoload.php
Normal 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
31
composer.json
Normal 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
14
config/account.php
Normal 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
9
config/api.php
Normal 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
9
config/url.php
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'success' => '',
|
||||
'fail' => '',
|
||||
'inprogress' => '',
|
||||
'return' => '',
|
||||
'iframe_target' => '_parent'
|
||||
];
|
36
docs/baseMethods.md
Normal file
36
docs/baseMethods.md
Normal 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
41
docs/config.md
Normal 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
144
docs/merchantAPI.md
Normal 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
180
docs/notifications.md
Normal 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
432
src/MonetaSdk.php
Normal 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'];
|
||||
}
|
||||
}
|
13
src/MonetaSdkException.php
Normal file
13
src/MonetaSdkException.php
Normal 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
167
src/MonetaSdkReceipt.php
Normal 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
111
src/MonetaSdkService.php
Normal 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
57
src/MonetaSdkSettings.php
Normal 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);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user