Kaynağa Gözat

feat(api): 添加1688订阅消息通知处理功能

- 新增AlibabaNotify控制器处理1688开放平台推送的订阅消息
- 实现订单发货通知处理逻辑,自动更新物流信息
- 添加路由配置支持alibaba/notify webhook回调
- 集成日志记录和错误处理机制
- 实现订单状态自动更新和物流信息同步
shichen 2 ay önce
ebeveyn
işleme
565d46062b
2 değiştirilmiş dosya ile 192 ekleme ve 0 silme
  1. 189 0
      app/controller/api/AlibabaNotify.php
  2. 3 0
      route/api.php

+ 189 - 0
app/controller/api/AlibabaNotify.php

@@ -0,0 +1,189 @@
1
+<?php
2
+/**
3
+ * 1688订阅消息通知处理
4
+ *
5
+ * 处理1688开放平台推送的订阅消息,包括订单发货通知等
6
+ *
7
+ * @author: yourname
8
+ * @day: 2026/05/08
9
+ */
10
+
11
+namespace app\controller\api;
12
+
13
+use app\common\repositories\store\order\StoreOrderStatusRepository;
14
+use app\services\ThirdParty\AlibabaAgent\OrderService;
15
+use think\facade\Db;
16
+use think\facade\Log;
17
+
18
+class AlibabaNotify
19
+{
20
+    /**
21
+     * 1688订阅消息入口
22
+     *
23
+     * 接收1688开放平台推送的HTTP POST通知
24
+     * 请求格式: application/x-www-form-urlencoded
25
+     * 参数:
26
+     *   - message: JSON字符串,包含订阅消息内容
27
+     *   - _aop_signature: 签名
28
+     *
29
+     * @return \think\Response
30
+     */
31
+    public function notify()
32
+    {
33
+        // 获取原始POST数据
34
+        $postData = request()->post();
35
+
36
+        Log::channel('alibaba')->info('[订阅消息通知] 收到请求', ['data' => json_encode($postData, JSON_UNESCAPED_UNICODE)]);
37
+
38
+        if (empty($postData['message'])) {
39
+            Log::channel('alibaba')->error('[订阅消息通知] message参数为空');
40
+            return response('fail: message is empty');
41
+        }
42
+
43
+        // 解析message
44
+        $message = json_decode($postData['message'], true);
45
+        if (json_last_error() !== JSON_ERROR_NONE) {
46
+            Log::channel('alibaba')->error('[订阅消息通知] message JSON解析失败', ['message' => $postData['message']]);
47
+            return response('fail: message json decode error');
48
+        }
49
+
50
+        $type = $message['type'] ?? '';
51
+        Log::channel('alibaba')->info('[订阅消息通知] 消息类型', ['type' => $type, 'message' => $message]);
52
+
53
+        try {
54
+            switch ($type) {
55
+                case 'ORDER_BUYER_VIEW_ANNOUNCE_SENDGOODS':
56
+                    return $this->handleOrderSendGoods($message);
57
+                default:
58
+                    Log::channel('alibaba')->warning('[订阅消息通知] 未知消息类型', ['type' => $type]);
59
+                    return response('success: unknown type');
60
+            }
61
+        } catch (\Throwable $e) {
62
+            Log::channel('alibaba')->error('[订阅消息通知] 处理异常', [
63
+                'type'    => $type,
64
+                'error'   => $e->getMessage(),
65
+                'trace'   => $e->getTraceAsString(),
66
+            ]);
67
+            return response('fail: exception - ' . $e->getMessage());
68
+        }
69
+    }
70
+
71
+    /**
72
+     * 处理订单发货通知
73
+     *
74
+     * 订阅消息类型: ORDER_BUYER_VIEW_ANNOUNCE_SENDGOODS
75
+     *
76
+     * 消息内容示例:
77
+     * {
78
+     *   "bizKey": "3300284931845138963",
79
+     *   "data": {
80
+     *     "buyerMemberId": "b2b-665170100",
81
+     *     "orderId": 3300284931845138963,
82
+     *     "currentStatus": "waitbuyerreceive",
83
+     *     "sellerMemberId": "b2b-1676547900b7bb3",
84
+     *     "msgSendTime": "2018-05-30 19:34:27"
85
+     *   },
86
+     *   "gmtBorn": 1778221635003,
87
+     *   "msgId": 189049289670,
88
+     *   "type": "ORDER_BUYER_VIEW_ANNOUNCE_SENDGOODS",
89
+     *   "userInfo": "b2b-22210711363891dff5"
90
+     * }
91
+     *
92
+     * 处理流程:
93
+     * 1. 记录日志
94
+     * 2. 根据 data.orderId 查询本地 store_order 表(alibaba_order_id)
95
+     * 3. 请求1688获取物流信息接口,获取物流公司和物流单号
96
+     * 4. 更新 store_order 表的 delivery_name(快递名称)和 delivery_id(快递单号)
97
+     *
98
+     * @param array $message 消息内容
99
+     * @return \think\Response
100
+     */
101
+    protected function handleOrderSendGoods(array $message)
102
+    {
103
+        $data = $message['data'] ?? [];
104
+        $orderId = $data['orderId'] ?? 0;
105
+
106
+        if (empty($orderId)) {
107
+            Log::channel('alibaba')->error('[发货通知] data.orderId为空', ['message' => $message]);
108
+            return response('fail: orderId is empty');
109
+        }
110
+
111
+        Log::channel('alibaba')->info('[发货通知] 开始处理', [
112
+            'alibaba_order_id' => $orderId,
113
+            'currentStatus'    => $data['currentStatus'] ?? '',
114
+            'msgSendTime'      => $data['msgSendTime'] ?? '',
115
+        ]);
116
+
117
+        // 1. 根据1688订单号查询本地订单
118
+        $storeOrder = Db::name('store_order')
119
+            ->where('alibaba_order_id', (string)$orderId)
120
+            ->find();
121
+
122
+        if (empty($storeOrder)) {
123
+            Log::channel('alibaba')->warning('[发货通知] 未找到匹配的本地订单', ['alibaba_order_id' => $orderId]);
124
+            return response('success: order not found locally');
125
+        }
126
+
127
+        Log::channel('alibaba')->info('[发货通知] 找到本地订单', [
128
+            'order_id'  => $storeOrder['order_id'],
129
+            'order_sn'  => $storeOrder['order_sn'],
130
+        ]);
131
+
132
+        // 2. 如果已有物流信息,跳过
133
+        if (!empty($storeOrder['delivery_name']) && !empty($storeOrder['delivery_id'])) {
134
+            Log::channel('alibaba')->info('[发货通知] 订单已有物流信息,跳过更新', [
135
+                'order_id'       => $storeOrder['order_id'],
136
+                'delivery_name'  => $storeOrder['delivery_name'],
137
+                'delivery_id'    => $storeOrder['delivery_id'],
138
+            ]);
139
+            return response('success: already has logistics info');
140
+        }
141
+
142
+        // 3. 请求1688获取物流信息
143
+        $orderService = new OrderService();
144
+        $logisticsResult = $orderService->getLogisticsInfosBuyerView([
145
+            'orderId' => $orderId,
146
+        ]);
147
+
148
+        if ($logisticsResult === false || empty($logisticsResult['logisticsItems'])) {
149
+            Log::channel('alibaba')->warning('[发货通知] 获取物流信息失败或物流信息为空', [
150
+                'alibaba_order_id' => $orderId,
151
+                'result'           => $logisticsResult,
152
+            ]);
153
+            return response('success: no logistics info yet');
154
+        }
155
+
156
+        // 4. 取第一条物流信息
157
+        $firstLogistics = $logisticsResult['logisticsItems'][0];
158
+        $deliveryName = $firstLogistics['logisticsName'] ?? '';
159
+        $deliveryId   = $firstLogistics['logisticsCode'] ?? '';
160
+
161
+        if (empty($deliveryName) || empty($deliveryId)) {
162
+            Log::channel('alibaba')->warning('[发货通知] 物流信息不完整', ['logistics' => $firstLogistics]);
163
+            return response('success: logistics info incomplete');
164
+        }
165
+
166
+        // 5. 更新 store_order 表
167
+        $updateData = [
168
+            'delivery_type' => 1,
169
+            'delivery_name' => $deliveryName,
170
+            'delivery_id'   => $deliveryId,
171
+            'status'        => 1, // 待收货
172
+        ];
173
+
174
+        Db::name('store_order')
175
+            ->where('order_id', $storeOrder['order_id'])
176
+            ->update($updateData);
177
+
178
+        app()->make(StoreOrderStatusRepository::class)->status($storeOrder['order_id'], 'delivery_0', '订单以配送【快递名称】:' . $deliveryName . '; 【快递单号】:' . $deliveryId);
179
+
180
+        Log::channel('alibaba')->info('[发货通知] 物流信息更新成功', [
181
+            'order_id'       => $storeOrder['order_id'],
182
+            'order_sn'       => $storeOrder['order_sn'],
183
+            'delivery_name'  => $deliveryName,
184
+            'delivery_id'    => $deliveryId,
185
+        ]);
186
+
187
+        return response('success');
188
+    }
189
+}

+ 3 - 0
route/api.php

@@ -1407,3 +1407,6 @@ Route::get('share_system_subsidy', 'api.shareProsperity.Task/system_subsidy');
1407 1407
 
1408 1408
 // 测试接口
1409 1409
 Route::get('/test', 'api.Test/test');
1410
+
1411
+// 1688订阅消息通知(开放平台webhook回调)
1412
+Route::any('alibaba/notify', 'api.AlibabaNotify/notify');