[StatusEnum::ENABLED, StatusEnum::DISABLED]] ]; if (!empty($params['order_no'])) { $where[] = ['like', 'order_no', $params['order_no']]; } $is_master = SettingService::isMasterMall($mall_id); if (!$is_master) { $where[] = ['mall_id' => $mall_id]; } elseif (!empty($params['keyword'])) { $mIds = Mall::find()->where(['or', ['like', 'id', $params['keyword']], ['like', 'name', $params['keyword']]]) ->select('id')->column(); if (empty($mIds)) return []; $where[] = ['mall_id' => $mIds]; } if (!empty($params['third_order_no'])) { $where[] = ['like', 'third_order_no', $params['third_order_no']]; } if (!empty($params['goods_name'])) { $where[] = ['like', 'content', $params['goods_name']]; } if (!empty($params['member'])) { $query = User::find(); if (!$is_master) $query->where(['mall_id' => $mall_id]); $uids = $query->andWhere(['or', ['like', 'id', $params['member']], ['like', 'mobile', $params['member']], ['like', 'nickname', $params['member']]]) ->andWhere(['status' => StatusEnum::ENABLED]) ->select('id')->column(); if (empty($uids)) return []; $where[] = ['user_id' => $uids]; } $ret = QiShangTongOrder::listPage([ 'where' => $where, 'order' => 'id desc', 'limit' => $params['limit'] ?? '', 'with' => ['order' => function($query) { $query->with(['detail']); }, 'mall'] ]); if (!empty(QiShangTongOrder::getStaticError())) return QiShangTongOrder::getStaticError(); if (!empty($ret['list'])) { foreach ($ret['list'] as &$item) { $item['mall']['logo'] = MallService::getLogo($item['mall_id']); } } return $ret; } /** * 创建订单 * @param array $order * @param int $a_order_id * @return bool */ public function create(array $order, int $a_order_id = 0) { try { $goods_ids = array_column($order['detail'], 'goods_id'); $list = QiShangTongGoods::lists([ 'where' => [ ['goods_id' => $goods_ids], ['mall_id' => $order['mall_id']] ], 'index' => 'goods_id', 'select'=> 'goods_id, third_goods_id' ]); $order_detail_ids = []; if (!empty($list)) { $goods = []; foreach ($order['detail'] as $item) { if (!empty($list[$item['goods_id']])) { $tGoods = new OrderConfirmGoodsItemModel(); $tGoods->goods_id = $list[$item['goods_id']]['third_goods_id']; $tGoods->spec_id = QiShangTongGoodsAttr::find()->where(['goods_attr_id' => $item['goods_attr_id']]) ->select('third_spec_id')->scalar(); // 商品规格ID $tGoods->num = $item['num']; $order_detail_ids[] = $item['id']; $goods[] = $tGoods; } } if (!empty($goods)) { if (!empty($a_order_id)) { $orderModel = QiShangTongOrder::findOne(['id' => $a_order_id]); } else { $orderModel = new QiShangTongOrder(); } $is_d = true; $region = QiShangTongRegion::findOne(['local_id' => $order['area']]); if (empty($region)) { $is_d = false; $region = QiShangTongRegion::findOne(['local_id' => $order['city']]); } $contentModel = new OrderCreateModel(); $contentModel->phone_mob = $order['mobile']; $contentModel->region_name = str_replace(' ', '', $order['region_name']); $contentModel->address = $order['address']; $contentModel->province = $region->province_id; // ID要相通 $contentModel->city = $region->city_id; // 直辖市可以传0,但是 区县/省市不能传0 $contentModel->area = $is_d ? $region->id : $region->district_id; $contentModel->consignee = $order['receiver_name']; $contentModel->order_no = $order['order_no']; $contentModel->details = $goods; // 商品信息 $res = RequestHelper::send(new OrderCreateRequest(), $contentModel, $order['mall_id']); $orderModel->req_success = 100; if (!is_array($res)) { // throw new \Exception($res); $orderModel->req_success = StatusEnum::ENABLED; } // 创建订单 $orderModel->content = [ 'create' => $res ]; $orderModel->post = [ 'create' => $contentModel->toArray() ]; if (empty($a_order_id)) { $orderModel->order_no = $order['order_no']; $orderModel->order_id = $order['id']; $orderModel->mall_id = $order['mall_id']; $orderModel->user_id = $order['user_id']; $orderModel->order_detail_ids = $order_detail_ids; } $orderModel->third_order_no = $res['order_parent_sn'] ?? ''; $orderModel->last_req = 'create'; $orderModel->last_resp = var_export($res, true); if (!$orderModel->save()) throw new \Exception($orderModel->getErrorMessage()); } } } catch (\Exception $e) { var_dump($e->getMessage(), $e->getLine(), $e->getFile()); \Yii::error(FormatHelper::exception($e, __METHOD__)); return false; } return true; } /** * 订单更新 * @param QiShangTongEvent $event * @param $type * @return void * @throws \Exception */ public function eventUpdate(QiShangTongEvent &$event, $type) { $aOrder = QiShangTongOrder::findOne(['third_order_no' => $event->content['order_parent_sn']]); if (empty($aOrder)) throw new \Exception("订单不存在!"); // 做处理 $order = Order::getOne([ ['id' => $aOrder->order_id] ], true, 'detail'); if (empty($order)) throw new \Exception("订单不存在"); $event->mall_id = $aOrder->mall_id; $t = \Yii::$app->db->beginTransaction(); try { switch ($type) { case 'ready': // 配货中 break; case 'delivery': // 已发货 // 执行发货 // 查快递 /** * @var $express Express */ $express = Express::getOne([ ['like', 'name', $event->content['Kuaidiname']] ]); if (empty($express)) { $express = Express::getOne([ ['id' => Express::EXPRESS_OTHER] ]); } $form['mall_id'] = $event->mall_id; $form['shipping_type'] = ShippingTypeEnum::LOGISTICS; $form['order_detail_ids'] = $aOrder->order_detail_ids; $form['express_id'] = $express->id; $form['express_no'] = $event->content['KuaidiNo']; $form['express_name'] = $express->name; $form['memo'] = "{$event->content['Kuaidiname']}, {$event->content['KuaidiNo']}, " . "{$event->content['third_code']}, {$event->content['Kuaidicode']}, " . date('Y-m-d H:i:s', $event->content['date']); $form['id'] = $aOrder->order_id; $form['mch_id'] = 0; $form['operator_id'] = 0; $form['operator_name'] = "企商通供应链发货"; $res = OrderExpress::delivery($form); // 发货 if ($res === false) throw new \Exception(OrderExpress::getStaticError()); break; } $aOrder->content = array_merge($aOrder->content, [ 'event' => [ $event->content['type'] => $event->content, ] ]); if (!$aOrder->save()) throw new \Exception($aOrder->getErrorMessage()); $t->commit(); } catch (\Exception $e) { $t->rollBack(); \Yii::error(FormatHelper::exception($e, __METHOD__)); throw new \Exception($e->getMessage()); } } /** * 订单取消 * @param array $order * @return true * @throws \Exception */ public function cancel(array $order) { $aOrder = QiShangTongOrder::findOne(['order_id' => $order['id']]); if (empty($aOrder)) return true; $contentModel = new OrderCancelModel(); $contentModel->order_no = $aOrder->order_no; $contentModel->order_parent_sn = $aOrder->third_order_no; $res = RequestHelper::send(new OrderCancelRequest(), $contentModel, $order['mall_id']); $aOrder->req_success = 100; if (!is_array($res)) { $aOrder->req_success = StatusEnum::ENABLED; } $aOrder->post = array_merge($aOrder->post, ['cancel' => $contentModel->toArray()]); $aOrder->content = array_merge($aOrder->content, ['cancel' => $res]); $aOrder->last_req = 'cancel'; $aOrder->last_resp = var_export($res, true); if (!$aOrder->save()) throw new \Exception($aOrder->getErrorMessage()); $aOrder->order_status = OrderStatusEnum::REPEAL; return true; } /** * 订单支付 * @param array $order * @return bool * @throws \Exception */ public function pay(array $order) { $aOrder = QiShangTongOrder::findOne(['order_id' => $order['id']]); if (empty($aOrder)) return true; try { $contentModel = new OrderPaidModel(); $contentModel->order_no = $aOrder->order_no; $contentModel->order_parent_sn = $aOrder->third_order_no; $contentModel->pay_time = $order['pay_time']; // 计算价格 $amount = 0; foreach ($order['detail'] as $item) { $price = QiShangTongGoodsAttr::find()->where(['goods_attr_id' => $item['goods_attr_id']])->select('gonghuojia')->scalar(); $amount += (int) bcmul(bcmul($price, 100), $item['num']); } $shipping_fee = (int) bcmul(!empty($order['shipping_money']) ? $order['shipping_money'] : 0, 100); // 如果失败了 这一行需要去掉 $shipping_fee_txt = bcmul($shipping_fee, 0.01, 2); $amount_txt = round(bcmul(bcmul($amount, MallService::rate($aOrder->mall_id), 2), 0.01, 3), 2); $balanceLogModel = (new FundService())->create([ 'mall_id' => $aOrder->mall_id, 'amount' => bcadd($amount_txt, $shipping_fee_txt, 2), 'remark' => "来自订单号为[{$aOrder->order_no}]的购物消费,其中商品金额为[{$amount_txt}],运费金额为[$shipping_fee_txt]", 'type' => QiShangTongEnums::BALANCE_LOG_TYPE_CONSUMER, 'direction' => QiShangTongEnums::BALANCE_DIRECTION_OUT, 'order_no' => $aOrder->order_no, 'addons' => AddonsEnum::ADDONS_NAME_QI_SHANG_TONG, ]); if (!is_string($balanceLogModel)) { $contentModel->amount = $amount + $shipping_fee; $res = RequestHelper::send(new OrderPaidRequest(), $contentModel, $order['mall_id']); $aOrder->req_success = 100; if (!is_array($res)) { // throw new \Exception($res); $aOrder->req_success = StatusEnum::ENABLED; } } else { // 无法回滚 $res = $balanceLogModel; $aOrder->req_success = StatusEnum::ENABLED; } $aOrder->post = array_merge($aOrder->post, ['pay' => $contentModel->toArray()]); $aOrder->content = array_merge($aOrder->content, ['pay' => $res ?? []]); $aOrder->order_status = OrderStatusEnum::PAY; $aOrder->last_req = 'pay'; $aOrder->last_resp = var_export($res ?? [], true); if (!$aOrder->save()) throw new \Exception($aOrder->getErrorMessage()); if ($aOrder->req_success != 100 && !empty($balanceLogModel) && !is_string($balanceLogModel)) { // 退回资金 FundService::asyncRefund($balanceLogModel->id); } } catch (\Exception $e) { return $e->getMessage(); } return true; } /** * 订单收货 * @param array $order * @return true * @throws \Exception */ public function takeDelivery(array $order) { $aOrder = QiShangTongOrder::findOne(['order_id' => $order['id']]); if (empty($aOrder)) return true; $orderDetails = OrderDetail::lists([ 'where' => [ ['id' => $aOrder->order_detail_ids] ] ]); $post = []; $resp = []; foreach ($orderDetails as $orderDetail) { $contentModel = new OrderMakeDeliveryModel(); $contentModel->order_no = $aOrder->order_no; $contentModel->order_parent_sn = $aOrder->third_order_no; $contentModel->order_sn = $orderDetail['id']; $aGoods = QiShangTongGoods::findOne(['goods_id' => $orderDetail['goods_id']]); $spec_id = QiShangTongGoodsAttr::find()->where(['goods_attr_id' => $orderDetail['goods_attr_id']])->select('third_spec_id')->scalar(); $contentModel->spec_id = $spec_id; $contentModel->goods_id = $aGoods->third_goods_id; $res = RequestHelper::send(new OrderMakeDeliveryRequest(), $contentModel, $aOrder->mall_id); $aOrder->req_success = 100; if (!is_array($res)) { $aOrder->req_success = StatusEnum::ENABLED; // throw new \Exception($res); } $post[] = $contentModel->toArray(); $resp[] = $res; } $aOrder->post = array_merge($aOrder->post, ['take_delivery' => $post]); $aOrder->content = array_merge($aOrder->content, ['take_delivery' => $resp]); $aOrder->order_status = OrderStatusEnum::SING; $aOrder->last_req = 'takeDelivery'; $aOrder->last_resp = var_export($resp, true); if (!$aOrder->save()) throw new \Exception($aOrder->getErrorMessage()); return true; } /** * 此任务不需要使用,因为有异步 * @return void * @throws \Exception */ public function logisticsTask() { foreach (QiShangTongOrder::find()->select('id, mall_id')->where(['is_logistics' => StatusEnum::DISABLED]) ->andWhere(['order_status' => OrderStatusEnum::PAY])->each() as $item) { \Yii::$app->services->rabbitMq->push(RabbitMqEnum::EXCHANGE_ORDER, RabbitMqEnum::ORDER_QUEUE, ['mall_id' => $item['mall_id'], 'id' => $item['id']], self::class, 'asyncDelivery'); // $this->asyncDelivery(['mall_id' => $item['mall_id'], 'id' => $item['id']]); } } /** * 同步发货信息 * @param array $params * @return bool */ public function asyncDelivery(array $params) { try { $aOrder = QiShangTongOrder::findOne(['id' => $params['id']]); if (empty($aOrder) || !empty($aOrder->is_logistics)) return true; $contentModel = new LogisticsModel(); $contentModel->order_no = $aOrder->order_no; $contentModel->order_parent_sn = $aOrder->third_order_no; $res = RequestHelper::send(new OrderMakeDeliveryRequest(), $contentModel, $params['mall_id']); if (!is_array($res)) { throw new \Exception($res); } $t = \Yii::$app->db->beginTransaction(); $aOrder->post = array_merge($aOrder->post, ['logistics' => $contentModel->toArray()]); $aOrder->content = array_merge($aOrder->content, ['logistics' => $res]); $aOrder->order_status = OrderStatusEnum::SHIPMENTS; $aOrder->is_logistics = StatusEnum::ENABLED; if (!$aOrder->save()) throw new \Exception($aOrder->getErrorMessage()); /** * @var $express Express */ $express = Express::getOne([ ['like', 'name', $res['Kuaidiname']] ]); if (!empty($express)) { $express = Express::getOne([ ['id' => Express::EXPRESS_OTHER] ]); } // 执行发货 $express_no = explode(",", $res['KuaidiNo']); $form['mall_id'] = $params['mall_id']; $form['mch_id'] = 0; $form['operator_id'] = 0; $form['shipping_type'] = ShippingTypeEnum::LOGISTICS; $form['express_id'] = $express->id; $form['express_name'] = $express->name; $form['express_no'] = $express_no[0] ?? ''; $form['memo'] = "{$res['Kuaidiname']}, {$res['KuaidiNo']}, {$res['Kuaidicode']}, {$res['third_code']}, {$res['ship_no_detail']}"; $form['order_detail_ids'] = ShippingTypeEnum::LOGISTICS; $form['operator_name'] = '企商通供应链发货'; $res = OrderExpress::delivery($form); // 发货 if ($res === false) throw new \Exception(OrderExpress::getStaticError()); $t->commit(); } catch (\Exception $e) { if (!empty($t)) $t->rollBack(); \Yii::error(FormatHelper::exception($e, __METHOD__)); return false; } return true; } public function compensate(int $mall_id, $id) { $aOrder = QiShangTongOrder::findOne(['id' => $id, 'mall_id' => $mall_id]); if (empty($aOrder)) return '记录不存在'; if ($aOrder->req_success == 100) return '当前状态无效补偿'; try { $order = Order::getOne([['id' => $aOrder->order_id]],true, ['detail']); switch ($aOrder->last_req) { case 'create': return $this->create($order); case 'takeDelivery': return $this->takeDelivery($order); case 'pay': return $this->pay($order); case 'cancel': return $this->cancel($order); } } catch (\Exception $e) { return $e->getMessage(); } return true; } /** * @param int $order_id * @return bool */ public static function existOrder(int $order_id) { return !empty(QiShangTongOrder::findOne(['order_id' => $order_id])); } }