AlibabaNotify.php 7.0 KB

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