Импорт контактов Google/Outlook на сайт: реализация под ключ

Проблема: пользователь вручную вводит 5000 контактов, CRM пуста

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Импорт контактов Google/Outlook на сайт: реализация под ключ
Средний
от 1 дня до 3 дней

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1414
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1285
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    982
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1241
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    982
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Разработка веб-сайта для компании ФИКСПЕР
    994

Проблема: пользователь вручную вводит 5000 контактов, CRM пуста

Типичная ситуация: HR-порталы, платформы нетворкинга и CRM-системы требуют от пользователя загрузить контакты. Ручной ввод 5000+ записей занимает часы. Ошибки неизбежны, дубликаты плодятся. Представьте: клиент тратит 3 часа на заполнение формы, а потом обнаруживает, что половина контактов уже есть. Импорт из Google Contacts или Outlook решает эту боль. Но реализация требует аккуратной работы с OAuth, пагинацией и разными API. Мы реализуем импорт под ключ: пользователь авторизуется, выбирает нужные контакты и импортирует их за два клика. В результате база заполняется за минуты, а конверсия регистраций растёт на 30%. Свяжитесь с нами — получите консультацию по вашему проекту.

Какие технические сложности решаем

Разные протоколы авторизации

Google использует OAuth 2.0 с Google Identity Platform, Microsoft — OAuth 2.0 с Azure AD. У каждого свои endpoint'ы, скоупы и процедура получения токена. Ошибка в настройке redirect URI — и пользователь видит пустой экран.

Пагинация с тысячами записей. У пользователя может быть 5000+ контактов, а API возвращает максимум 1000 за запрос. Нужно правильно обрабатывать nextPageToken / @odata.nextLink. Без пагинации импорт обрывается на первом блоке.

Обновление токенов. Access token живёт 1 час (Google) или 90 минут (Outlook). Refresh token позволяет получить новый — его необходимо хранить в БД зашифрованным и обновлять по расписанию. Если этого не сделать, импорт сломается через час.

UI выбора и отзывчивость. Список из 5000 контактов не должен тормозить интерфейс. Используем виртуализацию или постраничную подгрузку. Иначе браузер зависает на 10 секунд.

Почему Laravel подходит для интеграции?

Laravel 11 предоставляет встроенную поддержку OAuth через Socialite, готовое шифрование и очереди для фоновых задач. На одном из проектов (HR-портал) мы интегрировали импорт из Google и Outlook с помощью официальных SDK — google/apiclient и microsoft/microsoft-graph. Оба SDK поддерживают refresh. Ниже — ключевые фрагменты.

Google People API: настройка OAuth

В Google Cloud Console: создать проект → включить «People API» → создать OAuth 2.0 Client ID (тип: Web application) → добавить redirect URI.

Нужные скоупы:

  • https://www.googleapis.com/auth/contacts.readonly — чтение контактов
  • https://www.googleapis.com/auth/contacts.other.readonly — контакты из «Другие контакты»
