OrderCode::ORDER_TYPE_GOOD_PREFIX . '_' .date("YmdHis") . $userId . mt_rand(10000000, 99999999), OrderCode::ORDER_TYPE_BALANCE => OrderCode::ORDER_TYPE_BALANCE_PREFIX. '_' .date("YmdHis"). $userId. mt_rand(10000000, 99999999), }; } /** * 生成购物车数据 * @param array $data * @return void */ protected function buildCartData(array $data): void { $copies = 0; foreach ($data as $oneCopies) { $one = []; foreach ($oneCopies as $oneGood) { $this->cartFirstData[$oneGood] = ($this->cartFirstData[$oneGood] ?? 0) + 1; $one[$oneGood] = ($one[$oneGood] ?? 0) + 1; } $this->cartSecondData[] = $one; $copies++; } $this->copies = $copies; } /** * 检测商品 * @return void */ protected function checkGood(): void { foreach ($this->cartFirstData as $key => $one) { if (in_array($key, $this->goodIds)) continue; throw new ErrException('商品不存在',ApiCode::ORDER_GOOD_IN_EXISTENCE); } } /** * 检测库存 * @return void * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface */ protected function checkStock(): void { foreach ($this->cartFirstData as $key => $one) { if (($this->redis->zScore($this->stockKey,$key) ?? 0) >= $one) continue; throw new ErrException('商品库存不足',ApiCode::ORDER_GOOD_INSUFFICIENT_STOCK); } } /** * 检测地点 * @param int $siteId * @return int * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface */ protected function checkSite(int $siteId): int { $siteInfo = $this->siteCache->getSiteInfo($siteId); if (empty($siteInfo)) throw new ErrException('该地点暂时不支持点餐'); $kitchenId = (int)($siteInfo['kitchen_id'] ?? 0); if ($kitchenId <= 0) throw new ErrException('该地点暂时不支持点餐'); $this->orderRes['site_id'] = $siteId; $this->orderRes['site_info'] = $siteInfo; return $kitchenId; } /** * 获取商品信息 * @param int $kitchenId * @return void * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface */ protected function getGoodInfo(int $kitchenId): void { $this->stockKey = ApiRedisKey::goodStockKey($this->cycleId,$kitchenId); $mealGoodKey = ApiRedisKey::mealGoodListKey($this->cycleId,$kitchenId); $optionalGoodKey = ApiRedisKey::optionalGoodListKey($this->cycleId,$kitchenId); $mealGood = $this->redis->get($mealGoodKey); $optionalGood = $this->redis->get($optionalGoodKey); if (empty($mealGood) || empty($optionalGood)) throw new ErrException('商品不存在'); if (!$this->redis->exists($this->stockKey)) throw new ErrException('库存不足'); $mealGood = json_decode($mealGood, true); $optionalGood = json_decode($optionalGood, true); $skuArr = []; foreach ($mealGood as $one){ $skuArr = array_merge($skuArr,$one['sku_list']); } foreach ($optionalGood as $one){ $skuArr = array_merge($skuArr,$one['sku_list']); } $this->skuArr = array_column($skuArr,null,'id'); $this->goodIds = array_column($skuArr,'id'); unset($skuArr); } /** * @return int */ protected function getAutoCouponId(): int { return 0; } /** * 计算价格 * @return void */ protected function computePrice(): void { $this->orderRes['good_ids'] = $this->cartSecondData; foreach ($this->cartSecondData as $oneCopies) { $oneCopiesTotalPrice = '0.00'; $copiesType = 1; $oneCopiesGoodInfo = []; foreach ($oneCopies as $oneGood) { if (empty($oneCopiesGoodInfo[$oneGood])) { $oneCopiesGoodInfo[$oneGood] = [ 'num' => 1, 'good_name' => '1', 'good_url' => '1', 'unit_price' => $this->skuArr[$oneGood]['price'], 'type' => $this->skuArr[$oneGood]['type'], ]; } else { $oneCopiesGoodInfo[$oneGood]['num'] += 1; } $oneCopiesTotalPrice = bcadd($oneCopiesTotalPrice, $this->skuArr[$oneGood]['price'],2); if ($copiesType == 1 && $this->skuArr[$oneGood]['type'] == GoodCode::SPU_TYPE_MEAL) { $copiesType = 2; } } $this->orderRes['good'][] = [ 'good_ids' => $oneCopies, 'good_info' => $oneCopiesGoodInfo, 'price' => $oneCopiesTotalPrice, ]; if ($copiesType == 1) { $this->orderRes['optional_copies']++; } else { $this->orderRes['meal_copies']++; } $this->orderRes['total_good_price'] = bcadd($this->orderRes['total_good_price'],$oneCopiesTotalPrice,2); } } /** * 计算服务费 * @return void * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface */ protected function computeSundryPrice(): void { $this->orderRes['sundry_num'] = match ($this->configCache->getConfigValue(ConfigCode::SUNDRY_PRICE_COMPUTE_TYPE)) { 1 => $this->orderRes['optional_copies'], 2 => $this->orderRes['meal_copies'], 3 => $this->copies, }; $this->orderRes['sundry_price'] = $this->configCache->getConfigValue(ConfigCode::SUNDRY_UNIT_PRICE); $this->orderRes['total_sundry_price'] = bcmul($this->orderRes['sundry_price'],$this->orderRes['sundry_num'],2); } /** * 计算优惠 * @return void */ protected function computeFavorable(): void { if ($this->couponId <= 0 && $this->isAutoSelectCoupon == 1) { $this->couponId = $this->getAutoCouponId(); } if ($this->couponId <= 0) { $this->orderRes['coupon_id'] = 0; $this->orderRes['coupon'] = []; $this->orderRes['favorable_good_price'] = '0'; $this->orderRes['favorable_sundry_price'] = '0'; return; } $couponInfo = []; // todo 优惠券信息 $this->orderRes['coupon_id'] = $this->couponId; $this->orderRes['coupon'] = $couponInfo; //todo 优惠计算 $this->orderRes['favorable_good_price'] = '1.00'; $this->orderRes['favorable_sundry_price'] = '1.00'; } /** * 计算最终价格 * @return void */ protected function computeFinallyPrice(): void { $this->orderRes['good_after_discount_price'] = bcsub($this->orderRes['total_good_price'],$this->orderRes['favorable_good_price'],2); $this->orderRes['sundry_after_discount_price'] = bcsub($this->orderRes['total_sundry_price'],$this->orderRes['favorable_sundry_price'],2); $this->orderRes['total_price'] = bcadd($this->orderRes['total_good_price'],$this->orderRes['total_sundry_price'],2); $this->orderRes['actual_price'] = bcadd($this->orderRes['good_after_discount_price'],$this->orderRes['sundry_after_discount_price'],2); } /** * @param int $orderId * @param int $orderStatus * @return void * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface */ protected function sendStockMq(int $orderId,int $orderStatus): void { $message = new OrderGoodStockProducer([ 'order_id' => $orderId, 'type' => $orderStatus ]); $producer = ApplicationContext::getContainer()->get(Producer::class); $producer->produce($message); } /** * @var Order */ #[Inject] protected Order $orderModel; /** * @return void * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface */ protected function checkGoodOrder(): void { $this->orderInfo = $this->orderModel->getInfoByOrderSno($this->orderNo); if (empty($this->orderInfo)) { $this->log->debug(__CLASS__.':订单不存在,订单号:'.$this->orderNo); throw new ErrException('订单不存在'); } if ($this->orderInfo->status != OrderCode::WAIT_PAY) { $this->log->debug(__CLASS__.':订单已充值成功或取消,订单信息:'.json_encode($this->orderInfo->toArray())); throw new ErrException('订单已充值成功'); } if ($this->orderInfo->action != PayCode::WECHAT_PAY) { $this->log->debug(__CLASS__.':订单充值渠道错误,订单信息:'.json_encode($this->orderInfo->toArray())); throw new ErrException('订单充值渠道错误'); } } /** * 操作微信订单 * @return void */ protected function manageWxOrder(): void { // $this->orderInfo->status = OrderCode::STATUS_PAY; // $this->orderInfo->isAdd = 1; // $this->orderInfo->tradeno = $this->callbackData['transaction_id']; //// $this->orderInfo->payTime = date('Y-m-d H:i:s',strtotime($this->callbackData['time_end'])); // $this->orderInfo->payTime = strtotime($this->callbackData['success_time']); // $this->orderInfo->jsonData = [ // 'payData' => $this->callbackData, // 'jsonData' => $this->orderInfo->jsonData // ]; if (!$this->orderInfo->save()) { $this->log->debug(__CLASS__.':Function:manageWxOrder:更新充值订单的状态失败:'.$this->orderInfo->id); throw new ErrException('更新充值订单的状态失败'); } } /** * @return void * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface */ protected function manageGoodOrder(): void { try { }catch (Exception $e) { $this->log->error(__CLASS__.':Function:manageGoodOrder:'.$e->getMessage().':orderId:'.$this->orderInfo->id); throw new ErrException($e->getMessage()); } } }