handleRiderStatus($data); case 'order_complete': // 订单完成回调 return $this->handleOrderComplete($data); case 'sf_cancel': // 顺丰原因取消回调 return $this->handleSfCancel($data); case 'rider_exception': // 订单异常回调 return $this->handleRiderException($data); case 'rider_recall': // 骑士撤单回调 return $this->handleRiderRecall($data); case 'bindnotify': // 授权状态回调 return $this->handleBindNotify($data); case 'cancelbindnotify': // 取消授权状态回调 return $this->handleCancelBindNotify($data); default: Yii::warning('未知的顺丰回调类型: ' . $urlIndex, 'shunfeng-callback'); return false; } } catch (\Exception $e) { Yii::error('顺丰回调处理异常: ' . $e->getMessage() . ' | ' . $e->getTraceAsString(), 'shunfeng-callback'); return false; } } /** * 处理配送状态更改回调 * 状态包括:10-配送员接单/改派;12-配送员到店;15-配送员配送中 * * @param array $data 回调数据 * @return bool 处理结果 */ private function handleRiderStatus($data) { Yii::info('顺丰配送状态更改回调: ' . json_encode($data, JSON_UNESCAPED_UNICODE), 'shunfeng-callback'); // 验证必要参数 if (empty($data['sf_order_id']) || !isset($data['order_status'])) { Yii::error('顺丰配送状态回调参数不完整: ' . json_encode($data, JSON_UNESCAPED_UNICODE), 'shunfeng-callback'); return false; } $orderId = $data['sf_order_id']; // 查找配送订单 $deliveryOrder = GhsDeliveryOrderClass::getByCondition([ 'deliveryId' => 'shunfeng', 'orderId' => $orderId ], true); if (!$deliveryOrder) { Yii::error('顺丰配送订单不存在: sf_order_id=' . $orderId, 'shunfeng-callback'); return false; } // 更新配送订单信息 $updateData = []; // 更新配送员信息 $updateData['riderName'] = $data['operator_name']; $updateData['riderPhone'] = $data['operator_phone']; $updateData['riderLng'] = $data['rider_lng']; $updateData['riderLat'] = $data['rider_lat']; $updateData['statusDesc'] = $data['status_desc']; $updateData['pushTime'] = date('Y-m-d H:i:s', $data['push_time']); $orderStatus = $data['order_status']; // 转换顺丰订单状态到系统状态 $sendStatus = $this->convertOrderStatus($orderStatus); if ($sendStatus !== null) { // 更新配送订单 $deliveryOrder->orderStatus = $sendStatus; $deliveryOrder->save(); // 更新主订单的配送状态 $order = OrderClass::getById($deliveryOrder->ghsOrderId, true); if ($order) { $order->sendStatus = $sendStatus; $order->save(); } } else { return false; } return true; } /** * 处理订单完成回调 * 订单状态:17-配送员点击完成 * * @param array $data 回调数据 * @return bool 处理结果 */ private function handleOrderComplete($data) { Yii::info('顺丰订单完成回调: ' . json_encode($data, JSON_UNESCAPED_UNICODE), 'shunfeng-callback'); // 验证必要参数 if (empty($data['sf_order_id'])) { Yii::error('顺丰订单完成回调参数不完整: ' . json_encode($data, JSON_UNESCAPED_UNICODE), 'shunfeng-callback'); return false; } $orderId = $data['sf_order_id']; // 查找配送订单 $deliveryOrder = GhsDeliveryOrderClass::getByCondition([ 'deliveryId' => 'shunfeng', 'orderId' => $orderId ], true); if (!$deliveryOrder) { Yii::error('顺丰配送订单不存在: sf_order_id=' . $orderId, 'shunfeng-callback'); return false; } $sendStatus = $this->convertOrderStatus($data['order_status']); if ($sendStatus === null) { Yii::error('顺丰订单状态转换失败: ' . $data['order_status'], 'shunfeng-callback'); return false; } $deliveryOrder->orderStatus = $sendStatus; $deliveryOrder->save(); // 更新主订单状态为已送达 $order = OrderClass::getById($deliveryOrder->ghsOrderId, true, 'id,sendStatus,deliveryId,purchaseId,customId,status'); if ($order) { $order->sendStatus = $sendStatus; $order->save(); // 确认送达,更新主订单状态 if ($sendStatus == 5) { OrderClass::confirmReach($order, ['staffId' => 0, 'staffName' => '']); } } return true; } /** * 处理顺丰原因取消回调 * 订单状态:2-订单取消 * * @param array $data 回调数据 * @return bool 处理结果 */ private function handleSfCancel($data) { Yii::info('顺丰取消订单回调: ' . json_encode($data, JSON_UNESCAPED_UNICODE), 'shunfeng-callback'); // 验证必要参数 if (empty($data['sf_order_id'])) { Yii::error('顺丰取消回调参数不完整: ' . json_encode($data, JSON_UNESCAPED_UNICODE), 'shunfeng-callback'); return false; } $orderId = $data['sf_order_id']; // 查找配送订单 $deliveryOrder = GhsDeliveryOrderClass::getByCondition([ 'deliveryId' => 'shunfeng', 'orderId' => $orderId ], true); if (!$deliveryOrder) { Yii::error('顺丰配送订单不存在: sf_order_id=' . $orderId, 'shunfeng-callback'); return false; } $sendStatus = $this->convertOrderStatus($data['order_status']); if ($sendStatus === null) { Yii::error('顺丰订单状态转换失败: ' . $data['order_status'], 'shunfeng-callback'); return false; } $deliveryOrder->orderStatus = $sendStatus; $deliveryOrder->save(); // 更新主订单状态为取消 $order = OrderClass::getById($deliveryOrder->ghsOrderId, true, 'id,sendStatus,deliveryId,purchaseId,customId,status'); if ($order) { $order->sendStatus = $sendStatus; $order->save(); // 更新主订单状态为取消 if ($sendStatus == -1) { OrderClass::cancelOrderSend($order, ['staffId' => 0, 'staffName' => '']); } } return true; } /** * 处理订单异常回调 * 订单状态:91-骑士上报异常 * * @param array $data 回调数据 * @return bool 处理结果 */ private function handleRiderException($data) { Yii::info('顺丰订单异常回调: ' . json_encode($data, JSON_UNESCAPED_UNICODE), 'shunfeng-callback'); // 验证必要参数 if (empty($data['sf_order_id'])) { Yii::error('顺丰异常回调参数不完整: ' . json_encode($data, JSON_UNESCAPED_UNICODE), 'shunfeng-callback'); return false; } $orderId = $data['sf_order_id']; // 查找配送订单 $deliveryOrder = GhsDeliveryOrderClass::getByCondition([ 'deliveryId' => 'shunfeng', 'orderId' => $orderId ], true); if (!$deliveryOrder) { Yii::error('顺丰配送订单不存在: sf_order_id=' . $orderId, 'shunfeng-callback'); return false; } $sendStatus = $this->convertOrderStatus($data['order_status']); if ($sendStatus === null) { Yii::error('顺丰订单状态转换失败: ' . $data['order_status'], 'shunfeng-callback'); return false; } $deliveryOrder->orderStatus = $sendStatus; $deliveryOrder->save(); // 更新主订单状态为异常 $order = OrderClass::getById($deliveryOrder->ghsOrderId, true, 'id,sendStatus,deliveryId,purchaseId,customId,status'); if ($order) { $order->sendStatus = $sendStatus; $order->save(); // 更新主订单状态为异常 if ($sendStatus == -2) { OrderClass::cancelOrderSend($order, ['staffId' => 0, 'staffName' => '']); } } return true; } /** * 处理骑士撤单回调 * 订单状态:22-配送员撤单 * * @param array $data 回调数据 * @return bool 处理结果 */ private function handleRiderRecall($data) { Yii::info('顺丰骑士撤单回调: ' . json_encode($data, JSON_UNESCAPED_UNICODE), 'shunfeng-callback'); // 验证必要参数 if (empty($data['shop_order_id'])) { Yii::error('顺丰撤单回调参数不完整: ' . json_encode($data, JSON_UNESCAPED_UNICODE), 'shunfeng-callback'); return false; } $shopOrderId = $data['shop_order_id']; // 查找配送订单 $deliveryOrder = GhsDeliveryOrderClass::getByCondition([ 'deliveryId' => 'shunfeng', 'orderId' => $shopOrderId ], true); if (!$deliveryOrder) { Yii::error('顺丰配送订单不存在: shop_order_id=' . $shopOrderId, 'shunfeng-callback'); return false; } $sendStatus = $this->convertOrderStatus($data['order_status']); if ($sendStatus === null) { Yii::error('顺丰订单状态转换失败: ' . $data['order_status'], 'shunfeng-callback'); return false; } $deliveryOrder->orderStatus = $sendStatus; $deliveryOrder->save(); // 更新主订单状态为派单中 $order = OrderClass::getById($deliveryOrder->ghsOrderId, true); if ($order) { $order->sendStatus = $sendStatus; $order->save(); } return true; } /** * 处理顺丰授权成功回调 * * @param array $data * @return bool */ private function handleBindNotify($data) { $sign = Yii::$app->request->get('sign'); Yii::info('顺丰授权状态回调(sign=' . ($sign ?? '') . '): ' . json_encode($data, JSON_UNESCAPED_UNICODE), 'shunfeng-callback'); $mainId = isset($data['out_shop_id']) ? (int)$data['out_shop_id'] : 0; $shopId = isset($data['shop_id']) ? $data['shop_id'] : ''; if ($shopId === '') { Yii::error('顺丰授权状态回调参数缺失: ' . json_encode($data, JSON_UNESCAPED_UNICODE), 'shunfeng-callback'); return false; } $payload = [ 'mainId' => $mainId, 'platform' => 'shunfeng', 'shopId' => $shopId, 'authType' => 'all_store', 'accessToken' => $data['access_token'] ?? '', 'refreshToken' => $data['refresh_token'] ?? '', 'expiresAt' => time() + (100 * 86400 * 365), ]; $existing = DeliveryAuthTokenClass::getByCondition( ['mainId' => $mainId, 'platform' => 'shunfeng'], false, false, 'id' ); if ($existing && isset($existing['id'])) { DeliveryAuthTokenClass::updateById($existing['id'], [ 'shopId' => $payload['shopId'], 'authType' => $payload['authType'], 'accessToken' => $payload['accessToken'], 'refreshToken' => $payload['refreshToken'], 'expiresAt' => $payload['expiresAt'], ]); } else { DeliveryAuthTokenClass::add($payload); } return true; } /** * 处理顺丰取消授权回调 * * @param array $data * @return bool */ private function handleCancelBindNotify($data) { $sign = Yii::$app->request->get('sign'); Yii::info('顺丰取消授权状态回调(sign=' . ($sign ?? '') . '): ' . json_encode($data, JSON_UNESCAPED_UNICODE), 'shunfeng-callback'); $shopId = isset($data['shop_id']) ? $data['shop_id'] : ''; if ($shopId === '') { Yii::error('顺丰授权状态回调参数缺失: ' . json_encode($data, JSON_UNESCAPED_UNICODE), 'shunfeng-callback'); return false; } if (!empty($data['app_id'])) { $auth = new Auth(); if ((string)$auth->getAppKey() !== (string)$data['app_id']) { Yii::warning('顺丰取消授权回调 app_id 不匹配: ' . json_encode($data, JSON_UNESCAPED_UNICODE), 'shunfeng-callback'); return false; } } $condition = [ 'platform' => 'shunfeng', 'shopId' => $shopId ]; $deleted = DeliveryAuthTokenClass::deleteByCondition($condition); if ($deleted === 0) { Yii::warning('顺丰取消授权回调未删除任何记录: ' . json_encode($data, JSON_UNESCAPED_UNICODE), 'shunfeng-callback'); } return true; } /** * 转换顺丰订单状态到系统配送状态 * * 顺丰状态说明: * - 10: 配送员接单/配送员改派 * - 12: 配送员到店 * - 15: 配送员配送中 * - 17: 配送员点击完成 * - 2: 订单取消 * - 22: 配送员撤单 * - 91: 骑士上报异常 * * 系统状态说明: * - 0: 订单生成 * - 1: 系统已接单 * - 2: 派单中 * - 3: 待取货 * - 4: 配送中 * - 5: 已送达 * - -1: 已取消 * - -2: 异常 * - 10: 改派中 * - 20: 已分配骑手 * - 30: 骑手已到店 * - 40: 申请取消中 * - 50: 客服介入处理中 * * @param int $sfOrderStatus 顺丰订单状态 * @return int|null 系统配送状态,null表示不需要更新主订单状态 */ private function convertOrderStatus($sfOrderStatus) { // 顺丰状态映射到系统配送状态 $statusMap = [ 10 => 20, // 配送员接单/改派 -> 已分配骑手 12 => 30, // 配送员到店 -> 骑手已到店 15 => 4, // 配送员配送中 -> 配送中 17 => 5, // 配送完成 -> 已送达 2 => -1, // 订单取消 -> 已取消 22 => 2, // 配送员撤单 -> 派单中(重新派单) 91 => -2, // 骑士上报异常 -> 异常 ]; return $statusMap[$sfOrderStatus] ?? null; } }