ANG YU 5 лет назад
Родитель
Сommit
ddcfedba1a

+ 113 - 22
app/Services/LogisticQiaoSFService.php

@@ -4,6 +4,8 @@
 namespace App\Services;
 
 
+use Exception;
+use Illuminate\Http\Client\Response;
 use Illuminate\Support\Facades\Http;
 
 class LogisticQiaoSFService
@@ -20,10 +22,11 @@ class LogisticQiaoSFService
 
     /**
      * 获取顺丰快递揽收数据
-     * @param $logisticNums [logisticNums]快递单号数组
+     * @param array $logisticNums [logisticNums]快递单号数组
      * @return array 快递揽收信息数组
+     * @throws Exception 未知的丰桥opCode
      */
-    public function get($logisticNums): array
+    public function get(array $logisticNums): array
     {
         // 将$logisticNums以10个位单位进行分割,返回二维数组
         $logisticNums_size_10 = array_chunk($logisticNums, config('api_logistic.SF.max_size', 10));
@@ -44,22 +47,16 @@ class LogisticQiaoSFService
      * @param string $checkWord 客户秘钥
      * @param string $url 顺丰接口地址
      * @return array
+     * @throws Exception 未知的丰桥opCode
      */
     public function getResultFromSF(string $head, string $numbers, string $checkWord, string $url): array
     {
-        $xml = $this->buildXmlStr($head, $numbers);
-        $checkingJson = $xml . $checkWord;
-        $verifyCode = base64_encode(md5($checkingJson, true));
-        $response = Http::withHeaders(['Content-Type' => 'text/xml'])->get($url, ['xml' => $xml, 'verifyCode' => $verifyCode]);
-
-        $routeResponses = get_object_vars(simplexml_load_string($response)->Body)['RouteResponse'];
+        $responseBody = get_object_vars(simplexml_load_string($this->sendHttpToSF($head, $numbers, $checkWord, $url))->Body)['RouteResponse'];
         $result = [];
-        if (is_array($routeResponses)) {
-            foreach ($routeResponses as $routeResponse) {
-                $result[] = $this->buildData(get_object_vars($routeResponse), []);
-            }
+        if (is_array($responseBody)) {//SF返回多个单号的查询结果
+            $result = $this->transformSFMoreToArr($responseBody, $result);
         } else {
-            $result[] = $this->buildData(get_object_vars($routeResponses), []);
+            $result[] = $this->transformSFOneToArr(get_object_vars($responseBody), []);
         }
         return $result;
     }
@@ -70,7 +67,7 @@ class LogisticQiaoSFService
      * @param string $number
      * @return string
      */
-    public function buildXmlStr(string $head, string $number): string
+    private function buildXmlStr(string $head, string $number): string
     {
         return <<<xml
 <?xml version="1.0" encoding="utf-8" ?>
@@ -86,23 +83,117 @@ xml;
     }
 
     /**
-     * 将顺丰数据转换为数组
+     * 将单个单号的顺丰数据转换为数组
      * @param array $routeResponse
      * @param array $data
      * @return array
+     * @throws Exception
      */
-    public function buildData(array $routeResponse, array $data): array
+    public function transformSFOneToArr(array $routeResponse, array $data): array
     {
         $data['logistic_number'] = $routeResponse['@attributes'][$this->protected_switch['logistic_number']];
-        foreach ($routeResponse['Route'] as $route) {
+        $lastRoute = get_object_vars($routeResponse['Route'][count($routeResponse['Route']) - 1])['@attributes'];//获取最新的路由信息
+        $data = $this->switchOpCodeToStatus($lastRoute, $data);
+        $data['transfer_status'] = $this->transformRoutes($routeResponse['Route']);
+        return $data;
+    }
+
+    /**
+     * 转换快递路由信息
+     * @param array $routs 快递路由
+     * @return array
+     */
+    public function transformRoutes(array $routs): array
+    {
+        $result = [];
+        foreach ($routs as $route) {
             $route = get_object_vars($route)['@attributes'];
-            if ($route['opcode'] == config('api_logistic.SF.received_code', 50)) {
+            $data['accept_time'] = $route['accept_time'];
+            $data['accept_address'] = $route['accept_address'];
+            $data['remark'] = $route['remark'];
+            $result[] = $data;
+        }
+        return $result;
+    }
+
+    /**
+     * 将最新路由信息转换为数组
+     * @param array $lastRoute
+     * @param array $data
+     * @return array
+     * @throws Exception
+     */
+    public function switchOpCodeToStatus(array $lastRoute, array $data): array
+    {
+        switch ($lastRoute['opcode']) {
+            case 123:
+            case 130:
+            case 3036:
+            case 31:
+            case 30:
+                $data['status'] = '在途';
+                break;
+            case 70:
+            case 33:
+                $data['status'] = '派送异常';
+                $data['exception'] = '是';
+                break;
+            case 204:
+            case 44:
+                $data['status'] = '派送中';
+                break;
+            case 50:
                 $data['status'] = '已揽收';
-                $data['transfer_status'] = $route[$this->protected_switch['transfer_status']];
-                $data['received_at'] = $route[$this->protected_switch['received_at']];
-                continue;
-            }
+                break;
+            case 607:
+            case 8000:
+            case 80:
+                $data['status'] = '已收件';
+                $data['received_at'] = $lastRoute[$this->protected_switch['received_at']];
+                break;
+            case 648:
+            case 99:
+                $data['status'] = '返回中';
+                break;
+            default:
+                throw new Exception("未知的丰桥状态码: " . $lastRoute['opcode'] . '->' . json_encode($lastRoute));
         }
         return $data;
     }
+
+    /**
+     * @param string $head
+     * @param string $numbers
+     * @param string $checkWord
+     * @param string $url
+     * @return Response
+     * @throws Exception
+     */
+    public function sendHttpToSF(string $head, string $numbers, string $checkWord, string $url): Response
+    {
+        $xml = $this->buildXmlStr($head, $numbers);
+        $checkingJson = $xml . $checkWord;
+        $verifyCode = base64_encode(md5($checkingJson, true));
+        try {
+            $response = Http::withHeaders(['Content-Type' => 'text/xml'])->get($url, ['xml' => $xml, 'verifyCode' => $verifyCode]);
+        } catch (Exception $e) {
+            throw new Exception("HTTP请求顺丰接口异常" . '->' . $e->getMessage());
+        }
+        return $response;
+    }
+
+    /**
+     * 将多个顺丰的单号转换为数组
+     * @param array $responseBody
+     * @param array $result
+     * @return array
+     * @throws Exception
+     */
+    public function transformSFMoreToArr(array $responseBody, array $result): array
+    {
+        foreach ($responseBody as $routeResponse) {
+            $result[] = $this->transformSFOneToArr(get_object_vars($routeResponse), []);
+        }
+        return $result;
+    }
 }

+ 2 - 1
config/api_logistic.php

@@ -21,6 +21,7 @@ return [
             99 => '应客户要求,快件正在转寄中',
             648 => '快件已退回/转寄,新单号为: XXX,快件正在转寄中',
         ],
-        'received_code' => 50,
+        'received_code' => 80,
+        'error_code' => 33,
     ],
 ];

