isAutoSelectCoupon = 2; } /** * @var array */ private array $rollbackStockCache = []; /** * 统一下单逻辑 * @return array * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface */ public function handle(): array { //todo 加防抖 $this->siteId = (int)$this->request->input('site_id'); $this->couponId = (int)$this->request->input('coupon_id',0); $this->orderType = (int)$this->request->input('order_type'); // 生成购物车信息 , 检测商品和库存等 $this->check(); // 如果传递了优惠券的值 则进行检测 $this->getCouponInfo(); // 计算 $this->compute(); // 如果有优惠券的情况下 重载计算 $this->reloadCompute(); // 下单 减少库存 写入数据库 $this->placeOrder(); // 加入取消延迟队列 $this->joinCancelDelayQueue( $this->orderId, OrderCode::ORDER_TYPE_GOOD, (int)$this->configCache->getConfigValueByKey(ConfigCode::ORDER_CANCEL_TIME_KEY) * DateUtil::MINUTE * DateUtil::MS ); $this->sendStockMq($this->orderId,OrderCode::WAIT_PAY); $this->orderRes['order_id'] = $this->orderId; return $this->return->success('success',$this->orderRes); } /** * @return void * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface * @throws Exception */ private function reduceStock(): void { $this->rollbackStockCache = []; // var_dump($this->cartFirstData); foreach ($this->cartFirstData as $goodId => $stock) { $this->rollbackStockCache[$goodId] = $stock; if (!($this->redis->zIncrBy($this->stockKey,-$stock,$goodId))) { throw new Exception('cache error'); } } } /** * @return void * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface */ private function rollbackStock(): void { if (empty($this->rollbackStockCache)) return; foreach ($this->rollbackStockCache as $goodId => $stock) { $this->redis->zIncrBy($this->stockKey,$stock,$goodId); } } /** * 下单 * @return void * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface */ private function placeOrder(): void { try { Db::beginTransaction(); $this->reduceStock(); $this->insertOrder(); $this->insertOrderGoods(); Db::commit(); } catch (Exception $e){ echo $e->getMessage(); //回滚数据库 和 缓存 Db::rollBack(); $this->rollbackStock(); //意外抛出 throw new ErrException($e->getMessage()); } } /** * 插入订单商品 * @return void * @throws Exception */ private function insertOrderGoods(): void { $copiesNum = 0; $orderGoodInsertArr = []; foreach ($this->orderRes['good'] as $oneCopies) { $copiesNum++; foreach ($oneCopies['good_info'] as $one) { $orderGoodInsertArr[] = [ 'order_id' => $this->orderId, 'cycle_id' => $this->cycleId, 'kitchen_id' => $this->orderRes['site_info']['kitchen_id'], 'sku_id' => $one['id'], 'spu_id' => $one['spu_id'], 'user_id' => $this->userId, 'quantity' => $one['num'], 'unit_price' => $one['unit_price'], 'is_comment' => OrderCode::GOOD_COMMENT_NULL, 'copies' => $copiesNum, 'type' => $one['type'], 'status' => OrderCode::WAIT_PAY, 'create_time' => date('Y-m-d H:i:s'), 'update_time' => date('Y-m-d H:i:s'), ]; } } if (!(new OrderGood)->insert($orderGoodInsertArr)) throw new Exception('写入订单商品失败'); } /** * 插入订单 * @return void * @throws Exception */ private function insertOrder(): void { $orderInsertModel = new Order(); $orderInsertModel->order_sno = $this->generateOrderNo(OrderCode::ORDER_TYPE_GOOD, $this->userId); $orderInsertModel->user_id = $this->userId; $orderInsertModel->cycle_id = $this->cycleId; $orderInsertModel->site_id = $this->siteId; $orderInsertModel->city_id = $this->orderRes['site_info']['city_id']; $orderInsertModel->kitchen_id = $this->orderRes['site_info']['kitchen_id']; $orderInsertModel->coupon_id = $this->couponId; $orderInsertModel->copies = $this->orderRes['copies']; $orderInsertModel->type = $this->orderType; $orderInsertModel->total_price = $this->orderRes['total_price']; $orderInsertModel->actual_price = max($this->orderRes['actual_price'], 0); $orderInsertModel->discount_price = $this->orderRes['favorable_sundry_price'] + $this->orderRes['favorable_good_price']; $orderInsertModel->append_price = $this->orderRes['sundry_price']; $orderInsertModel->append_copies = $this->orderRes['sundry_num']; $orderInsertModel->status = OrderCode::WAIT_PAY; $orderInsertModel->is_refund_all = OrderCode::REFUND_NULL; $orderInsertModel->order_json = json_encode($this->orderRes); if (!$orderInsertModel->save()) throw new Exception('下单失败'); $this->orderId = $orderInsertModel->id; } }