Руководство по интеграции партнерского API и встраивания
В этом руководстве объясняется, как бэкэнд партнера создает сессию регистрации в WhatsApp, встраивает пользовательский интерфейс регистрации в iframe, получает события завершения и извлекает окончательные учетные данные приложения.
Обзор
Интеграция осуществляется с приоритетом бэкэнда:
- Ваша серверная часть обращается к API партнеров для создания сессии регистрации.
- API возвращает
registration_idиiframe_url. - Ваш фронтенд отображает
iframe_urlв iframe. - Пользователь проходит проверку по телефону, заполняет форму и регистрируется через встроенную мета-форму внутри iframe.
- По завершении процесса ChatArchitect отправляет подписанный веб-хук на ваш бэкэнд.
- Ваш бэкэнд хранит возвращенные значения
app_idиapp_secret. - Если доставка веб-хука не удалась или вам нужен резервный вариант, ваш бэкэнд может вызвать конечную точку результата.
iframe никогда не раскрывает параметр app_secret браузеру, DOM, URL-адресам или postMessage. Окончательные учетные данные передаются только на ваш бэкэнд через веб-хук или API результатов партнеров.
Базовый URL
Используйте общедоступный базовый URL-адрес, предоставленный ChatArchitect для вашей среды:
https://<chatarchitect-registration-domain>
Все конечные точки Partner API в этом руководстве указаны относительно базового URL-адреса.
Аутентификация
Для всех запросов к API партнеров требуется токен Bearer:
Авторизация: Предъявитель<partner_token>
ChatArchitect предоставляет вам этот токен. Рассматривайте его как секрет. Это же значение используется в качестве секрета HMAC для проверки подписи веб-перехватчика.
Создать сессию встраивания
Создайте новую сессию регистрации из своей административной панели.
POST /partner?action=create_session Authorization: Bearer<partner_token> Content-Type: application/json
Текст запроса:
{ "parent_origin": "https://partner.example", "webhook_url": "https://partner.example/api/chatarchitect/whatsapp-registration-webhook", "partner_user_id": "user_456", "partner_state": "opaque-state-value", "integration": "My CRM", "lang": "en" }
Поля:
| Поле | Необходимый | Описание |
|---|---|---|
родительский_источник |
Да | Источник родительской страницы, на которой будет размещен iframe, например, https://partner.example. Используйте только схему, хост и необязательный порт. Должно начинаться с http:// или https://. Используется в качестве целевого источника для postMessage . |
webhook_url |
Да | URL-адрес HTTPS, получающий веб-перехватчик завершения. Должен начинаться с https://. |
partner_user_id |
Нет | Ваш идентификатор пользователя/учетной записи/клиента. Возвращается без изменений в веб-хуке. |
партнер_штат |
Нет | Непрозрачное значение для вашей собственной корреляции или проверок CSRF/сессий. Возвращается в веб-хуке без изменений. |
интеграция |
Нет | Необязательное пользовательское название интеграции. Может быть любой строкой. Если оно опущено или пустое, при регистрации используется имя Partner. |
язык |
Нет | Начальный код языка. По умолчанию — en. Поддерживаемые значения: de, en, es, pt, ru. |
Успешный ответ:
{ "registration_id": "abc123def456ghi789jkl0", "iframe_url": "https://<chatarchitect-registration-domain> /?s=abc123def456ghi789jkl0&mode=embed", "expires_at": "2026-07-05T10:00:00+00:00", "status": "started" }
Примечания:
- Сохраните
registration_idв вашем бэкэнде. Он необходим для опроса результатов и повторной отправки веб-хуков. - Передавать
параметр iframe_urlна ваш фронтенд безопасно - Сохраненный режим сессии является авторитетным. Добавление
параметра mode=embedк другому URL-адресу не преобразует автономную сессию в сессию со встроенным контентом.
Пример с использованием curl:
curl -X POST "https://<chatarchitect-registration-domain> /partner?action=create_session" \ -H "Авторизация: Bearer"<partner_token> " \ -H "Content-Type: application/json" \ -d '{ "parent_origin": "https://partner.example", "webhook_url": "https://partner.example/api/chatarchitect/whatsapp-registration-webhook", "partner_user_id": "user_456", "partner_state": "opaque-state-value", "integration": "My CRM", "lang": "en" }'
Встроить iframe
Отобразите полученный iframe_url на вашем фронтенде.
<iframe id="ca-whatsapp-registration" src="https://<chatarchitect-registration-domain>/?s=abc123def456ghi789jkl0&mode=embed" style="width: 100%; height: 720px; border: 0;" allow="clipboard-write; encrypted-media; fullscreen" ></iframe>
Избегайте установки фиксированной минимальной высоты, если iframe находится внутри модального окна или другого контейнера с ограниченными размерами. iframe отправляет высоты при изменении своего содержимого, поэтому родительская страница может уменьшать или увеличивать размер iframe вместо того, чтобы принудительно добавлять дополнительную полосу прокрутки.
Если вы используете «песочница» , укажите достаточно прав доступа для процесса регистрации и встроенной формы регистрации Meta Embedded Signup:
<iframe src="https://<chatarchitect-registration-domain>/?s=abc123def456ghi789jkl0&mode=embed" sandbox="allow-scripts allow-forms allow-same-origin allow-popups allow-popups-to-escape-sandbox" ></iframe>
Избегайте размещения секретных данных в URL-адресе iframe. Единственное необходимое состояние iframe уже содержится в параметре iframe_url.
События Iframe
iframe отправляет родительскому окну только события, содержащие информацию о состоянии, используя метод postMessage.
Форма сообщения:
{ "type": "ca.whatsapp.registration", "event": "ready", "registration_id": "abc123def456ghi789jkl0" }
События:
| Событие | Значение |
|---|---|
готовый |
Iframe загружен и инициализирован. |
высота |
Высота iframe изменена. В полезную нагрузку может входить высота. |
телефон_проверен |
Пользователь подтвердил номер телефона WhatsApp. |
facebook_started |
Пользователь нажал «Подключить WhatsApp», и запустилась встроенная регистрация Meta. |
завершенный |
Регистрация завершена. Получите учетные данные из вашего бэкэнд-хранилища или API результатов партнеров. |
неуспешный |
Регистрация не удалась. Полезная нагрузка может включать сообщение. |
отменено |
Пользователь отменил регистрацию через Meta Embedded. |
Пример обработчика событий родительской страницы:
<script> const iframe = document.getElementById('ca-whatsapp-registration'); const expectedOrigin = 'https://<chatarchitect-registration-domain>'; const minHeight = 480; const maxModalHeight = () => Math.max(minHeight, window.innerHeight - 220); window.addEventListener('message', (event) => { if (event.origin !== expectedOrigin) return; const data = event.data || {}; if (data.type !== 'ca.whatsapp.registration') return; if (data.event === 'height' && data.height) { const contentHeight = Math.max(minHeight, Number(data.height)); iframe.style.height = `${Math.min(contentHeight, maxModalHeight())}px`; } if (data.event === 'completed') { // Your backend should receive the signed webhook. // Optionally call your own backend to refresh registration status. } if (data.event === 'failed') { // Show a retry/support state in your UI. } }); </script>
Сообщение postMessage никогда не содержит параметр app_secret.
Веб-хук завершения
После завершения регистрации встраивания ChatArchitect отправляет POST- запрос на адрес webhook_url из запроса на создание сессии.
Полезная нагрузка:
{ "event": "whatsapp.registration.completed", "registration_id": "abc123def456ghi789jkl0", "partner_user_id": "user_456", "partner_state": "opaque-state-value", "app_id": "ca_app_123", "app_secret": "secret_value", "phone": "421233221242", "integration": "My CRM", "completed_at": "2026-07-04T10:00:00+00:00" }
Заголовки:
Content-Type: application/json X-CA-Event-Id: evt_<registration_id> _<attempt> X-CA-Timestamp:<unix_timestamp> X-CA-Signature: sha256=<hmac_sha256>
Фирменная формула:
sha256=<HMAC_SHA256(X-CA-Timestamp + "." + raw_request_body, partner_token)>
Требования к проверке:
- Перед разбором JSON-данных прочтите исходное тело запроса.
- Отклоняйте устаревшие метки времени в соответствии с вашим временным окном воспроизведения, например, 5 минут.
- Вычислите HMAC SHA-256, используя ваш токен Bearer из партнерского API в качестве секрета.
- Сравните вычисленную подпись с
X-CA-Signature,используя сравнение за постоянное время. - Обрабатывайте события идемпотентно по
X-CA-Event-Idилиregistration_id.
Пример проверки Node.js:
import crypto from 'node:crypto'; function verifyChatArchitectWebhook({ rawBody, timestamp, signature, partnerToken }) { const expected = 'sha256=' + crypto .createHmac('sha256', partnerToken) .update(`${timestamp}.${rawBody}`) .digest('hex'); const expectedBuffer = Buffer.from(expected); const signatureBuffer = Buffer.from(signature || ''); if (expectedBuffer.length !== signatureBuffer.length) { return false; } return crypto.timingSafeEqual( expectedBuffer, signatureBuffer ); }
При принятии веб-хука отправьте ответ со статусом 2xx . Ответы со статусом, отличным от 2xx, рассматриваются как неудачная доставка и могут быть повторены через API партнера.
Получить результат регистрации
Используйте конечную точку результатов в качестве резервного варианта на стороне бэкэнда или для проверки статуса.
GET /partner?action=result®istration_id=<registration_id> Авторизация: Предъявитель<partner_token>
Если регистрация еще не завершена:
{ "status": "phone_verified" }
Возможные статусы "в процессе" включают:
started phone_code_sent phone_verified form_completed fb_started expired
Если регистрация завершена:
{ "status": "completed", "registration_id": "abc123def456ghi789jkl0", "app_id": "ca_app_123", "app_secret": "secret_value", "phone": "421233221242", "integration": "My CRM", "completed_at": "2026-07-04T10:00:00+00:00" }
Конечная точка для получения результата работает только с партнерским токеном, который использовался для создания сессии.
Повторить попытку через веб-перехватчик
Повторите попытку доставки веб-хука после завершения регистрации.
POST /partner?action=retry_webhook Authorization: Bearer<partner_token> Content-Type: application/json
Текст запроса:
{ "registration_id": "abc123def456ghi789jkl0" }
Ответ:
{ "status": "sent", "attempts": 2, "last_error": "" }
Если регистрация не завершена, конечная точка возвращает 409.
Ответы об ошибках
Типичная форма ошибки:
{ "status": "error", "message": "Неверный идентификатор регистрации" }
Типичные HTTP-статусы:
| Статус | Значение |
|---|---|
400 |
Недопустимое действие, тело запроса, parent_origin, webhook_urlили идентификатор регистрации. |
401 |
Отсутствует или недействителен токен Bearer. |
404 |
Сессия не найдена или принадлежит другому партнеру. |
409 |
Повторная попытка регистрации будет предпринята до завершения регистрации. |
500 |
Сбой на стороне сервера. |
Контрольный список безопасности
- Вызывайте API партнеров только из бэкэнда, никогда не используйте JavaScript в браузере.
- Храните токен партнерского API в секрете. Он также является секретным ключом для подписи веб-перехватчика.
- В рабочей среде используйте HTTPS для родительской страницы и конечной точки веб-перехватчика.
- Перед тем как доверять
параметрам app_idилиapp_secret, проверяйте подпись каждого веб-перехватчика . - Храните
app_secretтолько в бэкэнд-хранилище. - События
postMessageв iframe следует рассматривать только как подсказки о статусе, а не как источник учетных данных. - Проверяйте
event.originпри получении сообщений из iframe. - Обрабатывайте дубликаты веб-хуков идемпотентно.
Рекомендуемый расход
Участник sequenceDiagram PartnerBackend как участник бэкенда партнера PartnerFrontend как участник фронтенда партнера CA как участник регистрации ChatArchitect User как пользователь PartnerBackend->>CA: POST /partner?action=create_session CA-->>PartnerBackend: registration_id, iframe_url PartnerBackend-->>PartnerFrontend: iframe_url PartnerFrontend->>CA: Load iframe_url CA-->>PartnerFrontend: postMessage ready/height User->>CA: Verify phone, fill form, complete Meta signup CA-->>PartnerFrontend: postMessage completed CA->>PartnerBackend: Signed completion webhook PartnerBackend-->>CA: 2xx accepted PartnerBackend->>PartnerBackend: Store app_id and app_secret
Комментарии отсутствуют
Комментарии отсутствуют