소스 검색

第三方-淘宝客-更换接入应用

sunxbiao 8 달 전
부모
커밋
a7fcd32aab
2개의 변경된 파일256개의 추가작업 그리고 31개의 파일을 삭제
  1. 216 31
      app/controller/api/store/product/DaTaoKe.php
  2. 40 0
      app/utils/TimeUtil.php

+ 216 - 31
app/controller/api/store/product/DaTaoKe.php

@@ -13,6 +13,7 @@ use app\common\repositories\store\product\ProductRepository;
13 13
 use app\common\repositories\user\UserThirdRepository;
14 14
 use app\model\common\TbOrderModel;
15 15
 use app\model\common\UserThirdModel;
16
+use app\utils\TimeUtil;
16 17
 use http\Exception;
17 18
 use think\facade\Db;
18 19
 use think\facade\Log;
@@ -217,47 +218,231 @@ class DaTaoKe
217 218
     //订单查询接口(20分钟一个时间段)
218 219
     public function getOrder()
219 220
     {
221
+        // // 立即返回响应,断开客户端连接
222
+        // header('Content-Length: 0');
223
+        // header('Connection: close');
224
+        // ob_end_clean();
225
+        // ob_start();
226
+        // echo 'Request accepted'; // 可选的初始响应
227
+        //
228
+        // // 获取内容长度并发送头部
229
+        // header('Content-Length: ' . ob_get_length());
230
+        // ob_end_flush();
231
+        // flush();
232
+        //
233
+        // // 如果是FastCGI,还需要额外的刷新
234
+        // if (function_exists('fastcgi_finish_request')) {
235
+        //     fastcgi_finish_request();
236
+        // }
237
+
238
+        // 从这里开始,客户端已经断开,脚本可以长时间运行
239
+        ignore_user_abort(true); // 忽略用户中断
240
+        set_time_limit(0); // 取消时间限制
241
+
220 242
         try {
221
-            $startTime = date("Y-m-d H:i:00", strtotime("-50 minutes"));
222
-            $endTime = date("Y-m-d H:i:00");
223 243
             $url = 'https://openapi.dataoke.com/api/tb-service/get-order-details';
224
-            $queryTypes = [1, 2, 3];//1:按照订单淘客创建时间查询,2:按照订单淘客付款时间查询,3:按照订单淘客结算时间查询
225 244
             $orders = [];
226
-            foreach ($queryTypes as $queryType) {
227
-                $queryData = [
228
-                    'appKey' => self::$appKey,
229
-                    'version' => 'v1.0.0',
230
-                    'queryType' => $queryType,
231
-                    'pageSize' => 100,
232
-                    'startTime' => $startTime,
233
-                    'endTime' => $endTime,
234
-                    //1:常规订单,2:渠道订单,3:会员运营订单 默认为1
235
-                    'orderScene' => 2,
236
-                    'tkStatus' => 3
237
-                ];
238
-                $queryData['sign'] = self::makeSign($queryData, self::$appSecret);
239
-                $fullUrl = "{$url}?" . http_build_query($queryData);
240
-                $response = self::sendCurl($fullUrl);
241
-                $isError = $response['data']['error_response'] ?? '';
242
-                if ($isError) {//查询订单出错
243
-                    return app('json')->fail("拉取淘宝客订单出错", $response);
244
-                }
245
-                $responseOrders = $response['data']['results']['publisher_order_dto'] ?? [];
246
-                if ($responseOrders) {
247
-                    $orders = array_merge($orders, $responseOrders);
248
-                }
249
-            }
245
+
246
+            // 场景1:实时同步最近20分钟内有更新的订单
247
+            // $recentOrders = $this->queryRecentOrders($url);
248
+            // $orders = array_merge($orders, $recentOrders);
249
+
250
+            // 场景2:分批次查询历史订单(避免时间范围过大)
251
+            $refundOrders = $this->queryOrdersByBatch($url);
252
+            $orders = array_merge($orders, $refundOrders);
253
+
250 254
             if ($orders) {
251
-                //格式化拉取到的订单列表
252
-                $formatLists = self::formatOrderList($orders);
253
-                //创建/更新淘宝订单
255
+                // 去重处理
256
+                $uniqueOrders = $this->removeDuplicateOrders($orders);
257
+
258
+                // 格式化拉取到的订单列表
259
+                $formatLists = self::formatOrderList($uniqueOrders);
260
+                // 创建/更新淘宝订单
254 261
                 self::operateOrder($formatLists);
262
+
263
+                Log::info("订单处理完成". json_encode([
264
+                    '总订单数' => count($orders),
265
+                    '去重后订单数' => count($uniqueOrders),
266
+                    '处理时间' => date('Y-m-d H:i:s')
267
+                ], JSON_UNESCAPED_UNICODE));
268
+            } else {
269
+                Log::info("未获取到新订单");
255 270
             }
271
+
256 272
             return app('json')->success("拉取并处理淘宝客订单成功");
273
+
257 274
         } catch (\Throwable $throwable) {
258
-            return app('json')->fail("拉取并处理淘宝客订单出错{$throwable->getMessage()}");
275
+            Log::error("拉取订单异常". json_encode([
276
+                '错误信息' => $throwable->getMessage(),
277
+                '堆栈' => $throwable->getTraceAsString()
278
+            ], JSON_UNESCAPED_UNICODE));
279
+            return app('json')->fail("拉取并处理淘宝客订单出错: {$throwable->getMessage()}");
280
+        }
281
+
282
+        // try {
283
+        //     $startTime = date("Y-m-d H:i:00", strtotime("-50 minutes"));
284
+        //     $endTime = date("Y-m-d H:i:00");
285
+        //     $url = 'https://openapi.dataoke.com/api/tb-service/get-order-details';
286
+        //     $queryTypes = [1, 2, 3];//1:按照订单淘客创建时间查询,2:按照订单淘客付款时间查询,3:按照订单淘客结算时间查询
287
+        //     $orders = [];
288
+        //     foreach ($queryTypes as $queryType) {
289
+        //         $queryData = [
290
+        //             'appKey' => self::$appKey,
291
+        //             'version' => 'v1.0.0',
292
+        //             'queryType' => $queryType,
293
+        //             'pageSize' => 100,
294
+        //             'startTime' => $startTime,
295
+        //             'endTime' => $endTime,
296
+        //             //1:常规订单,2:渠道订单,3:会员运营订单 默认为1
297
+        //             'orderScene' => 2,
298
+        //             'tkStatus' => 3
299
+        //         ];
300
+        //         $queryData['sign'] = self::makeSign($queryData, self::$appSecret);
301
+        //         $fullUrl = "{$url}?" . http_build_query($queryData);
302
+        //         $response = self::sendCurl($fullUrl);
303
+        //         $isError = $response['data']['error_response'] ?? '';
304
+        //         if ($isError) {//查询订单出错
305
+        //             return app('json')->fail("拉取淘宝客订单出错", $response);
306
+        //         }
307
+        //         $responseOrders = $response['data']['results']['publisher_order_dto'] ?? [];
308
+        //         if ($responseOrders) {
309
+        //             $orders = array_merge($orders, $responseOrders);
310
+        //         }
311
+        //     }
312
+        //     if ($orders) {
313
+        //         //格式化拉取到的订单列表
314
+        //         $formatLists = self::formatOrderList($orders);
315
+        //         //创建/更新淘宝订单
316
+        //         self::operateOrder($formatLists);
317
+        //     }
318
+        //     return app('json')->success("拉取并处理淘宝客订单成功");
319
+        // } catch (\Throwable $throwable) {
320
+        //     return app('json')->fail("拉取并处理淘宝客订单出错{$throwable->getMessage()}");
321
+        // }
322
+
323
+    }
324
+
325
+    /**
326
+     * 查询最近20分钟内有更新的订单
327
+     */
328
+    private function queryRecentOrders($url)
329
+    {
330
+        $endTime = date("Y-m-d H:i:00");
331
+        $startTime = date("Y-m-d H:i:00", strtotime("-20 minutes"));
332
+
333
+        $queryData = [
334
+            'appKey' => self::$appKey,
335
+            'version' => 'v1.0.0',
336
+            'queryType' => 4, // 按照订单更新时间查询
337
+            'pageSize' => 100,
338
+            'startTime' => $startTime,
339
+            'endTime' => $endTime,
340
+            'orderScene' => 2,
341
+        ];
342
+
343
+        $queryData['sign'] = self::makeSign($queryData, self::$appSecret);
344
+        $fullUrl = "{$url}?" . http_build_query($queryData);
345
+
346
+        Log::info("查询最近订单". json_encode(['时间范围' => "{$startTime} 至 {$endTime}"], JSON_UNESCAPED_UNICODE));
347
+
348
+        $response = self::sendCurl($fullUrl);
349
+        $isError = $response['data']['error_response'] ?? '';
350
+
351
+        if ($isError) {
352
+            Log::error("查询最近订单错误". json_encode(['错误' => $isError], JSON_UNESCAPED_UNICODE));
353
+            return [];
354
+        }
355
+
356
+        return $response['data']['results']['publisher_order_dto'] ?? [];
357
+    }
358
+
359
+    /**
360
+     * 分批查询退款订单
361
+     */
362
+    private function queryOrdersByBatch($url): array
363
+    {
364
+        $allRefundOrders = [];
365
+
366
+        // 定义查询的时间段 大促期间 只能查20分钟的
367
+        $batchIntervals = TimeUtil::generateTimeIntervals(
368
+            date("Y-m-d H:i:00", strtotime("-1 days")), // 开始时间:10天前
369
+            date("Y-m-d H:i:00"),   // 结束时间 当前
370
+            20
371
+        );
372
+
373
+        foreach ($batchIntervals as $interval) {
374
+            $orders = $this->queryOrdersInInterval($url, $interval['start'], $interval['end']);
375
+            $allRefundOrders = array_merge($allRefundOrders, $orders);
376
+
377
+            // 添加延迟,避免请求过于频繁
378
+            // usleep(5000); // 0.5秒延迟
379
+        }
380
+
381
+        Log::info("分批查询退款订单完成". json_encode([
382
+            '时间段数量' => count($batchIntervals),
383
+            '退款订单数' => count($allRefundOrders)
384
+        ], JSON_UNESCAPED_UNICODE));
385
+
386
+        return $allRefundOrders;
387
+    }
388
+
389
+    /**
390
+     * 在指定时间区间内查询退款订单
391
+     */
392
+    private function queryOrdersInInterval($url, $startTime, $endTime)
393
+    {
394
+        $queryData = [
395
+            'appKey' => self::$appKey,
396
+            'version' => 'v1.0.0',
397
+            'queryType' => 2, // 按照 付款时间查询
398
+            'pageSize' => 100,
399
+            'startTime' => $startTime,
400
+            'endTime' => $endTime,
401
+            'orderScene' => 2,
402
+            // 'tkStatus' => 13
403
+        ];
404
+
405
+        $queryData['sign'] = self::makeSign($queryData, self::$appSecret);
406
+        $fullUrl = "{$url}?" . http_build_query($queryData);
407
+
408
+        Log::debug("查询订单时间段". json_encode([
409
+            '开始时间' => $startTime,
410
+            '结束时间' => $endTime,
411
+            '时间差(分钟)' => round((strtotime($endTime) - strtotime($startTime)) / 60, 2)
412
+        ], JSON_UNESCAPED_UNICODE));
413
+
414
+        $response = self::sendCurl($fullUrl);
415
+        Log::debug("查询结果". json_encode($response, JSON_UNESCAPED_UNICODE));
416
+        $isError = $response['data']['error_response'] ?? '';
417
+
418
+        if ($isError) {
419
+            Log::warning("查询订单出错". json_encode([
420
+                '时间段' => "{$startTime} 至 {$endTime}",
421
+                '错误' => $isError
422
+            ], JSON_UNESCAPED_UNICODE));
423
+            return [];
424
+        }
425
+
426
+        return $response['data']['results']['publisher_order_dto'] ?? [];
427
+    }
428
+
429
+    /**
430
+     * 订单去重
431
+     */
432
+    private function removeDuplicateOrders($orders): array
433
+    {
434
+        $uniqueOrders = [];
435
+        $orderIds = [];
436
+
437
+        foreach ($orders as $order) {
438
+            $orderId = $order['trade_parent_id'] ?? '';
439
+            if ($orderId && !in_array($orderId, $orderIds)) {
440
+                $uniqueOrders[] = $order;
441
+                $orderIds[] = $orderId;
442
+            }
259 443
         }
260 444
 
445
+        return $uniqueOrders;
261 446
     }
