137 lines
5.1 KiB
PHP
137 lines
5.1 KiB
PHP
<?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);
|
|
}
|
|
}
|