feat: moneta 2.0, MONETA.Assistant payment module for PHPShop 6.7+
This commit is contained in:
@@ -0,0 +1,525 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once dirname(__DIR__) . '/class/autoload.php';
|
||||
|
||||
use MonetaPhpShop\host\Database;
|
||||
use MonetaPhpShop\host\ErrorLogLogger;
|
||||
use MonetaPhpShop\host\HostCharset;
|
||||
use MonetaPhpShop\host\HostVatRates;
|
||||
use MonetaPhpShop\host\SettingsRepository;
|
||||
use MonetaPhpShop\host\ShopContext;
|
||||
use MonetaPhpShop\order\OrderStatusOptions;
|
||||
use MonetaPhpShop\protocol\PaymentServer;
|
||||
use MonetaPhpShop\receipt\PaymentMethod;
|
||||
use MonetaPhpShop\receipt\PaymentObject;
|
||||
use MonetaPhpShop\receipt\TaxSystem;
|
||||
use MonetaPhpShop\receipt\VatRateWarnings;
|
||||
use MonetaPhpShop\receipt\VatSetting;
|
||||
use MonetaPhpShop\SelectOptions;
|
||||
use MonetaPhpShop\Settings;
|
||||
use MonetaPhpShop\SettingsWriteGuard;
|
||||
|
||||
$PHPShopOrm = new PHPShopOrm($PHPShopModules->getParam('base.moneta.moneta_system'));
|
||||
|
||||
/**
|
||||
* Ïðàâî «Ìîäóëè: ðåäàêòèðîâàíèå» è çàïðîñ ñî ñòðàíèöû ìàãàçèíà — äî ëþáîé çàïèñè íàñòðîåê.
|
||||
* ßäðî ñàìî ïðîâåðÿåò ïðàâà, òîëüêî åñëè êëèåíò ïðèñëàë ñóôôèêñ `.modules.edit` â èìåíè
|
||||
* äåéñòâèÿ, ïîýòîìó ïðîâåðÿåì çäåñü ({@see SettingsWriteGuard}). Ïðè îòêàçå âûâîäèò ñîîáùåíèå,
|
||||
* êàê ÿäðî ïðè íåõâàòêå ïðàâ.
|
||||
*/
|
||||
function monetaSettingsWriteAllowed(): bool
|
||||
{
|
||||
global $PHPShopBase;
|
||||
|
||||
$reason = SettingsWriteGuard::denialReason(
|
||||
(bool) $PHPShopBase->Rule->CheckedRules('modules', 'edit'),
|
||||
$_SERVER,
|
||||
);
|
||||
if ($reason === null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$reasons = [
|
||||
SettingsWriteGuard::DENIED_RIGHTS => 'ó àäìèíèñòðàòîðà íåò ïðàâà «Ìîäóëè: ðåäàêòèðîâàíèå»',
|
||||
SettingsWriteGuard::DENIED_METHOD => 'çàïðîñ íå POST (ïåðåõîä ïî ññûëêå)',
|
||||
SettingsWriteGuard::DENIED_ORIGIN => 'çàïðîñ îòïðàâëåí íå ñî ñòðàíèöû ìàãàçèíà (Origin/Referer)',
|
||||
];
|
||||
(new ErrorLogLogger())->error('Íàñòðîéêè íå ñîõðàíåíû: ' . ($reasons[$reason] ?? $reason) . '.');
|
||||
if (isset($_REQUEST['ajax'])) {
|
||||
exit(json_encode(['success' => false]));
|
||||
}
|
||||
if ($reason === SettingsWriteGuard::DENIED_RIGHTS) {
|
||||
$PHPShopBase->Rule->BadUserFormaWindow();
|
||||
} else {
|
||||
echo '<div class="alert alert-danger" role="alert">' . HostCharset::toPage(
|
||||
'Íàñòðîéêè íå ñîõðàíåíû: çàïðîñ ïðèø¸ë íå ñî ñòðàíèöû ýòîãî ìàãàçèíà. '
|
||||
. 'Îòêðîéòå íàñòðîéêè ìîäóëÿ çàíîâî è íàæìèòå «Ïðèìåíèòü».',
|
||||
) . '</div>';
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Êíîïêà «Îáíîâèòü ìîäóëü»: SQL èç updates/<âåðñèÿ â ÁÄ>/ è íîâàÿ âåðñèÿ èç module.xml.
|
||||
*/
|
||||
function actionBaseUpdate()
|
||||
{
|
||||
global $PHPShopModules, $PHPShopOrm;
|
||||
|
||||
if (!monetaSettingsWriteAllowed()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$PHPShopOrm->clean();
|
||||
$option = $PHPShopOrm->select();
|
||||
$newVersion = $PHPShopModules->getUpdate($option['version']);
|
||||
$PHPShopOrm->clean();
|
||||
$action = $PHPShopOrm->update(['version_new' => $newVersion]);
|
||||
header('Location: ?path=modules&id=' . urlencode((string) $_GET['id']));
|
||||
|
||||
return $action;
|
||||
}
|
||||
|
||||
function actionUpdate()
|
||||
{
|
||||
global $PHPShopOrm, $PHPShopModules;
|
||||
|
||||
if (!monetaSettingsWriteAllowed()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Çàùèòà íà âðåìÿ ìåæäó çàìåíîé ôàéëîâ è êíîïêîé «Îáíîâèòü ìîäóëü». Ïîêà îíà íå íàæàòà,
|
||||
// òàáëèöà íàñòðîåê — åù¸ îò âñòðîåííîãî ìîäóëÿ «Ìîíåòà» 1.0: êîëîíîê account_id,
|
||||
// integrity_code è îñòàëüíûõ íåò (èõ äîáàâëÿåò updates/1.2/update_module.sql). UPDATE ïî íèì
|
||||
// óïàë áû, à ÿäðî íå ïîêàçûâàåò îøèáêó — ââåä¸ííîå ïðîïàëî áû. Ïîýòîìó ñîõðàíåíèå
|
||||
// ïðîïóñêàåì; íà âêëàäêå «Îñíîâíîå» â ýòî âðåìÿ âèñèò ïðåäóïðåæäåíèå (actionStart()).
|
||||
// Ïîñëå ìèãðàöèè ïðîâåðêà âñåãäà ïðîõîäèò: ýòî îäèí SELECT ñòðîêè íàñòðîåê íà «Ïðèìåíèòü».
|
||||
// clean() — ñáðîñ ñîñòîÿíèÿ ORM ÿäðà äî è ïîñëå select(), êàê â actionBaseUpdate().
|
||||
$PHPShopOrm->clean();
|
||||
$row = $PHPShopOrm->select();
|
||||
if (!is_array($row) || SettingsRepository::needsUpgrade($row)) {
|
||||
header('Location: ?path=modules&id=' . urlencode((string) $_GET['id']));
|
||||
|
||||
return false;
|
||||
}
|
||||
$PHPShopOrm->clean();
|
||||
|
||||
// Âèòðèíû ìóëüòèñàéòà, íà êîòîðûõ âêëþ÷¸í ìîäóëü.
|
||||
$PHPShopModules->updateOption($_GET['id'], $_POST['servers'] ?? null);
|
||||
|
||||
$post = static function (string $name): string {
|
||||
$value = $_POST[$name] ?? '';
|
||||
|
||||
return is_string($value) ? trim($value) : '';
|
||||
};
|
||||
|
||||
$update = [
|
||||
'payment_server_new' => PaymentServer::fromSetting($post('payment_server_new'))->getValue(),
|
||||
'test_mode_new' => $post('test_mode_new') === '1' ? '1' : '0',
|
||||
'title_end_new' => strip_tags($post('title_end_new')),
|
||||
'fiscalization_new' => $post('fiscalization_new') === '1' ? '1' : '0',
|
||||
'sno_new' => TaxSystem::fromSetting($post('sno_new'))->getValue(),
|
||||
'payment_method_new' => PaymentMethod::fromSetting($post('payment_method_new'))->getValue(),
|
||||
'payment_object_new' => PaymentObject::fromSetting($post('payment_object_new'))->getValue(),
|
||||
'goods_vat_new' => VatSetting::fromSetting($post('goods_vat_new'))->getValue(),
|
||||
'delivery_vat_new' => VatSetting::fromSetting($post('delivery_vat_new'))->getValue(),
|
||||
'status_new' => (int) $post('status_new'),
|
||||
'paid_status_new' => (int) $post('paid_status_new') > 0
|
||||
? (int) $post('paid_status_new')
|
||||
: Settings::STATUS_PAID_BY_GATEWAY,
|
||||
];
|
||||
|
||||
$receiptEmail = $post('receipt_email_new');
|
||||
$update['receipt_email_new'] = strlen($receiptEmail) <= 64
|
||||
&& filter_var($receiptEmail, FILTER_VALIDATE_EMAIL) !== false
|
||||
? $receiptEmail
|
||||
: '';
|
||||
|
||||
$accountId = preg_replace('/[^0-9]/', '', $post('account_id_new')) ?? '';
|
||||
if ($accountId !== '') {
|
||||
$update['account_id_new'] = $accountId;
|
||||
}
|
||||
|
||||
$integrityCode = $post('integrity_code_new');
|
||||
if ($integrityCode !== '') {
|
||||
$update['integrity_code_new'] = $integrityCode;
|
||||
}
|
||||
|
||||
// «Email äëÿ ÷åêîâ» îáÿçàòåëåí ïðè ôèñêàëèçàöèè: áåç àäðåñà âêëþ÷åíèå íå ñîõðàíÿåòñÿ, à óæå
|
||||
// âêëþ÷¸ííàÿ ôèñêàëèçàöèÿ ìîë÷à íå âûêëþ÷àåòñÿ — î ïóñòîì àäðåñå ïðåäóïðåæäàåò actionStart().
|
||||
if ($update['fiscalization_new'] === '1' && $update['receipt_email_new'] === '') {
|
||||
$update['fiscalization_new'] = ((string) ($row['fiscalization'] ?? '0') === '1') ? '1' : '0';
|
||||
}
|
||||
|
||||
$PHPShopOrm->debug = false;
|
||||
$action = $PHPShopOrm->update($update);
|
||||
header('Location: ?path=modules&id=' . urlencode((string) $_GET['id']));
|
||||
|
||||
return $action;
|
||||
}
|
||||
|
||||
function actionStart()
|
||||
{
|
||||
global $PHPShopGUI, $PHPShopOrm;
|
||||
|
||||
PHPShopObj::loadClass('order');
|
||||
|
||||
$data = $PHPShopOrm->select();
|
||||
$statuses = (new PHPShopOrderStatusArray())->getArray();
|
||||
$statuses = is_array($statuses) ? $statuses : [];
|
||||
|
||||
$settings = Settings::fromRow(is_array($data) ? $data : []);
|
||||
$context = new ShopContext();
|
||||
|
||||
// Íà ìàãàçèíå ñ áàçîé utf-8 ÿäðî ïåðåêîäèðóåò òîëüêî ñòðîêè, êîòîðûå ñàìî ïðîïóñêàåò ÷åðåç
|
||||
// __() (ïîäïèñè ïîëåé, ïîäñêàçêè, âêëàäêè). Òåêñòû setAlert(..., false), ïóíêòû setSelect()
|
||||
// è ñîáñòâåííàÿ ðàçìåòêà âûâîäÿòñÿ êàê åñòü — èõ ïåðåêîäèðóåò ìîäóëü. Ñòðîêè èç ÁÄ
|
||||
// (ñòàòóñû çàêàçà) óæå â êîäèðîâêå ñòðàíèöû.
|
||||
$page = static function (string $text): string {
|
||||
return HostCharset::toPage($text);
|
||||
};
|
||||
|
||||
$Tab1 = '';
|
||||
$needsUpgrade = is_array($data) && SettingsRepository::needsUpgrade($data);
|
||||
// Êíîïêà «Îáíîâèòü ìîäóëü» ÿäðà îòïðàâëÿåò ýòó æå ôîðìó: ïóñòûå îáÿçàòåëüíûå ïîëÿ ñòàðîé
|
||||
// ñõåìû áðàóçåð íå ïðîïóñòèë áû, è êíîïêà íå ñðàáàòûâàëà áû.
|
||||
$requiredText = $needsUpgrade ? 'text' : 'text.required';
|
||||
if ($needsUpgrade) {
|
||||
$Tab1 .= $PHPShopGUI->setAlert(
|
||||
HostCharset::toPage(
|
||||
'Ôàéëû ìîäóëÿ îáíîâëåíû, à íàñòðîéêè åù¸ îò âñòðîåííîãî ìîäóëÿ «Ìîíåòà». Íàæìèòå «Îáíîâèòü ìîäóëü»'
|
||||
. ' íà âêëàäêå «Î ìîäóëå» - íîìåð ñ÷¸òà è êîä ïðîâåðêè öåëîñòíîñòè ïåðåíåñóòñÿ. Äî ýòîãî ïðè¸ì'
|
||||
. ' îïëàò âûêëþ÷åí, à èçìåíåíèÿ íà ýòîé âêëàäêå íå ñîõðàíÿþòñÿ.',
|
||||
),
|
||||
'warning',
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
$Tab1 .= $PHPShopGUI->setField(
|
||||
'Íîìåð ñ÷¸òà',
|
||||
$PHPShopGUI->setInput($requiredText, 'account_id_new', $settings->getAccountId(), false, 300)
|
||||
. $PHPShopGUI->setHelp('Âàø íîìåð ðàñøèðåííîãî ñ÷¸òà'),
|
||||
);
|
||||
|
||||
// Ñîõðàí¸ííûé êîä â HTML íå âûâîäèòñÿ: ïóñòîå ïîëå ïðè ñîõðàíåíèè — «íå ìåíÿòü» (actionUpdate()).
|
||||
// Ðàçìåòêà ñâîÿ: setInput() ÿäðà íå óìååò autocomplete, à áåç new-password áðàóçåð ïîäñòàâèë áû
|
||||
// ñþäà ñîõðàí¸ííûé ïàðîëü àäìèíèñòðàòîðà è ïðè ñîõðàíåíèè çàò¸ð áû èì êîä.
|
||||
$hasIntegrityCode = is_array($data) && (string) ($data['integrity_code'] ?? '') !== '';
|
||||
$Tab1 .= $PHPShopGUI->setField(
|
||||
'Êîä ïðîâåðêè öåëîñòíîñòè äàííûõ',
|
||||
'<input class="form-control input-sm" type="password" name="integrity_code_new" value=""'
|
||||
. ' autocomplete="new-password" style="width:300px"'
|
||||
. ($hasIntegrityCode ? ' placeholder="' . HostCharset::toPage('Ñîõðàí¸í') . '"' : '')
|
||||
. (($hasIntegrityCode || $needsUpgrade) ? '' : ' required')
|
||||
. '>'
|
||||
. $PHPShopGUI->setHelp(
|
||||
'Êîä ïðîâåðêè öåëîñòíîñòè äàííûõ, óêàçàííûé â íàñòðîéêàõ ðàñøèðåííîãî ñ÷¸òà'
|
||||
. ($hasIntegrityCode ? '. Ñîõðàí¸ííûé êîä íå ïîêàçûâàåòñÿ — îñòàâüòå ïîëå ïóñòûì, ÷òîáû åãî íå ìåíÿòü' : ''),
|
||||
),
|
||||
);
|
||||
|
||||
$servers = [
|
||||
[HostCharset::toPage('Áîåâîé'), PaymentServer::PROD, $settings->getPaymentServer()->getValue()],
|
||||
[HostCharset::toPage('Äåìî'), PaymentServer::DEMO, $settings->getPaymentServer()->getValue()],
|
||||
];
|
||||
$Tab1 .= $PHPShopGUI->setField('Ñåðâåð ïëàòåæåé', $PHPShopGUI->setSelect('payment_server_new', $servers, 300));
|
||||
|
||||
$Tab1 .= $PHPShopGUI->setField(
|
||||
'Òåñòîâûé ðåæèì',
|
||||
$PHPShopGUI->setCheckbox('test_mode_new', '1', '', $settings->isTestMode() ? 1 : 0)
|
||||
. $PHPShopGUI->setHelp('Äîëæåí ñîâïàäàòü ñ ôëàãîì «Òåñòîâûé ðåæèì» â íàñòðîéêàõ ðàñøèðåííîãî ñ÷¸òà'),
|
||||
);
|
||||
|
||||
// Òîëüêî äëÿ ÷òåíèÿ, ñ êíîïêîé êîïèðîâàíèÿ: navigator.clipboard åñòü ëèøü íà HTTPS è localhost,
|
||||
// íà HTTP-àäìèíêå — çàïàñíîé ïóòü ÷åðåç âûäåëåíèå ïîëÿ è execCommand('copy').
|
||||
$callbackUrl = htmlspecialchars($context->callbackUrl(), ENT_QUOTES, 'Windows-1251');
|
||||
$Tab1 .= $PHPShopGUI->setField(
|
||||
'URL äëÿ óâåäîìëåíèé',
|
||||
HostCharset::toPage(
|
||||
'<div class="input-group" style="max-width:600px">'
|
||||
. '<input class="form-control input-sm" type="text" id="moneta_callback_url" value="',
|
||||
)
|
||||
// Àäðåñ — èç èìåíè ñåðâåðà, íå ëèòåðàë ìîäóëÿ: â êîäèðîâêå ñòðàíèöû, íå ïåðåêîäèðóåòñÿ.
|
||||
. $callbackUrl
|
||||
. HostCharset::toPage(
|
||||
'"'
|
||||
. ' readonly onfocus="this.select()">'
|
||||
. '<span class="input-group-btn"><button type="button" class="btn btn-default btn-sm" onclick="'
|
||||
. "var f=document.getElementById('moneta_callback_url'),b=this,t=b.textContent,"
|
||||
. "d=function(){b.textContent='Ñêîïèðîâàíî';setTimeout(function(){b.textContent=t;},1500);},"
|
||||
. "c=function(){f.select();try{document.execCommand('copy');d();}catch(e){}};"
|
||||
. "if(navigator.clipboard&&window.isSecureContext){navigator.clipboard.writeText(f.value).then(d,c);}else{c();}"
|
||||
. '">Êîïèðîâàòü</button></span></div>',
|
||||
)
|
||||
. $PHPShopGUI->setHelp(
|
||||
'Óêàæèòå ýòîò àäðåñ â íàñòðîéêàõ ðàñøèðåííîãî ñ÷¸òà êàê Check URL è Pay URL',
|
||||
),
|
||||
);
|
||||
|
||||
$Tab1 .= $PHPShopGUI->setField(
|
||||
'Îïèñàíèå îïëàòû',
|
||||
$PHPShopGUI->setTextarea(
|
||||
'title_end_new',
|
||||
htmlspecialchars($settings->getPaymentDescription(), ENT_QUOTES, 'Windows-1251'),
|
||||
false,
|
||||
300,
|
||||
80,
|
||||
)
|
||||
. $PHPShopGUI->setHelp(
|
||||
'Òåêñò íàä ñóììîé è êíîïêîé îïëàòû íà ñòðàíèöå «Çàêàç îôîðìëåí» è â ëè÷íîì êàáèíåòå. Ïóñòî — áåç òåêñòà',
|
||||
),
|
||||
);
|
||||
|
||||
$Tab1 .= $PHPShopGUI->setField(
|
||||
'Ôèñêàëèçàöèÿ ÷åêîâ',
|
||||
$PHPShopGUI->setCheckbox('fiscalization_new', '1', '', $settings->isFiscalization() ? 1 : 0)
|
||||
. $PHPShopGUI->setHelp('Ôèñêàëèçàöèÿ ÷åêîâ ïî 54-ÔÇ ñðåäñòâàìè ñèñòåìû ÌÎÍÅÒÀ ñåðâèñîì kassa.payanyway.ru'),
|
||||
);
|
||||
|
||||
// Ïîëÿ ÷åêà äëÿ êàññû âèäíû òîëüêî ïðè âêëþ÷¸ííîé ôèñêàëèçàöèè; çíà÷åíèÿ
|
||||
// ñîõðàíÿþòñÿ è ïðè ñêðûòûõ ïîëÿõ.
|
||||
$fiscal = 'moneta-fiscal';
|
||||
|
||||
if ($settings->isFiscalization() && $settings->getReceiptEmail() === '') {
|
||||
$Tab1 .= $PHPShopGUI->setAlert(
|
||||
HostCharset::toPage(
|
||||
'Ôèñêàëèçàöèÿ âêëþ÷åíà, à «Email äëÿ ÷åêîâ» íå çàïîëíåí. Óêàæèòå àäðåñ: íà íåãî ïðèä¸ò ÷åê,'
|
||||
. ' åñëè ó ïîêóïàòåëÿ íåò íè email, íè òåëåôîíà.',
|
||||
),
|
||||
'warning',
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
$Tab1 .= $PHPShopGUI->setField(
|
||||
'Email äëÿ ÷åêîâ',
|
||||
$PHPShopGUI->setInput(
|
||||
'email',
|
||||
'receipt_email_new',
|
||||
htmlspecialchars($settings->getReceiptEmail(), ENT_QUOTES, 'Windows-1251'),
|
||||
false,
|
||||
300,
|
||||
)
|
||||
. $PHPShopGUI->setHelp(
|
||||
'Ïîäñòàâëÿåòñÿ â ÷åê, åñëè ó ïîêóïàòåëÿ íåò íè email, íè òåëåôîíà — ÷åê ïðèä¸ò íà ýòîò àäðåñ, à ÔÈÎ ïîêóïàòåëÿ â ÷åêå ñîõðàíèòñÿ',
|
||||
),
|
||||
1,
|
||||
null,
|
||||
$fiscal,
|
||||
);
|
||||
|
||||
$Tab1 .= $PHPShopGUI->setField(
|
||||
'Ñèñòåìà íàëîãîîáëîæåíèÿ',
|
||||
$PHPShopGUI->setSelect(
|
||||
'sno_new',
|
||||
SelectOptions::fromLabels(array_map($page, TaxSystem::LABELS), $settings->getTaxSystem()->getValue()),
|
||||
300,
|
||||
)
|
||||
. $PHPShopGUI->setHelp('Åñëè íå ïåðåäàâàòü, êàññà âîçüì¸ò ñèñòåìó íàëîãîîáëîæåíèÿ èç ñâîèõ íàñòðîåê'),
|
||||
1,
|
||||
null,
|
||||
$fiscal,
|
||||
);
|
||||
|
||||
// Ñòàâêè PHPShop íå èç ïåðå÷íÿ êàññû (ñâîáîäíîå ÷èñëî, íàïðèìåð îïå÷àòêà 23): ïîçèöèè ñ íèìè
|
||||
// óõîäÿò â ÷åê «áåç ÍÄÑ», î êàæäîé òàêîé ïîçèöèè ìîäóëü ïèøåò è â æóðíàë PHP.
|
||||
$vatWarnings = [];
|
||||
try {
|
||||
$vatRates = new HostVatRates(Database::fromHost());
|
||||
$vatWarnings = VatRateWarnings::find(
|
||||
$settings->isFiscalization(),
|
||||
$vatRates->isEnabled(),
|
||||
$settings->getGoodsVat(),
|
||||
$settings->getDeliveryVat(),
|
||||
$vatRates->systemPercent(),
|
||||
$vatRates->enabledDeliveries(),
|
||||
);
|
||||
} catch (\Throwable $exception) {
|
||||
(new ErrorLogLogger())->error('Ñòàâêè ÍÄÑ PHPShop íå ïðîâåðåíû: ' . $exception->getMessage());
|
||||
}
|
||||
if ($vatWarnings !== []) {
|
||||
$escape = static function (string $text): string {
|
||||
return htmlspecialchars($text, ENT_QUOTES, 'Windows-1251');
|
||||
};
|
||||
$Tab1 .= $PHPShopGUI->setAlert(
|
||||
HostCharset::toPage(
|
||||
'Ñòàâêè ÍÄÑ íå èç ïåðå÷íÿ êàññû — ýòè ïîçèöèè óõîäÿò â ÷åê «áåç ÍÄÑ»: '
|
||||
. implode('; ', array_map($escape, $vatWarnings))
|
||||
. '. Èñïðàâüòå «Çíà÷åíèå ÍÄÑ» â ðàçäåëå «Íàñòðîéêà öåí» èëè â ñïîñîáå äîñòàâêè'
|
||||
. ' ëèáî âûáåðèòå ñòàâêó â ïîëÿõ íèæå.',
|
||||
),
|
||||
'warning',
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
$Tab1 .= $PHPShopGUI->setField(
|
||||
'ÍÄÑ íà òîâàðû',
|
||||
$PHPShopGUI->setSelect(
|
||||
'goods_vat_new',
|
||||
SelectOptions::fromLabels(
|
||||
array_map($page, VatSetting::labels('Èç íàñòðîåê ðàçäåëà «Íàñòðîéêà öåí»')),
|
||||
$settings->getGoodsVat()->getValue(),
|
||||
),
|
||||
300,
|
||||
)
|
||||
. $PHPShopGUI->setHelp('Îäíà ñòàâêà íà âñå òîâàðû èëè «Çíà÷åíèå ÍÄÑ» èç ðàçäåëà «Íàñòðîéêà öåí»'),
|
||||
1,
|
||||
null,
|
||||
$fiscal,
|
||||
);
|
||||
|
||||
$Tab1 .= $PHPShopGUI->setField(
|
||||
'ÍÄÑ íà äîñòàâêó',
|
||||
$PHPShopGUI->setSelect(
|
||||
'delivery_vat_new',
|
||||
SelectOptions::fromLabels(
|
||||
array_map($page, VatSetting::labels('Èç íàñòðîåê ñïîñîáà äîñòàâêè')),
|
||||
$settings->getDeliveryVat()->getValue(),
|
||||
),
|
||||
300,
|
||||
)
|
||||
. $PHPShopGUI->setHelp('Îäíà ñòàâêà íà äîñòàâêó èëè «Çíà÷åíèå ÍÄÑ» ñïîñîáà äîñòàâêè.'),
|
||||
1,
|
||||
null,
|
||||
$fiscal,
|
||||
);
|
||||
|
||||
$Tab1 .= $PHPShopGUI->setField(
|
||||
'Ïðèçíàê ñïîñîáà ðàñ÷¸òà',
|
||||
$PHPShopGUI->setSelect(
|
||||
'payment_method_new',
|
||||
SelectOptions::fromLabels(array_map($page, PaymentMethod::LABELS), $settings->getPaymentMethod()->getValue()),
|
||||
300,
|
||||
)
|
||||
. $PHPShopGUI->setHelp('Ó âñåõ ïîçèöèé ÷åêà, âêëþ÷àÿ äîñòàâêó'),
|
||||
1,
|
||||
null,
|
||||
$fiscal,
|
||||
);
|
||||
|
||||
$Tab1 .= $PHPShopGUI->setField(
|
||||
'Ïðèçíàê ïðåäìåòà ðàñ÷¸òà',
|
||||
$PHPShopGUI->setSelect(
|
||||
'payment_object_new',
|
||||
SelectOptions::fromLabels(array_map($page, PaymentObject::LABELS), $settings->getPaymentObject()->getValue()),
|
||||
300,
|
||||
)
|
||||
. $PHPShopGUI->setHelp('Ó òîâàðîâ; äîñòàâêà â ÷åêå — âñåãäà «Óñëóãà»'),
|
||||
1,
|
||||
null,
|
||||
$fiscal,
|
||||
);
|
||||
|
||||
// Ñêðûòîå ïîëå email ñ îøèáêîé áðàóçåð íå äàë áû îòïðàâèòü, à ïîäñêàçêó íå ïîêàçàë áû —
|
||||
// íà âðåìÿ ñêðûòèÿ îíî ñòàíîâèòñÿ òåêñòîâûì è íåîáÿçàòåëüíûì (àäðåñ âñ¸ ðàâíî ïðîâåðÿåò
|
||||
// actionUpdate()); ïðè ôèñêàëèçàöèè «Email äëÿ ÷åêîâ» îáÿçàòåëåí.
|
||||
$Tab1 .= '<script>jQuery(function ($) {
|
||||
const box = $("#fiscalization_new");
|
||||
const sync = function () {
|
||||
const on = box.is(":checked");
|
||||
$(".' . $fiscal . '").toggle(on);
|
||||
$("[name=receipt_email_new]").attr("type", on ? "email" : "text").prop("required", on);
|
||||
};
|
||||
box.on("change", sync);
|
||||
sync();
|
||||
});</script>';
|
||||
|
||||
$Tab1 .= $PHPShopGUI->setField(
|
||||
'Îïëàòà ïðè ñòàòóñå',
|
||||
$PHPShopGUI->setSelect(
|
||||
'status_new',
|
||||
OrderStatusOptions::build($statuses, $settings->getPayableStatus(), $page('Íîâûé çàêàç'), Settings::STATUS_NEW),
|
||||
300,
|
||||
),
|
||||
);
|
||||
$Tab1 .= $PHPShopGUI->setField(
|
||||
'Ñòàòóñ ïîñëå îïëàòû',
|
||||
$PHPShopGUI->setSelect(
|
||||
'paid_status_new',
|
||||
OrderStatusOptions::build(
|
||||
$statuses,
|
||||
$settings->getPaidStatus(),
|
||||
$page('Îïëà÷åíî ïëàòåæíûìè ñèñòåìàìè'),
|
||||
Settings::STATUS_PAID_BY_GATEWAY,
|
||||
),
|
||||
300,
|
||||
),
|
||||
);
|
||||
|
||||
// Òîëüêî ñèìâîëû cp1251: ñáîðêà ïåðåêîäèðóåò ôàéë. Ïàíåëü ñîáèðàåòñÿ çäåñü, à íå ÷åðåç
|
||||
// setInfo(): òîò íà UTF-8-áàçå ïðîïóñêàåò áëîê ÷åðåç __() ñî strip_tags è âûðåçàåò òàáëèöó.
|
||||
$link = static function (string $url, string $text): string {
|
||||
return '<a href="' . $url . '" target="_blank" rel="noopener noreferrer">' . $text . '</a>';
|
||||
};
|
||||
$kassa = $link('https://kassa.payanyway.ru/', 'kassa.payanyway.ru');
|
||||
|
||||
$accountRows = [
|
||||
['Ïñåâäîíèì', 'ëþáîé, íàïðèìåð <code>Ìîíåòà</code>'],
|
||||
['Òåñòîâûé ðåæèì', 'êàê â íàñòðîéêå ìîäóëÿ'],
|
||||
['Check URL è Pay URL', '<code>' . $callbackUrl . '</code>'],
|
||||
['HTTP-ìåòîä (Check URL, Pay URL)', '<code>POST</code> èëè <code>GET</code>'],
|
||||
[
|
||||
'Êîä ïðîâåðêè öåëîñòíîñòè äàííûõ',
|
||||
'ïðîèçâîëüíûé íàáîð ñèìâîëîâ; òîò æå êîä óêàæèòå â íàñòðîéêàõ ìîäóëÿ',
|
||||
],
|
||||
['Ïîäïèñü ôîðìû îïëàòû îáÿçàòåëüíà', '<code>Äà</code>'],
|
||||
['Ìîæíî ïåðåîïðåäåëÿòü íàñòðîéêè â URL', '<code>Äà</code>'],
|
||||
['Success URL', 'îñòàâèòü ïóñòûì'],
|
||||
['Fail URL', 'îñòàâèòü ïóñòûì'],
|
||||
['InProgress URL', 'îñòàâèòü ïóñòûì'],
|
||||
['Return URL', 'îñòàâèòü ïóñòûì'],
|
||||
];
|
||||
$accountTable = '';
|
||||
foreach ($accountRows as [$field, $value]) {
|
||||
$accountTable .= '<tr><td>' . $field . '</td><td>' . $value . '</td></tr>';
|
||||
}
|
||||
|
||||
$info = '<h4>Íàñòðîéêà ñ÷¸òà â ëè÷íîì êàáèíåòå ' . $link('https://moneta.ru/', 'MONETA.RU') . '</h4>
|
||||
<ol>
|
||||
<li>' . $link('https://payanyway.ru/partnerRegistration.htm', 'Çàðåãèñòðèðóéòåñü') . '
|
||||
â ïëàò¸æíîé ñèñòåìå PayAnyWay è çàïîëíèòå âñå íåîáõîäèìûå äàííûå. Äîæäèòåñü ïðîâåðêè àêêàóíòà
|
||||
è ñîçäàéòå ðàñøèðåííûé ñ÷¸ò.</li>
|
||||
<li>Çàïîëíèòå íàñòðîéêè ðàñøèðåííîãî ñ÷¸òà â ëè÷íîì êàáèíåòå: «Ìîé ñ÷¸ò» -> «Óïðàâëåíèå
|
||||
ñ÷åòàìè» -> «Ðåäàêòèðîâàòü ñ÷¸ò» -> «Ïîêàçàòü äîïîëíèòåëüíûå ïîëÿ».
|
||||
<table class="table table-bordered table-condensed" style="margin-top:10px">
|
||||
<thead><tr><th>Ïîëå â ëè÷íîì êàáèíåòå</th><th>Çíà÷åíèå</th></tr></thead>
|
||||
<tbody>' . $accountTable . '</tbody>
|
||||
</table>
|
||||
</li>
|
||||
<li>Íà âêëàäêå «Îñíîâíîå» óêàæèòå íîìåð ñ÷¸òà è òîò æå êîä ïðîâåðêè öåëîñòíîñòè äàííûõ.
|
||||
Íà äåìî-ïëîùàäêå demo.moneta.ru íîìåð ñ÷¸òà ñâîé.</li>
|
||||
<li>Äëÿ ôèñêàëèçàöèè ÷åêîâ ïî 54-ÔÇ ñðåäñòâàìè çà ðàìêàìè PHPShop íàñòðîéòå âàøó êàññó â ñåðâèñå
|
||||
' . $kassa . ', â íàñòðîéêàõ ðàñøèðåííîãî ñ÷¸òà â MONETA.RU óñòàíîâèòå Pay URL
|
||||
<code>https://kassa.payanyway.ru/index.php?do=invoicepayurl</code>, à â íàñòðîéêàõ êàññû
|
||||
ïðîïèøèòå Pay URL âàøåãî èíòåðíåò-ìàãàçèíà ' . '<code>' . $callbackUrl . '</code>' . '.  ýòîì ñëó÷àå ÷åê ïî 54-ÔÇ
|
||||
áóäåò ïðîáèâàòüñÿ ÷åðåç ' . $kassa . ', à çàïðîñ íà Pay URL ìàãàçèíà áóäåò ïðîõîäèòü
|
||||
÷åðåç ýòîò ñåðâèñ òðàíçèòîì.</li>
|
||||
</ol>
|
||||
<p><span class="text-danger">Âàæíî!</span> Äëÿ êèðèëëè÷åñêîãî äîìåíà Check URL è Pay URL óêàæèòå
|
||||
â êîäèðîâêå ' . $link('https://2ip.ru/punycode/', 'Punycode') . '.</p>
|
||||
<h4>Âûêëþ÷åíèå ìîäóëÿ</h4>
|
||||
<p>Âûêëþ÷åíèå ìîäóëÿ â PHPShop óäàëÿåò åãî òàáëèöû: íàñòðîéêè ïðèä¸òñÿ ââåñòè çàíîâî.</p>';
|
||||
$Tab2 = '<div class="panel panel-default"><div class="panel-body">' . HostCharset::toPage($info) . '</div></div>';
|
||||
|
||||
$Tab3 = $PHPShopGUI->setPay(false, false, $data['version'], true);
|
||||
|
||||
$PHPShopGUI->setTab(['Îñíîâíîå', $Tab1, true], ['Èíñòðóêöèÿ', $Tab2], ['Î ìîäóëå', $Tab3]);
|
||||
|
||||
$ContentFooter = $PHPShopGUI->setInput('hidden', 'rowID', $data['id'])
|
||||
. $PHPShopGUI->setInput('submit', 'saveID', 'Ïðèìåíèòü', 'right', 80, '', 'but', 'actionUpdate.modules.edit');
|
||||
|
||||
$PHPShopGUI->setFooter($ContentFooter);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Îáðàáîòêà ñîáûòèé
|
||||
$PHPShopGUI->getAction();
|
||||
|
||||
// Âûâîä ôîðìû ïðè ñòàðòå
|
||||
$PHPShopGUI->setLoader($_POST['saveID'] ?? null, 'actionStart');
|
||||
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Æóðíàë îïåðàöèé ìîäóëÿ «Ìîíåòà» â àäìèíêå PHPShop (Ìîäóëè -> Ìîíåòà -> Æóðíàë îïåðàöèé).
|
||||
*
|
||||
* Êàê ôàéë ïîïàäàåò â àäìèíêó: ïóíêò ïîäìåíþ â `install/module.xml` (`podmenu_action` = `dir.moneta`)
|
||||
* âåä¸ò íà `admin.php?path=modules.dir.moneta`. `admpanel/admin.php` ÿäðà ðåæåò ïóòü ïî òî÷êàì
|
||||
* è ïîäêëþ÷àåò `admpanel/modules/admin_dir.php`, à òîò — `modules/<òðåòüÿ ÷àñòü ïóòè>/admpanel/
|
||||
* admin_<òðåòüÿ ÷àñòü ïóòè>.php`, òî åñòü ýòîò ôàéë (èìÿ ôàéëà ìåíÿòü íåëüçÿ). Ïåðåä ýòèì ÿäðî
|
||||
* çàïîëíÿåò ãëîáàëüíûå `$TitlePage` è `$select_name` (çàãîëîâîê è ïóíêòû ïîäìåíþ), ïîñëå — âûçûâàåò
|
||||
* ãëîáàëüíóþ ôóíêöèþ `actionStart()`: èìÿ òîæå çàäà¸ò ÿäðî (`$loader_function`). Òàê æå â 6.7 è 7.0.
|
||||
*
|
||||
* Ïîäïèñü çàïðîñà è êîä ïðîâåðêè öåëîñòíîñòè â æóðíàë íå ïèøóòñÿ.
|
||||
*/
|
||||
|
||||
require_once dirname(__DIR__) . '/class/autoload.php';
|
||||
|
||||
use MonetaPhpShop\callback\CallbackEvent;
|
||||
use MonetaPhpShop\host\Database;
|
||||
use MonetaPhpShop\host\HostCharset;
|
||||
use MonetaPhpShop\host\OperationRepository;
|
||||
use MonetaPhpShop\protocol\TransactionId;
|
||||
|
||||
function actionStart()
|
||||
{
|
||||
global $PHPShopInterface, $TitlePage, $select_name;
|
||||
|
||||
// Íà ñòðàíèöó îòäà¸ì òîëüêî 500 ïîñëåäíèõ çàïèñåé, íîâûå ñâåðõó. Ïîñòðàíè÷íûé âûâîä, ïîèñê
|
||||
// è ñîðòèðîâêó äåëàåò DataTables, êîòîðûì ÿäðî îáîðà÷èâàåò òàáëèöó àäìèíêè (admpanel/js/phpshop.js),
|
||||
// — â áðàóçåðå, ïî óæå âûâåäåííûì ñòðîêàì; áåç ëèìèòà ñòðàíèöà ðîñëà áû âìåñòå ñ æóðíàëîì.
|
||||
// À îí íå ÷èñòèòñÿ è ðàñò¸ò áûñòðî: íà êàæäîå óâåäîìëåíèå ñòðîêà, íà çàêàç èõ ìèíèìóì äâå
|
||||
// (Check URL è Pay URL), ïðîâåðî÷íûé çàïðîñ MONETA.RU ìîæåò ïðèñëàòü íåñêîëüêî ðàç, à Pay URL
|
||||
// ïîñëå îòâåòà FAIL ïîâòîðÿåò äî ñóòîê. Ñòàðûå çàïèñè îñòàþòñÿ â òàáëèöå, íà ýêðàí íå âûâîäÿòñÿ.
|
||||
$limit = 500;
|
||||
|
||||
$escape = static function (string $value): string {
|
||||
return htmlspecialchars($value, ENT_QUOTES, 'Windows-1251');
|
||||
};
|
||||
// Íà ìàãàçèíå ñ áàçîé utf-8 ÿäðî ïåðåêîäèðóåò çàãîëîâêè setCaption(), íî íå ÿ÷åéêè setRow()
|
||||
// è íå ðàçìåòêó ïàíåëè — òåêñòû ìîäóëÿ ïåðåêîäèðóþòñÿ çäåñü. Ââåä¸ííîå â ïîèñê è ñòðîêè
|
||||
// æóðíàëà (ASCII) óæå â êîäèðîâêå ñòðàíèöû.
|
||||
$page = static function (string $text): string {
|
||||
return HostCharset::toPage($text);
|
||||
};
|
||||
|
||||
// Ôèëüòð ïî çàêàçó: íîìåð (`33-57`) èëè öåëèêîì MNT_TRANSACTION_ID èç êàáèíåòà MONETA.RU.
|
||||
// Èùåò ïî âñåìó æóðíàëó, à íå òîëüêî ïî âûâåäåííûì ñòðîêàì, êàê ïîèñê DataTables.
|
||||
$input = isset($_GET['moneta_order']) && is_string($_GET['moneta_order']) ? trim($_GET['moneta_order']) : '';
|
||||
$orderUid = $input !== '' ? TransactionId::orderUidFromInput($input) : null;
|
||||
|
||||
$PHPShopInterface->checkbox_action = false;
|
||||
$PHPShopInterface->setActionPanel($TitlePage, $select_name, false);
|
||||
// Ïîä ïàíåëüþ ñ çàãîëîâêîì, âíå ôîðì ÿäðà: Compile() âûâîäèò actionPanel ïåðåä òàáëèöåé.
|
||||
$PHPShopInterface->actionPanel .= '<form method="get" class="form-inline" style="margin: 0 0 10px 15px">'
|
||||
. '<input type="hidden" name="path" value="modules.dir.moneta">'
|
||||
. '<input type="text" name="moneta_order" value="' . $escape($input) . '" class="form-control input-sm"'
|
||||
. $page(
|
||||
' style="width: 300px" placeholder="Íîìåð çàêàçà èëè MNT_TRANSACTION_ID"> '
|
||||
. '<button type="submit" class="btn btn-default btn-sm">Íàéòè</button> '
|
||||
. ($input !== '' ? '<a href="?path=modules.dir.moneta" class="btn btn-link btn-sm">Ñáðîñèòü</a>' : '')
|
||||
. ($input !== '' && $orderUid === null
|
||||
? ' <span class="text-danger">Íîìåð çàêàçà íå ðàñïîçíàí — ïîêàçàí âåñü æóðíàë</span>'
|
||||
: '')
|
||||
. '</form>',
|
||||
);
|
||||
$PHPShopInterface->setCaption(
|
||||
['Äàòà', '12%'],
|
||||
['Çàêàç', '8%'],
|
||||
['Çàïðîñ', '8%'],
|
||||
['Ñîáûòèå', '30%'],
|
||||
['Îòâåò', '6%'],
|
||||
['Ñóììà', '8%'],
|
||||
['Íîìåð îïåðàöèè', '8%'],
|
||||
['Èäåíòèôèêàòîð çàêàçà', '20%']
|
||||
);
|
||||
|
||||
$rows = (new OperationRepository(Database::fromHost()))->latest($limit, $orderUid);
|
||||
foreach ($rows as $row) {
|
||||
$orderId = (int) $row['order_id'];
|
||||
$order = $orderId > 0
|
||||
? ['name' => $escape((string) $row['order_uid']), 'link' => '?path=order&id=' . $orderId]
|
||||
: $page('—');
|
||||
$command = (string) $row['command'] === 'CHECK' ? 'Ïðîâåðêà' : 'Îïëàòà';
|
||||
if ((string) $row['test_mode'] === '1') {
|
||||
$command .= ' (òåñò)';
|
||||
}
|
||||
|
||||
$resultCode = $row['result_code'] === null ? null : (int) $row['result_code'];
|
||||
$icon = CallbackEvent::iconHtml((string) $row['event'], $resultCode);
|
||||
$event = ($icon === '' ? '' : $icon . ' ') . $escape(CallbackEvent::label((string) $row['event']));
|
||||
|
||||
$PHPShopInterface->setRow(
|
||||
PHPShopDate::get((int) $row['created_at'], true),
|
||||
$order,
|
||||
$page($command),
|
||||
$page($event),
|
||||
$row['result_code'] === null ? 'FAIL' : (string) $row['result_code'],
|
||||
['name' => $escape((string) $row['amount']), 'align' => 'right'],
|
||||
$escape((string) $row['operation_id']),
|
||||
$escape((string) $row['transaction_id'])
|
||||
);
|
||||
}
|
||||
|
||||
$PHPShopInterface->Compile();
|
||||
}
|
||||
Reference in New Issue
Block a user