with(['mallOrder' => function ($query) { return $query->select('id, receiver_name as consignee, mobile, goods_price, pay_time, pay_money, status as order_status, order_source'); }, 'mallOrderDetail' => function ($query) { return $query->select('order_id, num, goods_name, pic_url, goods_attr_name'); }]); $model->andWhere(['mall_id' => $this->mall_id]); if (!empty($params['order_no'])) { $ids = MallOrderModel::find()->where(['mall_id' => $this->mall_id])->andWhere(['like', 'order_no', $params['order_no']])->select('id')->column(); $model->andWhere(['in', 'order_id', $ids]); } if (!empty($params['user_id'])) { $ids = MallOrderModel::find()->where(['mall_id' => $this->mall_id])->andWhere(['=', 'user_id', $params['user_id']])->select('id')->column(); $model->andWhere(['in', 'order_id', $ids]); } if (!empty($params['search_words'])) { $ids = OrderDetail::find()->where(['mall_id' => $this->mall_id])->andWhere(['like', 'goods_name', $params['search_words']])->select('order_id')->column(); $model->andWhere(['in', 'order_id', $ids]); } if (!empty($params['push_status']) && $params['push_status'] > 0) { $model->andWhere(['=', 'status', $params['push_status']]); } if (!empty($params['order_status']) && $params['order_status'] > 0) { $ids = MallOrderModel::find()->where(['mall_id' => $this->mall_id])->andWhere(['=', 'status', $params['order_status']])->select('id')->column(); $model->andWhere(['in', 'order_id', $ids]); } if (!empty($params['source']) && $params['source'] > 0) { $model->andWhere(['=', 'source', $params['source']]); } if (!empty($params['name'])) { $ids = MallOrderModel::find()->where(['mall_id' => $this->mall_id])->andWhere(['like', 'receiver_name', $params['name']])->select('id')->column(); $model->andWhere(['in', 'order_id', $ids]); } if (!empty($params['supply_id'])) { $model->andWhere(['supply_id'=>$params['supply_id']]); } $pagination = new Pagination(['totalCount' => $model->count(), 'pageSize' => $limit]); $model->limit($pagination->limit)->offset($pagination->offset); $list = $model->orderBy('created_at desc') ->asArray() ->all(); $model = SupplysModel::find()->select('id,app_name')->where(['mall_id' => $this->mall_id]); $supply_list = $model->indexBy('id')->asArray()->all(); foreach ($list as &$item) { if(!empty($item['order_detail_id'])){ $item['mallOrderDetail'] = OrderDetail::find()->where(['id'=>$item['order_detail_id']])->select('order_id, num, goods_name, pic_url, goods_attr_name')->asArray()->one(); } // 推送状态 $item['status_text'] = OrderEnum::getValue($item['status']) ?? '未知'; $item['supply_name'] = isset($supply_list[$item['supply_id']]) ? $supply_list[$item['supply_id']]['app_name'] : ""; } $data['list'] = $list; $data['page_count'] = $pagination->pageCount; $data['current_page'] = $page + 1; return $data; } /** * 聚合供应链生成订单前置检测 * * @param BaseOrderForm $form 商城订单数据 * @param booleam $is_new_record 是否创建订单 * @return void */ public function createBeforeCheck($form, $is_new_record = false) { $total_price = 0; $order_goods = $form->order_goods; // 获取购买的AttrId foreach ($order_goods as $goods) { $goods_id = $goods['goods_id']; $attr_id = $goods['goods_attr_id']; // 数量 $num = $goods['num']; // 总价 $total_price += $goods['goods_price']; } $sku = GoodsSkuModel::getSku($goods_id, $attr_id); $sku_id = $sku->sku_id; if (empty($sku_id)) { throw new Exception('下单商品SKU不存在,请重新下单'); } // 获取用户收货地址信息 if (empty($extra['address'])) { $address = UserAddress::getOne([['id' => $form['address_id']], ['user_id' => $form['user_id']]], true); $extra['address'] = $address; } else { $address = $extra['address']; } // 订单加上聚合供应链标识 $group_order_goods = $form->group_order_goods; // 未选择地址不进行计算运费 if (!empty($address)) { // 特殊地址处理 $address = static::formatAddress($address); // 提交的地址 $sub_address = [ 'consignee' => $address['name'], 'phone' => $address['mobile'], 'province' => $address['province'], 'city' => $address['city'], 'area' => $address['district'], 'street' => $address['town'], 'description' => $address['detail'], ]; // 获取运费请求参数 $data = [ 'spu' => [ [ 'sku' => $sku_id, 'goods_id' => $goods_id, 'shop_goods_id' => $sku->supply_goods_id, 'number' => intval($num), ] ], 'address' => $sub_address, ]; // 收货人名称过短 if (mb_strlen($address['name']) < static::NAME_MIN_LENGTH && $is_new_record) { throw new Exception('收货人名称过短'); } $api = ApiService::getConnect($this->mall_id, $sku->supply_id); $is_valid = $api->availableCheck($data); if (isset($is_valid['ban']) && $is_new_record) { throw new Exception('下单失败,此商品不支持在当前地区销售'); } // 邮费 $freight = $api->orderBeforeCheck($data); if ($is_new_record && $freight === false) { throw new Exception('下单失败:' . $api->error); } if(!empty($freight['desc'])){ throw new Exception('下单失败:'.$freight['desc']); } $freight_money = $freight['freight'] ?? 0; // 风控检测 $setting = new SettingService(['mall_id' => $this->mall_id]); $result = $setting->checkDanger($total_price, $sku->sku_id, $num, $sku->supply_goods_id, $sku->supply_id); if(!$result) { MallGoodsModel::updateDown($this->mall_id, $goods_id); throw new Exception($setting->error); } // 计算邮费 $freight = $this->getFreight($freight_money); $form->marketing['deduct']['shipping_fee'] = [ 'name' => '运费', 'money' => $freight, ]; foreach ($group_order_goods as $k => &$v) { if ($v['mch_order_info']) { // 标识 $v['mch_order_info']['order_source'] = QiJuheEnum::PLUGIN_SIGN; // 邮费 $v['mch_order_info']['shipping_type'] = ShippingTypeEnum::LOGISTICS; // 默认物流配送 $v['mch_order_info']['shipping_money'] = $freight; // 收货地址 $v['mch_order_info']['province'] = $address['province_id']; $v['mch_order_info']['city'] = $address['city_id']; $v['mch_order_info']['area'] = $address['district_id']; $v['mch_order_info']['town'] = $address['town_id']; $v['mch_order_info']['region_name'] = $address['province'] .' '. $address['city'] .' '. $address['district'].' '.$address['town']; $v['mch_order_info']['address'] = $address['detail']; $v['mch_order_info']['receiver_name'] = $address['name']; $v['mch_order_info']['mobile'] = $address['mobile']; } } // 计算总额 $form['total_pay_money'] = bcadd($form['total_pay_money'], $freight, 2); } $form->group_order_goods = $group_order_goods; return $form; } public function validForm(BaseOrderForm $form, $is_new_record = false) { if ($form->type == 'buy_now') { $order_goods = $form->order_goods; } else { $order_goods = $form->group_order_goods[QiJuheEnum::PLUGIN_SIGN]['goods']; } if (empty($order_goods)) return $form; // 获取用户收货地址信息 if (empty($extra['address'])) { $address = UserAddress::getOne([['id' => $form['address_id']], ['user_id' => $form['user_id']]], true); $extra['address'] = $address; } else { $address = $extra['address']; } $spu_list = []; $total_prices = []; $total_nums = []; $total_sku_nums = []; // 获取购买的AttrId foreach ($order_goods as $goods) { if ($form->type == 'buy_now') { $this->valid($goods['goods_id'], $goods['goods_attr_id'], $goods['num'], $goods, $is_new_record, $spu_list, $total_prices, $total_nums, $total_sku_nums); } else { foreach ($goods['goods_details'] as $goods_detail) { $this->valid($goods_detail['goods_id'], $goods_detail['goods_attr_id'], $goods_detail['num'], $goods_detail, $is_new_record, $spu_list, $total_prices, $total_nums, $total_sku_nums); } } } if (empty($spu_list)) return $form; // 订单加上聚合供应链标识 $group_order_goods = $form->group_order_goods; $free_shopping_total_amount = 0; $free_shopping_goods_ids = []; // 未选择地址不进行计算运费 if (!empty($address)) { $config = (new SettingService(['mall_id' => $form->mall_id]))->getSetting(); $rate = !empty($sell) ? $sell['sell_agreement'] : 1.5; $rate = 1; $shopping_cart_free_amount = !empty($config['shopping_cart_free_amount']) ? $config['shopping_cart_free_amount'] : 59; $shopping_cart_free_amount = bcmul($shopping_cart_free_amount, $rate, 2); $freight_amount = 0; $freight_amount_list = []; // 特殊地址处理 $address = static::formatAddress($address); // 提交的地址 $sub_address = [ 'consignee' => $address['name'], 'phone' => $address['mobile'], 'province' => $address['province'], 'city' => $address['city'], 'area' => $address['district'], 'street' => $address['town'], 'description' => $address['detail'], ]; $sell = null; $source_goods = []; foreach ($spu_list as $supply_id => $i_spu_list) { // 库存检测 self::validStock($form->mall_id, $supply_id, $total_sku_nums[$supply_id]); foreach ($i_spu_list as $source => $spus) { // 获取运费请求参数 $data = [ 'spu' => $spus, 'address' => $sub_address, ]; // 收货人名称过短 if (mb_strlen($address['name']) < static::NAME_MIN_LENGTH && $is_new_record) { throw new Exception('收货人名称过短'); } $api = ApiService::getConnect($this->mall_id, $supply_id); $is_valid = $api->availableCheck($data); if (isset($is_valid['ban']) && $is_new_record) { throw new Exception('下单失败,此商品不支持在当前地区销售'); } // 邮费 $freight = $api->orderBeforeCheck($data); if ($freight === false) { throw new Exception('下单失败:' . $api->error); } if(!empty($freight['desc'])){ throw new Exception('下单失败:'.$freight['desc']); } $freight_money = $freight['freight'] ?? 0; // 风控检测 $setting = new SettingService(['mall_id' => $this->mall_id]); foreach ($spus as $spu) { $result = $setting->checkDanger($total_prices[$supply_id][$source], $spu['sku'], $spu['number'], $spu['shop_goods_id'], $supply_id); if(!$result) { MallGoodsModel::updateDown($this->mall_id, $spu['goods_id']); throw new Exception($setting->error); } // 供应链商品 $s_goods = GoodsModel::findOne(['goods_id' => $spu['shop_goods_id'], 'mall_id' => $form->mall_id]); // 最低购买量 if ($total_nums[$supply_id][$source][$spu['shop_goods_id']] < $s_goods->min_buy_qty) { $l_goods = Goods::findOne(['id' => $spu['goods_id']]); throw new Exception("商品 {$l_goods->goods_name} 起订量 $s_goods->min_buy_qty 件起"); } if ($source == QiJuheEnum::FREE_SHIPPING_SOURCE && $s_goods->source_name == QiJuheEnum::FREE_SHIPPING_SOURCE_NAME) { // 优选供应链的 // if ($source == QiJuheEnum::FREE_SHIPPING_SOURCE) { // 优选供应链的 // $goodsInfo = $api->goodsInfo([$spu['shop_goods_id']]); // if (!empty($goodsInfo[0])) { $free_shopping_total_amount += $total_prices[$supply_id][$source]; // 取协议价 // $free_shopping_goods_ids[] = $spu['goods_id']; // } if (empty($sell)) { $supply = SupplysModel::findOne(['id' => $supply_id]); $sell = Json::decode(!empty($supply->sell) ? $supply->sell : '[]'); } } // 属于哪个供应链 if (empty($source_goods[$source]) || !in_array($spu['goods_id'], $source_goods[$source])) { $source_goods[$source][] = $spu['goods_id']; } } if (!empty($config['is_enable_shopping_cart_settle']) && !empty($free_shopping_total_amount) && $free_shopping_total_amount >= $shopping_cart_free_amount) { $freight_money = 0; // 强制免邮 array_push($free_shopping_goods_ids, ...array_column($spus, 'goods_id')); } $freight_amount_list[QiJuheEnum::PLUGIN_SIGN . $source] = $freight_money ? $this->getFreight($freight_money) : 0; // 计算邮费 $freight_amount += $freight_money ? $this->getFreight($freight_money) : 0; $free_shopping_total_amount = 0; } } // $free_shopping_total_amount = bcmul($free_shopping_total_amount, $rate, 2); $form->marketing['deduct']['shipping_fee'] = [ 'name' => '运费', 'money' => $freight_amount, ]; if ($is_new_record) { // 请求云众的时候需要将子供应链进行拆分 // 从这里拆单 $t_group_order_goods = []; foreach ($group_order_goods as $k => $tv) { if (strpos($k, QiJuheEnum::PLUGIN_SIGN) === 0) { foreach ($tv['goods'] as $goods_id => $good) { foreach ($source_goods as $source => $source_good) { if (in_array($goods_id, $source_good)) { $t_k = "{$k}{$source}"; if (empty($t_group_order_goods[$t_k])) { // 如果有优惠,那么需要怎么处理? $tv['mch_order_info']['pay_money'] = 0; $tv['mch_order_info']['goods_price'] = 0; $tv['mch_order_info']['original_goods_price'] = 0; $t_group_order_goods[$t_k] = [ 'mch_order_info' => $tv['mch_order_info'], 'goods' => [] ]; } foreach ($good['goods_details'] as $goods_detail) { $t_group_order_goods[$t_k]['mch_order_info']['pay_money'] += (float) $goods_detail['goods_price']; $t_group_order_goods[$t_k]['mch_order_info']['goods_price'] += (float) $goods_detail['goods_price']; $t_group_order_goods[$t_k]['mch_order_info']['original_goods_price']+= $goods_detail['original_goods_price']; } $t_group_order_goods[$t_k]['goods'][$goods_id] = $good; } } } } else { $t_group_order_goods[$k] = $tv; } } $group_order_goods = $t_group_order_goods; } foreach ($group_order_goods as $k => &$v) { // 如果是创建,那么就将所有商品合为一个订单 if (($v['mch_order_info'] && strpos($k, QiJuheEnum::PLUGIN_SIGN) === 0) || $form->type == 'buy_now') { // 标识 $v['mch_order_info']['order_source'] = QiJuheEnum::PLUGIN_SIGN; // 邮费 $v['mch_order_info']['shipping_type'] = ShippingTypeEnum::LOGISTICS; // 默认物流配送 $v['mch_order_info']['shipping_money'] = $form->type == 'buy_now' ? $freight_amount : ($freight_amount_list[$k] ?? 0); // 不同运费 // 收货地址 $v['mch_order_info']['province'] = $address['province_id']; $v['mch_order_info']['city'] = $address['city_id']; $v['mch_order_info']['area'] = $address['district_id']; $v['mch_order_info']['town'] = $address['town_id']; $v['mch_order_info']['region_name'] = $address['province'] .' '. $address['city'] .' '. $address['district'].' '.$address['town']; $v['mch_order_info']['address'] = $address['detail']; $v['mch_order_info']['receiver_name'] = $address['name']; $v['mch_order_info']['mobile'] = $address['mobile']; if (!empty($config['is_enable_shopping_cart_settle'])) { $v['mch_order_info']['extra_info'] = Json::encode([ 'mall_info' => [ 'mall_name' => $config['shopping_cart_mall_name'], 'mall_logo' => $config['shopping_cart_mall_logo'], ] ]); foreach ($v['goods'] as $goods_id => $good) { // 判断是否为满包邮 foreach ($good['goods_details'] as $dk => $detail) { // 判断是否需要包邮 if (in_array($goods_id, $free_shopping_goods_ids)) { $free_shipping_deduct_info = ['amount' => 0, 'money' => 0, 'tips' => "满{$shopping_cart_free_amount}包邮", 'name' => "满{$shopping_cart_free_amount}包邮", 'ids' => $free_shopping_goods_ids];//积分抵扣信息 if (empty($detail['marketing']['deduct_currency'])) { $deduct_currency = ['free_shipping' => $free_shipping_deduct_info]; } else { $deduct_currency = Json::decode($detail['marketing']['deduct_currency'], true); $deduct_currency['free_shipping'] = $free_shipping_deduct_info; } $v['goods'][$goods_id]['goods_details'][$dk]['marketing']['deduct_currency'] = Json::encode($deduct_currency); } } } } } } // 计算总额 $form['total_pay_money'] = bcadd($form['total_pay_money'], $freight_amount, 2); } $form = $form->toArray(); $form['group_order_goods'] = array_values($group_order_goods); return $form; } protected function valid($goods_id, $attr_id, $num, $goods, $is_new_record, &$spu_list, &$total_prices, &$total_nums, &$total_sku_nums) { $sku = GoodsSkuModel::getSku($goods_id, $attr_id); if (empty($sku)) { throw new Exception('下单商品SKU不存在,请重新下单: ' . $attr_id); } $t_goods = GoodsModel::findOne(['goods_id' => $sku->supply_goods_id, 'mall_id' => $sku->mall_id]); // 总价 if (empty($total_prices[$sku->supply_id][$t_goods->source])) $total_prices[$sku->supply_id][$t_goods->source] = 0; $total_prices[$sku->supply_id][$t_goods->source] += $goods['goods_price']; if (empty($spu_list[$sku->supply_id][$t_goods->source])) $spu_list[$sku->supply_id][$t_goods->source] = []; $spu_list[$sku->supply_id][$t_goods->source][] = [ 'sku' => $sku->sku_id, 'goods_id' => $goods_id, 'shop_goods_id' => $sku->supply_goods_id, 'number' => intval($num), ]; // 累加数量 if (empty($total_nums[$sku->supply_id][$t_goods->source][$sku->supply_goods_id])) $total_nums[$sku->supply_id][$t_goods->source][$sku->supply_goods_id] = 0; $total_nums[$sku->supply_id][$t_goods->source][$sku->supply_goods_id] += intval($num); $total_sku_nums[$sku->supply_id][$sku->supply_goods_id][$sku->sku_id] = intval($num); } protected static function validStock(int $mall_id, int $supply_id, array $third_goods_ids) { $ids = array_keys($third_goods_ids); $api = ApiService::getConnect($mall_id, $supply_id); $resp = $api->goodsInfo($ids); if (!empty($api->error)) throw new Exception($api->error); if (empty($resp) || count($resp) < count($ids)) throw new Exception('商品不存在'); foreach ($resp as $item) { foreach ($item['skus'] as $sku) { if ($third_goods_ids[$item['id']][$sku['id']] > $sku['stock']) { throw new Exception("{$item['title']} - {$sku['title']} 库存不足"); } } } } public static function createOrderV2($order_id) { // 订单详情 $order = MallOrderModel::getOrder($order_id); if ($order && $order->order_source != QiJuheEnum::PLUGIN_SIGN && $order->order_source != AddonsEnum::ADDONS_NAME_CARD_COUPONS) return false; if (!$order->pay_status == StatusEnum::ENABLED) return false; if (empty($order->detail)) return false; foreach ($order->detail as $detail) { if($order->order_source == AddonsEnum::ADDONS_NAME_CARD_COUPONS) { $goods = Goods::findOne($detail->goods_id); if(!$goods || $goods['goods_source'] != QiJuheEnum::PLUGIN_SIGN) continue; } // skuId $sku = GoodsSkuModel::getSku($detail->goods_id, $detail->goods_attr_id); if (empty($sku)) return false; // 聚合商品信息 $supply_goods = GoodsModel::find()->where(['goods_id' => $sku->supply_goods_id])->select('goods_id, supply_id, source')->one(); if (empty($supply_goods)) return false; // 以平台分类 $supply_orders[$sku->supply_id][] = [ 'sku' => $sku->sku_id, 'number' => intval($detail->num), 'goods_id' => $supply_goods->goods_id, 'source' => $supply_goods->source, 'order_detail_id' => $detail['id'], ]; } if (empty($supply_orders)) return false; $sku_arr = []; $order_model_arr = []; foreach ($supply_orders as $supply_id => $skus) { // 接口 $api = ApiService::getConnect($order->mall_id, $supply_id); foreach ($skus as $sku) { // 创建订单 $order_model = new OrderModel(); $order_model->supply_id = $supply_id; $order_model->user_id = $order->user_id; $order_model->order_no = $order->order_no; $order_model->order_id = $order_id; $order_model->order_detail_id = $sku['order_detail_id']; $order_model->goods_id = $sku['goods_id']; $order_model->source = strval($sku['source']); $order_model->mall_id = $order->mall_id; $order_model->sku_id = $sku['sku']; $order_model->created_at = $order_model->updated_at = time(); if (!$order_model->save()) { throw new Exception("聚合供应链订单:{$order->order_no}生成失败"); return false; } $order_model_arr[] = $order_model; // spu $sku_arr[] = [ 'sku' => $sku['sku'], 'number' => intval($sku['number']), ]; } } // 地址 $region = explode(' ', $order->region_name); $address = [ 'province' => $region[0], 'city' => $region[1], 'district' => $region[2], 'town' => $region[3], ]; // 格式化地址 $address = static::formatAddress($address); // 提交的地址 $sub_address = [ 'consignee' => $order->receiver_name, 'phone' => $order->mobile, 'province' => $address['province'], 'city' => $address['city'], 'area' => $address['district'], 'street' => $address['town'], 'description' => $order->address, ]; $data = [ 'order_sn' => $order->order_no, 'spu' => $sku_arr, 'address' => $sub_address, 'remark' => !empty($order->remark) ? $order->remark : '', ]; // 收货人名称过短 if (mb_strlen($order->receiver_name) < static::NAME_MIN_LENGTH) { throw new Exception('收货人名称过短'); } // 保留api提交数据 OrderModel::updateAll(['order_json'=>Json::encode($data)],['order_no'=>$order->order_no]); // 推送订单 $result = $api->createOreder($data); if (!$result) { // 修改状态 foreach($order_model_arr as $order_model){ $order_model->pushFail($api->error); } // 队列执行 // Yii::$app->services->rabbitMq->push(RabbitMqEnum::EXCHANGE_TASK, RabbitMqEnum::TASK_QUEUE, [ // 'mall_id' => $order->mall_id, // ], OrderFailListener::class, 'async_handle'); throw new Exception("聚合供应链订单:{$order->order_no}推送失败"); } // 推送成功修改状态 // $order_data = $api->getOrderInfo($order->order_no); foreach($order_model_arr as $order_model){ $res = $order_model->payOk('', $result); if (!$res) { throw new Exception("聚合供应链订单:{$order->order_no}修改成功状态失败"); } } } /** * 创建聚合订单 * * @param integer $order_id 订单ID * @param string $order_sn 订单编号 * @return void */ public static function createOrder($order_id/* , $order_no */) { // 订单详情 $order = MallOrderModel::getOrder($order_id); if ($order && $order->order_source != QiJuheEnum::PLUGIN_SIGN && $order->order_source != AddonsEnum::ADDONS_NAME_CARD_COUPONS) return false; if (!$order->pay_status == StatusEnum::ENABLED) return false; if (empty($order->detail)) return false; foreach ($order->detail as $detail) { if($order->order_source == AddonsEnum::ADDONS_NAME_CARD_COUPONS) { $goods = Goods::findOne($detail->goods_id); if(!$goods || $goods['goods_source'] != QiJuheEnum::PLUGIN_SIGN) continue; } // skuId $sku = GoodsSkuModel::getSku($detail->goods_id, $detail->goods_attr_id); if (empty($sku)) return false; // 聚合商品信息 $supply_goods = GoodsModel::find()->where(['goods_id' => $sku->supply_goods_id])->select('goods_id, supply_id, source')->one(); if (empty($supply_goods)) return false; // 以平台分类 $supply_orders[$sku->supply_id][] = [ 'sku' => $sku->sku_id, 'number' => intval($detail->num), 'goods_id' => $supply_goods->goods_id, 'source' => $supply_goods->source, 'order_detail_id' => $detail['id'], ]; } if (empty($supply_orders)) return false; foreach ($supply_orders as $supply_id => $skus) { // 接口 $api = ApiService::getConnect($order->mall_id, $supply_id); $order_model_arr = []; $sku_arr = []; foreach ($skus as $sku) { // 创建订单 $order_model = new OrderModel(); $order_model->supply_id = $supply_id; $order_model->user_id = $order->user_id; $order_model->order_no = $order->order_no; $order_model->order_id = $order_id; $order_model->order_detail_id = $sku['order_detail_id']; $order_model->goods_id = $sku['goods_id']; $order_model->source = strval($sku['source']); $order_model->mall_id = $order->mall_id; $order_model->sku_id = $sku['sku']; $order_model->created_at = $order_model->updated_at = time(); if (!$order_model->save()) { throw new Exception("聚合供应链订单:{$order->order_no}生成失败"); return false; } $order_model_arr[] = $order_model; // spu $sku_arr[] = [ 'sku' => $sku['sku'], 'number' => intval($sku['number']), ]; } // 地址 $region = explode(' ', $order->region_name); $address = [ 'province' => $region[0], 'city' => $region[1], 'district' => $region[2], 'town' => $region[3], ]; // 格式化地址 $address = static::formatAddress($address); // 提交的地址 $sub_address = [ 'consignee' => $order->receiver_name, 'phone' => $order->mobile, 'province' => $address['province'], 'city' => $address['city'], 'area' => $address['district'], 'street' => $address['town'], 'description' => $order->address, ]; $data = [ 'order_sn' => $order->order_no, 'spu' => $sku_arr, 'address' => $sub_address, ]; // 收货人名称过短 if (mb_strlen($order->receiver_name) < static::NAME_MIN_LENGTH) { throw new Exception('收货人名称过短'); } // 保留api提交数据 OrderModel::updateAll(['order_json'=>Json::encode($data)],['order_no'=>$order->order_no]); // 推送订单 $result = $api->createOreder($data); if (!$result) { // 修改状态 foreach($order_model_arr as $order_model){ $order_model->pushFail($api->error); } // 队列执行 // Yii::$app->services->rabbitMq->push(RabbitMqEnum::EXCHANGE_TASK, RabbitMqEnum::TASK_QUEUE, [ // 'mall_id' => $order->mall_id, // ], OrderFailListener::class, 'async_handle'); throw new Exception("聚合供应链订单:{$order->order_no}推送失败"); } // 推送成功修改状态 // $order_data = $api->getOrderInfo($order->order_no); foreach($order_model_arr as $order_model){ $res = $order_model->payOk('', $result); if (!$res) { throw new Exception("聚合供应链订单:{$order->order_no}修改成功状态失败"); } } } } /** * 聚合平台交易完成(淘宝 jd确认收货 订单完成了) * 目前不需要修改系统订单状态,使用系统自带的收货完成 * * @param string $order_no * @return void */ public function orderSuccess($order_no) { $juhe_order = OrderModel::findOne(['order_no' => $order_no, 'mall_id' => $this->mall_id]); if(empty($juhe_order)) { } $mall_order = MallOrderModel::findOne(['order_no' => $order_no, 'mall_id' => $this->mall_id]); if(empty($sys_order)) { } } /** * 用户确认收货 * * @param string $order_no * @return void */ public static function orderDelivered($order_id) { $juhe_order = OrderModel::find()->where(['order_id' => $order_id])->select('id, mall_id, supply_id, order_data')->one(); if (empty($juhe_order)) { return false; } $data = Json::decode($juhe_order->order_data); if (empty($data['Orders'])) { return false; } $api = ApiService::getConnect($juhe_order->mall_id, $juhe_order->supply_id); foreach ($data['Orders'] as $order) { $res = $api->orderReceive($order['id']); } } /** * 商家发货 * * @param string $order_no * @param integer $sku * @return void */ public function orderDelivery($order_no, $sku) { $juhe_order = OrderModel::findOne(['order_no' => $order_no, 'mall_id' => $this->mall_id]); if(empty($juhe_order)) { throw new Exception("聚合供应链订单{$order_no}不存在"); } $mall_order = MallOrderModel::find()->where(['order_no' => $order_no, 'mall_id' => $this->mall_id])->select('id')->one(); if(empty($mall_order)) { throw new Exception("商城订单{$order_no}不存在"); } $res = MallOrderModel::delivery(['mall_id' => $this->mall_id, 'id' => $mall_order->id]); if ($res === false) { throw new Exception("商城订单商家发货{$order_no}" . MallOrderModel::$static_error); } } /** * 订单转换成普通订单 * * @param integer $id * @return boolean */ public function changeOrder(int $id) { $order = OrderModel::findOne(['id' => $id, 'mall_id' => $this->mall_id]); if (empty($order)) return $this->error('订单不存在'); /** * @var MallOrderModel|null */ $mall_order = $order->mallOrder; if (empty($mall_order)) return $this->error('商城订单不存在'); return $mall_order->changeOrder(); } /** * 批量补单 * * @param array $ids * @return void */ public function patchOrder(array $ids) { $error = []; $success = []; try { $juhe_order = OrderModel::find()->with('mallOrder')->where(['id' => $ids])->all(); if (empty($juhe_order)) { throw new Exception('订单不存在'); } foreach ($juhe_order as $order) { // 订单状态 if (!in_array($order->status, [OrderEnum::PUSH_NOT, OrderEnum::PUSH_FAIL])) { $error[] = [ 'order_no' => $order->order_no, 'msg' => '订单状态不正常', ]; continue; } // 不是待发货状态,不允许补单 if ($order->mallOrder->status != OrderStatusEnum::PAY || $order->mallOrder->is_feedback != OrderStatusEnum::NOT_FEEDBACK) { $error[] = [ 'order_no' => $order->order_no, 'msg' => '订单未付款或者正在售后~', ]; continue; } $api = ApiService::getConnect($order->mall_id, $order->supply_id); // 接口没有批量补单 $result = $api->createOreder(Json::decode($order->order_json)); if (!$result) { $order->pushFail($api->error); $error[] = [ 'order_no' => $order->order_no, 'msg' => $order->order_no.'【'.$api->error.'】', ]; continue; } // 补单成功 $order->payOk('', $result); $success[] = [ 'order_no' => $order->order_no, 'msg' => '成功', ]; } } catch (Exception $e) { $error[] = $e->getMessage(); } return compact('success', 'error'); } /** * 计算聚合供应链邮费 * * @param array $juhe_money 聚合供应链返回邮费数据 * @return mixed */ protected function getFreight($money) { if($money <= 0) return 0; return bcdiv($money, 100, 2); } /** * 中台发货,更新物流信息 * @param $order_sn */ public function updateLogistic($order_sn) { $orders = OrderModel::find() ->where(['order_no'=>$order_sn]) // ->with(['mallOrder' => function ($q) { // return $q->select('id')->with(['detail' => function ($q) { // return $q->select('id, order_id,goods_id'); // }]); // }]) ->select('id, mall_id, order_no, order_id, supply_id,goods_id,order_detail_id') ->all(); if(empty($orders)) return true; $order_list = []; foreach($orders as $order_item){ $order_list[$order_item['supply_id']][] = $order_item; } foreach($order_list as $supply_id => $orders){ $this->mall_id = $orders[0]['mall_id']; // 获取物流信息 $api = ApiService::getConnect(['mall_id' => $this->mall_id, 'supply_id' => $supply_id]); $logistic = $api->orderLogistic($order_sn); try { if(empty($logistic)) throw new \Exception("获取物流信息异常"); foreach($logistic as $express_order){ $params = $this->getExpressParams($orders, $express_order); \Yii::$app->custom->logs('物流信息: ' . json_encode($params)); $res = OrderExpress::delivery($params); if ($res === false) { // 这里选择不抛出错误(因为如果有多个发货,假设第一个已经发货就会进入来这里,抛出错误后导致其他的也发不了) $errorMsg = '商家已发货:' . 'OrderExpress::delivery订单发货失败: ' . OrderExpress::$static_error . ', 位于File:' . __FILE__ . ', 位于Line:' . __LINE__ . ', 参数:' . json_encode($params ?? []) . $order_sn; Yii::error($errorMsg); // throw new Exception('OrderExpress::delivery订单发货失败: ' . OrderExpress::$static_error); } } return true; } catch (Exception $e) { $errorMsg = '商家已发货:' . $e->getMessage() . ', 位于File:' . $e->getFile() . ', 位于Line:' . $e->getLine() . ', 参数:' . json_encode($params ?? []) . $order_sn; Yii::error($errorMsg); return false; } } } /** * 获取物流信息 * * @param OrderModel $order * @param array $logistic * @return array */ private function getExpressParams($orders, $express_order) { $params = []; $code = $express_order['company_code']; $express = ExpressModel::getExpress($code); if (!empty($express_order['order_items'])) { $params['id'] = $orders[0]['order_id']; foreach ($orders as $order) { foreach($express_order['order_items'] as $order_item){ if($order_item['product_id'] == $order->goods_id){ $params['order_detail_ids'][] = $order->order_detail_id; } } } $params['order_detail_ids'] = array_unique($params['order_detail_ids']); $params['shipping_type'] = 0; if (!empty($express)) { $params['shipping_type'] = 1; $params['express_id'] = $express->express_id; $params['express_name'] = $express->name; // 判断是否是顺丰物流,顺丰物流返回格式=SF1632145481624:5419,需要做切割处理 if (strpos($express_order['express_no'], ':') !== false) { $arr_express_no = explode(':', $express_order['express_no']); $express_order['express_no'] = current($arr_express_no); } $params['express_no'] = $express_order['express_no']; } $params['mall_id'] = $this->mall_id; $params['mch_id'] = 0; $params['operator_id'] = 0; $params['operator_name'] = ''; } return $params; } /** * 格式化部分区域地址 * * @param array $address * @return array */ protected static function formatAddress(array $address) { if ($address['city'] == '东莞市') { $address['town'] = $address['district']; $address['district'] = $address['city']; } if ($address['city'] == '中山市') { $address['town'] = $address['district']; $address['district'] = $address['city']; } if (($address['city'] == '长沙市') && ($address['district'] == '宁乡县')) { $address['district'] = '宁乡市'; } return $address; } }