feat: moneta 2.0, MONETA.Assistant payment module for PHPShop 6.7+

This commit is contained in:
2026-10-27 11:45:22 +03:00
parent 78b7405637
commit f8c12ce44a
82 changed files with 7387 additions and 58 deletions
+158
View File
@@ -0,0 +1,158 @@
<?php
declare(strict_types=1);
namespace MonetaPhpShop\host;
use Closure;
use MonetaPhpShop\callback\Logger;
use MonetaPhpShop\callback\ReceiptSource;
use MonetaPhpShop\order\Order;
use MonetaPhpShop\receipt\Receipt;
use MonetaPhpShop\receipt\ReceiptBuilder;
use MonetaPhpShop\receipt\Vat;
use MonetaPhpShop\receipt\VatRateWarnings;
use MonetaPhpShop\Settings;
/**
* ×åê çàêàçà äëÿ îòâåòîâ Check/Pay URL. Ñòàâêè ÍÄÑ — ôèêñèðîâàííûå èç íàñòðîåê ìîäóëÿ
* («ÍÄÑ íà òîâàðû», «ÍÄÑ íà äîñòàâêó»), à ïî óìîë÷àíèþ èç PHPShop: âûêëþ÷åí ÍÄÑ
* â íàñòðîéêàõ ìàãàçèíà — «áåç ÍÄÑ» íà âñåõ ñòðîêàõ; âêëþ÷¸í — ñèñòåìíàÿ ñòàâêà ó òîâàðîâ
* è ñòàâêà ñïîñîáà äîñòàâêè (`phpshop_delivery.ofd_nds`, ïóñòî — ñèñòåìíàÿ) ó äîñòàâêè.
*
* Ñòàâêó íå èç ïåðå÷íÿ êàññû (â PHPShop ýòî ñâîáîäíîå ÷èñëî, íàïðèìåð îïå÷àòêà `23`) ìîäóëü íå óãàäûâàåò:
* ïîçèöèÿ óõîäèò «áåç ÍÄÑ», à â æóðíàë PHP ïèøåòñÿ ïðåäóïðåæäåíèå — òî æå ïîêàçûâàþò íàñòðîéêè ìîäóëÿ
* ({@see VatRateWarnings}).
*
* Áåç ôèñêàëèçàöèè àòðèáóòû óðåçàíû, à «Email äëÿ ÷åêîâ» íå ïîäñòàâëÿåòñÿ: ÷åê íå ïðîáèâàåòñÿ,
* MONETA.RU òîëüêî ñîõðàíÿåò àòðèáóòû â îïåðàöèè.
*
* Ñáîé ñáîðêè ÷åêà íå äîëæåí ðîíÿòü ïîäòâåðæäåíèå îïëàòû: àòðèáóòû òîãäà ïóñòûå, JSON — null.
*/
final class HostReceiptSource implements ReceiptSource
{
/** @var Settings */
private $settings;
/** @var HostVatRates */
private $vatRates;
/** @var Logger */
private $logger;
/** @var array<int, Receipt> */
private $receipts = [];
public function __construct(Settings $settings, Database $database, Logger $logger)
{
$this->settings = $settings;
$this->vatRates = new HostVatRates($database);
$this->logger = $logger;
}
public function attributes(Order $order): array
{
$receipt = $this->receipt($order);
return ($receipt !== null)
? $receipt->toAttributes($this->settings->isFiscalization(), $this->settings->getTaxSystem())
: [];
}
public function jsonReceipt(Order $order): ?array
{
$receipt = $this->receipt($order);
return ($receipt !== null) ? $receipt->toJsonReceipt() : null;
}
private function receipt(Order $order): ?Receipt
{
if (isset($this->receipts[$order->getId()])) {
return $this->receipts[$order->getId()];
}
try {
$builder = new ReceiptBuilder(
Closure::fromCallable([HostCharset::class, 'toUtf8']),
$this->settings->getPaymentMethod(),
$this->settings->getPaymentObject(),
$this->settings->getGoodsVat()->getFixed(),
);
$receiptEmail = $this->settings->isFiscalization() ? $this->settings->getReceiptEmail() : '';
$receipt = $builder->build($order, $this->goodsVat($order), $this->deliveryVat($order), $receiptEmail);
} catch (\Throwable $exception) {
$this->logger->error(
sprintf(
'×åê çàêàçà %s íå ñîáðàí: %s: %s',
$order->getUid(),
get_class($exception),
$exception->getMessage(),
),
);
return null;
}
return $this->receipts[$order->getId()] = $receipt;
}
private function goodsVat(Order $order): Vat
{
$fixed = $this->settings->getGoodsVat()->getFixed();
if ($fixed !== null) {
return $fixed;
}
if (!$this->vatRates->isEnabled()) {
return Vat::none();
}
return $this->platformVat($order, $this->vatRates->systemPercent(), 'ñèñòåìíàÿ ñòàâêà PHPShop (òîâàðû)');
}
private function deliveryVat(Order $order): Vat
{
$fixed = $this->settings->getDeliveryVat()->getFixed();
if ($fixed !== null) {
return $fixed;
}
if (!$this->vatRates->isEnabled()) {
return Vat::none();
}
$percent = $this->vatRates->deliveryPercent($order->getDeliveryMethodId());
if ($percent !== '') {
return $this->platformVat($order, $percent, 'ñòàâêà ñïîñîáà äîñòàâêè');
}
return $this->platformVat($order, $this->vatRates->systemPercent(), 'ñèñòåìíàÿ ñòàâêà PHPShop (äîñòàâêà)');
}
/**
* Ñòàâêà èç PHPShop; íå èç ïåðå÷íÿ êàññû — «áåç ÍÄÑ» è ïðåäóïðåæäåíèå, åñëè ÷åê ïðîáèâàåòñÿ.
*/
private function platformVat(Order $order, string $percent, string $source): Vat
{
$vat = Vat::tryFromPercent($percent);
if ($vat !== null) {
return $vat;
}
if ($this->settings->isFiscalization()) {
$this->logger->error(
sprintf(
'Çàêàç %s: %s %s íå èç ïåðå÷íÿ êàññû — ïîçèöèÿ óõîäèò â ÷åê «áåç ÍÄÑ».'
. ' Èñïðàâüòå ñòàâêó â PHPShop èëè çàäàéòå ñòàâêó â íàñòðîéêàõ ìîäóëÿ.',
$order->getUid(),
$source,
//  æóðíàë — òîëüêî òî, ÷òî ïîõîæå íà ÷èñëî: çíà÷åíèå ââîäèò àäìèíèñòðàòîð.
VatRateWarnings::shown((string) preg_replace('/[^0-9.,%+\- ]/', '?', substr($percent, 0, 16))),
),
);
}
return Vat::none();
}
}