185 lines
7.2 KiB
PHP
185 lines
7.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace MonetaPhpShop\host;
|
|
|
|
use MonetaPhpShop\form\AmountText;
|
|
use MonetaPhpShop\form\PaymentForm;
|
|
use MonetaPhpShop\form\ReturnAccess;
|
|
use MonetaPhpShop\form\ReturnUrls;
|
|
use MonetaPhpShop\order\Order;
|
|
use MonetaPhpShop\order\PaymentEligibility;
|
|
use MonetaPhpShop\protocol\AssistantProtocol;
|
|
use MonetaPhpShop\Settings;
|
|
|
|
/**
|
|
* Êíîïêà îïëàòû äëÿ õóêîâ âèòðèíû: ïîñëå îôîðìëåíèÿ çàêàçà (`send_to_order`) è â ëè÷íîì
|
|
* êàáèíåòå (`userorderpaymentlink`). Îøèáêà ìîäóëÿ íå äîëæíà ðîíÿòü ñòðàíèöó ìàãàçèíà:
|
|
* ïîêóïàòåëü âèäèò íåéòðàëüíûé òåêñò, ïîäðîáíîñòè — â æóðíàëå PHP.
|
|
*/
|
|
final class CheckoutView
|
|
{
|
|
private const MESSAGES = [
|
|
PaymentEligibility::NOT_CONFIGURED => 'Îïëàòà ÷åðåç Ìîíåòó âðåìåííî íåäîñòóïíà. Ñâÿæèòåñü ñ ìàãàçèíîì.',
|
|
PaymentEligibility::ALREADY_PAID => 'Çàêàç îïëà÷åí.',
|
|
PaymentEligibility::CANCELLED => 'Çàêàç îòìåí¸í.',
|
|
PaymentEligibility::AWAITING_STATUS => 'Çàêàç îáðàáàòûâàåòñÿ ìåíåäæåðîì.',
|
|
PaymentEligibility::UNSUPPORTED_CURRENCY => 'Îïëàòà ÷åðåç Ìîíåòó âîçìîæíà òîëüêî â ðóáëÿõ.',
|
|
PaymentEligibility::ZERO_AMOUNT => 'Îïëàòà íå òðåáóåòñÿ.',
|
|
];
|
|
|
|
/** Òåêñò êíîïêè îïëàòû; íà êàðòî÷êå ïîñëå îôîðìëåíèÿ ê íåìó äîáàâëÿåòñÿ ñóììà. */
|
|
private const BUTTON_TITLE = 'Îïëàòèòü';
|
|
|
|
private const UNAVAILABLE = 'Îïëàòà âðåìåííî íåäîñòóïíà. Ïîïðîáóéòå ïîçæå èëè ñâÿæèòåñü ñ ìàãàçèíîì.';
|
|
|
|
/** @var SettingsRepository */
|
|
private $settingsRepository;
|
|
|
|
/** @var OrderRepository */
|
|
private $orderRepository;
|
|
|
|
/** @var ShopContext */
|
|
private $shopContext;
|
|
|
|
public function __construct(
|
|
SettingsRepository $settingsRepository,
|
|
OrderRepository $orderRepository,
|
|
ShopContext $shopContext
|
|
) {
|
|
$this->settingsRepository = $settingsRepository;
|
|
$this->orderRepository = $orderRepository;
|
|
$this->shopContext = $shopContext;
|
|
}
|
|
|
|
public static function create(): self
|
|
{
|
|
return new self(new SettingsRepository(), new OrderRepository(), new ShopContext());
|
|
}
|
|
|
|
/**
|
|
* Áëîê íà ñòðàíèöå «Çàêàç îôîðìëåí»: ñóììà è êíîïêà, åñëè çàêàç óæå ìîæíî îïëàòèòü, èíà÷å
|
|
* òåêñò î ñîñòîÿíèè çàêàçà. Ðàçìåòêó ñîáèðàåò øàáëîí `payment_forma.tpl` â õóêå; ÷àñòè — â cp1251.
|
|
*/
|
|
public function afterCheckout(int $orderId): CheckoutBlock
|
|
{
|
|
return $this->block($orderId, true);
|
|
}
|
|
|
|
/**
|
|
* ß÷åéêà «Ñïîñîá îïëàòû» â ëè÷íîì êàáèíåòå: îïèñàíèå îïëàòû è êíîïêà èëè ñîñòîÿíèå çàêàçà, áåç ñóììû.
|
|
*/
|
|
public function inAccount(int $orderId): string
|
|
{
|
|
$block = $this->block($orderId, false);
|
|
if ($block->isEmpty()) {
|
|
return '';
|
|
}
|
|
$info = ($block->getInfo() === '') ? '' : '<p class="moneta-payment-info">' . $block->getInfo() . '</p>';
|
|
|
|
return HostCharset::toPage('<div class="moneta-payment">' . $info . $block->getForm() . '</div>');
|
|
}
|
|
|
|
/**
|
|
* ×òî ïîêàçàòü ïî ñîñòîÿíèþ çàêàçà: ôîðìó îïëàòû ñ ñóììîé, åñëè çàêàç ìîæíî îïëàòèòü,
|
|
* èíà÷å — òåêñò î ñîñòîÿíèè.
|
|
*
|
|
* @param string $formHtml ôîðìà îïëàòû; íóæíà òîëüêî äëÿ {@see PaymentEligibility::PAYABLE}
|
|
* @param string $total ñóììà ê îïëàòå òåêñòîì; ïîêàçûâàåòñÿ òîëüêî âìåñòå ñ ôîðìîé
|
|
* @param string $description «Îïèñàíèå îïëàòû» îáû÷íûì òåêñòîì; ïîêàçûâàåòñÿ òîëüêî âìåñòå ñ ôîðìîé:
|
|
* «Îïëàòèòå çàêàç» áåç êíîïêè (çàêàç æä¸ò ìåíåäæåðà) ñáèâàë áû ñ òîëêó
|
|
*/
|
|
public static function compose(
|
|
string $eligibility,
|
|
string $formHtml,
|
|
string $total = '',
|
|
string $description = ''
|
|
): CheckoutBlock {
|
|
if ($eligibility === PaymentEligibility::PAYABLE) {
|
|
return new CheckoutBlock($formHtml, $total, self::descriptionHtml($description));
|
|
}
|
|
|
|
return new CheckoutBlock('<p>' . (self::MESSAGES[$eligibility] ?? self::UNAVAILABLE) . '</p>');
|
|
}
|
|
|
|
private function block(int $orderId, bool $afterCheckout): CheckoutBlock
|
|
{
|
|
try {
|
|
$settings = $this->settingsRepository->load();
|
|
$order = $this->orderRepository->findById($orderId);
|
|
if ($order === null) {
|
|
return new CheckoutBlock('');
|
|
}
|
|
// Ëè÷íûé êàáèíåò îòêðûâàåò çàêàç ïî îäíîìó uid, íå ñâåðÿÿ âëàäåëüöà
|
|
// (`users.core/action_order_info.php` ÿäðà): ôîðìó è çàïèñü â ñåññèþ — òîëüêî âëàäåëüöó.
|
|
if (!$afterCheckout && !ReturnAccess::isOwner($order, $this->shopContext->sessionUserId())) {
|
|
return new CheckoutBlock('');
|
|
}
|
|
|
|
$currency = $this->shopContext->orderCurrency();
|
|
$eligibility = PaymentEligibility::check($settings, $order, $currency);
|
|
if ($eligibility !== PaymentEligibility::PAYABLE) {
|
|
return self::compose($eligibility, '');
|
|
}
|
|
$this->shopContext->rememberPayableOrder($order->getId());
|
|
|
|
// Íà êàðòî÷êå ïîñëå îôîðìëåíèÿ — ñóììà îòäåëüíîé ñòðîêîé è â êíîïêå,
|
|
// ñî çíàêîì âàëþòû âèòðèíû; â ÿ÷åéêå ëè÷íîãî êàáèíåòà — êîðîòêàÿ êíîïêà.
|
|
$amount = '';
|
|
$currencyIcon = '';
|
|
if ($afterCheckout) {
|
|
$amount = AmountText::format($order->getAmount(), $this->shopContext->priceDecimals());
|
|
$currencyIcon = $this->shopContext->currencyIcon();
|
|
}
|
|
$suffix = ($currencyIcon === '') ? '' : ' ' . $currencyIcon;
|
|
$formHtml = $this->form(
|
|
$settings,
|
|
$order,
|
|
(string) AssistantProtocol::normalizeCurrency($currency),
|
|
($amount === '') ? self::BUTTON_TITLE : self::BUTTON_TITLE . ' ' . $amount,
|
|
($amount === '') ? '' : $suffix,
|
|
);
|
|
$total = ($amount === '') ? '' : $amount . $suffix;
|
|
$description = HostCharset::fromDatabase($settings->getPaymentDescription());
|
|
|
|
return self::compose($eligibility, $formHtml, $total, $description);
|
|
} catch (\Throwable $exception) {
|
|
(new ErrorLogLogger())->error(
|
|
'Êíîïêà îïëàòû çàêàçà ' . $orderId . ' íå ïîñòðîåíà: ' . $exception->getMessage(),
|
|
);
|
|
|
|
return new CheckoutBlock('<p>' . self::UNAVAILABLE . '</p>');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Òåêñò ìåð÷àíòà èç íàñòðîåê — â HTML: ýêðàíèðîâàíèå, ïåðåíîñû ñòðîê — `<br>`.
|
|
*/
|
|
private static function descriptionHtml(string $text): string
|
|
{
|
|
$text = trim($text);
|
|
|
|
return ($text === '') ? '' : nl2br(htmlspecialchars($text, ENT_QUOTES, 'Windows-1251'), false);
|
|
}
|
|
|
|
private function form(
|
|
Settings $settings,
|
|
Order $order,
|
|
string $currency,
|
|
string $buttonTitle,
|
|
string $buttonSuffixHtml
|
|
): string {
|
|
return PaymentForm::create(
|
|
$settings,
|
|
$order,
|
|
$currency,
|
|
$this->shopContext->now(),
|
|
new ReturnUrls($this->shopContext->returnPageUrl()),
|
|
'Îïëàòà çàêàçà ¹' . $order->getUid(),
|
|
$this->shopContext->cms(),
|
|
AssistantProtocol::normalizeLocale($this->shopContext->shopLocale()),
|
|
)->toHtml($buttonTitle, $buttonSuffixHtml);
|
|
}
|
|
}
|