+ 3 - 3
database/migrations/2020_12_16_114253_add_status_and_sent_and_at_and_received_at_and_execption_and_tarnsfer_status_and_remark_to_order_package.php

@@ -15,11 +15,11 @@ class AddStatusAndSentAndAtAndReceivedAtAndExecptionAndTarnsferStatusAndRemarkTo
     {
         Schema::table('order_packages', function (Blueprint $table) {
             //
-            $table->enum('status',['无','已称重','已揽收','在途','在途异常','派送中','派送异常','返回中','返回异常','返回派件','其他异常'])->default('无')->comment('包裹信息状态');
+            $table->enum('status', ['无', '已称重', '已揽收', '在途', '在途异常', '派送中', '派送异常', '返回中', '返回异常', '返回派件', '其他异常', '已收件'])->default('无')->comment('包裹信息状态');
             $table->dateTime('sent_at')->nullable()->comment('发出时间');
             $table->dateTime('received_at')->nullable()->comment('揽收时间');
-            $table->enum('exception',['是','否'])->default('否')->comment('异常状态');
-            $table->string('transfer_status')->nullable()->comment('更新信息');
+            $table->enum('exception', ['是', '否'])->default('否')->comment('异常状态');
+            $table->text('transfer_status')->nullable()->comment('更新信息');
             $table->string('remark')->nullable()->comment('备注');
             $table->index(['sent_at', 'exception']);
             $table->index(['received_at', 'exception']);