Files
webman-buildadmin/app/common/service/DepositOrderExpireService.php
2026-04-23 10:15:01 +08:00

82 lines
2.5 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
namespace app\common\service;
use support\think\Db;
/**
* 充值待支付订单超时处理:
* - 同用户最多允许 3 笔待支付订单
* - 待支付订单创建后 60 秒未支付,自动标记为失败并写失败原因
*/
final class DepositOrderExpireService
{
public const MAX_PENDING_DEPOSIT = 3;
public const EXPIRE_SECONDS = 60;
/**
* 超时失效处理。
*
* @param int|null $userId 仅处理某用户null 表示不过滤用户
* @param string|null $orderNo 仅处理某订单null 表示不过滤订单
*
* @return int 本次转失败的订单数
*/
public static function expirePendingOrders(?int $userId = null, ?string $orderNo = null): int
{
$expireBefore = time() - self::EXPIRE_SECONDS;
$query = Db::name('deposit_order')
->where('status', 0)
->where('create_time', '<=', $expireBefore);
if ($userId !== null && $userId > 0) {
$query->where('user_id', $userId);
}
if ($orderNo !== null && $orderNo !== '') {
$query->where('order_no', $orderNo);
}
$rows = $query->field(['id', 'remark'])->select()->toArray();
if ($rows === []) {
return 0;
}
$now = time();
$affectedCount = 0;
foreach ($rows as $row) {
$id = isset($row['id']) && is_numeric($row['id']) ? intval($row['id']) : 0;
if ($id <= 0) {
continue;
}
$oldRemark = isset($row['remark']) && is_string($row['remark']) ? trim($row['remark']) : '';
$reason = '[timeout] unpaid over ' . self::EXPIRE_SECONDS . 's';
$remark = $oldRemark === '' ? $reason : mb_substr($oldRemark . ' | ' . $reason, 0, 255);
$affected = Db::name('deposit_order')
->where('id', $id)
->where('status', 0)
->update([
'status' => 2,
'remark' => $remark,
'update_time' => $now,
]);
if (is_numeric($affected) && intval($affected) > 0) {
$affectedCount++;
}
}
return $affectedCount;
}
public static function pendingCountByUserId(int $userId): int
{
if ($userId <= 0) {
return 0;
}
return Db::name('deposit_order')
->where('user_id', $userId)
->where('status', 0)
->count();
}
}