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
+194
View File
@@ -0,0 +1,194 @@
<?php
declare(strict_types=1);
namespace MonetaPhpShop\order;
use InvalidArgumentException;
use MonetaPhpShop\Money;
/**
* Ñíèìîê çàêàçà PHPShop (`phpshop_orders`) — òî, ÷òî ìîäóëþ íóæíî äëÿ ôîðìû è êîëáýêîâ.
* Ñòðîêè â êîäèðîâêå âèòðèíû (cp1251).
*/
final class Order
{
/**
* Àíîíèìíîìó ïîêóïàòåëþ áåç email ÿäðî ïîäñòàâëÿåò `guest@<äîìåí>`
* (`PHPShopDone::send_to_order()`) — ýòî íå àäðåñ ïîêóïàòåëÿ.
*/
private const GUEST_EMAIL_PREFIX = 'guest@';
/** @var int */
private $id;
/** @var string */
private $uid;
/** @var Money */
private $amount;
/** @var int */
private $statusId;
/** @var bool */
private $paid;
/** @var int */
private $paymentMethodId;
/** @var string */
private $email;
/** @var string */
private $phone;
/** @var string */
private $customerName;
/** @var int */
private $userId;
/** @var array<string, mixed> */
private $cart;
/** @var float */
private $discountPercent;
/** @var int */
private $deliveryMethodId;
private function __construct() {}
/**
* @param array<string, mixed> $row ñòðîêà `phpshop_orders`
* @param array<string, mixed> $details ðàñïàêîâàííîå ïîëå `orders`: `['Cart' => ..., 'Person' => ...]`
*/
public static function fromRow(array $row, array $details): self
{
$id = (int) ($row['id'] ?? 0);
$uid = (string) ($row['uid'] ?? '');
if (($id <= 0) || ($uid === '')) {
throw new InvalidArgumentException('Ñòðîêà çàêàçà áåç id èëè uid.');
}
$person = isset($details['Person']) && is_array($details['Person']) ? $details['Person'] : [];
$cart = isset($details['Cart']) && is_array($details['Cart']) ? $details['Cart'] : [];
$order = new self();
$order->id = $id;
$order->uid = $uid;
$order->amount = Money::fromFloat((float) ($row['sum'] ?? 0));
$order->statusId = (int) ($row['statusi'] ?? 0);
$order->paid = (int) ($row['paid'] ?? 0) === 1;
$order->paymentMethodId = (int) ($person['order_metod'] ?? 0);
$order->email = self::email((string) ($person['mail'] ?? ''));
$order->phone = trim((string) ($row['tel'] ?? ''));
$order->customerName = trim((string) ($row['fio'] ?? ''));
$order->userId = (int) ($row['user'] ?? 0);
$order->cart = $cart;
$order->discountPercent = (float) ($person['discount'] ?? 0);
$order->deliveryMethodId = (int) ($person['dostavka_metod'] ?? 0);
return $order;
}
public function getId(): int
{
return $this->id;
}
/**
* Íîìåð çàêàçà, êîòîðûé âèäèò ïîêóïàòåëü (`4-36`).
*/
public function getUid(): string
{
return $this->uid;
}
/**
* Èòîã çàêàçà (`phpshop_orders.sum`): òîâàðû ñî ñêèäêàìè, áîíóñû è äîñòàâêà óæå ó÷òåíû ÿäðîì.
*/
public function getAmount(): Money
{
return $this->amount;
}
public function getStatusId(): int
{
return $this->statusId;
}
public function isPaidFlag(): bool
{
return $this->paid;
}
public function getPaymentMethodId(): int
{
return $this->paymentMethodId;
}
/**
* Email ïîêóïàòåëÿ èëè ïóñòàÿ ñòðîêà (ãîñòåâîé `guest@...` íå ñ÷èòàåòñÿ).
*/
public function getEmail(): string
{
return $this->email;
}
public function getPhone(): string
{
return $this->phone;
}
public function getCustomerName(): string
{
return $this->customerName;
}
/**
* ID ïîêóïàòåëÿ PHPShop (`phpshop_shopusers.id`), 0 — íåò.
*/
public function getUserId(): int
{
return $this->userId;
}
/**
* Êîðçèíà çàêàçà êàê å¸ õðàíèò ÿäðî (`Cart`: `cart`, `dostavka`, `sum`...) — äëÿ ÷åêà.
*
* @return array<string, mixed>
*/
public function getCart(): array
{
return $this->cart;
}
/**
* Ñêèäêà ïîêóïàòåëÿ â ïðîöåíòàõ (`Person.discount`): ÿäðî ïðèìåíÿåò å¸ êî âñåì òîâàðàì,
* êðîìå òîâàðîâ ñ ïðîìî-öåíîé.
*/
public function getDiscountPercent(): float
{
return $this->discountPercent;
}
/**
* Ñïîñîá äîñòàâêè (`phpshop_delivery.id`), 0 — íå âûáðàí.
*/
public function getDeliveryMethodId(): int
{
return $this->deliveryMethodId;
}
private static function email(string $raw): string
{
$email = trim($raw);
if (($email === '') || stripos($email, self::GUEST_EMAIL_PREFIX) === 0) {
return '';
}
return (filter_var($email, FILTER_VALIDATE_EMAIL) !== false) ? $email : '';
}
}
+42
View File
@@ -0,0 +1,42 @@
<?php
declare(strict_types=1);
namespace MonetaPhpShop\order;
/**
* Ñïèñîê ñòàòóñîâ çàêàçà äëÿ âûïàäàþùèõ ñïèñêîâ íàñòðîåê («Îïëàòà ïðè ñòàòóñå»,
* «Ñòàòóñ ïîñëå îïëàòû») â ôîðìàòå `PHPShopGUI::setSelect()`: `[ïîäïèñü, çíà÷åíèå, òåêóùåå]`.
* Ñòàòóñû ìàãàçèíà ÷èòàåò àäìèíêà ìîäóëÿ èç `PHPShopOrderStatusArray`; çäåñü — òîëüêî ñáîðêà.
*/
final class OrderStatusOptions
{
private function __construct() {}
/**
* Ïåðâûì èä¸ò çàäàííûé ïóíêò, çà íèì ñòàòóñû ìàãàçèíà. Ñòàòóñ ñ òåì æå çíà÷åíèåì, ÷òî
* ó ïåðâîãî ïóíêòà, ïðîïóñêàåòñÿ: «Îïëà÷åíî ïëàòåæíûìè ñèñòåìàìè» (101) ÿäðî ñîçäà¸ò
* êàê îáû÷íûé ñòàòóñ, è áåç ýòîãî îí ïîïàë áû â ñïèñîê äâàæäû.
*
* @param array<mixed> $statuses ñòàòóñû ìàãàçèíà: ñòðîêè ñ êëþ÷àìè `id` è `name`
* @param int $current çíà÷åíèå èç íàñòðîåê — ïóíêò ñ íèì áóäåò âûáðàí
*
* @return array<int, array{0: string, 1: int, 2: int}>
*/
public static function build(array $statuses, int $current, string $firstLabel, int $firstValue): array
{
$options = [[$firstLabel, $firstValue, $current]];
foreach ($statuses as $status) {
if (!is_array($status) || !isset($status['id'], $status['name'])) {
continue;
}
$id = (int) $status['id'];
if ($id !== $firstValue) {
$options[] = [(string) $status['name'], $id, $current];
}
}
return $options;
}
}
+76
View File
@@ -0,0 +1,76 @@
<?php
declare(strict_types=1);
namespace MonetaPhpShop\order;
use MonetaPhpShop\ModuleInfo;
use MonetaPhpShop\protocol\AssistantProtocol;
use MonetaPhpShop\Settings;
/**
* Ìîæíî ëè ñåé÷àñ îïëàòèòü çàêàç ÷åðåç Ìîíåòó. Îäíî ïðàâèëî äëÿ êíîïêè îïëàòû
* è äëÿ Check URL, ÷òîáû ôîðìà íå âûäàâàëàñü òàì, ãäå ïðîâåðî÷íûé çàïðîñ îòêàæåò.
*
* Çíà÷åíèÿ êîíñòàíò — êîäû ïðè÷èí äëÿ æóðíàëà ìîäóëÿ; íå ïåðåèìåíîâûâàòü.
*/
final class PaymentEligibility
{
public const PAYABLE = 'payable';
public const NOT_CONFIGURED = 'not_configured';
public const OTHER_PAYMENT_METHOD = 'other_payment_method';
public const ALREADY_PAID = 'already_paid';
public const CANCELLED = 'cancelled';
public const AWAITING_STATUS = 'awaiting_status';
public const UNSUPPORTED_CURRENCY = 'unsupported_currency';
public const ZERO_AMOUNT = 'zero_amount';
/** Ñòàòóñ PHPShop «Àííóëèðîâàí» (`PHPShopOrderFunction::changeStatus()` âîçâðàùàåò òîâàð íà ñêëàä). */
public const STATUS_CANCELLED = 1;
private function __construct() {}
/**
* @param string $shopCurrency ISO-êîä âàëþòû çàêàçà èç PHPShop (`getDefaultValutaIso(true)`)
*/
public static function check(Settings $settings, Order $order, string $shopCurrency): string
{
if (!$settings->isConfigured()) {
return self::NOT_CONFIGURED;
}
if ($order->getPaymentMethodId() !== ModuleInfo::PAYMENT_METHOD_ID) {
return self::OTHER_PAYMENT_METHOD;
}
if (self::isPaid($settings, $order)) {
return self::ALREADY_PAID;
}
if ($order->getStatusId() === self::STATUS_CANCELLED) {
return self::CANCELLED;
}
if (!$settings->isPayableRightAfterCheckout() && $order->getStatusId() !== $settings->getPayableStatus()) {
return self::AWAITING_STATUS;
}
if (AssistantProtocol::normalizeCurrency($shopCurrency) === null) {
return self::UNSUPPORTED_CURRENCY;
}
if (!$order->getAmount()->isPositive()) {
return self::ZERO_AMOUNT;
}
return self::PAYABLE;
}
/**
* Îïëà÷åí: ôëàã `paid` ÿäðà èëè ñòàòóñ «ïîñëå îïëàòû» èç íàñòðîåê ìîäóëÿ.
*/
public static function isPaid(Settings $settings, Order $order): bool
{
return $order->isPaidFlag() || ($order->getStatusId() === $settings->getPaidStatus());
}
}