getDepartmentUserList($departmentId, true); Log::info('获取到企业成员数量: ' . count($userList)); if (empty($userList)) { Log::error('未获取到企业成员列表'); self::$error = '未获取到企业成员列表'; return false; } $syncCount = 0; $updateCount = 0; $newCount = 0; $processedCustomers = []; // 记录已处理的客户,避免重复 Db::startTrans(); try { // 2. 遍历每个成员,获取其客户列表 foreach ($userList as $user) { $userId = $user['userid'] ?? ''; if (empty($userId)) { continue; } Log::info('获取成员客户列表 - userId: ' . $userId . ', name: ' . ($user['name'] ?? '')); // 获取该成员的客户列表 $customerList = $service->getExternalContactList($userId); // 如果返回false,说明API调用失败(权限问题) if ($customerList === false) { Log::error('获取客户列表失败 - 可能是API权限未开启(错误码48002)'); throw new \Exception('企业微信API权限不足,请在企业微信管理后台开启"客户联系"权限'); } Log::info('成员 ' . $userId . ' 的客户数量: ' . count($customerList)); if (empty($customerList)) { continue; } // 3. 遍历客户列表,获取详情并保存 foreach ($customerList as $externalUserId) { // 避免重复处理同一个客户 if (isset($processedCustomers[$externalUserId])) { continue; } $processedCustomers[$externalUserId] = true; // 获取客户详情 $detail = $service->getExternalContactDetail($externalUserId); if (empty($detail)) { continue; } $externalContact = $detail['external_contact'] ?? []; $followUsers = $detail['follow_user'] ?? []; // 保存或更新客户信息 $data = [ 'external_userid' => $externalContact['external_userid'] ?? '', 'name' => $externalContact['name'] ?? '', 'avatar' => $externalContact['avatar'] ?? '', 'type' => $externalContact['type'] ?? 1, 'gender' => $externalContact['gender'] ?? 0, 'unionid' => $externalContact['unionid'] ?? '', 'position' => $externalContact['position'] ?? '', 'corp_name' => $externalContact['corp_name'] ?? '', 'corp_full_name' => $externalContact['corp_full_name'] ?? '', 'external_profile' => json_encode($externalContact['external_profile'] ?? [], JSON_UNESCAPED_UNICODE), 'follow_users' => json_encode($followUsers, JSON_UNESCAPED_UNICODE), 'update_time' => time(), ]; $existing = QywxExternalContact::where('external_userid', $data['external_userid'])->find(); if ($existing) { $existing->save($data); $updateCount++; } else { $data['create_time'] = time(); QywxExternalContact::create($data); $newCount++; } $syncCount++; } } // 4. 更新同步设置 self::updateSyncStatus('success', $syncCount); Db::commit(); Log::info('同步完成 - 总数: ' . $syncCount . ', 新增: ' . $newCount . ', 更新: ' . $updateCount); return [ 'sync_count' => $syncCount, 'new_count' => $newCount, 'update_count' => $updateCount, ]; } catch (\Throwable $e) { Db::rollback(); Log::error('同步企业微信客户失败: ' . $e->getMessage()); self::$error = '同步失败: ' . $e->getMessage(); self::updateSyncStatus('failed', 0, $e->getMessage()); return false; } } catch (\Throwable $e) { Log::error('同步企业微信客户异常: ' . $e->getMessage()); self::$error = '同步异常: ' . $e->getMessage(); self::updateSyncStatus('failed', 0, $e->getMessage()); return false; } } /** * @notes 获取统计信息 */ public static function getStats() { $total = QywxExternalContact::whereNull('delete_time')->count(); $todayStart = strtotime(date('Y-m-d 00:00:00')); $today = QywxExternalContact::where('create_time', '>=', $todayStart) ->whereNull('delete_time') ->count(); $settings = self::getSyncSettings(); $lastSyncTime = $settings['last_sync_time'] ?? 0; $lastSync = $lastSyncTime > 0 ? date('Y-m-d H:i:s', $lastSyncTime) : ''; return [ 'total' => $total, 'today' => $today, 'lastSync' => $lastSync, 'syncStatus' => $settings['sync_status'] ?? 'idle', 'syncStatusText' => self::getSyncStatusText($settings['sync_status'] ?? 'idle'), ]; } /** * @notes 获取同步设置 */ public static function getSyncSettings() { $setting = QywxSyncSettings::where('setting_key', 'customer_sync')->find(); if (!$setting) { return [ 'auto_sync' => false, 'interval' => 3600, 'last_sync_time' => 0, 'sync_status' => 'idle', ]; } $value = json_decode($setting->setting_value, true); return $value ?: [ 'auto_sync' => false, 'interval' => 3600, 'last_sync_time' => 0, 'sync_status' => 'idle', ]; } /** * @notes 保存同步设置 */ public static function saveSyncSettings(array $params) { try { $currentSettings = self::getSyncSettings(); $newSettings = array_merge($currentSettings, [ 'auto_sync' => (bool)($params['auto_sync'] ?? false), 'interval' => (int)($params['interval'] ?? 3600), ]); $setting = QywxSyncSettings::where('setting_key', 'customer_sync')->find(); if ($setting) { $setting->setting_value = json_encode($newSettings, JSON_UNESCAPED_UNICODE); $setting->update_time = time(); $setting->save(); } else { QywxSyncSettings::create([ 'setting_key' => 'customer_sync', 'setting_value' => json_encode($newSettings, JSON_UNESCAPED_UNICODE), 'create_time' => time(), 'update_time' => time(), ]); } return true; } catch (\Throwable $e) { self::$error = '保存失败: ' . $e->getMessage(); return false; } } /** * @notes 更新同步状态 */ private static function updateSyncStatus(string $status, int $syncCount = 0, string $error = '') { try { $settings = self::getSyncSettings(); $settings['sync_status'] = $status; $settings['last_sync_time'] = time(); $settings['last_sync_count'] = $syncCount; if ($error) { $settings['last_error'] = $error; } $setting = QywxSyncSettings::where('setting_key', 'customer_sync')->find(); if ($setting) { $setting->setting_value = json_encode($settings, JSON_UNESCAPED_UNICODE); $setting->update_time = time(); $setting->save(); } } catch (\Throwable $e) { Log::error('更新同步状态失败: ' . $e->getMessage()); } } /** * @notes 获取同步状态文本 */ private static function getSyncStatusText(string $status): string { $map = [ 'idle' => '未同步', 'syncing' => '同步中', 'success' => '同步成功', 'failed' => '同步失败', ]; return $map[$status] ?? '未知'; } }