Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f81c7f2fe | ||
|
|
6598b95bb8 | ||
|
|
d1ac3d989b | ||
|
|
d53430155a | ||
|
|
f94dc40eee | ||
|
|
c3189d2439 | ||
|
|
83f1d8d101 | ||
|
|
1e168ded8c |
@@ -4,7 +4,7 @@
|
|||||||

|

|
||||||

|

|
||||||
|
|
||||||
> **📦 Версия модуля: 1.0.0**
|
> **📦 Версия модуля: 1.0.4**
|
||||||
|
|
||||||
> **ℹ️ Совместимость версий OpenCart:**
|
> **ℹ️ Совместимость версий OpenCart:**
|
||||||
> 3.0.0.0, 3.0.1.1, 3.0.1.2, 3.0.2.0, 3.0.3.0, 3.0.3.1, 3.0.3.2, 3.0.3.3, 3.0.3.4, 3.0.3.5, 3.0.3.6, 3.0.3.7, 3.0.3.8, 3.0.3.9, 3.0.4.0, 3.0.4.1, 3.0.5.0
|
> 3.0.0.0, 3.0.1.1, 3.0.1.2, 3.0.2.0, 3.0.3.0, 3.0.3.1, 3.0.3.2, 3.0.3.3, 3.0.3.4, 3.0.3.5, 3.0.3.6, 3.0.3.7, 3.0.3.8, 3.0.3.9, 3.0.4.0, 3.0.4.1, 3.0.5.0
|
||||||
@@ -29,11 +29,11 @@
|
|||||||
│ │ ├── view/image/payment/payanyway.png
|
│ │ ├── view/image/payment/payanyway.png
|
||||||
│ │ └── view/template/extension/payment/payanyway.twig
|
│ │ └── view/template/extension/payment/payanyway.twig
|
||||||
│ └── catalog
|
│ └── catalog
|
||||||
│ ├── controller/extension/payment/payanyway.php
|
│ ├── controller/extension/payment/payanyway.php — форма оплаты, Check URL и Pay URL
|
||||||
│ ├── language/{en-gb,ru-ru}/extension/payment/payanyway.php
|
│ ├── language/{en-gb,ru-ru}/extension/payment/payanyway.php
|
||||||
│ ├── model/extension/payment/payanyway.php
|
│ ├── model/extension/payment/payanyway.php
|
||||||
│ └── view/theme/default/template/extension/payment/payanyway.twig
|
│ └── view/theme/default/template/extension/payment/payanyway.twig
|
||||||
├── install.xml
|
├── install.xml — OCMOD: приём Check/Pay URL методом POST (правка роутера витрины)
|
||||||
└── README.md
|
└── README.md
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -48,20 +48,31 @@
|
|||||||
- **«Редактировать»** — для перехода к настройкам
|
- **«Редактировать»** — для перехода к настройкам
|
||||||
4. ✏️ Заполните соответствующие поля в настройках способа оплаты:
|
4. ✏️ Заполните соответствующие поля в настройках способа оплаты:
|
||||||
|
|
||||||
| Поле | Описание |
|
| Поле | Описание |
|
||||||
|-------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------|
|
|-------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| **Включить модуль оплаты** | Включите или выключите модуль оплаты |
|
| **Включить модуль оплаты** | Включите или выключите модуль оплаты |
|
||||||
| **Номер счёта** | Ван номер расширенного счёта в системе [MONETA.RU](https://moneta.ru/) |
|
| **Номер счёта** | Ваш номер расширенного счёта в системе [MONETA.RU](https://moneta.ru/), только цифры |
|
||||||
| **Код проверки целостности данных** | Код проверки целостности данных, указанный в настройках расширенного счёта в системе [MONETA.RU](https://moneta.ru/) |
|
| **Код проверки целостности данных** | Код проверки целостности данных, указанный в настройках расширенного счёта в системе [MONETA.RU](https://moneta.ru/). Сохраняется ровно так, как введён, в том числе с символами `&`, `"`, `<`, `>` |
|
||||||
| **Сервер платежей** | `Боевой` / `Тестовый` |
|
| **Сервер платежей** | `Боевой` / `Демо` (демо-площадка MONETA.RU) |
|
||||||
| **НДС** | Выберите из списка |
|
| **Тестовый режим** | Имитация оплаты без реального списания средств. Должен совпадать с настройкой счёта в MONETA.RU: уведомление в другом режиме модуль отклоняет |
|
||||||
| **Валюта платежа** | `RUB` |
|
| **Фискализация чеков** | Включайте, только если к счёту подключён кассовый сервис [kassa.payanyway.ru](https://kassa.payanyway.ru/). Включена — на проверочный запрос модуль отвечает чеком для кассы (без кассы MONETA.RU вернёт ошибку `-700`). Выключена — в операцию уходят только позиции заказа и контакты покупателя. По умолчанию включена |
|
||||||
| **Статусы заказа** | Выберите соответствующие статусы заказа из списка |
|
| **Email для чеков** | Обязателен при фискализации. Подставляется в чек, только если у покупателя нет ни e-mail, ни телефона (ФИО покупателя в чеке остаётся) |
|
||||||
| **Обрабатываемый** | Укажите статус заказа, который выставляется при его создании |
|
| **НДС** | Ставка НДС всех позиций чека |
|
||||||
| **Успешный** | Укажите статус заказа, который выставляется при успешной оплате |
|
| **Признак способа расчёта** | Для товаров, доставки и сборов. Обычно `Полный расчёт`. Проданные подарочные сертификаты всегда идут авансом |
|
||||||
| **Неуспешный** | Укажите статус заказа, который выставляется при ошибке оплаты |
|
| **Признак предмета расчёта** | Для товаров. Доставка и сборы всегда идут услугой, подарочные сертификаты — платежом |
|
||||||
| **Регион отображения** | Географическая зона, в которой будет отображаться способ оплаты |
|
| **Валюта платежа** | `RUB` |
|
||||||
| **Порядок сортировки** | Определяет порядок отображения платежного метода в списке методов оплаты при оформлении заказа. Чем меньше число, тем выше позиция в списке |
|
| **Статусы заказа** | Выберите соответствующие статусы заказа из списка |
|
||||||
|
| **Обрабатываемый** | Укажите статус заказа, который выставляется при его создании |
|
||||||
|
| **Успешный** | Укажите статус заказа, который выставляется при успешной оплате |
|
||||||
|
| **Неуспешный** | Укажите статус заказа, который выставляется при ошибке оплаты |
|
||||||
|
| **Отменённые** | Заказ в этих статусах не оплачивается: на проверочный запрос модуль отвечает отказом. По умолчанию `Canceled`, `Canceled Reversal`, `Voided` |
|
||||||
|
| **URL для уведомлений** | Адрес Check URL и Pay URL для настроек счёта MONETA.RU, кнопка «Скопировать» |
|
||||||
|
| **Регион отображения** | Географическая зона, в которой будет отображаться способ оплаты |
|
||||||
|
| **Порядок сортировки** | Определяет порядок отображения платежного метода в списке методов оплаты при оформлении заказа. Чем меньше число, тем выше позиция в списке |
|
||||||
|
|
||||||
|
Сумма позиций чека всегда равна сумме оплаты: налоги OpenCart входят в цену товаров, скидки (купоны, подарочные сертификаты, бонусные баллы) распределяются по товарам, доставка и сборы идут отдельными позициями. В истории заказа при оплате сохраняется номер операции MONETA.RU: «Заказ оплачен. Номер операции: N».
|
||||||
|
|
||||||
|
> ⚠️ **После обновления модуля** нажмите **«Модули / Расширения» → «Модификации» → «Обновить»**, затем откройте настройки PayAnyWay, проверьте новые поля (фискализация после обновления включена) и нажмите **«Сохранить»**. Пока при включённой фискализации не задан «Email для чеков», над формой настроек показывается предупреждение.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -76,7 +87,7 @@
|
|||||||
| **Тестовый режим** | `Нет` |
|
| **Тестовый режим** | `Нет` |
|
||||||
| **Check URL** | `https://your_site_name/index.php?route=extension/payment/payanyway/callback` |
|
| **Check URL** | `https://your_site_name/index.php?route=extension/payment/payanyway/callback` |
|
||||||
| **Pay URL** | `https://your_site_name/index.php?route=extension/payment/payanyway/callback` |
|
| **Pay URL** | `https://your_site_name/index.php?route=extension/payment/payanyway/callback` |
|
||||||
| **HTTP method** | `GET` / `POST` |
|
| **HTTP method<sup>\*</sup>** | `GET` или `POST` (требуется настройка) |
|
||||||
| **Можно переопределять настройки в URL** | `Да` |
|
| **Можно переопределять настройки в URL** | `Да` |
|
||||||
| **Подпись формы оплаты обязательна** | `Да` |
|
| **Подпись формы оплаты обязательна** | `Да` |
|
||||||
| **Код проверки целостности данных** | `ваш_код` (произвольный набор символов) |
|
| **Код проверки целостности данных** | `ваш_код` (произвольный набор символов) |
|
||||||
@@ -87,6 +98,18 @@
|
|||||||
|
|
||||||
> ⚠️ **Важно!** Для кириллического домена PayURL и CheckURL должны быть указаны в кодировке [Punycode](https://2ip.ru/punycode/).
|
> ⚠️ **Важно!** Для кириллического домена PayURL и CheckURL должны быть указаны в кодировке [Punycode](https://2ip.ru/punycode/).
|
||||||
|
|
||||||
|
### <sup>\*</sup> 📨 Уведомления методом POST
|
||||||
|
|
||||||
|
При **HTTP method** = `POST` MONETA.RU переносит параметры из адреса Check URL / Pay URL в тело запроса, в том числе `route=extension/payment/payanyway/callback`. Штатный OpenCart 3 ищет маршрут только в адресе и без доработки отвечает главной страницей, а платёжная форма показывает «Код ошибки: 302».
|
||||||
|
|
||||||
|
Модуль решает это модификацией OCMOD из `install.xml`: маршрут колбэка (и только его) берётся из тела запроса. Чтобы модификация заработала:
|
||||||
|
|
||||||
|
1. Устанавливайте модуль только через **«Модули / Расширения» → «Установка расширений»** (архив `payanyway.ocmod.zip`). При заливке файлов по FTP модификация не регистрируется.
|
||||||
|
2. После установки или обновления модуля откройте **«Модули / Расширения» → «Модификации»** (Extensions → Modifications) и нажмите синюю кнопку **«Обновить»** вверху справа. Повторяйте это после включения, выключения или удаления любой модификации и после кнопки «Очистить».
|
||||||
|
3. Откройте настройки PayAnyWay. Если модификация не применена, над формой будет жёлтое предупреждение. Причину смотрите на вкладке «Лог» в «Модификациях»: строка `NOT FOUND` у файла `catalog/controller/startup/router.php` означает, что роутер уже изменён другой модификацией.
|
||||||
|
|
||||||
|
Если модификацию применить не удаётся, выберите в настройках счёта **HTTP method** = `GET`: при GET модификация не нужна.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📚 Полезные ресурсы OpenCart
|
## 📚 Полезные ресурсы OpenCart
|
||||||
|
|||||||
+20
-1
@@ -2,7 +2,26 @@
|
|||||||
<modification>
|
<modification>
|
||||||
<name>PayAnyWay</name>
|
<name>PayAnyWay</name>
|
||||||
<code>payanyway</code>
|
<code>payanyway</code>
|
||||||
<version>1.0.0</version>
|
<version>1.0.4</version>
|
||||||
<author>PayAnyWay</author>
|
<author>PayAnyWay</author>
|
||||||
<link>https://payanyway.ru/</link>
|
<link>https://payanyway.ru/</link>
|
||||||
|
<!--
|
||||||
|
При методе POST MONETA.RU переносит query string Check/Pay URL в тело запроса:
|
||||||
|
route=extension/payment/payanyway/callback приходит в POST, а OpenCart берёт маршрут
|
||||||
|
только из GET и отдаёт главную страницу. Маршрут колбэка (и только его) берётся из POST,
|
||||||
|
если в GET маршрута нет. После установки — «Расширения» → «Модификации» → «Обновить».
|
||||||
|
Строка не найдена (роутер изменён другой модификацией или сборкой) — запись в ocmod.log,
|
||||||
|
админка модуля показывает предупреждение (маркер payanyway-post-route).
|
||||||
|
-->
|
||||||
|
<file path="catalog/controller/startup/router.php">
|
||||||
|
<operation error="log">
|
||||||
|
<search><![CDATA[if (isset($this->request->get['route']) && $this->request->get['route'] != 'startup/router') {]]></search>
|
||||||
|
<add position="before"><![CDATA[
|
||||||
|
// payanyway-post-route: маршрут Check/Pay URL, пришедший в теле POST (см. install.xml модуля PayAnyWay).
|
||||||
|
if (!isset($this->request->get['route']) && isset($this->request->post['route']) && ($this->request->post['route'] === 'extension/payment/payanyway/callback')) {
|
||||||
|
$this->request->get['route'] = $this->request->post['route'];
|
||||||
|
}
|
||||||
|
]]></add>
|
||||||
|
</operation>
|
||||||
|
</file>
|
||||||
</modification>
|
</modification>
|
||||||
|
|||||||
@@ -9,9 +9,13 @@
|
|||||||
class ControllerExtensionPaymentPayanyway extends Controller {
|
class ControllerExtensionPaymentPayanyway extends Controller {
|
||||||
const CMS_NAME = 'OpenCart';
|
const CMS_NAME = 'OpenCart';
|
||||||
const MODULE_NAME = 'payanyway';
|
const MODULE_NAME = 'payanyway';
|
||||||
const MODULE_VERSION = '1.0.0';
|
const MODULE_VERSION = '1.0.4';
|
||||||
const MODULE_DEFAULT_SORT_ORDER = 0;
|
const MODULE_DEFAULT_SORT_ORDER = 0;
|
||||||
|
|
||||||
|
/** Маркер вставки OCMOD из install.xml в роутере витрины (приём Check/Pay URL методом POST). */
|
||||||
|
const OCMOD_ROUTER_MARKER = 'payanyway-post-route';
|
||||||
|
const OCMOD_ROUTER_FILE = 'catalog/controller/startup/router.php';
|
||||||
|
|
||||||
private $supportedCurrencies = array('RUB');
|
private $supportedCurrencies = array('RUB');
|
||||||
private $availableVatRates = array(
|
private $availableVatRates = array(
|
||||||
'vat_none' => '1105',
|
'vat_none' => '1105',
|
||||||
@@ -26,6 +30,47 @@ class ControllerExtensionPaymentPayanyway extends Controller {
|
|||||||
'vat122' => '1114'
|
'vat122' => '1114'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/** Признак способа расчёта (kassaspecification.pdf, pm). */
|
||||||
|
private $paymentMethods = array(
|
||||||
|
'full_prepayment',
|
||||||
|
'prepayment',
|
||||||
|
'advance',
|
||||||
|
'full_payment',
|
||||||
|
'partial_payment',
|
||||||
|
'credit',
|
||||||
|
'credit_payment'
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Признак предмета расчёта (kassaspecification.pdf, po). */
|
||||||
|
private $paymentObjects = array(
|
||||||
|
'commodity',
|
||||||
|
'excise',
|
||||||
|
'job',
|
||||||
|
'service',
|
||||||
|
'gambling_bet',
|
||||||
|
'gambling_prize',
|
||||||
|
'lottery',
|
||||||
|
'lottery_prize',
|
||||||
|
'intellectual_activity',
|
||||||
|
'payment',
|
||||||
|
'agent_commission',
|
||||||
|
'composite',
|
||||||
|
'another',
|
||||||
|
'property_right',
|
||||||
|
'sales_tax',
|
||||||
|
'resort_fee',
|
||||||
|
'award',
|
||||||
|
'non_operating',
|
||||||
|
'insurance_premium'
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Canceled, Canceled Reversal, Voided штатной установки OpenCart. */
|
||||||
|
private $defaultCanceledOrderStatusIds = array(7, 9, 16);
|
||||||
|
|
||||||
|
const RECEIPT_EMAIL_MAX_LENGTH = 64;
|
||||||
|
const DEFAULT_PAYMENT_METHOD = 'full_payment';
|
||||||
|
const DEFAULT_PAYMENT_OBJECT = 'commodity';
|
||||||
|
|
||||||
private $error = array();
|
private $error = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -47,6 +92,15 @@ class ControllerExtensionPaymentPayanyway extends Controller {
|
|||||||
|
|
||||||
$data = array();
|
$data = array();
|
||||||
$this->applyValidationErrors($data);
|
$this->applyValidationErrors($data);
|
||||||
|
$data['warning_ocmod'] = $this->isRouterModificationApplied()
|
||||||
|
? ''
|
||||||
|
: sprintf(
|
||||||
|
$this->language->get('warning_ocmod_router'),
|
||||||
|
$this->url->link('marketplace/modification', 'user_token=' . $this->session->data['user_token'], true)
|
||||||
|
);
|
||||||
|
$data['warning_receipt_email'] = ($this->isFiscalizationEnabled() && ('' === (string)$this->config->get('payment_payanyway_receipt_email')))
|
||||||
|
? $this->language->get('warning_receipt_email')
|
||||||
|
: '';
|
||||||
|
|
||||||
$data['breadcrumbs'] = $this->getBreadcrumbs();
|
$data['breadcrumbs'] = $this->getBreadcrumbs();
|
||||||
$data['action'] = $this->url->link('extension/payment/payanyway', 'user_token=' . $this->session->data['user_token'], true);
|
$data['action'] = $this->url->link('extension/payment/payanyway', 'user_token=' . $this->session->data['user_token'], true);
|
||||||
@@ -56,6 +110,13 @@ class ControllerExtensionPaymentPayanyway extends Controller {
|
|||||||
$data['payment_payanyway_account'] = $this->retrieveValue('payment_payanyway_account');
|
$data['payment_payanyway_account'] = $this->retrieveValue('payment_payanyway_account');
|
||||||
$data['payment_payanyway_integrity_code'] = $this->getIntegrityCode('payment_payanyway_integrity_code');
|
$data['payment_payanyway_integrity_code'] = $this->getIntegrityCode('payment_payanyway_integrity_code');
|
||||||
$data['payment_payanyway_server'] = $this->retrieveValue('payment_payanyway_server');
|
$data['payment_payanyway_server'] = $this->retrieveValue('payment_payanyway_server');
|
||||||
|
$data['payment_payanyway_test_mode'] = (string)$this->retrieveValue('payment_payanyway_test_mode');
|
||||||
|
$data['payment_payanyway_fiscalization'] = $this->isFiscalizationEnabled() ? '1' : '0';
|
||||||
|
$data['payment_payanyway_receipt_email'] = htmlspecialchars((string)$this->retrieveRawValue('payment_payanyway_receipt_email'), ENT_QUOTES, 'UTF-8');
|
||||||
|
$data['payment_payanyway_payment_methods'] = $this->getOptions($this->paymentMethods, 'entry_payment_method_');
|
||||||
|
$data['payment_payanyway_payment_method'] = $this->retrieveValueOrDefault('payment_payanyway_payment_method', self::DEFAULT_PAYMENT_METHOD);
|
||||||
|
$data['payment_payanyway_payment_objects'] = $this->getOptions($this->paymentObjects, 'entry_payment_object_');
|
||||||
|
$data['payment_payanyway_payment_object'] = $this->retrieveValueOrDefault('payment_payanyway_payment_object', self::DEFAULT_PAYMENT_OBJECT);
|
||||||
$data['payment_payanyway_vat_rates'] = $this->getModuleVatRates();
|
$data['payment_payanyway_vat_rates'] = $this->getModuleVatRates();
|
||||||
$data['payment_payanyway_vat_rate'] = $this->retrieveValue('payment_payanyway_vat_rate');
|
$data['payment_payanyway_vat_rate'] = $this->retrieveValue('payment_payanyway_vat_rate');
|
||||||
$data['payment_payanyway_currencies'] = $this->getModuleCurrencies();
|
$data['payment_payanyway_currencies'] = $this->getModuleCurrencies();
|
||||||
@@ -64,10 +125,11 @@ class ControllerExtensionPaymentPayanyway extends Controller {
|
|||||||
$data['payment_payanyway_pending_order_status_id'] = $this->retrieveValue('payment_payanyway_pending_order_status_id');
|
$data['payment_payanyway_pending_order_status_id'] = $this->retrieveValue('payment_payanyway_pending_order_status_id');
|
||||||
$data['payment_payanyway_success_order_status_id'] = $this->retrieveValue('payment_payanyway_success_order_status_id');
|
$data['payment_payanyway_success_order_status_id'] = $this->retrieveValue('payment_payanyway_success_order_status_id');
|
||||||
$data['payment_payanyway_error_order_status_id'] = $this->retrieveValue('payment_payanyway_error_order_status_id');
|
$data['payment_payanyway_error_order_status_id'] = $this->retrieveValue('payment_payanyway_error_order_status_id');
|
||||||
|
$data['payment_payanyway_canceled_order_status_ids'] = $this->getCanceledOrderStatusIds();
|
||||||
$data['geo_zones'] = $this->getAvailableGeoZones();
|
$data['geo_zones'] = $this->getAvailableGeoZones();
|
||||||
$data['payment_payanyway_geo_zone_id'] = $this->retrieveValue('payment_payanyway_geo_zone_id');
|
$data['payment_payanyway_geo_zone_id'] = $this->retrieveValue('payment_payanyway_geo_zone_id');
|
||||||
$data['payment_payanyway_sort_order'] = $this->retrieveValue('payment_payanyway_sort_order');
|
$data['payment_payanyway_sort_order'] = $this->retrieveValue('payment_payanyway_sort_order');
|
||||||
$data['payment_payanyway_cms_module_version'] = $this->getCmsModuleVersion();
|
$data['callback_url'] = HTTPS_CATALOG . 'index.php?route=extension/payment/payanyway/callback';
|
||||||
|
|
||||||
$data['header'] = $this->load->controller('common/header');
|
$data['header'] = $this->load->controller('common/header');
|
||||||
$data['column_left'] = $this->load->controller('common/column_left');
|
$data['column_left'] = $this->load->controller('common/column_left');
|
||||||
@@ -76,6 +138,39 @@ class ControllerExtensionPaymentPayanyway extends Controller {
|
|||||||
$this->response->setOutput($this->load->view('extension/payment/payanyway', $data));
|
$this->response->setOutput($this->load->view('extension/payment/payanyway', $data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function isFiscalizationEnabled() {
|
||||||
|
$value = $this->retrieveValue('payment_payanyway_fiscalization');
|
||||||
|
|
||||||
|
return (null === $value) ? true : (bool)$value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int[]
|
||||||
|
*/
|
||||||
|
private function getCanceledOrderStatusIds() {
|
||||||
|
$value = $this->retrieveValue('payment_payanyway_canceled_order_status_ids');
|
||||||
|
if (null === $value) {
|
||||||
|
return $this->defaultCanceledOrderStatusIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_map('intval', (array)$value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function isRouterModificationApplied() {
|
||||||
|
$file = DIR_MODIFICATION . self::OCMOD_ROUTER_FILE;
|
||||||
|
if (!is_file($file)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false !== strpos((string)file_get_contents($file), self::OCMOD_ROUTER_MARKER);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return void
|
* @return void
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
@@ -86,8 +181,14 @@ class ControllerExtensionPaymentPayanyway extends Controller {
|
|||||||
'payment_payanyway_account' => '',
|
'payment_payanyway_account' => '',
|
||||||
'payment_payanyway_integrity_code' => '',
|
'payment_payanyway_integrity_code' => '',
|
||||||
'payment_payanyway_server' => 'prod',
|
'payment_payanyway_server' => 'prod',
|
||||||
|
'payment_payanyway_test_mode' => 0,
|
||||||
|
'payment_payanyway_fiscalization' => 1,
|
||||||
|
'payment_payanyway_receipt_email' => '',
|
||||||
|
'payment_payanyway_payment_method' => self::DEFAULT_PAYMENT_METHOD,
|
||||||
|
'payment_payanyway_payment_object' => self::DEFAULT_PAYMENT_OBJECT,
|
||||||
|
'payment_payanyway_canceled_order_status_ids' => $this->defaultCanceledOrderStatusIds,
|
||||||
'payment_payanyway_sort_order' => 0,
|
'payment_payanyway_sort_order' => 0,
|
||||||
'payment_payanyway_cms_module_version' => $this->getCmsModuleVersion(),
|
'payment_payanyway_cms_name' => $this->getCmsName(),
|
||||||
);
|
);
|
||||||
|
|
||||||
$orderStatuses = $this->getAvailableOrderStatuses();
|
$orderStatuses = $this->getAvailableOrderStatuses();
|
||||||
@@ -139,14 +240,45 @@ class ControllerExtensionPaymentPayanyway extends Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isset($request->post['payment_payanyway_account']) ||
|
if (!isset($request->post['payment_payanyway_account']) ||
|
||||||
|
!preg_match('/^[0-9]{1,20}$/', (string)$request->post['payment_payanyway_account']) ||
|
||||||
((int)$request->post['payment_payanyway_account'] <= 0)
|
((int)$request->post['payment_payanyway_account'] <= 0)
|
||||||
) {
|
) {
|
||||||
$this->error['account'] = $this->language->get('error_account');
|
$this->error['account'] = $this->language->get('error_account');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($request->post['payment_payanyway_integrity_code'])) {
|
// OpenCart экранирует весь POST (htmlspecialchars в system/library/request.php): код с & " < >
|
||||||
|
// сохранился бы экранированным, и подписи не сошлись бы с MONETA.RU.
|
||||||
|
$integrityCode = $this->decodePostedString($request, 'payment_payanyway_integrity_code');
|
||||||
|
if ('' === $integrityCode) {
|
||||||
$this->error['integrity_code'] = $this->language->get('error_integrity_code');
|
$this->error['integrity_code'] = $this->language->get('error_integrity_code');
|
||||||
}
|
}
|
||||||
|
$request->post['payment_payanyway_integrity_code'] = $integrityCode;
|
||||||
|
|
||||||
|
$fiscalization = !empty($request->post['payment_payanyway_fiscalization']);
|
||||||
|
$request->post['payment_payanyway_fiscalization'] = $fiscalization ? 1 : 0;
|
||||||
|
$request->post['payment_payanyway_test_mode'] = empty($request->post['payment_payanyway_test_mode']) ? 0 : 1;
|
||||||
|
|
||||||
|
$receiptEmail = $this->decodePostedString($request, 'payment_payanyway_receipt_email');
|
||||||
|
if (($fiscalization || ('' !== $receiptEmail)) && !$this->isValidReceiptEmail($receiptEmail)) {
|
||||||
|
$this->error['receipt_email'] = $this->language->get('error_receipt_email');
|
||||||
|
}
|
||||||
|
$request->post['payment_payanyway_receipt_email'] = $receiptEmail;
|
||||||
|
|
||||||
|
if (!isset($request->post['payment_payanyway_payment_method']) ||
|
||||||
|
!in_array($request->post['payment_payanyway_payment_method'], $this->paymentMethods, true)
|
||||||
|
) {
|
||||||
|
$request->post['payment_payanyway_payment_method'] = self::DEFAULT_PAYMENT_METHOD;
|
||||||
|
}
|
||||||
|
if (!isset($request->post['payment_payanyway_payment_object']) ||
|
||||||
|
!in_array($request->post['payment_payanyway_payment_object'], $this->paymentObjects, true)
|
||||||
|
) {
|
||||||
|
$request->post['payment_payanyway_payment_object'] = self::DEFAULT_PAYMENT_OBJECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
$canceled = isset($request->post['payment_payanyway_canceled_order_status_ids'])
|
||||||
|
? (array)$request->post['payment_payanyway_canceled_order_status_ids']
|
||||||
|
: array();
|
||||||
|
$request->post['payment_payanyway_canceled_order_status_ids'] = array_values(array_unique(array_map('intval', $canceled)));
|
||||||
|
|
||||||
if (empty($request->post['payment_payanyway_pending_order_status_id'])) {
|
if (empty($request->post['payment_payanyway_pending_order_status_id'])) {
|
||||||
$this->error['pending_order_status'] = $this->language->get('error_order_status');
|
$this->error['pending_order_status'] = $this->language->get('error_order_status');
|
||||||
@@ -162,7 +294,7 @@ class ControllerExtensionPaymentPayanyway extends Controller {
|
|||||||
? (int)$request->post['payment_payanyway_sort_order']
|
? (int)$request->post['payment_payanyway_sort_order']
|
||||||
: self::MODULE_DEFAULT_SORT_ORDER;
|
: self::MODULE_DEFAULT_SORT_ORDER;
|
||||||
$request->post['payment_payanyway_sort_order'] = $sortOrder;
|
$request->post['payment_payanyway_sort_order'] = $sortOrder;
|
||||||
$request->post['payment_payanyway_cms_module_version'] = $this->getCmsModuleVersion();
|
$request->post['payment_payanyway_cms_name'] = $this->getCmsName();
|
||||||
|
|
||||||
return empty($this->error);
|
return empty($this->error);
|
||||||
}
|
}
|
||||||
@@ -175,6 +307,7 @@ class ControllerExtensionPaymentPayanyway extends Controller {
|
|||||||
$data['error_warning'] = isset($this->error['warning']) ? $this->error['warning'] : '';
|
$data['error_warning'] = isset($this->error['warning']) ? $this->error['warning'] : '';
|
||||||
$data['error_account'] = isset($this->error['account']) ? $this->error['account'] : '';
|
$data['error_account'] = isset($this->error['account']) ? $this->error['account'] : '';
|
||||||
$data['error_integrity_code'] = isset($this->error['integrity_code']) ? $this->error['integrity_code'] : '';
|
$data['error_integrity_code'] = isset($this->error['integrity_code']) ? $this->error['integrity_code'] : '';
|
||||||
|
$data['error_receipt_email'] = isset($this->error['receipt_email']) ? $this->error['receipt_email'] : '';
|
||||||
$data['error_pending_order_status'] = isset($this->error['pending_order_status']) ? $this->error['pending_order_status'] : '';
|
$data['error_pending_order_status'] = isset($this->error['pending_order_status']) ? $this->error['pending_order_status'] : '';
|
||||||
$data['error_success_order_status'] = isset($this->error['success_order_status']) ? $this->error['success_order_status'] : '';
|
$data['error_success_order_status'] = isset($this->error['success_order_status']) ? $this->error['success_order_status'] : '';
|
||||||
$data['error_error_order_status'] = isset($this->error['error_order_status']) ? $this->error['error_order_status'] : '';
|
$data['error_error_order_status'] = isset($this->error['error_order_status']) ? $this->error['error_order_status'] : '';
|
||||||
@@ -203,12 +336,31 @@ class ControllerExtensionPaymentPayanyway extends Controller {
|
|||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
private function getIntegrityCode($key) {
|
private function getIntegrityCode($key) {
|
||||||
$value = $this->retrieveValue($key);
|
return htmlspecialchars((string)$this->retrieveRawValue($key), ENT_QUOTES, 'UTF-8');
|
||||||
if (null === $value) {
|
}
|
||||||
return '';
|
|
||||||
|
/**
|
||||||
|
* @param string $email
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function isValidReceiptEmail($email) {
|
||||||
|
return ('' !== $email)
|
||||||
|
&& (strlen($email) <= self::RECEIPT_EMAIL_MAX_LENGTH)
|
||||||
|
&& (false !== filter_var($email, FILTER_VALIDATE_EMAIL));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string[] $values
|
||||||
|
* @param string $labelPrefix
|
||||||
|
* @return array<string, string>
|
||||||
|
*/
|
||||||
|
private function getOptions(array $values, $labelPrefix) {
|
||||||
|
$result = array();
|
||||||
|
foreach ($values as $value) {
|
||||||
|
$result[$value] = $this->language->get($labelPrefix . $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return array<string, mixed> */
|
/** @return array<string, mixed> */
|
||||||
@@ -280,21 +432,15 @@ class ControllerExtensionPaymentPayanyway extends Controller {
|
|||||||
return $this->model_localisation_geo_zone->getGeoZones();
|
return $this->model_localisation_geo_zone->getGeoZones();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return string */
|
/**
|
||||||
private function getCmsModuleVersion() {
|
* @return string
|
||||||
|
*/
|
||||||
|
private function getCmsName() {
|
||||||
$this->load->language('common/footer');
|
$this->load->language('common/footer');
|
||||||
$textFooter = $this->language->get('text_footer');
|
$textFooter = $this->language->get('text_footer');
|
||||||
$textFooter = is_string($textFooter) ? $textFooter : '';
|
$textFooter = is_string($textFooter) ? $textFooter : '';
|
||||||
|
|
||||||
$cmsName = $this->detectCmsByPatterns($textFooter);
|
return $this->detectCmsByPatterns($textFooter);
|
||||||
$cmsVersion = defined('VERSION') ? constant('VERSION') : '.unknown';
|
|
||||||
|
|
||||||
return sprintf('%s v%s | %s v%s',
|
|
||||||
$cmsName,
|
|
||||||
$cmsVersion,
|
|
||||||
self::MODULE_NAME,
|
|
||||||
self::MODULE_VERSION
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function detectCmsByPatterns($textFooter) {
|
private function detectCmsByPatterns($textFooter) {
|
||||||
@@ -330,4 +476,41 @@ class ControllerExtensionPaymentPayanyway extends Controller {
|
|||||||
|
|
||||||
return $this->config->get($name);
|
return $this->config->get($name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Строка с формы без экранирования OpenCart: htmlspecialchars_decode обращает ENT_COMPAT
|
||||||
|
* из system/library/request.php.
|
||||||
|
*
|
||||||
|
* @param \Request $request
|
||||||
|
* @param string $name
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function decodePostedString($request, $name) {
|
||||||
|
$value = isset($request->post[$name]) && is_string($request->post[$name]) ? $request->post[$name] : '';
|
||||||
|
|
||||||
|
return trim(htmlspecialchars_decode($value, ENT_COMPAT));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $name
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function retrieveRawValue($name) {
|
||||||
|
if (isset($this->request->post[$name]) && is_string($this->request->post[$name])) {
|
||||||
|
return $this->request->post[$name];
|
||||||
|
}
|
||||||
|
|
||||||
|
return (string)$this->config->get($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $name
|
||||||
|
* @param string $default
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function retrieveValueOrDefault($name, $default) {
|
||||||
|
$value = (string)$this->retrieveValue($name);
|
||||||
|
|
||||||
|
return ('' !== $value) ? $value : $default;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,41 @@ $_['entry_error_order_status_label'] = 'Error';
|
|||||||
$_['entry_geo_zone_label'] = 'Area of display';
|
$_['entry_geo_zone_label'] = 'Area of display';
|
||||||
$_['entry_sort_order_label'] = 'Sort Order';
|
$_['entry_sort_order_label'] = 'Sort Order';
|
||||||
|
|
||||||
|
$_['entry_test_mode_label'] = 'Test mode';
|
||||||
|
$_['entry_fiscalization_label'] = 'Receipt fiscalization';
|
||||||
|
$_['entry_receipt_email_label'] = 'Email for receipts';
|
||||||
|
$_['entry_payment_method_label'] = 'Payment method';
|
||||||
|
$_['entry_payment_object_label'] = 'Payment object';
|
||||||
|
$_['entry_canceled_order_status_label'] = 'Canceled';
|
||||||
|
$_['entry_callback_url_label'] = 'Notification URL';
|
||||||
|
|
||||||
|
$_['entry_payment_method_full_prepayment'] = 'Full prepayment';
|
||||||
|
$_['entry_payment_method_prepayment'] = 'Partial prepayment';
|
||||||
|
$_['entry_payment_method_advance'] = 'Advance';
|
||||||
|
$_['entry_payment_method_full_payment'] = 'Full payment';
|
||||||
|
$_['entry_payment_method_partial_payment'] = 'Partial payment and credit';
|
||||||
|
$_['entry_payment_method_credit'] = 'Credit';
|
||||||
|
$_['entry_payment_method_credit_payment'] = 'Credit payment';
|
||||||
|
$_['entry_payment_object_commodity'] = 'Commodity';
|
||||||
|
$_['entry_payment_object_excise'] = 'Excise commodity';
|
||||||
|
$_['entry_payment_object_job'] = 'Job';
|
||||||
|
$_['entry_payment_object_service'] = 'Service';
|
||||||
|
$_['entry_payment_object_gambling_bet'] = 'Gambling bet';
|
||||||
|
$_['entry_payment_object_gambling_prize'] = 'Gambling prize';
|
||||||
|
$_['entry_payment_object_lottery'] = 'Lottery ticket';
|
||||||
|
$_['entry_payment_object_lottery_prize'] = 'Lottery prize';
|
||||||
|
$_['entry_payment_object_intellectual_activity'] = 'Intellectual activity';
|
||||||
|
$_['entry_payment_object_payment'] = 'Payment (advance, deposit, prepayment, credit)';
|
||||||
|
$_['entry_payment_object_agent_commission'] = 'Agent commission';
|
||||||
|
$_['entry_payment_object_composite'] = 'Composite';
|
||||||
|
$_['entry_payment_object_another'] = 'Another';
|
||||||
|
$_['entry_payment_object_property_right'] = 'Property right';
|
||||||
|
$_['entry_payment_object_sales_tax'] = 'Sales tax';
|
||||||
|
$_['entry_payment_object_resort_fee'] = 'Resort fee';
|
||||||
|
$_['entry_payment_object_award'] = 'Contribution, penalty, fine, reward, bonus';
|
||||||
|
$_['entry_payment_object_non_operating'] = 'Non-operating income';
|
||||||
|
$_['entry_payment_object_insurance_premium'] = 'Insurance premium';
|
||||||
|
|
||||||
// Help
|
// Help
|
||||||
$_['help_pending_order_status'] = 'Specify the order status that is set when the order is created';
|
$_['help_pending_order_status'] = 'Specify the order status that is set when the order is created';
|
||||||
$_['help_success_order_status'] = 'Specify the order status that is set upon successful payment';
|
$_['help_success_order_status'] = 'Specify the order status that is set upon successful payment';
|
||||||
@@ -51,8 +86,24 @@ $_['help_error_order_status'] = 'Specify the order status that is set upon pay
|
|||||||
$_['help_geo_zone'] = 'Geographic area where the payment method will be displayed';
|
$_['help_geo_zone'] = 'Geographic area where the payment method will be displayed';
|
||||||
$_['help_sort_order'] = 'Determines the display order of the payment method. The smaller the number, the higher the position in the list';
|
$_['help_sort_order'] = 'Determines the display order of the payment method. The smaller the number, the higher the position in the list';
|
||||||
|
|
||||||
|
$_['help_test_mode'] = 'Simulates payments without charging. Must match the account setting in MONETA.RU';
|
||||||
|
$_['help_fiscalization'] = 'Enable only if the kassa.payanyway.ru cash register service is connected to the account';
|
||||||
|
$_['help_receipt_email'] = 'Required with fiscalization. Used in the receipt only when the customer has neither e-mail nor phone: the cash register does not accept a receipt without a contact, so it is sent to this address (the customer name stays in the receipt)';
|
||||||
|
$_['help_canceled_order_status'] = 'Orders in these statuses are not paid: the module rejects the check request';
|
||||||
|
$_['help_callback_url'] = 'Set this address as Check URL and Pay URL in the MONETA.RU account settings. It must be reachable from the internet';
|
||||||
|
|
||||||
|
// Button
|
||||||
|
$_['button_integrity_code_toggle'] = 'Show or hide';
|
||||||
|
$_['button_copy'] = 'Copy';
|
||||||
|
$_['text_copied'] = 'Copied';
|
||||||
|
|
||||||
|
// Warning
|
||||||
|
$_['warning_ocmod_router'] = 'The PayAnyWay router modification is not applied: Check URL and Pay URL notifications sent by POST will not reach the module. Click <a href="%s">Extensions → Modifications → Refresh</a> and check the modification log. Not needed if the account uses the GET method.';
|
||||||
|
$_['warning_receipt_email'] = 'Receipt fiscalization is enabled but "Email for receipts" is empty: a customer without e-mail and phone will not get a receipt. Set the address below or disable fiscalization if no cash register service is connected.';
|
||||||
|
|
||||||
// Error
|
// Error
|
||||||
$_['error_permission'] = 'Warning: You do not have permission to modify payment PayAnyWay!';
|
$_['error_permission'] = 'Warning: You do not have permission to modify payment PayAnyWay!';
|
||||||
$_['error_account'] = 'Account Number is required and must be greater than 0';
|
$_['error_account'] = 'Account number is required and must contain digits only';
|
||||||
$_['error_integrity_code'] = 'Account Integrity Code Required';
|
$_['error_integrity_code'] = 'Account Integrity Code Required';
|
||||||
$_['error_order_status'] = 'Select order status';
|
$_['error_order_status'] = 'Select order status';
|
||||||
|
$_['error_receipt_email'] = 'Enter a valid e-mail no longer than 64 characters';
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ $_['entry_integrity_code_label'] = 'Код проверки целостн
|
|||||||
$_['entry_integrity_code_description'] = 'Код проверки целостности данных, указанный в настройках расширенного счёта в системе MONETA.RU';
|
$_['entry_integrity_code_description'] = 'Код проверки целостности данных, указанный в настройках расширенного счёта в системе MONETA.RU';
|
||||||
$_['entry_server_label'] = 'Сервер платежей';
|
$_['entry_server_label'] = 'Сервер платежей';
|
||||||
$_['entry_server_prod_label'] = 'Боевой';
|
$_['entry_server_prod_label'] = 'Боевой';
|
||||||
$_['entry_server_demo_label'] = 'Тестовый';
|
$_['entry_server_demo_label'] = 'Демо';
|
||||||
|
|
||||||
$_['entry_vat_rate_label'] = 'НДС';
|
$_['entry_vat_rate_label'] = 'НДС';
|
||||||
$_['entry_vat_none_label'] = 'Без НДС';
|
$_['entry_vat_none_label'] = 'Без НДС';
|
||||||
@@ -44,6 +44,41 @@ $_['entry_error_order_status_label'] = 'Неуспешный';
|
|||||||
$_['entry_geo_zone_label'] = 'Регион отображения';
|
$_['entry_geo_zone_label'] = 'Регион отображения';
|
||||||
$_['entry_sort_order_label'] = 'Порядок сортировки';
|
$_['entry_sort_order_label'] = 'Порядок сортировки';
|
||||||
|
|
||||||
|
$_['entry_test_mode_label'] = 'Тестовый режим';
|
||||||
|
$_['entry_fiscalization_label'] = 'Фискализация чеков';
|
||||||
|
$_['entry_receipt_email_label'] = 'Email для чеков';
|
||||||
|
$_['entry_payment_method_label'] = 'Признак способа расчёта';
|
||||||
|
$_['entry_payment_object_label'] = 'Признак предмета расчёта';
|
||||||
|
$_['entry_canceled_order_status_label'] = 'Отменённые';
|
||||||
|
$_['entry_callback_url_label'] = 'URL для уведомлений';
|
||||||
|
|
||||||
|
$_['entry_payment_method_full_prepayment'] = 'Полная предоплата';
|
||||||
|
$_['entry_payment_method_prepayment'] = 'Частичная предоплата';
|
||||||
|
$_['entry_payment_method_advance'] = 'Аванс';
|
||||||
|
$_['entry_payment_method_full_payment'] = 'Полный расчёт';
|
||||||
|
$_['entry_payment_method_partial_payment'] = 'Частичный расчёт и кредит';
|
||||||
|
$_['entry_payment_method_credit'] = 'Передача в кредит';
|
||||||
|
$_['entry_payment_method_credit_payment'] = 'Оплата кредита';
|
||||||
|
$_['entry_payment_object_commodity'] = 'Товар';
|
||||||
|
$_['entry_payment_object_excise'] = 'Подакцизный товар';
|
||||||
|
$_['entry_payment_object_job'] = 'Работа';
|
||||||
|
$_['entry_payment_object_service'] = 'Услуга';
|
||||||
|
$_['entry_payment_object_gambling_bet'] = 'Ставка азартной игры';
|
||||||
|
$_['entry_payment_object_gambling_prize'] = 'Выигрыш азартной игры';
|
||||||
|
$_['entry_payment_object_lottery'] = 'Лотерейный билет';
|
||||||
|
$_['entry_payment_object_lottery_prize'] = 'Выигрыш лотереи';
|
||||||
|
$_['entry_payment_object_intellectual_activity'] = 'Результаты интеллектуальной деятельности';
|
||||||
|
$_['entry_payment_object_payment'] = 'Платёж (аванс, задаток, предоплата, кредит)';
|
||||||
|
$_['entry_payment_object_agent_commission'] = 'Агентское вознаграждение';
|
||||||
|
$_['entry_payment_object_composite'] = 'Составной предмет расчёта';
|
||||||
|
$_['entry_payment_object_another'] = 'Иной предмет расчёта';
|
||||||
|
$_['entry_payment_object_property_right'] = 'Имущественное право';
|
||||||
|
$_['entry_payment_object_sales_tax'] = 'Торговый сбор';
|
||||||
|
$_['entry_payment_object_resort_fee'] = 'Курортный сбор';
|
||||||
|
$_['entry_payment_object_award'] = 'Взнос в счёт оплаты, пени, штраф, вознаграждение, бонус';
|
||||||
|
$_['entry_payment_object_non_operating'] = 'Внереализационный доход';
|
||||||
|
$_['entry_payment_object_insurance_premium'] = 'Страховой сбор';
|
||||||
|
|
||||||
// Help
|
// Help
|
||||||
$_['help_pending_order_status'] = 'Укажите статус заказа, который выставляется при его создании';
|
$_['help_pending_order_status'] = 'Укажите статус заказа, который выставляется при его создании';
|
||||||
$_['help_success_order_status'] = 'Укажите статус заказа, который выставляется при успешной оплате';
|
$_['help_success_order_status'] = 'Укажите статус заказа, который выставляется при успешной оплате';
|
||||||
@@ -51,8 +86,24 @@ $_['help_error_order_status'] = 'Укажите статус заказа, к
|
|||||||
$_['help_geo_zone'] = 'Географическая зона, в которой будет отображаться способ оплаты';
|
$_['help_geo_zone'] = 'Географическая зона, в которой будет отображаться способ оплаты';
|
||||||
$_['help_sort_order'] = 'Определяет порядок отображения платежного метода в списке методов оплаты при оформлении заказа. Чем меньше число, тем выше позиция в списке';
|
$_['help_sort_order'] = 'Определяет порядок отображения платежного метода в списке методов оплаты при оформлении заказа. Чем меньше число, тем выше позиция в списке';
|
||||||
|
|
||||||
|
$_['help_test_mode'] = 'Имитация оплаты без реального списания средств. Режим должен совпадать с настройкой счёта в MONETA.RU';
|
||||||
|
$_['help_fiscalization'] = 'Включайте, только если к счёту подключён кассовый сервис kassa.payanyway.ru';
|
||||||
|
$_['help_receipt_email'] = 'Обязателен при фискализации. Подставляется в чек, только если у покупателя нет ни e-mail, ни телефона: без контакта касса чек не примет, поэтому он уйдёт на этот адрес (ФИО покупателя в чеке остаётся)';
|
||||||
|
$_['help_canceled_order_status'] = 'Заказ в этих статусах не оплачивается: на проверочный запрос модуль отвечает отказом';
|
||||||
|
$_['help_callback_url'] = 'Укажите этот адрес в настройках счёта MONETA.RU как Check URL и Pay URL. Он должен быть доступен из интернета';
|
||||||
|
|
||||||
|
// Button
|
||||||
|
$_['button_integrity_code_toggle'] = 'Показать или скрыть';
|
||||||
|
$_['button_copy'] = 'Скопировать';
|
||||||
|
$_['text_copied'] = 'Скопировано';
|
||||||
|
|
||||||
|
// Warning
|
||||||
|
$_['warning_ocmod_router'] = 'Модификация PayAnyWay для роутера не применена: уведомления Check URL и Pay URL методом POST не дойдут до модуля. Нажмите <a href="%s">Расширения → Модификации → Обновить</a> и проверьте лог модификаций. При методе GET в настройках счёта модификация не нужна.';
|
||||||
|
$_['warning_receipt_email'] = 'Фискализация чеков включена, а «Email для чеков» не задан: покупателю без e-mail и телефона чек не будет пробит. Укажите адрес в настройках ниже или выключите фискализацию, если кассовый сервис не подключён.';
|
||||||
|
|
||||||
// Error
|
// Error
|
||||||
$_['error_permission'] = 'Недостаточно прав для изменения настроек способа оплаты PayAnyWay';
|
$_['error_permission'] = 'Недостаточно прав для изменения настроек способа оплаты PayAnyWay';
|
||||||
$_['error_account'] = 'Номер счёта обязателен';
|
$_['error_account'] = 'Номер счёта обязателен и состоит только из цифр';
|
||||||
$_['error_integrity_code'] = 'Код проверки целостности данных обязателен';
|
$_['error_integrity_code'] = 'Код проверки целостности данных обязателен';
|
||||||
$_['error_order_status'] = 'Выберите статус заказа';
|
$_['error_order_status'] = 'Выберите статус заказа';
|
||||||
|
$_['error_receipt_email'] = 'Укажите корректный e-mail не длиннее 64 символов';
|
||||||
|
|||||||
Executable → Regular
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 150 KiB After Width: | Height: | Size: 10 KiB |
@@ -16,6 +16,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
|
{% if warning_ocmod %}
|
||||||
|
<div class="alert alert-warning"><i class="fa fa-exclamation-triangle"></i> {{ warning_ocmod }}</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if warning_receipt_email %}
|
||||||
|
<div class="alert alert-warning"><i class="fa fa-exclamation-triangle"></i> {{ warning_receipt_email }}</div>
|
||||||
|
{% endif %}
|
||||||
{% if error_warning %}
|
{% if error_warning %}
|
||||||
<div class="alert alert-danger"><i class="fa fa-exclamation-circle"></i> {{ error_warning }}
|
<div class="alert alert-danger"><i class="fa fa-exclamation-circle"></i> {{ error_warning }}
|
||||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||||
@@ -27,7 +33,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="panel-heading text-center">
|
<div class="panel-heading text-center">
|
||||||
<a href="https://www.payanyway.ru/" target="_blank">
|
<a href="https://www.payanyway.ru/" target="_blank">
|
||||||
<img src="view/image/payment/payanyway.png" alt="PayAnyWay" title="PayAnyWay" width="250" height="29"/>
|
<img src="view/image/payment/payanyway.png" alt="PayAnyWay" title="PayAnyWay" width="336" height="50"/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
@@ -64,9 +70,15 @@
|
|||||||
<div class="form-group required">
|
<div class="form-group required">
|
||||||
<label class="col-sm-2 control-label" for="input-integrity-code">{{ entry_integrity_code_label }}</label>
|
<label class="col-sm-2 control-label" for="input-integrity-code">{{ entry_integrity_code_label }}</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<input type="text" name="payment_payanyway_integrity_code" value="{{ payment_payanyway_integrity_code }}"
|
<div class="input-group">
|
||||||
placeholder="{{ entry_integrity_code_description }}" id="input-integrity-code"
|
<input type="password" name="payment_payanyway_integrity_code" value="{{ payment_payanyway_integrity_code }}"
|
||||||
class="form-control"/>
|
placeholder="{{ entry_integrity_code_description }}" id="input-integrity-code"
|
||||||
|
class="form-control" autocomplete="off"/>
|
||||||
|
<span class="input-group-btn">
|
||||||
|
<button type="button" class="btn btn-default" id="button-integrity-code-toggle"
|
||||||
|
data-toggle="tooltip" title="{{ button_integrity_code_toggle }}"><i class="fa fa-eye"></i></button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
{% if error_integrity_code %}
|
{% if error_integrity_code %}
|
||||||
<div class="text-danger">{{ error_integrity_code }}</div>
|
<div class="text-danger">{{ error_integrity_code }}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -84,18 +96,87 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{# НДС #}
|
{# Тестовый режим #}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-sm-2 control-label" for="input-vat-rate">{{ entry_vat_rate_label }}</label>
|
<div class="col-sm-10 col-sm-offset-2">
|
||||||
<div class="col-sm-10">
|
<div class="form-check" style="display: flex; column-gap: 8px;">
|
||||||
<select name="payment_payanyway_vat_rate" id="input-vat-rate" class="form-control">
|
<input type="hidden" name="payment_payanyway_test_mode" value="0"/>
|
||||||
{% for vat_id, label in payment_payanyway_vat_rates %}
|
<input class="form-check-input" type="checkbox" name="payment_payanyway_test_mode" id="input-test-mode"
|
||||||
<option value="{{ vat_id }}"
|
value="1"
|
||||||
{% if vat_id == payment_payanyway_vat_rate %}selected="selected"{% endif %}>
|
{% if payment_payanyway_test_mode == "1" %} checked{% endif %}>
|
||||||
{{ label }}
|
<label class="form-check-label" for="input-test-mode">{{ entry_test_mode_label }}</label>
|
||||||
</option>
|
</div>
|
||||||
{% endfor %}
|
<p class="help-block">{{ help_test_mode }}</p>
|
||||||
</select>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{# Фискализация чеков #}
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-sm-10 col-sm-offset-2">
|
||||||
|
<div class="form-check" style="display: flex; column-gap: 8px;">
|
||||||
|
<input type="hidden" name="payment_payanyway_fiscalization" value="0"/>
|
||||||
|
<input class="form-check-input" type="checkbox" name="payment_payanyway_fiscalization"
|
||||||
|
id="input-fiscalization" value="1"
|
||||||
|
{% if payment_payanyway_fiscalization == "1" %} checked{% endif %}>
|
||||||
|
<label class="form-check-label" for="input-fiscalization">{{ entry_fiscalization_label }}</label>
|
||||||
|
</div>
|
||||||
|
<p class="help-block">{{ help_fiscalization }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{# Поля чека — только при фискализации. Скрываются, а не блокируются: заблокированное
|
||||||
|
поле браузер не отправляет, и значение потерялось бы. #}
|
||||||
|
<div id="fiscalization-fields">
|
||||||
|
{# Email для чеков #}
|
||||||
|
<div class="form-group required">
|
||||||
|
<label class="col-sm-2 control-label" for="input-receipt-email">{{ entry_receipt_email_label }}</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input type="email" name="payment_payanyway_receipt_email" value="{{ payment_payanyway_receipt_email }}"
|
||||||
|
placeholder="shop@example.ru" id="input-receipt-email" class="form-control" maxlength="64"/>
|
||||||
|
<p class="help-block">{{ help_receipt_email }}</p>
|
||||||
|
{% if error_receipt_email %}
|
||||||
|
<div class="text-danger">{{ error_receipt_email }}</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{# НДС #}
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label" for="input-vat-rate">{{ entry_vat_rate_label }}</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<select name="payment_payanyway_vat_rate" id="input-vat-rate" class="form-control">
|
||||||
|
{% for vat_id, label in payment_payanyway_vat_rates %}
|
||||||
|
<option value="{{ vat_id }}"
|
||||||
|
{% if vat_id == payment_payanyway_vat_rate %}selected="selected"{% endif %}>
|
||||||
|
{{ label }}
|
||||||
|
</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{# Признак способа расчёта #}
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label" for="input-payment-method">{{ entry_payment_method_label }}</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<select name="payment_payanyway_payment_method" id="input-payment-method" class="form-control">
|
||||||
|
{% for value, label in payment_payanyway_payment_methods %}
|
||||||
|
<option value="{{ value }}" {% if value == payment_payanyway_payment_method %}selected="selected"{% endif %}>{{ label }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{# Признак предмета расчёта #}
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label" for="input-payment-object">{{ entry_payment_object_label }}</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<select name="payment_payanyway_payment_object" id="input-payment-object" class="form-control">
|
||||||
|
{% for value, label in payment_payanyway_payment_objects %}
|
||||||
|
<option value="{{ value }}" {% if value == payment_payanyway_payment_object %}selected="selected"{% endif %}>{{ label }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -192,6 +273,28 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{# canceled #}
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-3 control-label">
|
||||||
|
<span data-toggle="tooltip"
|
||||||
|
title="{{ help_canceled_order_status }}">{{ entry_canceled_order_status_label }}</span>
|
||||||
|
</label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<div class="well well-sm" style="height: 150px; overflow: auto; margin-bottom: 0;">
|
||||||
|
{% for order_status in order_statuses %}
|
||||||
|
<div class="checkbox">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" name="payment_payanyway_canceled_order_status_ids[]"
|
||||||
|
value="{{ order_status.order_status_id }}"
|
||||||
|
{% if order_status.order_status_id in payment_payanyway_canceled_order_status_ids %} checked="checked"{% endif %}/>
|
||||||
|
{{ order_status.name }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -218,6 +321,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{# URL для уведомлений #}
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label" for="input-callback-url">{{ entry_callback_url_label }}</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="text" value="{{ callback_url }}" id="input-callback-url" class="form-control" readonly/>
|
||||||
|
<span class="input-group-btn">
|
||||||
|
<button type="button" class="btn btn-default" id="button-callback-url-copy">{{ button_copy }}</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<p class="help-block">{{ help_callback_url }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{# sort-order #}
|
{# sort-order #}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-sm-2 control-label" for="input-sort-order">
|
<label class="col-sm-2 control-label" for="input-sort-order">
|
||||||
@@ -234,4 +351,34 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<style>
|
||||||
|
{# Разделитель админки — .form-group + .form-group: обёртка полей чека его разрывает. #}
|
||||||
|
#fiscalization-fields > .form-group:first-child,
|
||||||
|
#fiscalization-fields + .form-group {
|
||||||
|
border-top: 1px solid #ededed;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
$(function () {
|
||||||
|
function toggleFiscalizationFields() {
|
||||||
|
$('#fiscalization-fields').toggle($('#input-fiscalization').is(':checked'));
|
||||||
|
}
|
||||||
|
$('#input-fiscalization').on('change', toggleFiscalizationFields);
|
||||||
|
toggleFiscalizationFields();
|
||||||
|
|
||||||
|
$('#button-integrity-code-toggle').on('click', function () {
|
||||||
|
var $input = $('#input-integrity-code');
|
||||||
|
$input.attr('type', $input.attr('type') === 'password' ? 'text' : 'password');
|
||||||
|
$(this).find('i').toggleClass('fa-eye fa-eye-slash');
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#button-callback-url-copy').on('click', function () {
|
||||||
|
var $button = $(this);
|
||||||
|
$('#input-callback-url').trigger('select');
|
||||||
|
document.execCommand('copy');
|
||||||
|
$button.text('{{ text_copied }}');
|
||||||
|
setTimeout(function () { $button.text('{{ button_copy }}'); }, 2000);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
{{ footer }}
|
{{ footer }}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
// Text
|
// Text
|
||||||
|
$_['text_locale'] = 'en';
|
||||||
$_['text_title'] = 'PayAnyWay (MIR, VISA, MasterCard and 30+ other ways)';
|
$_['text_title'] = 'PayAnyWay (MIR, VISA, MasterCard and 30+ other ways)';
|
||||||
$_['text_ap_pay_with'] = 'Pay with';
|
$_['text_ap_pay_with'] = 'Pay with';
|
||||||
$_['text_ap_and_other'] = 'or another payment method';
|
$_['text_ap_and_other'] = 'or another payment method';
|
||||||
@@ -11,4 +12,9 @@ $_['text_paw_back_to_card'] = 'Back to payment by card';
|
|||||||
$_['text_order_confirmed'] = 'Order confirmed';
|
$_['text_order_confirmed'] = 'Order confirmed';
|
||||||
$_['text_payment_processing'] = 'Payment processing';
|
$_['text_payment_processing'] = 'Payment processing';
|
||||||
$_['text_payment_completed'] = 'Order is paid';
|
$_['text_payment_completed'] = 'Order is paid';
|
||||||
$_['text_payment_error'] = 'Payment error';
|
$_['text_payment_operation'] = 'Operation number: %s';
|
||||||
|
|
||||||
|
$_['text_description'] = 'Payment for order';
|
||||||
|
$_['text_description_number'] = 'No. %s';
|
||||||
|
$_['text_description_customer'] = 'from %s';
|
||||||
|
$_['text_payment_error'] = 'Payment error';
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
// Text
|
// Text
|
||||||
|
$_['text_locale'] = 'ru';
|
||||||
$_['text_title'] = 'PayAnyWay (МИР, Visa, MasterCard и более 30-и способов оплаты)';
|
$_['text_title'] = 'PayAnyWay (МИР, Visa, MasterCard и более 30-и способов оплаты)';
|
||||||
$_['text_ap_pay_with'] = 'Оплатить с';
|
$_['text_ap_pay_with'] = 'Оплатить с';
|
||||||
$_['text_ap_and_other'] = 'или другой способ оплаты';
|
$_['text_ap_and_other'] = 'или другой способ оплаты';
|
||||||
@@ -11,4 +12,9 @@ $_['text_paw_back_to_card'] = 'Вернуться к оплате картой
|
|||||||
$_['text_order_confirmed'] = 'Заказ подтвержден';
|
$_['text_order_confirmed'] = 'Заказ подтвержден';
|
||||||
$_['text_payment_processing'] = 'Обработка платежа';
|
$_['text_payment_processing'] = 'Обработка платежа';
|
||||||
$_['text_payment_completed'] = 'Заказ оплачен';
|
$_['text_payment_completed'] = 'Заказ оплачен';
|
||||||
$_['text_payment_error'] = 'Ошибка оплаты';
|
$_['text_payment_operation'] = 'Номер операции: %s';
|
||||||
|
|
||||||
|
$_['text_description'] = 'Оплата заказа';
|
||||||
|
$_['text_description_number'] = '№%s';
|
||||||
|
$_['text_description_customer'] = 'от %s';
|
||||||
|
$_['text_payment_error'] = 'Ошибка оплаты';
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
<input type="hidden" name="MNT_SUCCESS_URL" value="{{ MNT_SUCCESS_URL }}"/>
|
<input type="hidden" name="MNT_SUCCESS_URL" value="{{ MNT_SUCCESS_URL }}"/>
|
||||||
<input type="hidden" name="MNT_FAIL_URL" value="{{ MNT_FAIL_URL }}"/>
|
<input type="hidden" name="MNT_FAIL_URL" value="{{ MNT_FAIL_URL }}"/>
|
||||||
<input type="hidden" name="MNT_RETURN_URL" value="{{ MNT_RETURN_URL }}"/>
|
<input type="hidden" name="MNT_RETURN_URL" value="{{ MNT_RETURN_URL }}"/>
|
||||||
|
<input type="hidden" name="moneta.locale" value="{{ moneta_locale }}"/>
|
||||||
<input type="hidden" name="MNT_CMS" value="{{ MNT_CMS }}"/>
|
<input type="hidden" name="MNT_CMS" value="{{ MNT_CMS }}"/>
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<div class="{% if ap_use %} text-center {% else %} pull-right {% endif %}">
|
<div class="{% if ap_use %} text-center {% else %} pull-right {% endif %}">
|
||||||
|
|||||||
Reference in New Issue
Block a user