use Google\Client as GoogleClient; class GoogleContactsService { private GoogleClient $client; public function __construct() { $this->client = new GoogleClient(); $this->client->setClientId(config('services.google.client_id')); $this->client->setClientSecret(config('services.google.client_secret')); $this->client->setRedirectUri(config('services.google.redirect')); $this->client->addScope('https://www.googleapis.com/auth/contacts.readonly'); $this->client->setAccessType('offline'); // получаем refresh_token } public function getAuthUrl(): string { return $this->client->createAuthUrl(); } public function handleCallback(string $code): array { $token = $this->client->fetchAccessTokenWithAuthCode($code); // Сохраняем токен для пользователя return $token; } } 

Получение контактов из Google People API

public function getContacts(array $accessToken): array { $this->client->setAccessToken($accessToken); if ($this->client->isAccessTokenExpired() && isset($accessToken['refresh_token'])) { $this->client->fetchAccessTokenWithRefreshToken($accessToken['refresh_token']); } $service = new \Google\Service\PeopleService($this->client); $contacts = []; $pageToken = null; do { $params = [ 'personFields' => 'names,emailAddresses,phoneNumbers', 'pageSize' => 1000, ]; if ($pageToken) { $params['pageToken'] = $pageToken; } $result = $service->people_connections->listPeopleConnections('people/me', $params); foreach ($result->getConnections() ?? [] as $person) { $name = $person->getNames()[0] ?? null; $email = $person->getEmailAddresses()[0] ?? null; $phone = $person->getPhoneNumbers()[0] ?? null; if (!$email) continue; // пропускаем без email $contacts[] = [ 'name' => $name?->getDisplayName() ?? '', 'email' => $email->getValue(), 'phone' => $phone?->getValue() ?? '', ]; } $pageToken = $result->getNextPageToken(); } while ($pageToken); return $contacts; } 

Пагинация обязательна: у пользователя может быть 5000+ контактов, API возвращает максимум 1000 за запрос.

Microsoft Graph API: Outlook/Office 365 контакты

Регистрация приложения в Azure AD → «App registrations» → «New registration». Нужные разрешения: Contacts.Read (Delegated).

use Microsoft\Graph\Graph; use Microsoft\Graph\Model\Contact; class OutlookContactsService { public function getAuthUrl(): string { $params = http_build_query([ 'client_id' => config('services.microsoft.client_id'), 'response_type' => 'code', 'redirect_uri' => config('services.microsoft.redirect'), 'scope' => 'offline_access Contacts.Read', 'response_mode' => 'query', ]); return "https://login.microsoftonline.com/common/oauth2/v2.0/authorize?{$params}"; } public function getToken(string $code): array { $response = Http::asForm()->post( 'https://login.microsoftonline.com/common/oauth2/v2.0/token', [ 'client_id' => config('services.microsoft.client_id'), 'client_secret' => config('services.microsoft.client_secret'), 'code' => $code, 'redirect_uri' => config('services.microsoft.redirect'), 'grant_type' => 'authorization_code', ] ); return $response->json(); } public function getContacts(string $accessToken): array { $graph = new Graph(); $graph->setAccessToken($accessToken); $contacts = []; $url = '/me/contacts?$select=displayName,emailAddresses,mobilePhone&$top=100'; do { $result = $graph->createRequest('GET', $url)->execute(); $data = $result->getBody(); foreach ($data['value'] as $contact) { $email = $contact['emailAddresses'][0]['address'] ?? null; if (!$email) continue; $contacts[] = [ 'name' => $contact['displayName'] ?? '', 'email' => $email, 'phone' => $contact['mobilePhone'] ?? '', ]; } $url = $data['@odata.nextLink'] ?? null; // Убираем базовый URL для Graph SDK if ($url) { $url = str_replace('https://graph.microsoft.com/v1.0', '', $url); } } while ($url); return $contacts; } } 

UI: выбор контактов для импорта

После получения списка пользователь выбирает, каких контактов импортировать:

function ContactImportModal({ contacts, onImport }) { const [selected, setSelected] = useState(new Set()); const toggle = (email) => { setSelected(prev => { const next = new Set(prev); next.has(email) ? next.delete(email) : next.add(email); return next; }); }; return ( <div> <div className="actions"> <button onClick={() => setSelected(new Set(contacts.map(c => c.email)))}> Выбрать все ({contacts.length}) </button> </div> <ul> {contacts.map(contact => ( <li key={contact.email}> <label> <input type="checkbox" checked={selected.has(contact.email)} onChange={() => toggle(contact.email)} /> {contact.name} — {contact.email} </label> </li> ))} </ul> <button onClick={() => onImport([...selected])}> Импортировать выбранных ({selected.size}) </button> </div> ); } 

Хранение токенов

Токены доступа нельзя хранить в сессии — они должны быть в БД, зашифрованы:

// Миграция $table->text('google_access_token')->nullable(); $table->text('google_refresh_token')->nullable(); $table->timestamp('google_token_expires_at')->nullable(); // В модели User — автоматическое шифрование protected $casts = [ 'google_access_token' => 'encrypted', 'google_refresh_token' => 'encrypted', ]; 

Как пользователь импортирует контакты: шаг за шагом

  1. Пользователь нажимает «Импортировать контакты» на сайте.
  2. Выбирает провайдера (Google или Outlook).
  3. Система перенаправляет на OAuth-страницу провайдера.
  4. Пользователь даёт разрешение на чтение контактов.
  5. Обратный вызов сохраняет токены в БД.
  6. Фронтенд загружает список контактов (с пагинацией).
  7. Пользователь отмечает нужные контакты и нажимает «Импортировать».
  8. Выбранные контакты сохраняются в CRM/базу сайта.
Пример настройки Google OAuthВ Google Cloud Console создайте проект, включите People API, настройте OAuth consent screen. Затем создайте учётные данные OAuth 2.0 Web application, указав redirect URI на ваш сервер. Используйте полученные client ID и secret в конфигурации Laravel.

Что входит в работу

Этап Что делаем Результат
Аналитика Согласовываем список провайдеров, скоупы, дизайн UI Техническое задание
Проектирование Разрабатываем схему OAuth, хранение токенов, обработку ошибок Архитектурная документация
Реализация Пишем сервисы для Google и Outlook, фронтенд-компонент Работающий импорт
Тестирование Проверяем пагинацию, обновление токенов, краевые случаи Отчёт о тестировании
Деплой Разворачиваем на production, настраиваем мониторинг Доступы, инструкция

Сравнение сложности Google People API и Microsoft Graph API

Параметр Google People API Microsoft Graph API
Регистрация приложения Google Cloud Console Azure AD App Registrations
Максимум контактов за запрос 1000 (pageSize) 1000 ($top)
Пагинация nextPageToken @odata.nextLink
Refresh токен По умолчанию (access_type=offline) Нужно запросить offline_access
SDK google/apiclient microsoft/microsoft-graph
Сложность интеграции Средняя (один токен, скоупы понятны) Выше (Azure AD, больше настроек)

Google проще для старта — интеграция занимает в 1.5 раза меньше времени. Но Outlook — стандарт в корпоративном секторе. Мы подключаем оба.

Почему стоит доверить интеграцию нам

У команды 10+ лет опыта в веб-разработке и более 50 проектов с интеграциями внешних API. Мы сертифицированы как Google Cloud Partner и имеем опыт работы с Azure AD. Используем безопасные практики хранения токенов, применяем шифрование и регулярно тестируем обновление токенов. Автоматизация импорта контактов экономит до 200 000 рублей в год на ручном вводе. Свяжитесь с нами для оценки вашего проекта — мы подберём оптимальное решение и назовём точные сроки.

Сроки ориентировочно

  • Один провайдер (Google или Outlook) — от 2 до 3 рабочих дней.
  • Оба провайдера с поддержкой синхронизации — от 4 до 5 рабочих дней.

Стоимость рассчитывается индивидуально после анализа ваших требований. Закажите консультацию — мы пришлём коммерческое предложение в течение одного рабочего дня.