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
+136
View File
@@ -0,0 +1,136 @@
<?php
declare(strict_types=1);
namespace MonetaPhpShop\host;
use MonetaPhpShop\callback\OrderGateway;
use MonetaPhpShop\Money;
use MonetaPhpShop\order\Order;
use MonetaPhpShop\protocol\TransactionId;
use MonetaPhpShop\Settings;
use PHPShopOrderFunction;
use PHPShopOrm;
use RuntimeException;
/**
* Çàêàçû PHPShop (`phpshop_orders`).
*
* `PHPShopOrm` ñîáèðàåò SQL êîíêàòåíàöèåé, ïîýòîìó â óñëîâèÿ ïîïàäàåò òîëüêî òî, ÷òî óæå
* ïðîâåðåíî: öåëîå ÷èñëî èëè íîìåð çàêàçà ïî øàáëîíó {@see TransactionId::ORDER_UID}
* (ëàòèíèöà, öèôðû, äåôèñ — áåç êàâû÷åê).
*/
final class OrderRepository implements OrderGateway
{
/** Èìÿ ñïîñîáà îïëàòû â æóðíàëå îïëàò ÿäðà (`phpshop_payment.name`). */
private const PAYMENT_LOG_NAME = 'Moneta';
/** Íàçâàíèå ñòàòóñà 101, åñëè åãî åù¸ íåò, — êàê ó ÿäðà (`PHPShopPaymentResult::set_order_status_101()`). */
private const STATUS_PAID_BY_GATEWAY_NAME = 'Îïëà÷åíî ïëàòåæíûìè ñèñòåìàìè';
public function findById(int $id): ?Order
{
if ($id <= 0) {
return null;
}
return $this->findOne(['id' => '=' . $id]);
}
public function findByUid(string $uid): ?Order
{
if (preg_match('/\A' . TransactionId::ORDER_UID . '\z/', $uid) !== 1) {
return null;
}
return $this->findOne(['uid' => "='" . $uid . "'"]);
}
/**
* Êàê øòàòíûå ìîäóëè ÿäðà: ñòðîêà â æóðíàëå îïëàò, `changeStatus()` (ïèñüìî ïîêóïàòåëþ,
* ñêëàä, ìåññåíäæåðû — ïî íàñòðîéêàì ñòàòóñà) è ôëàã `paid`. `ofd()` ÿäðà íå âûçûâàåòñÿ:
* ÷åê ïðîáèâàåò êàññà MONETA.
*/
public function markPaid(Order $order, int $paidStatus, Money $amount): void
{
$database = Database::fromHost();
if ($paidStatus === Settings::STATUS_PAID_BY_GATEWAY) {
$this->ensurePaidByGatewayStatus($database);
}
$this->logPayment($database, $order, $amount);
$orderFunction = new PHPShopOrderFunction($order->getId());
$orderFunction->changeStatus($paidStatus, $order->getStatusId());
$orderFunction->changePaymentStatus(1);
}
/**
* `phpshop_payment`: êëþ÷ — íîìåð çàêàçà áåç äåôèñà ÷èñëîì (`4-36` -> 436), ïî íåìó ÿäðî
* ïîêàçûâàåò äàòó îïëàòû (`PHPShopOrderFunction::checkPay()`). Íîìåð íå øòàòíîãî âèäà
* (ïåðåîïðåäåë¸í õóêîì `setNum`) â ýòó òàáëèöó íå çàïèñûâàåòñÿ — çàïèñü ïðîïóñêàåòñÿ.
*/
private function logPayment(Database $database, Order $order, Money $amount): void
{
if (preg_match('/\A([0-9]+)-([0-9]+)\z/', $order->getUid(), $matches) !== 1) {
return;
}
$database->execute(
'INSERT IGNORE INTO `' . self::table('payment') . '` (uid, name, sum, datas) VALUES (?, ?, ?, ?)',
[(int) ($matches[1] . $matches[2]), self::PAYMENT_LOG_NAME, $amount->toDecimal(), time()],
);
}
private function ensurePaidByGatewayStatus(Database $database): void
{
$database->execute(
'INSERT IGNORE INTO `' . self::table('order_status') . "` (id, name, color, external_code, bot_message)"
. " VALUES (?, ?, '#ccff00', '', '')",
[Settings::STATUS_PAID_BY_GATEWAY, HostCharset::toDatabase(self::STATUS_PAID_BY_GATEWAY_NAME)],
);
}
private static function table(string $key): string
{
$table = $GLOBALS['SysValue']['base'][$key] ?? null;
// ßâíûé êëàññ, à íå \w: áåç /u \w ñëåäóåò ëîêàëè, à PHPShop ñòàâèò ñâîþ (setlocale â
// class/base.class.php) — â cp1251 \w ïðîïóñòèë áû êèðèëëèöó â èìÿ òàáëèöû, êîòîðîå èä¸ò â SQL.
if (!is_string($table) || preg_match('/\A[0-9A-Za-z_]+\z/', $table) !== 1) {
throw new RuntimeException("Íåò òàáëèöû ÿäðà {$key} â êîíôèãóðàöèè.");
}
return $table;
}
/**
* @param array<string, string> $where
*/
private function findOne(array $where): ?Order
{
$orm = new PHPShopOrm($GLOBALS['SysValue']['base']['orders']);
$orm->debug = false;
$row = $orm->select(['*'], $where, false, ['limit' => 1]);
if (!is_array($row) || empty($row['id'])) {
return null;
}
$details = @unserialize((string) ($row['orders'] ?? ''), ['allowed_classes' => false]);
if (!is_array($details)) {
$details = [];
}
foreach (['fio', 'tel'] as $field) {
if (isset($row[$field]) && is_string($row[$field])) {
$row[$field] = HostCharset::fromDatabase($row[$field]);
}
}
// Íàçâàíèÿ òîâàðîâ â êîðçèíå — â êîäèðîâêå ÁÄ, êàê è îñòàëüíûå ñòðîêè çàêàçà.
if (isset($details['Cart']['cart']) && is_array($details['Cart']['cart'])) {
foreach ($details['Cart']['cart'] as $key => $product) {
if (is_array($product) && isset($product['name']) && is_string($product['name'])) {
$details['Cart']['cart'][$key]['name'] = HostCharset::fromDatabase($product['name']);
}
}
}
return Order::fromRow($row, $details);
}
}