refactor: 移除 qr_issued_at 字段
QR payload 改为实时生成,不存储发放时间。 前端 localStorage 自行管理缓存。feat/phase4-ticket-wallet
parent
6903522b5a
commit
ac676d00be
|
|
@ -13,34 +13,6 @@
|
|||
return array (
|
||||
'listen' =>
|
||||
array (
|
||||
'plugins_service_admin_menu_data' =>
|
||||
array (
|
||||
0 => 'app\\plugins\\vr_ticket\\Hook',
|
||||
),
|
||||
'plugins_service_order_pay_success_handle_end' =>
|
||||
array (
|
||||
0 => 'app\\plugins\\vr_ticket\\Hook',
|
||||
),
|
||||
'plugins_service_order_delete_success' =>
|
||||
array (
|
||||
0 => 'app\\plugins\\vr_ticket\\Hook',
|
||||
),
|
||||
'plugins_view_admin_goods_save' =>
|
||||
array (
|
||||
0 => 'app\\plugins\\vr_ticket\\hook\\AdminGoodsSave',
|
||||
),
|
||||
'plugins_service_goods_save_handle' =>
|
||||
array (
|
||||
0 => 'app\\plugins\\vr_ticket\\hook\\AdminGoodsSaveHandle',
|
||||
),
|
||||
'plugins_service_goods_save_thing_end' =>
|
||||
array (
|
||||
0 => 'app\\plugins\\vr_ticket\\hook\\AdminGoodsSaveHandle',
|
||||
),
|
||||
'plugins_css_data' =>
|
||||
array (
|
||||
0 => 'app\\plugins\\vr_ticket\\hook\\ViewGoodsCss',
|
||||
),
|
||||
),
|
||||
);
|
||||
?>
|
||||
|
|
@ -30,7 +30,6 @@ CREATE TABLE IF NOT EXISTS `{{prefix}}vr_tickets` (
|
|||
`verify_time` INT UNSIGNED DEFAULT 0 COMMENT '核销时间',
|
||||
`verifier_id` BIGINT UNSIGNED DEFAULT 0 COMMENT '核销员ID',
|
||||
`issued_at` INT UNSIGNED DEFAULT 0 COMMENT '票发放时间',
|
||||
`qr_issued_at` INT UNSIGNED DEFAULT 0 COMMENT 'QR发放时间戳',
|
||||
`created_at` INT UNSIGNED DEFAULT 0 COMMENT '创建时间',
|
||||
`updated_at` INT UNSIGNED DEFAULT 0 COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`),
|
||||
|
|
|
|||
|
|
@ -19,12 +19,6 @@ class WalletService extends BaseService
|
|||
*/
|
||||
const QR_TTL = 1800; // 30分钟
|
||||
|
||||
/**
|
||||
* QR 刷新阈值(秒)
|
||||
* 剩余有效期 > 此值时返回缓存
|
||||
*/
|
||||
const QR_REFRESH_THRESHOLD = 900; // 15分钟
|
||||
|
||||
/**
|
||||
* 获取用户所有票
|
||||
*
|
||||
|
|
@ -79,8 +73,6 @@ class WalletService extends BaseService
|
|||
'verify_status' => $ticket['verify_status'],
|
||||
'issued_at' => $ticket['issued_at'],
|
||||
'short_code' => $shortCode,
|
||||
// 是否需要刷新 QR
|
||||
'qr_need_refresh' => self::qrNeedsRefresh($ticket['qr_issued_at'] ?? 0),
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -141,10 +133,7 @@ class WalletService extends BaseService
|
|||
/**
|
||||
* 生成 QR payload
|
||||
*
|
||||
* 缓存策略:
|
||||
* - QR 有效期 30 分钟
|
||||
* - 剩余有效期 > 15 分钟:返回缓存
|
||||
* - 剩余有效期 ≤ 15 分钟:刷新
|
||||
* QR 有效期 30 分钟,动态生成,不存储
|
||||
*
|
||||
* @param array $ticket 票数据
|
||||
* @return array ['payload' => string, 'expires_at' => int, 'expires_in' => int]
|
||||
|
|
@ -152,51 +141,27 @@ class WalletService extends BaseService
|
|||
public static function getQrPayload(array $ticket): array
|
||||
{
|
||||
$now = time();
|
||||
$issuedAt = $ticket['qr_issued_at'] ?? 0;
|
||||
$expiresAt = $issuedAt + self::QR_TTL;
|
||||
$expiresAt = $now + self::QR_TTL;
|
||||
|
||||
// 检查是否需要刷新
|
||||
$needsRefresh = ($issuedAt == 0) || (($expiresAt - $now) <= self::QR_REFRESH_THRESHOLD);
|
||||
$payload = [
|
||||
'id' => $ticket['id'],
|
||||
'g' => $ticket['goods_id'],
|
||||
'iat' => $now,
|
||||
'exp' => $expiresAt,
|
||||
];
|
||||
|
||||
if ($needsRefresh) {
|
||||
// 生成新 QR
|
||||
$issuedAt = $now;
|
||||
$expiresAt = $now + self::QR_TTL;
|
||||
|
||||
$payload = [
|
||||
'id' => $ticket['id'],
|
||||
'g' => $ticket['goods_id'],
|
||||
'iat' => $issuedAt,
|
||||
'exp' => $expiresAt,
|
||||
];
|
||||
|
||||
$encoded = self::signQrPayload($payload);
|
||||
|
||||
// 回写数据库(更新 qr_issued_at)
|
||||
\think\facade\Db::name('vr_tickets')
|
||||
->where('id', $ticket['id'])
|
||||
->update(['qr_issued_at' => $issuedAt]);
|
||||
} else {
|
||||
// 返回缓存的 payload
|
||||
// 重新构建 payload(从数据库读取 iat)
|
||||
$payload = [
|
||||
'id' => $ticket['id'],
|
||||
'g' => $ticket['goods_id'],
|
||||
'iat' => $issuedAt,
|
||||
'exp' => $expiresAt,
|
||||
];
|
||||
$encoded = self::signQrPayload($payload);
|
||||
}
|
||||
$encoded = self::signQrPayload($payload);
|
||||
|
||||
return [
|
||||
'payload' => $encoded,
|
||||
'expires_at' => $expiresAt,
|
||||
'expires_in' => max(0, $expiresAt - $now),
|
||||
'expires_in' => self::QR_TTL,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 强制刷新 QR payload
|
||||
* 重新生成一个新的 QR payload(有效期重新计算)
|
||||
*
|
||||
* @param int $ticketId 票ID
|
||||
* @param int $userId 用户ID
|
||||
|
|
@ -204,32 +169,10 @@ class WalletService extends BaseService
|
|||
*/
|
||||
public static function refreshQrPayload(int $ticketId, int $userId): ?array
|
||||
{
|
||||
// 先清零 qr_issued_at,强制刷新
|
||||
\think\facade\Db::name('vr_tickets')
|
||||
->where('id', $ticketId)
|
||||
->update(['qr_issued_at' => 0]);
|
||||
|
||||
// 直接调用 getTicketDetail,它会重新生成 QR
|
||||
return self::getTicketDetail($ticketId, $userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查 QR 是否需要刷新
|
||||
*
|
||||
* @param int $qrIssuedAt QR 发放时间戳
|
||||
* @return bool
|
||||
*/
|
||||
public static function qrNeedsRefresh(int $qrIssuedAt): bool
|
||||
{
|
||||
if ($qrIssuedAt == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$now = time();
|
||||
$expiresAt = $qrIssuedAt + self::QR_TTL;
|
||||
|
||||
return (($expiresAt - $now) <= self::QR_REFRESH_THRESHOLD);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析座位信息
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue