ajaxReturn(array( 'code' => 0, 'msg' => '访问密钥错误', 'data' => null )); } // 设置最大执行时间 set_time_limit(300); } /** * 同步骑手订单状态到原始订单 * 当骑手接单后,修改原始订单状态为发货 * 当骑手配送完成后,修改原始订单状态为完成 */ public function syncRiderOrderStatus() { $startTime = microtime(true); $result = array( 'code' => 1, 'msg' => '执行成功', 'data' => array( 'start_time' => date('Y-m-d H:i:s'), 'end_time' => '', 'duration' => 0, 'accept_sync' => array('success' => 0, 'fail' => 0), 'complete_sync' => array('success' => 0, 'fail' => 0), 'total_success' => 0, 'total_fail' => 0 ) ); try { // 1. 检查是否启用自动同步 if (!$this->isAutoSyncEnabled()) { $result['msg'] = '自动同步未启用'; $this->log('自动同步未启用,任务终止'); $this->ajaxReturn($result); } // 2. 同步骑手接单状态(将原始订单状态改为发货) $acceptResult = $this->syncAcceptedOrders(); $result['data']['accept_sync'] = $acceptResult; // 3. 同步骑手配送完成状态(将原始订单状态改为完成) $completeResult = $this->syncCompletedOrders(); $result['data']['complete_sync'] = $completeResult; // 4. 计算总计 $result['data']['total_success'] = $acceptResult['success'] + $completeResult['success']; $result['data']['total_fail'] = $acceptResult['fail'] + $completeResult['fail']; $result['data']['end_time'] = date('Y-m-d H:i:s'); $result['data']['duration'] = round(microtime(true) - $startTime, 2); // 记录日志 $this->log("同步任务完成,成功 {$result['data']['total_success']} 个,失败 {$result['data']['total_fail']} 个"); } catch (\Exception $e) { $result['code'] = 0; $result['msg'] = '同步任务异常:' . $e->getMessage(); $result['data']['error'] = $e->getTraceAsString(); $this->log('同步任务异常:' . $e->getMessage()); } $this->ajaxReturn($result); } /** * 检查是否启用自动同步 * @return bool */ private function isAutoSyncEnabled() { $config = M('rider_config')->where(array('merchant_id' => 0))->find(); if (!$config) { // 如果没有配置,尝试获取任意一个商户的配置 $config = M('rider_config')->where(array('auto_sync_enabled' => 1))->find(); } return $config && $config['auto_sync_enabled'] == 1; } /** * 同步骑手接单状态 * 将原始订单状态更新为发货(status=2) * * @return array 统计结果 */ private function syncAcceptedOrders() { $successCount = 0; $failCount = 0; $errors = array(); // 查询已接单但原订单未发货的骑手订单 $where = array(); $where['ro.order_status'] = array('in', array(1, 2, 3, 4, 5)); // 已接单到配送中的状态 $where['o.status'] = 1; // 原订单状态为未发货 $orders = M('rider_order')->alias('ro') ->join('LEFT JOIN ls_retail_bill_online o ON ro.bill_id = o.bill_id') ->where($where) ->field('ro.id as rider_order_id, ro.bill_id, ro.order_status, ro.rider_id, o.status as original_status') ->select(); if (empty($orders)) { return array('success' => 0, 'fail' => 0, 'message' => '没有需要同步的接单订单'); } foreach ($orders as $order) { try { // 更新原始订单状态为发货(status=2) $result = M('retail_bill_online')->where(array('bill_id' => $order['bill_id']))->save(array( 'status' => 2, 'send_time' => date('Y-m-d H:i:s') )); if ($result !== false) { $successCount++; // 记录同步日志 $this->logSyncStatus( $order['bill_id'], $order['rider_order_id'], $order['rider_id'], 'accept', $order['original_status'], 2, 1, '' ); } else { $failCount++; $errors[] = "订单 {$order['bill_id']} 状态更新失败"; $this->logSyncStatus( $order['bill_id'], $order['rider_order_id'], $order['rider_id'], 'accept', $order['original_status'], 2, 0, '数据库更新失败' ); } } catch (\Exception $e) { $failCount++; $errors[] = "订单 {$order['bill_id']} 处理异常:{$e->getMessage()}"; $this->logSyncStatus( $order['bill_id'], $order['rider_order_id'], $order['rider_id'], 'accept', $order['original_status'], 2, 0, $e->getMessage() ); } } return array( 'success' => $successCount, 'fail' => $failCount, 'total' => count($orders), 'errors' => $errors ); } /** * 同步骑手配送完成状态 * 将原始订单状态更新为完成(status=3) * * @return array 统计结果 */ private function syncCompletedOrders() { $successCount = 0; $failCount = 0; $errors = array(); // 查询配送完成但原订单未完成的骑手订单 $where = array(); $where['ro.order_status'] = 6; // 已送达 $where['o.status'] = array('in', array(1, 2)); // 原订单状态为未发货或已发货 $orders = M('rider_order')->alias('ro') ->join('LEFT JOIN ls_retail_bill_online o ON ro.bill_id = o.bill_id') ->where($where) ->field('ro.id as rider_order_id, ro.bill_id, ro.order_status, ro.rider_id, ro.delivery_time, o.status as original_status') ->select(); if (empty($orders)) { return array('success' => 0, 'fail' => 0, 'message' => '没有需要同步的完成订单'); } foreach ($orders as $order) { try { // 更新原始订单状态为完成(status=3) $updateData = array( 'status' => 3, 'receipt_time' => !empty($order['delivery_time']) ? $order['delivery_time'] : date('Y-m-d H:i:s') ); $result = M('retail_bill_online')->where(array('bill_id' => $order['bill_id']))->save($updateData); if ($result !== false) { $successCount++; // 记录同步日志 $this->logSyncStatus( $order['bill_id'], $order['rider_order_id'], $order['rider_id'], 'complete', $order['original_status'], 3, 1, '' ); } else { $failCount++; $errors[] = "订单 {$order['bill_id']} 状态更新失败"; $this->logSyncStatus( $order['bill_id'], $order['rider_order_id'], $order['rider_id'], 'complete', $order['original_status'], 3, 0, '数据库更新失败' ); } } catch (\Exception $e) { $failCount++; $errors[] = "订单 {$order['bill_id']} 处理异常:{$e->getMessage()}"; $this->logSyncStatus( $order['bill_id'], $order['rider_order_id'], $order['rider_id'], 'complete', $order['original_status'], 3, 0, $e->getMessage() ); } } return array( 'success' => $successCount, 'fail' => $failCount, 'total' => count($orders), 'errors' => $errors ); } /** * 记录同步状态日志 * * @param int $billId 原订单ID * @param int $riderOrderId 骑手订单ID * @param int $riderId 骑手ID * @param string $operationType 操作类型 * @param int $oldStatus 原状态 * @param int $newStatus 新状态 * @param int $syncResult 同步结果 * @param string $errorMsg 错误信息 */ private function logSyncStatus($billId, $riderOrderId, $riderId, $operationType, $oldStatus, $newStatus, $syncResult, $errorMsg = '') { $now = date('Y-m-d H:i:s'); $logData = array( 'bill_id' => intval($billId), 'rider_order_id' => intval($riderOrderId), 'rider_id' => intval($riderId), 'operation_type' => $operationType, 'old_status' => intval($oldStatus), 'new_status' => intval($newStatus), 'sync_result' => intval($syncResult), 'error_msg' => $errorMsg ? $errorMsg : null, 'sync_time' => $now, 'retry_count' => 0, 'add_time' => $now, 'update_time' => $now, ); M('rider_order_sync_log')->add($logData); } /** * 记录运行日志到文件 * * @param string $message 日志消息 */ private function log($message) { $logFile = RUNTIME_PATH . 'Logs/OrderSync/' . date('Y-m-d') . '.log'; $logDir = dirname($logFile); if (!is_dir($logDir)) { mkdir($logDir, 0755, true); } $logContent = '[' . date('Y-m-d H:i:s') . '] ' . $message . "\n"; file_put_contents($logFile, $logContent, FILE_APPEND); } /** * 手动触发批量同步(供管理员使用) * 用于将原始订单同步创建为骑手订单 */ public function batchSync() { try { $syncService = new OrderSyncService(); $result = $syncService->batchSyncOrders(); $this->log("批量同步完成:{$result['message']}"); $this->ajaxReturn($result); } catch (\Exception $e) { $this->log('批量同步异常:' . $e->getMessage()); $this->ajaxReturn(array( 'success' => false, 'message' => '批量同步异常:' . $e->getMessage() )); } } /** * 健康检查接口 */ public function health() { $this->ajaxReturn(array( 'code' => 1, 'msg' => 'OK', 'data' => array( 'time' => date('Y-m-d H:i:s'), 'auto_sync_enabled' => $this->isAutoSyncEnabled() ) )); } }