| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529 |
- <?php
- namespace addons\QiShangTong\common\service;
- use addons\QiShangTong\common\enums\QiShangTongEnums;
- use addons\QiShangTong\common\expand\sdk\qishangtong\src\model\LogisticsModel;
- use addons\QiShangTong\common\expand\sdk\qishangtong\src\model\OrderCancelModel;
- use addons\QiShangTong\common\expand\sdk\qishangtong\src\model\OrderConfirmGoodsItemModel;
- use addons\QiShangTong\common\expand\sdk\qishangtong\src\model\OrderCreateModel;
- use addons\QiShangTong\common\expand\sdk\qishangtong\src\model\OrderMakeDeliveryModel;
- use addons\QiShangTong\common\expand\sdk\qishangtong\src\model\OrderPaidModel;
- use addons\QiShangTong\common\expand\sdk\qishangtong\src\request\OrderCancelRequest;
- use addons\QiShangTong\common\expand\sdk\qishangtong\src\request\OrderCreateRequest;
- use addons\QiShangTong\common\expand\sdk\qishangtong\src\request\OrderMakeDeliveryRequest;
- use addons\QiShangTong\common\expand\sdk\qishangtong\src\request\OrderPaidRequest;
- use addons\QiShangTong\common\helper\RequestHelper;
- use addons\QiShangTong\common\models\QiShangTongEvent;
- use addons\QiShangTong\common\models\QiShangTongGoods;
- use addons\QiShangTong\common\models\QiShangTongGoodsAttr;
- use addons\QiShangTong\common\models\QiShangTongOrder;
- use addons\QiShangTong\common\models\QiShangTongRegion;
- use common\enums\AddonsEnum;
- use common\enums\OrderStatusEnum;
- use common\enums\RabbitMqEnum;
- use common\enums\ShippingTypeEnum;
- use common\enums\StatusEnum;
- use common\helpers\FormatHelper;
- use common\models\common\Express;
- use common\models\mall\Mall;
- use common\models\order\Order;
- use common\models\order\OrderDetail;
- use common\models\order\OrderExpress;
- use common\models\user\User;
- class OrderService
- {
- public function page(int $mall_id, array $params)
- {
- $where = [
- ['status' => [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]));
- }
- }
|