|
|
@@ -277,6 +277,111 @@ class OrderController extends APIController
|
|
|
];
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 物流轨迹查询
|
|
|
+ *
|
|
|
+ * GET /api/customer/orders/tracking?track_number=xxx
|
|
|
+ *
|
|
|
+ * @param Request $request
|
|
|
+ * @return JsonResponse
|
|
|
+ */
|
|
|
+ public function tracking(Request $request): JsonResponse
|
|
|
+ {
|
|
|
+ $trackNumber = $request->input('track_number');
|
|
|
+
|
|
|
+ if (empty($trackNumber)) {
|
|
|
+ return ApiResponse::validationError('track_number is required');
|
|
|
+ }
|
|
|
+ if (mb_strlen($trackNumber) > 100) {
|
|
|
+ return ApiResponse::validationError('track_number must not exceed 100 characters');
|
|
|
+ }
|
|
|
+ $type = $request->input('type');
|
|
|
+ try {
|
|
|
+ $info = $this->gettrack_erp($trackNumber,$type);
|
|
|
+ $data=array();
|
|
|
+ if($info['success']){
|
|
|
+ $data['trackinfo']=$info['track']['data'];
|
|
|
+ return ApiResponse::success($data);
|
|
|
+ }else{
|
|
|
+ return ApiResponse::error($info['msg']);
|
|
|
+ }
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ return ApiResponse::error('Tracking query failed: ' . $e->getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 调用 ERP 物流查询 API
|
|
|
+ */
|
|
|
+ public function gettrack_erp($track_number,$type)
|
|
|
+ {
|
|
|
+ $data = [
|
|
|
+ 'shop' => 2,
|
|
|
+ 'order_no' => $track_number,
|
|
|
+ 'time' => time(),
|
|
|
+ 'key' => $this->getTrackKey(time()),
|
|
|
+ ];
|
|
|
+ if($type){
|
|
|
+ $data['type']=$type;
|
|
|
+ }
|
|
|
+ $datas = json_encode($data);
|
|
|
+ $requestUrl = 'https://1.wepolicy.cn/apiexpress/logistics';
|
|
|
+ $result = $this->_getApiData($requestUrl, 'POST', $datas, 1);
|
|
|
+ if(preg_match('/^\xEF\xBB\xBF/',$result))
|
|
|
+ {
|
|
|
+ $result = substr($result,3);
|
|
|
+ }
|
|
|
+ $res = json_decode(trim($result),true);
|
|
|
+ return $res;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成物流查询加密 Key
|
|
|
+ */
|
|
|
+ public function getTrackKey($time)
|
|
|
+ {
|
|
|
+ $key = "6amg!pnfrlbpnjgirv";
|
|
|
+ $iv = "6ook4k!2w94m6jtm";
|
|
|
+ $serect = "asteriahair";
|
|
|
+ $decrypt = $serect . "+" . $time;
|
|
|
+
|
|
|
+ return openssl_encrypt($decrypt, 'AES-128-CBC', $key, 0, $iv);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 通用 HTTP 请求
|
|
|
+ */
|
|
|
+ private function _getApiData($url, $method = 'GET', $data = null, $timeout = 30)
|
|
|
+ {
|
|
|
+ $ch = curl_init();
|
|
|
+
|
|
|
+ curl_setopt($ch, CURLOPT_URL, $url);
|
|
|
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
|
+ curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
|
|
|
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
|
|
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
|
|
+
|
|
|
+ if (strtoupper($method) === 'POST') {
|
|
|
+ curl_setopt($ch, CURLOPT_POST, true);
|
|
|
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
|
|
+ curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
|
|
+ 'Content-Type: application/json',
|
|
|
+ 'Content-Length: ' . strlen($data),
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+ $response = curl_exec($ch);
|
|
|
+ $error = curl_error($ch);
|
|
|
+
|
|
|
+ curl_close($ch);
|
|
|
+
|
|
|
+ if ($error) {
|
|
|
+ throw new \Exception('CURL Error: ' . $error);
|
|
|
+ }
|
|
|
+
|
|
|
+ return $response;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 获取状态中文标签
|
|
|
*/
|