Files
webman-buildadmin/app/common/service/DepositOrderExpireService.php
zhenhui 1b8d947f97 0.使用模拟数据进行充值和提现
1.优化提现接口/api/finance/withdrawCreate
2.优化充值接口/api/finance/depositCreate
2026-05-20 15:57:19 +08:00

127 lines
4.2 KiB
PHP
Raw Permalink 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 笔待支付订单
* - 待支付订单创建后超过有效期未支付,自动标记为失败
* - 有效秒数由 .env DEPOSIT_PENDING_EXPIRE_SECONDS 配置(默认 60全渠道统一
*/
final class DepositOrderExpireService
{
public const MAX_PENDING_DEPOSIT = 3;
/**
* 待支付充值单有效秒数(与 config app.deposit_pending_expire_seconds / .env 一致)
*/
public static function pendingExpireSeconds(): int
{
$cfg = config('app.deposit_pending_expire_seconds', 60);
if (is_numeric($cfg)) {
$v = intval($cfg);
if ($v > 0) {
return $v;
}
}
return 60;
}
/**
* @param array<string, mixed> $order
*/
public static function expireSecondsForOrder(array $order): int
{
return self::pendingExpireSeconds();
}
/**
* @param int|null $userId 仅处理某用户null 表示不过滤用户
* @param string|null $orderNo 仅处理某订单null 表示不过滤订单
*
* @return int 本次转失败的订单数
*/
public static function expirePendingOrders(?int $userId = null, ?string $orderNo = null): int
{
$query = Db::name('deposit_order')->where('status', 0);
if ($userId !== null && $userId > 0) {
$query->where('user_id', $userId);
}
if ($orderNo !== null && $orderNo !== '') {
$query->where('order_no', $orderNo);
}
$rows = $query->field(['id', 'remark', 'pay_channel', 'create_time'])->select()->toArray();
if ($rows === []) {
return 0;
}
$now = time();
$expireSec = self::pendingExpireSeconds();
$affectedCount = 0;
foreach ($rows as $row) {
if (!is_array($row)) {
continue;
}
$id = isset($row['id']) && is_numeric($row['id']) ? intval($row['id']) : 0;
if ($id <= 0) {
continue;
}
$createTime = isset($row['create_time']) && is_numeric($row['create_time']) ? intval($row['create_time']) : 0;
if ($createTime > 0 && $createTime + $expireSec > $now) {
continue;
}
$oldRemark = isset($row['remark']) && is_string($row['remark']) ? trim($row['remark']) : '';
$reason = '[timeout] unpaid over ' . $expireSec . '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();
}
/**
* 订单是否仍在待支付有效期内
*
* @param array<string, mixed> $order
*/
public static function isPendingPaymentValid(array $order): bool
{
$status = isset($order['status']) && is_numeric($order['status']) ? intval($order['status']) : -1;
if ($status !== 0) {
return false;
}
$createTime = isset($order['create_time']) && is_numeric($order['create_time']) ? intval($order['create_time']) : 0;
if ($createTime <= 0) {
return false;
}
return $createTime + self::pendingExpireSeconds() > time();
}
}