262 447
 
263 448
     //订单查询接口(20分钟一个时间段)

+ 40 - 0
app/utils/TimeUtil.php

@@ -0,0 +1,40 @@
1
+<?php
2
+
3
+namespace app\utils;
4
+
5
+class TimeUtil
6
+{
7
+    /**
8
+     * 生成时间间隔数组
9
+     */
10
+    public static function generateTimeIntervals($startTime, $endTime, $intervalMinutes = 20): array
11
+    {
12
+        $intervals = [];
13
+        $currentStart = strtotime($startTime);
14
+        $endTimestamp = strtotime($endTime);
15
+
16
+        while ($currentStart < $endTimestamp) {
17
+            $currentEnd = $currentStart + ($intervalMinutes * 60);
18
+
19
+            // 确保不超过结束时间
20
+            if ($currentEnd > $endTimestamp) {
21
+                $currentEnd = $endTimestamp;
22
+            }
23
+
24
+            $intervals[] = [
25
+                'start' => date("Y-m-d H:i:00", $currentStart),
26
+                'end' => date("Y-m-d H:i:00", $currentEnd)
27
+            ];
28
+
29
+            $currentStart = $currentEnd;
30
+
31
+            // 如果已经到达结束时间,退出循环
32
+            if ($currentStart >= $endTimestamp) {
33
+                break;
34
+            }
35
+        }
36
+
37
+        return $intervals;
38
+    }
39
+
40
+}