99) { throw new \Exception('商品数量不合法'); } $product = Product::find($item['productId']); if (!$product || $product->status != 1) { throw new \Exception('商品不存在或已下架'); } $subtotal = $product->price * $qty; $totalAmount += $subtotal; $orderItems[] = [ 'product_id' => $product->id, 'product_name' => $product->name, 'emoji' => $product->emoji ?? '', 'price' => $product->price, 'quantity' => $qty, ]; } if ($totalAmount <= 0) { throw new \Exception('订单金额无效'); } // BUG-03 (旧): 订单号增加秒级精度避免并发冲突 $orderNo = 'OD' . date('His') . substr($cardNo, -3) . rand(10, 99); $order = Order::create([ 'order_no' => $orderNo, 'card_no' => $cardNo, 'total_amount' => $totalAmount, 'status' => 0, 'note' => $note, 'submitted_at' => date('Y-m-d H:i:s'), ]); foreach ($orderItems as &$oi) { $oi['order_id'] = $order->id; } (new OrderItem())->saveAll($orderItems); return ['orderNo' => $order->order_no]; }); } // 顾客订单列表 public function listByCard(string $cardNo): array { $orders = Order::with('items') ->where('card_no', $cardNo) ->order('submitted_at', 'desc') ->select() ->toArray(); return array_map(function ($o) { return [ 'id' => $o['id'], 'orderNo' => $o['order_no'], 'cardNo' => $o['card_no'], 'status' => $o['status'], 'note' => $o['note'] ?? '', 'remindCount' => $o['remind_count'] ?? 0, 'submittedAt' => date('H:i', strtotime($o['submitted_at'])), 'items' => array_map(function ($i) { return [ 'name' => $i['product_name'], 'emoji' => $i['emoji'] ?? '', 'alc' => 0.0, 'qty' => $i['quantity'], ]; }, $o['items'] ?? []), ]; }, $orders); } // BUG-01: 催单增加归属校验 + 状态校验 + 频率限制 public function remind(int $orderId, string $cardNo): void { $order = Order::find($orderId); if (!$order) { throw new \Exception('订单不存在'); } // 归属校验 if ($order->card_no !== $cardNo) { throw new \Exception('无权操作此订单'); } // 状态校验:仅新单可催 if ($order->status !== 0) { throw new \Exception('当前订单状态不可催单'); } // 频率限制:30秒冷却 $lastRemind = strtotime($order->updated_at ?? $order->submitted_at); if (time() - $lastRemind < 30) { throw new \Exception('催单太频繁,请30秒后再试'); } // 上限:最多5次 if ($order->remind_count >= 5) { throw new \Exception('催单次数已达上限'); } Order::where('id', $orderId)->inc('remind_count', 1)->update(); } }