134 lines
4.8 KiB
PHP
134 lines
4.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace MonetaPhpShop\host;
|
|
|
|
use MonetaPhpShop\callback\OperationJournal;
|
|
use MonetaPhpShop\ModuleInfo;
|
|
use MonetaPhpShop\order\Order;
|
|
use MonetaPhpShop\protocol\CallbackNotification;
|
|
use MonetaPhpShop\protocol\ResultCode;
|
|
use MonetaPhpShop\protocol\TransactionId;
|
|
use RuntimeException;
|
|
|
|
/**
|
|
* Æóðíàë îïåðàöèé — òàáëèöà `[base] moneta_operations` èç `inc/config.ini` ìîäóëÿ.
|
|
*
|
|
* Ñòðîêà íà êàæäîå ïîäïèñàííîå óâåäîìëåíèå; ó ñòðîêè çà÷ò¸ííîé îïëàòû çàïîëíåí
|
|
* `paid_order_id` ñ UNIQUE-êëþ÷îì — âòîðîé çà÷¸ò òîãî æå çàêàçà íåâîçìîæåí äàæå áåç áëîêèðîâêè.
|
|
* Ïîäïèñü è êîä ïðîâåðêè öåëîñòíîñòè íå õðàíÿòñÿ.
|
|
*/
|
|
final class OperationRepository implements OperationJournal
|
|
{
|
|
private const COMMAND_PAY = 'PAY';
|
|
|
|
/** @var Database */
|
|
private $database;
|
|
|
|
public function __construct(Database $database)
|
|
{
|
|
$this->database = $database;
|
|
}
|
|
|
|
public function findPaidOperation(int $orderId): ?string
|
|
{
|
|
$value = $this->database->fetchValue(
|
|
'SELECT operation_id FROM `' . self::table() . '` WHERE paid_order_id = ? LIMIT 1',
|
|
[$orderId],
|
|
);
|
|
|
|
return $value === null ? null : (string) $value;
|
|
}
|
|
|
|
public function recordPaid(CallbackNotification $notification, Order $order, string $event): bool
|
|
{
|
|
try {
|
|
$this->insert($notification, $order, $event, ResultCode::paid(), $order->getId());
|
|
} catch (RuntimeException $exception) {
|
|
if ($exception->getCode() === Database::ER_DUP_ENTRY) {
|
|
return false;
|
|
}
|
|
|
|
throw $exception;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public function note(
|
|
CallbackNotification $notification,
|
|
?Order $order,
|
|
string $event,
|
|
?ResultCode $resultCode
|
|
): void {
|
|
$this->insert($notification, $order, $event, $resultCode, null);
|
|
}
|
|
|
|
/**
|
|
* Ïîñëåäíèå çàïèñè æóðíàëà äëÿ àäìèíêè, íîâûå ñâåðõó.
|
|
*
|
|
* @param string|null $orderUid òîëüêî çàïèñè ýòîãî çàêàçà ({@see TransactionId::orderUidFromInput()}):
|
|
* ñ ýòèì `order_uid` èëè — åñëè çàêàç íå ðàñïîçíàí — ñ `MNT_TRANSACTION_ID` âèäà `<íîìåð>_…`
|
|
*
|
|
* @return array<int, array<string, mixed>>
|
|
*/
|
|
public function latest(int $limit, ?string $orderUid = null): array
|
|
{
|
|
$where = '';
|
|
$params = [];
|
|
if ($orderUid !== null) {
|
|
// Â íîìåðå çàêàçà íåò `_` è `%` (TransactionId::ORDER_UID) — ýêðàíèðîâàòü â LIKE
|
|
// íóæíî òîëüêî ñàì ðàçäåëèòåëü `_`.
|
|
$where = ' WHERE order_uid = ? OR transaction_id LIKE ?';
|
|
$params = [$orderUid, $orderUid . '\\' . TransactionId::SEPARATOR . '%'];
|
|
}
|
|
$params[] = $limit;
|
|
|
|
return $this->database->fetchAll(
|
|
'SELECT id, created_at, command, transaction_id, operation_id, order_id, order_uid, amount,'
|
|
. ' test_mode, result_code, event FROM `' . self::table() . '`' . $where . ' ORDER BY id DESC LIMIT ?',
|
|
$params,
|
|
);
|
|
}
|
|
|
|
public static function table(): string
|
|
{
|
|
$table = $GLOBALS['SysValue']['base'][ModuleInfo::PATH]['moneta_operations'] ?? 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('Ìîäóëü íå óñòàíîâëåí: íåò òàáëèöû îïåðàöèé â êîíôèãóðàöèè.');
|
|
}
|
|
|
|
return $table;
|
|
}
|
|
|
|
private function insert(
|
|
CallbackNotification $notification,
|
|
?Order $order,
|
|
string $event,
|
|
?ResultCode $resultCode,
|
|
?int $paidOrderId
|
|
): void {
|
|
$amount = $notification->getAmount();
|
|
$this->database->execute(
|
|
'INSERT INTO `' . self::table() . '` (created_at, command, transaction_id, operation_id, order_id,'
|
|
. ' order_uid, amount, test_mode, result_code, event, paid_order_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
|
|
[
|
|
time(),
|
|
$notification->isCheck() ? $notification->getCommand() : self::COMMAND_PAY,
|
|
$notification->getTransactionId(),
|
|
$notification->getOperationId(),
|
|
($order !== null) ? $order->getId() : 0,
|
|
($order !== null) ? $order->getUid() : '',
|
|
($amount !== null) ? $amount->toDecimal() : '',
|
|
$notification->getRawTestMode(),
|
|
($resultCode !== null) ? $resultCode->getValue() : null,
|
|
$event,
|
|
$paidOrderId,
|
|
],
|
|
);
|
|
}
|
|
}
|