coupon/claim_code.php

120 lines
6.0 KiB
PHP
Executable File
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
require_once __DIR__ . '/includes/auth.php';
require_once __DIR__ . '/includes/functions.php';
requireLogin();
$pageTitle = '兑换码领取';
require __DIR__ . '/includes/header.php';
$msg = '';
$pid = getCurrentProductId();
// 获取所有面值及对应可领取数量
$stmt = $pdo->prepare("SELECT value, COUNT(*) AS cnt FROM redemption_codes WHERE status = 1 AND (expired_at IS NULL OR expired_at > NOW()) AND product_id = ? GROUP BY value ORDER BY value ASC");
$stmt->execute([$pid]);
$valueOptions = $stmt->fetchAll();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!verifyCsrf($_POST['csrf_token'] ?? '')) { die('CSRF token无效'); }
$codeValue = trim($_POST['code_value'] ?? '');
$quantity = max(1, min(100, (int)($_POST['quantity'] ?? 1)));
// 校验面值是否有效
$validValues = array_map(fn($v) => $v['value'], $valueOptions);
if (!in_array($codeValue, $validValues, true)) {
$msg = '<div class="alert alert-danger">无效的面值</div>';
} else {
// 检查当前用户未使用兑换码数量
$stmt = $pdo->prepare("SELECT COUNT(*) FROM claim_records WHERE user_id = ? AND product_id = ? AND status = 1");
$stmt->execute([getCurrentUserId(), $pid]);
$unusedCount = (int)$stmt->fetchColumn();
if ($unusedCount >= 200) {
$msg = '<div class="alert alert-danger">您当前未使用的兑换码已达 ' . $unusedCount . ' 条上限200条请先使用后再领取</div>';
} else {
// 检查频繁领取同面值距上一次领取不足3天
$stmt = $pdo->prepare("SELECT MAX(claimed_at) FROM claim_records WHERE user_id = ? AND product_id = ? AND value = ?");
$stmt->execute([getCurrentUserId(), $pid, $codeValue]);
$lastClaim = $stmt->fetchColumn();
if ($lastClaim && strtotime($lastClaim) > strtotime('-3 days')) {
$remaining = ceil((strtotime($lastClaim) + 3 * 86400 - time()) / 3600);
$msg = '<div class="alert alert-danger">当前面值兑换码距上次领取不足3天请 ' . $remaining . ' 小时后再领取</div>';
} else {
$pdo->beginTransaction();
try {
// 查找指定面值的可领取兑换码
$stmt = $pdo->prepare('SELECT * FROM redemption_codes WHERE value = ? AND status = 1 AND (expired_at IS NULL OR expired_at > NOW()) AND product_id = ? ORDER BY id ASC LIMIT ? FOR UPDATE');
$stmt->execute([$codeValue, $pid, $quantity]);
$available = $stmt->fetchAll();
if (count($available) < $quantity) {
$msg = '<div class="alert alert-danger">该面值的可领取兑换码不足,当前仅有 ' . count($available) . ' 个可用</div>';
$pdo->rollBack();
} else {
$claimed = 0;
foreach ($available as $code) {
$stmt = $pdo->prepare('UPDATE redemption_codes SET status = 2, claim_user_id = ?, claimed_at = NOW() WHERE id = ?');
$stmt->execute([getCurrentUserId(), $code['id']]);
$stmt = $pdo->prepare('INSERT INTO claim_records (product_id, created_at, user_id, code_name, batch_no, code_type, code, value, status, expired_at, price_tier1, price_tier2, claim_user, claimed_at) VALUES (?, NOW(), ?, ?, ?, ?, ?, ?, 1, ?, ?, ?, ?, NOW())');
$stmt->execute([
$code['product_id'],
getCurrentUserId(),
$code['name'],
$code['batch_no'],
$code['type'],
$code['code'],
$code['value'],
$code['expired_at'],
$code['price_tier1'],
$code['price_tier2'],
getCurrentUsername()
]);
$claimed++;
}
$pdo->commit();
$_SESSION['flash_msg'] = '成功领取 ' . $claimed . ' 个兑换码!';
$_SESSION['flash_type'] = 'success';
redirect('claim_code.php');
}
} catch (Exception $e) {
$pdo->rollBack();
$msg = '<div class="alert alert-danger">领取失败,请重试</div>';
}
}
}
}
}
$totalAvailable = array_sum(array_column($valueOptions, 'cnt'));
?>
<div class="card">
<h2>兑换码领取</h2>
<?php if (isset($_SESSION['flash_msg'])): ?>
<div class="alert alert-<?= h($_SESSION['flash_type'] ?? 'success') ?>"><?= h($_SESSION['flash_msg']) ?></div>
<?php unset($_SESSION['flash_msg'], $_SESSION['flash_type']); ?>
<?php endif; ?>
<?= $msg ?>
<form method="post">
<input type="hidden" name="csrf_token" value="<?= csrfToken() ?>">
<div class="form-group">
<label>兑换码面值</label>
<select name="code_value" class="form-control" required>
<option value="">-- 请选择面值 --</option>
<?php foreach ($valueOptions as $opt): ?>
<option value="<?= h($opt['value']) ?>" <?= (isset($_POST['code_value']) && $_POST['code_value'] === $opt['value']) ? 'selected' : '' ?>>
<?= h($opt['value']) ?>(剩余 <?= $opt['cnt'] ?> 个)
</option>
<?php endforeach; ?>
</select>
</div>
<div class="form-group">
<label>领取数量</label>
<input type="number" name="quantity" class="form-control" value="1" min="1" max="100" required>
<div style="font-size:12px;color:#999;margin-top:4px;">当前共计可领取: <?= $totalAvailable ?> 个单次最多100个</div>
</div>
<button type="submit" class="btn btn-success" onclick="return confirm('确认领取?')">立即领取</button>
<button type="button" class="btn btn-default" onclick="history.back()" style="margin-left:8px;">取消</button>
</form>
</div>
<?php require __DIR__ . '/includes/footer.php'; ?>