152 lines
5.2 KiB
PHP
152 lines
5.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace MonetaPhpShop\form;
|
|
|
|
use DateTimeImmutable;
|
|
use MonetaPhpShop\order\Order;
|
|
use MonetaPhpShop\PhoneNumber;
|
|
use MonetaPhpShop\protocol\AssistantProtocol;
|
|
use MonetaPhpShop\protocol\TransactionId;
|
|
use MonetaPhpShop\Settings;
|
|
|
|
/**
|
|
* Ïëàò¸æíàÿ ôîðìà MONETA.Assistant.
|
|
*
|
|
* Êàæäûé ïîêàç ôîðìû — íîâûé `MNT_TRANSACTION_ID` (`<uid>_<ñóììà>_<YmdHis>UTC`): ïîâòîðíóþ îïëàòó
|
|
* óæå îïëà÷åííîãî çàêàçà îñòàíàâëèâàåò Check URL.
|
|
*/
|
|
final class PaymentForm
|
|
{
|
|
/** Ïðåôèêñ ID ïîêóïàòåëÿ PHPShop â `MNT_SUBSCRIBER_ID`. */
|
|
public const SUBSCRIBER_USER_PREFIX = 'USER_';
|
|
|
|
/** Òåêñò êíîïêè ïîñëå íàæàòèÿ; áåç êàâû÷åê è ðàçìåòêè — ïîäñòàâëÿåòñÿ â onsubmit. */
|
|
private const REDIRECTING = 'Ïåðåõîäèì ê îïëàòå...';
|
|
|
|
/** @var string */
|
|
private $action;
|
|
|
|
/** @var array<string, string> */
|
|
private $fields;
|
|
|
|
/**
|
|
* @param array<string, string> $fields
|
|
*/
|
|
private function __construct(string $action, array $fields)
|
|
{
|
|
$this->action = $action;
|
|
$this->fields = $fields;
|
|
}
|
|
|
|
/**
|
|
* @param string $currency `MNT_CURRENCY_CODE` ({@see AssistantProtocol::normalizeCurrency()})
|
|
* @param ReturnUrls $returnUrls àäðåñà âîçâðàòà ïîêóïàòåëÿ
|
|
* @param string $description `MNT_DESCRIPTION` â êîäèðîâêå âèòðèíû
|
|
* @param string $cms `MNT_CMS`
|
|
* @param string $locale `moneta.locale` — ÿçûê ïëàò¸æíîé ôîðìû ({@see AssistantProtocol::normalizeLocale()})
|
|
*/
|
|
public static function create(
|
|
Settings $settings,
|
|
Order $order,
|
|
string $currency,
|
|
DateTimeImmutable $issuedAt,
|
|
ReturnUrls $returnUrls,
|
|
string $description,
|
|
string $cms,
|
|
string $locale
|
|
): self {
|
|
$amount = $order->getAmount();
|
|
$transactionId = TransactionId::build($order->getUid(), $amount, $issuedAt);
|
|
$subscriberId = self::subscriberId($order);
|
|
$testMode = $settings->isTestMode();
|
|
|
|
$fields = [
|
|
'MNT_ID' => $settings->getAccountId(),
|
|
'MNT_TRANSACTION_ID' => $transactionId,
|
|
'MNT_CURRENCY_CODE' => $currency,
|
|
'MNT_AMOUNT' => $amount->toDecimal(),
|
|
'MNT_TEST_MODE' => AssistantProtocol::testModeFlag($testMode),
|
|
'MNT_SUBSCRIBER_ID' => $subscriberId,
|
|
'MNT_SIGNATURE' => $settings->signature()->forPaymentForm(
|
|
$settings->getAccountId(),
|
|
$transactionId,
|
|
$amount,
|
|
$currency,
|
|
$subscriberId,
|
|
$testMode,
|
|
),
|
|
'MNT_DESCRIPTION' => $description,
|
|
'MNT_SUCCESS_URL' => $returnUrls->getSuccess(),
|
|
'MNT_FAIL_URL' => $returnUrls->getFail(),
|
|
'MNT_INPROGRESS_URL' => $returnUrls->getInProgress(),
|
|
'MNT_RETURN_URL' => $returnUrls->getReturn(),
|
|
'MNT_CMS' => $cms,
|
|
'moneta.locale' => $locale,
|
|
];
|
|
|
|
return new self($settings->getPaymentServer()->url(), $fields);
|
|
}
|
|
|
|
/**
|
|
* `MNT_SUBSCRIBER_ID`: email -> òåëåôîí (`+öèôðû`) -> ID ïîêóïàòåëÿ PHPShop; ïóñòî — äàííûõ íåò
|
|
*/
|
|
public static function subscriberId(Order $order): string
|
|
{
|
|
if ($order->getEmail() !== '') {
|
|
return $order->getEmail();
|
|
}
|
|
|
|
$phone = PhoneNumber::normalize($order->getPhone());
|
|
if ($phone !== null) {
|
|
return $phone;
|
|
}
|
|
|
|
return ($order->getUserId() > 0) ? self::SUBSCRIBER_USER_PREFIX . $order->getUserId() : '';
|
|
}
|
|
|
|
public function getAction(): string
|
|
{
|
|
return $this->action;
|
|
}
|
|
|
|
/**
|
|
* @return array<string, string>
|
|
*/
|
|
public function getFields(): array
|
|
{
|
|
return $this->fields;
|
|
}
|
|
|
|
/**
|
|
* HTML ôîðìû ñ îäíîé êíîïêîé; ñòðîêè â êîäèðîâêå âèòðèíû (cp1251).
|
|
*
|
|
* `accept-charset="UTF-8"`: áðàóçåð ïåðåêîäèðóåò çíà÷åíèÿ èç cp1251 ñòðàíèöû â UTF-8,
|
|
* êîòîðóþ æä¸ò Ìîíåòà. Êíîïêà ïîñëå íàæàòèÿ áëîêèðóåòñÿ (îò äâîéíîé îòïðàâêè), ïîêà îòêðûâàåòñÿ ñòðàíèöà Ìîíåòû.
|
|
*/
|
|
/**
|
|
* @param string $buttonTitle òåêñò êíîïêè, ýêðàíèðóåòñÿ
|
|
* @param string $buttonSuffixHtml ãîòîâûé HTML ïîñëå òåêñòà (çíàê âàëþòû âèòðèíû), íå ýêðàíèðóåòñÿ
|
|
*/
|
|
public function toHtml(string $buttonTitle, string $buttonSuffixHtml = ''): string
|
|
{
|
|
$html = '<form class="moneta-payment-form" method="post" action="' . self::escape($this->action) . '"'
|
|
. ' accept-charset="UTF-8"'
|
|
. ' onsubmit="var b=this.querySelector(\'button\');if(b){b.disabled=true;'
|
|
. 'b.textContent=\'' . self::REDIRECTING . '\';}">';
|
|
foreach ($this->fields as $name => $value) {
|
|
$html .= '<input type="hidden" name="' . self::escape($name) . '" value="' . self::escape($value) . '">';
|
|
}
|
|
$html .= '<button type="submit" class="btn btn-primary moneta-payment-button">'
|
|
. self::escape($buttonTitle) . $buttonSuffixHtml . '</button>';
|
|
|
|
return $html . '</form>';
|
|
}
|
|
|
|
private static function escape(string $value): string
|
|
{
|
|
return htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, 'Windows-1251');
|
|
}
|
|
}
|