Контактная форма / обратная связь: пример Next.js
На этой странице показано, как интегрировать вебхук Contact / feedback form в приложение Next.js через BFF-маршрут: браузер отправляет данные в ваше приложение, которое вызывает Mailoo с серверными учётными данными. API-ключ не попадает на клиент.
Это не интеграция Form (рассылка): обратная связь использует POST /api/v1/webhooks/feedback/... и интеграцию CONTACT_FORM. Для форм подписки см. website-forms{.interpreted-text role="doc"} и website-forms-nextjs-example{.interpreted-text role="doc"}. Для описания API (заголовки, тело, CORS) см. contact-feedback-form{.interpreted-text role="doc"}.
- Проект Mailoo с интеграцией Contact / feedback form
- Разрешённые источники (необязательно) в интеграции --- при установке CORS применяется для запросов с заголовком
Origin - API-ключ с Feedback form submissions (
webhook.feedback-submission) для RESTRICTED или Full Access
Добавьте в .env.local (или в окружение деплоя). Все четыре основные переменные обязательны для работы BFF.
MAILOO_FEEDBACK_INTEGRATION_API=https://api.mailoo.app
MAILOO_FEEDBACK_INTEGRATION_API_KEY=your-api-key-here
MAILOO_FEEDBACK_INTEGRATION_PROJECT_UID=your-project-uid-here
MAILOO_FEEDBACK_INTEGRATION_ID=your-contact-form-integration-id-here
Необязательно (добавляется в metadata каждой отправки на сервере):
# MAILOO_FEEDBACK_INTEGRATION_FORM_NAMESPACE=production-site
# MAILOO_FEEDBACK_INTEGRATION_SITE_ID=my-brand
Опциональный список разрешённых ключей форм: если задан, BFF отклоняет отправки, чей metadata.formKey (или formKey верхнего уровня) не входит в список (через запятую). Укажите каждый formKey, который отправляют ваши интерфейсы (например, web-contact-page).
# MAILOO_FEEDBACK_INTEGRATION_ALLOWED_FORM_KEYS=web-contact-page,support-widget
Используйте только на стороне сервера; не применяйте NEXT_PUBLIC_* для URL API или ключа.
Несколько форм, одна интеграция
Обычно в окружении настраивается одна интеграция обратной связи, но может быть несколько интерфейсов (страница контактов, виджет поддержки и т. д.). Различайте их в теле JSON через metadata --- например, formKey (фиксированная строка для каждой формы) и entryPoint (например, contact_page, support_widget). Mailoo API сохраняет этот объект в записи сообщения и обратной связи; см. contact-feedback-form{.interpreted-text role="doc"}.
Несколько интеграций, несколько BFF-маршрутов
Когда нужны отдельные интеграции CONTACT_FORM (разные API-ключи, почтовые ящики или списки разрешённых источников), создайте один BFF-маршрут на интеграцию и передайте пользовательский prefix окружения (или getConfig). Не сопоставляйте несколько интеграций с MAILOO_FEEDBACK_INTEGRATION_*.
// app/api/v1/webhooks/team-subscription/submit/route.ts
import { createFeedbackSubmitHandler } from '@mailoo/forms/routes'
export const POST = createFeedbackSubmitHandler({
prefix: 'MAILOO_TEAM_SUBSCRIPTION_FORM',
})
Окружение для этого маршрута (тот же паттерн суффиксов, что и у стандартного префикса обратной связи):
MAILOO_TEAM_SUBSCRIPTION_FORM_API=https://api.mailoo.app
MAILOO_TEAM_SUBSCRIPTION_FORM_API_KEY=...
MAILOO_TEAM_SUBSCRIPTION_FORM_PROJECT_UID=...
MAILOO_TEAM_SUBSCRIPTION_FORM_INTEGRATION_ID=...
# Необязательно:
# MAILOO_TEAM_SUBSCRIPTION_FORM_ALLOWED_FORM_KEYS=pricing-team-request
Клиентские хуки принимают endpoint, указывающий на этот BFF-путь.
Используйте @mailoo/forms/routes --- не реализуйте валидацию или прокси вебхука заново.
Создайте app/api/v1/webhooks/feedback/submit/route.ts:
import { createFeedbackSubmitHandler } from '@mailoo/forms/routes'
export const POST = createFeedbackSubmitHandler()
// Необязательно: { prefix, getConfig, logger }
// Префикс по умолчанию: MAILOO_FEEDBACK_INTEGRATION
Фабрика:
- Возвращает 503, если учётные данные для привязанного префикса (или
getConfig) отсутствуют. - Валидирует
email/message, включаетformKeyвmetadata, применяет${prefix}_FORM_NAMESPACE,${prefix}_SITE_IDи${prefix}_ALLOWED_FORM_KEYS. - Пересылает на
${api}/api/v1/webhooks/feedback/${projectUid}/${integrationId}сX-API-KeyиOrigin/Refererчерез@mailoo/next-core.
Рекомендуемый хелпер конфигурации для условного отображения в макете:
import {
getMailooFormsIntegrationConfig,
MAILOO_FEEDBACK_INTEGRATION_PREFIX,
} from '@mailoo/forms'
const config = getMailooFormsIntegrationConfig({
prefix: MAILOO_FEEDBACK_INTEGRATION_PREFIX,
})
Устаревшие (по-прежнему экспортируются; не расширяйте): getMailooFeedbackIntegrationConfig, getMailooFormIntegrationConfig, isMailooFeedbackIntegrationConfigured.
Из клиентского компонента отправьте POST с JSON на /api/v1/webhooks/feedback/submit с полями как минимум email и message. Включите metadata.formKey (и любой другой контекст), чтобы в панели управления было видно, какая форма использовалась. Или используйте useMailooFeedbackSubmit из @mailoo/forms/hooks.
'use client'
async function submitFeedback() {
const res = await fetch('/api/v1/webhooks/feedback/submit', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: 'user@example.com',
message: 'The checkout button does nothing on mobile.',
subject: 'Bug report',
name: 'Jane',
metadata: {
formKey: 'web-contact-page',
pageUrl: typeof window !== 'undefined' ? window.location.href : '',
},
}),
})
const data = await res.json()
if (!res.ok) throw new Error(data.message || 'Submit failed')
return data
}
Обработайте 503 (интеграция не настроена) и 400 (ошибка валидации или запрещённый formKey) в вашем интерфейсе.
- Пакет:
@mailoo/forms(createFeedbackSubmitHandlerиз@mailoo/forms/routes,useMailooFeedbackSubmitиз@mailoo/forms/hooks) --- см.nextjs-packages{.interpreted-text role="doc"}
contact-feedback-form{.interpreted-text role="doc"} --- эндпоинт и поля JSONwebsite-forms-nextjs-example{.interpreted-text role="doc"} --- паттерн BFF для Form (рассылка)nextjs-packages{.interpreted-text role="doc"} --- обзор@mailoo/forms- OpenAPI:
https://api.mailoo.app/docs/v1