50], [['express_name', 'customer_name'], 'string', 'max' => 100], ]; } /** * {@inheritdoc} */ public function attributeLabels() { return [ 'id' => 'ID', 'mall_id' => 'Mall ID', 'order_express_id' => 'qimall_order_express对应id', 'express_no' => '运单编号', 'express_id' => '快递公司id', 'express_name' => '物流公司名称', 'customer_name' => '京东物流编号', 'express_code' => '物流公司编码', 'order_id' => '订单id', 'table_express_status' => '物流状态0/未完成 1/已完成', 'express_status' => '当前物流状态(物流公司状态)', 'status' => '状态[-1:删除;0:禁用;1启用]', 'list' => '物流具体轨迹信息', 'created_at' => '创建时间', 'updated_at' => '更新时间', ]; } protected static function order(array $params) { try { $params['where'] = [['order_id' => $params['order_id'],'status' => StatusEnum::ENABLED]]; $express_list = OrderExpress::lists($params); $pic_urls = OrderDetail::lists(['select' => ['pic_url', 'id'], 'where' => [['order_id' => $params['order_id']]]]); $list = []; $pic = []; $order_detail_ids = []; if ($pic_urls) { foreach ($pic_urls as $key) { $pic[$key['id']] = $key['pic_url']; } } if ($express_list) { foreach ($express_list as $k) { $order_detail_ids[$k['id']] = json_decode($k['order_detail_ids'], true); } $express_ids = array_column($express_list, 'id'); $list = OrderExpressLog::lists(['where' => [['in', 'order_express_id', $express_ids]]]); if (!is_null($list)) { $time = time(); $hour = Yii::$app->services->setting->mall->get($params['mall_id'], 'logistics.update');// 获取更新物流时间设置 if (empty($hour) && is_array($hour)) $hour = 8;// 默认8小时更新一次 foreach ($list as &$item) { $item['pic_url'] = ''; $now_express_id = $order_detail_ids[$item['order_express_id']] ?? []; foreach ($now_express_id as $keys) { $item['pic_url'] = isset($pic[$keys]) ? $pic[$keys] : ''; } $item['status'] = ExpressEnum::getStatusMap($item['express_status']); // unset($item['order_express_id']); // unset($item['order_id']); // 检查物流是否已完成,未完成且距离上次修改时间超过一个小时 if ($item['table_express_status'] == StatusEnum::DISABLED && $item['updated_at'] + $hour * 3600 < $time) { $params['express_status'] = $item['express_status']; $item['list'] = OrderExpressLog::execExpressLog($params['mall_id'], $item); } unset($item['express_status']); $item['list'] = json_decode($item['list'], true); // 因为七件事订单物流和快递鸟数据不一致,所以需要处理 $request_type = Yii::$app->services->setting->mall->get($params['mall_id'], 'logistics.request_type'); if ($request_type == 1) { // 如果是快递鸟需要倒序 if ($item['list']['Traces']) { $item['list']['Traces'] = array_reverse($item['list']['Traces']); } } } } } } catch (\Exception $e) { $list = []; } return $list; } protected static function cloudStock($params) { try { $list = OrderExpressLog::lists(['where' => [['cs_order_id' => $params['order_id']]]]); if (!is_null($list)) { $time = time(); $hour = Yii::$app->services->setting->mall->get($params['mall_id'], 'logistics.update');// 获取更新物流时间设置 if (empty($hour) && is_array($hour)) $hour = 8;// 默认8小时更新一次 $cOrder = CloudStockAgentOrder::getOne([ ['id' => $params['order_id']] ], true, ['goods']); foreach ($list as &$item) { $item['pic_url'] = $cOrder['goods']['cover_pic'] ?? ''; $item['goods_name'] = $cOrder['goods']['goods_name'] ?? ''; $item['num'] = $cOrder['num']; $item['status'] = ExpressEnum::getStatusMap($item['express_status']); unset($item['order_express_id']); unset($item['order_id']); // 检查物流是否已完成,未完成且距离上次修改时间超过一个小时 if ($item['table_express_status'] == StatusEnum::DISABLED && $item['updated_at'] + $hour * 3600 < $time) { $params['express_status'] = $item['express_status']; $item['list'] = OrderExpressLog::execExpressLog($params['mall_id'], $item); } unset($item['express_status']); $item['list'] = json_decode($item['list'], true); if ($item['list']['Traces']) { $item['list']['Traces'] = array_reverse($item['list']['Traces']); } } } } catch (\Exception $e) { $list = []; } return $list; } /** * 获取物流轨迹 * User: wniu * Date: 2021/10/12 * Time: 5:36 下午 * @param $params * @return array */ public static function getExpressLog($params): array { if (!empty($params['type']) && $params['type'] == AddonsEnum::ADDONS_NAME_CLOUD_STOCK) { return self::cloudStock($params); } return self::order($params); } /** * 保存物流轨迹记录 * User: wniu * Date: 2021/10/13 * Time: 5:04 下午 * * * @param $params * @param false $is_update * @return bool */ public static function saveLog($params, bool $is_update = false): bool { unset($params['status']); if ($is_update) { $where[] = ['order_express_id' => $params['id']]; $order_express_log = self::getOne($where); if (empty($order_express_log) && $params['shipping_type'] != StatusEnum::ENABLED) return true; //如果没有物流轨迹信息,需新增 if (empty($order_express_log)){ $order_express_log = new self(); $order_express_log->order_express_id = $params['id']; $order_express_log->order_id = OrderExpress::find() ->select('order_id') ->where(['id' => $params['id']]) ->scalar(); } if ($order_express_log->express_id != $params['express_id']) { $params['express_code'] = self::getExpressCode($params['express_id']); } if (!$order_express_log->load($params, '') || !$order_express_log->save()) throw new \Exception($order_express_log::getStaticError()); } else { if ($params['shipping_type'] == 1) { $params['express_code'] = self::getExpressCode($params['express_id']); $order_express_log = new self(); if (!$order_express_log->load($params, '') || !$order_express_log->save()) throw new \Exception($order_express_log::getStaticError()); } } return true; } /** * 获取物流code码 * User: wniu * Date: 2021/10/13 * Time: 5:04 下午 * * * @param $express_id * @return mixed */ public static function getExpressCode($express_id) { $where[] = ['id' => $express_id]; $express_code = Express::getOne($where, false, [], false, 'code'); return $express_code->code; } /** * 更新物流轨迹信息 * User: wniu * Date: 2021/10/14 * Time: 3:23 下午 * * @throws InvalidArgumentException */ public static function updateExpressLog() { try { $mall_list = \common\models\mall\Mall::getEnableMallList(); foreach ($mall_list as $mall) { $mall_id = $mall['id']; $express_account['kdn_business_iD'] = MallSetting::conf($mall_id, 'logistics.kdniao_mch_id'); $express_account['kdn_app_key'] = MallSetting::conf($mall_id, 'logistics.kdniao_api_key'); $express_account['kdn_request_type'] = MallSetting::conf($mall_id, 'logistics.kdniao_request_type'); $part = 1; $limit = 200; //测试 -start // $express_account['kdn_business_iD'] = '1757494'; // $express_account['kdn_app_key'] = '49533209-91e9-4cb7-a55d-232169a6a91d'; // $params = []; // $part_where = [['=', 'mall_id', $mall_id], ['=', 'table_express_status', ExpressEnum::TABLE_EXPRESS_WAIT]]; // $part_data = self::batchGetExpressLog($params, $part, $limit); // self::updateLog($part_data, $express_account); //测试 -end $select = "id,mall_id,order_id,express_no,customer_name,express_code,express_id"; $part_where = [['=', 'mall_id', $mall_id], ['=', 'status', StatusEnum::ENABLED], ['=', 'table_express_status', ExpressEnum::TABLE_EXPRESS_WAIT]]; $params = ['where' => $part_where, 'select' => $select]; while ($part_data = self::batchGetExpressLog($params, $part, $limit)) { if ($part_data) { self::updateLog($part_data, $express_account); } $part++; } } return true; } catch (\Exception $e) { $exception = FormatHelper::exception($e, "物流更新"); Yii::error($exception); self::setStaticError($exception); return false; } } /** * 分片查询 * @Author: lun * @DateTime: 2021/12/4 0004 10:21 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $params * @param $user_id * @param $offset * @param $limit * @return bool|mixed */ public static function batchGetExpressLog($params, $part, $limit) { $params['offset'] = ($part - 1) * $limit; $params['limit'] = $limit; return self::lists($params, false); } /** * @throws \Flex\Express\Exceptions\HttpException * @throws \Flex\Express\Exceptions\InvalidArgumentException */ public static function updateLog($part_data, $express_account) { try { foreach ($part_data as $item) { //顺丰快递,需提供手机后4位 if ($item->express_code == "SF") { $phone = Order::getOne([['id' => $item->order_id]], true, '', '', 'mobile'); if (!$phone) { continue; } $item['customer_name'] = "'" . mb_substr($phone['mobile'], 0 - 4) . "'"; } $new_data = LogisticsSearch::getExpressBird($item, $express_account); if ($new_data) { $new_data->updated_at = time(); $new_data->save(); } } return true; } catch (\Exception $e) { Yii::error('物流更新任务处理出错:' . $e->getMessage()); self::setStaticError($e->getMessage()); return false; } } /** * 物流信息获取 - 每条数据每隔N个小时才能获取一次 * @Author: lun * @DateTime: 2022/7/25 0025 15:18 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $params * @throws \Flex\Express\Exceptions\HttpException * @throws \Flex\Express\Exceptions\InvalidArgumentException */ public static function execExpressLog($mall_id, $express) { try { // 获取物流配置 $express_config = Yii::$app->services->setting->mall->get($mall_id,'logistics'); if ($express_config['kdniao_request_type'] == 3) { // 阿里云 if (MallAddons::isInstall($mall_id, AddonsEnum::ADDONS_NAME_LOGISTICS)) { $lExpress = ExpressService::getCode($express['express_id']); if (!empty($lExpress)) { if (in_array($lExpress->code, ['SFEXPRESS', 'ZTO'])) { $phone = Order::getOne([['id' => $express['order_id']]], true, '', '', 'mobile'); if ($phone) $phone = mb_substr($phone['mobile'], 0 - 4); } $new_express = LogisticsSearch::getExpressAliyun([ 'mall_id' => $mall_id, 'type' => $lExpress->code, 'no' => $express['express_no'] . (!empty($phone) ? ":{$phone}" : ''), 'id' => $express['id'] ]); if (!$new_express) { $new_express['list']['err'] = LogisticsSearch::getStaticError(); $new_express['list']['Traces'] = []; } } else { $new_express['list']['err'] = '快递公司未匹配物流接入插件快递公司'; $new_express['list']['Traces'] = []; } } else { $new_express['list']['err'] = '未安装物流接入插件'; $new_express['list']['Traces'] = []; } if (is_array($new_express['list'])) $new_express['list'] = Json::encode($new_express['list']); } else { //顺丰快递、中通快递,需提供手机后4位 $expressCode = ['SF', 'ZTO']; if (in_array($express['express_code'], $expressCode)) { $phone = Order::getOne([['id' => $express['order_id']]], true, '', '', 'mobile'); if ($phone) $express['customer_name'] = mb_substr($phone['mobile'], 0 - 4); } // 获取物流信息 $new_express = LogisticsSearch::getExpressBird($express, $express_config); } // 修改物流信息 self::updateAll([ 'list' => $new_express['list'], 'express_status' => $new_express['express_status'] ?? 0, 'table_express_status' => $new_express['table_express_status'] ?? 0, 'updated_at' => time() ], ['id' => $express['id']]); $event = new UpdateExpressLogEvent($mall_id); Yii::$app->services->events->dispatch($event,['id'=>$new_express['id']], $event->listeners); return $new_express['list']; } catch (\Exception $e) { Yii::error($e->getMessage()); self::setStaticError($e->getMessage()); return false; } } }