2.1 版本文件

This commit is contained in:
2026-08-14 10:55:06 +08:00
commit a3434ec620
67 changed files with 12559 additions and 0 deletions
+153
View File
@@ -0,0 +1,153 @@
<?php
// 结算下单:登录后填写收货信息,生成订单并扣减库存
require __DIR__ . '/includes/init.php';
requireLogin('checkout.php');
$pageTitle = '结算';
$user = currentUser();
$cart = $_SESSION['cart'] ?? [];
$items = [];
$total = 0;
if (!empty($cart)) {
$ids = array_keys($cart);
$ph = implode(',', array_fill(0, count($ids), '?'));
$stmt = db()->prepare('SELECT * FROM ' . tn('products') . ' WHERE id IN (' . $ph . ') AND status = 1');
$stmt->execute($ids);
foreach ($stmt->fetchAll() as $p) {
$qty = (int) $cart[$p['id']];
if ($qty > $p['stock']) $qty = $p['stock'];
$pointsSub = (!empty($p['points_price']) ? (int)$p['points_price'] * $qty : 0);
$items[] = ['p' => $p, 'qty' => $qty, 'points_sub' => $pointsSub];
}
}
// 积分支付可用性:仅当订单内所有商品都设置了积分价
$pointsElg = !empty($items);
$pointsTotal = 0;
foreach ($items as $it) {
$pp = (int) ($it['p']['points_price'] ?? 0);
if ($pp <= 0) { $pointsElg = false; break; }
$pointsTotal += $pp * $it['qty'];
}
if ($pointsTotal <= 0) { $pointsElg = false; }
$userPoints = 0;
if (isLoggedIn()) {
$userPoints = getUserPoints($user['id']);
}
$err = '';
if (empty($items)) {
redirect('cart.php');
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
verifyCsrf();
$contact = trim($_POST['contact'] ?? '');
$contactEmail = trim($_POST['contact_email'] ?? '');
$address = trim($_POST['address'] ?? '');
$note = trim($_POST['note'] ?? '');
if ($contact === '') $err = '请填写联系人';
elseif ($address === '') $err = '请填写收货地址';
elseif ($contactEmail === '') $contactEmail = $user['email']; // 留空则使用账号邮箱
elseif (!filter_var($contactEmail, FILTER_VALIDATE_EMAIL)) $err = '联系邮箱格式不正确';
if ($err === '') {
$payType = ($pointsElg && ($_POST['pay_type'] ?? '') === 'points') ? 'points' : 'direct';
if ($payType === 'points') {
if ($userPoints < $pointsTotal) {
$err = '积分不足,当前 ' . $userPoints . ' 分,本单需 ' . $pointsTotal . ' 分';
}
}
}
if ($err === '') {
$pdo = db();
try {
$pdo->beginTransaction();
// 二次校验库存
foreach ($items as $it) {
$chk = $pdo->prepare('SELECT stock FROM ' . tn('products') . ' WHERE id = ? FOR UPDATE');
$chk->execute([$it['p']['id']]);
$row = $chk->fetch();
if (!$row || $row['stock'] < $it['qty']) {
throw new Exception('「' . $it['p']['name'] . '」库存不足,请返回购物车调整');
}
}
// 计算本单周期(取商品中最大的周期天数)与到期时间
$maxPeriod = 0;
foreach ($items as $it) {
$maxPeriod = max($maxPeriod, (int) ($it['p']['period_days'] ?? 0));
}
$expiresAt = $maxPeriod > 0 ? date('Y-m-d H:i:s', strtotime("+$maxPeriod days")) : null;
// 本商城不收取现金,现金合计固定记 0;积分支付时抵扣并记流水
$orderTotal = 0;
$pointsUsed = 0;
if ($payType === 'points') {
$pointsUsed = $pointsTotal;
$pdo->prepare('UPDATE ' . tn('users') . ' SET points = points - ? WHERE id = ? AND points >= ?')
->execute([$pointsUsed, $user['id'], $pointsUsed]);
$bal = getUserPoints($user['id']);
$pdo->prepare('INSERT INTO ' . tn('points_log') . ' (user_id,type,amount,balance,remark,created_at) VALUES (?,?,?,?,?,NOW())')
->execute([$user['id'], 'purchase', -$pointsUsed, $bal, '积分兑换:' . $orderNo]);
}
// 生成订单号
$orderNo = 'FNW' . date('Ymd') . strtoupper(substr(md5(uniqid($user['id'], true)), 0, 10));
$pdo->prepare('INSERT INTO ' . tn('orders') . ' (order_no,user_id,total,status,contact,contact_email,address,note,period_days,expires_at,pay_type,points_used,created_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,NOW())')
->execute([$orderNo, $user['id'], $orderTotal, 'paid', $contact, $contactEmail, $address, $note, $maxPeriod, $expiresAt, $payType, $pointsUsed]);
$orderId = $pdo->lastInsertId();
foreach ($items as $it) {
// 商城已取消现金支付,价格字段保留为 0 供历史兼容
$pdo->prepare('INSERT INTO ' . tn('order_items') . ' (order_id,product_id,name,price,qty,subtotal,period_days) VALUES (?,?,?,?,?,?,?)')
->execute([$orderId, $it['p']['id'], $it['p']['name'], 0, $it['qty'], 0, (int) ($it['p']['period_days'] ?? 0)]);
$pdo->prepare('UPDATE ' . tn('products') . ' SET stock = stock - ? WHERE id = ?')
->execute([$it['qty'], $it['p']['id']]);
}
$pdo->commit();
$_SESSION['cart'] = [];
redirect('myorders.php?paid=' . urlencode($orderNo));
} catch (Exception $e) {
$pdo->rollBack();
$err = $e->getMessage();
}
}
}
require 'includes/header.php';
?>
<section class="section">
<h2 class="sec-title"><i class="fas fa-credit-card"></i> 订单结算</h2>
<div class="checkout">
<div class="co-items">
<h3>商品清单</h3>
<?php foreach ($items as $it): ?>
<div class="co-row">
<span><?= h($it['p']['name']) ?> × <?= $it['qty'] ?></span>
<span><?= $it['points_sub'] > 0 ? (int)$it['points_sub'] . ' 积分' : '直接下单' ?></span>
</div>
<?php endforeach; ?>
</div>
<form method="post" action="" class="co-form">
<?= csrfField() ?>
<h3>收货信息</h3>
<?php if ($err): ?><p class="form-err"><?= h($err) ?></p><?php endif; ?>
<label>联系人<input type="text" name="contact" value="<?= h($_POST['contact'] ?? $user['username']) ?>" required></label>
<label>联系邮箱<input type="email" name="contact_email" value="<?= h($_POST['contact_email'] ?? $user['email']) ?>" placeholder="用于接收订单/发货通知" required></label>
<label>收货地址<input type="text" name="address" value="<?= h($_POST['address'] ?? '') ?>" required></label>
<label>备注<input type="text" name="note" value="<?= h($_POST['note'] ?? '') ?>" placeholder="选填"></label>
<?php if ($pointsElg): ?>
<div class="co-pay">
<h3>支付方式</h3>
<input type="hidden" name="pay_type" value="points">
<p class="pay-opt"><i class="fas fa-coins"></i> 积分支付(<?= $pointsTotal ?> 积分)<span class="muted" style="margin-left:10px;font-size:.85em;">当前积分 <?= (int)$userPoints ?></span></p>
</div>
<?php else: ?>
<input type="hidden" name="pay_type" value="direct">
<?php endif; ?>
<p class="co-tip">下单后如有积分价格要求,用积分支付;无积分价格,直接支付即可(发工单即代表您已同意资源领取/续期规定)。</p>
<button type="submit" class="btn btn-primary" style="width:100%;">提交订单</button>
</form>
</div>
</section>
<?php require 'includes/footer.php'; ?>