info('入驻钉钉对接未启用。'); return self::SUCCESS; } $limit = max(1, min(50, (int) $this->option('limit'))); $cursorKey = 'courier-onboarding:dingtalk-profile-cursor'; $cursor = (int) Cache::get($cursorKey, 0); $query = $profiles->candidates(); $records = (clone $query)->where('id', '>', $cursor)->orderBy('id')->limit($limit)->get(); if ($records->isEmpty() && $cursor > 0) { $records = $query->orderBy('id')->limit($limit)->get(); } if ($records->isEmpty()) { $this->info('没有需要同步的入驻审批。'); return self::SUCCESS; } try { $token = $client->accessToken(); } catch (CourierOnboardingDingTalkException $exception) { $this->error($exception->getMessage()); return self::FAILURE; } $started = microtime(true); $counts = ['synced' => 0, 'pending' => 0, 'closed' => 0, 'skipped' => 0, 'failed' => 0]; foreach ($records as $record) { // 两分钟调度内最多执行90秒,单接口自带8秒超时。 if (microtime(true) - $started >= 90) { break; } try { $result = $profiles->synchronize($record->company_id, $record->id, $token); $counts[$result]++; } catch (Throwable $exception) { $counts['failed']++; $message = $exception instanceof CourierOnboardingDingTalkException ? $exception->getMessage() : '钉钉快递资料同步异常,请联系管理员核查。'; $profiles->recordFailure($record, $message); } // 每次从上次结束位置继续,避免前面的待审批单一直占满查询批次。 Cache::put($cursorKey, $record->id, now()->addDay()); } $this->info('快递资料同步:' . json_encode($counts, JSON_UNESCAPED_UNICODE)); return $counts['failed'] > 0 ? self::FAILURE : self::SUCCESS; } }