WhatsApp Business API для уведомления об отказе в верификации
Сценарий отправляет клиенту персонализированный шаблон WhatsApp, когда его eKYC или проверка личности отклонены.
Обзор сценария
Сценарий отправляет клиенту персонализированный шаблон WhatsApp, когда его eKYC или проверка личности отклонена. Сообщение включает имя клиента, процесс проверки и статус или причину отклонения. Статическая кнопка URL открывает страницу с деталями проверки или портал клиента.
Пример шаблона
Здравствуйте, {{1}}! Ваше {{2}}не было одобрено. Статус: {{3}}. Ознакомьтесь с деталями и следующими шагами, нажав на кнопку ниже. Если у вас есть вопросы — мы готовы помочь.
- {{1}}имя клиента
- {{2}}процесс верификации (например, eKYC-проверка, проверка личности, проверка документов)
- {{3}}статус или причина отклонения (например, не одобрено, документ нечитаем, проверка не пройдена)
- “Просмотреть детали”кнопка — исправлено в шаблоне Meta

Когда использовать
Используйте этот сценарий, когда клиент подал документы для eKYC или завершил процесс верификации личности, а дело отклонено — и вам нужно заранее объяснить причины и предложить дальнейшие шаги до того, как он обратиться в поддержку. Он подходит для финтех-команд, обрабатывающих очереди KYC, маркетплейсов, отклоняющих проверки личности продавцов, и агентств, подключающих вебхуки отказа от eKYC-провайдера или комплаенса к исходящим сообщениям в WhatsApp.
Как это работает
- Поведение клиентов
Клиент отправляет документы для eKYC или завершает проверку.
user action - Статус отслеживается
Бэк-офис, поставщик eKYC или интеграция помечают случай как отклонённый с указанием причины или метки статуса.
status:"read" - Захватить событие
Система определяет номер телефона получателя и поля отклонения.
phone:"+…" - Собрать и отправить
Персонализированное сообщение по шаблону создаётся с тремя переменными в теле и статической кнопкой URL.
POST/sendTemplate - Доставлено
Клиент получает уведомление WhatsApp о том, что проверку не одобрили.
delivered - Результат доставки записан
Результат доставки фиксируется; ошибки обрабатываются по правилам платформы.
status:"read"

Техническая реализация
Предварительные условия
- Ключ API 1MSG · Как получить API-ключ
- Аккаунт WhatsApp Business · Как подключить WABA
- Шаблон WhatsApp · Как одобрить шаблон WABA
- Подписка клиента на рассылку · Как управлять согласием клиентов
Примеры кода
#!/usr/bin/env bash
set -euo pipefail
# === Configuration (replace "___" placeholders) ===
API_BASE_URL="https://api.1msg.io" # production 1MSG API base URL
CHANNEL_ID="___" # channel ID from 1MSG dashboard
API_TOKEN="___" # channel JWT token (Bearer)
TEMPLATE_NAME="___" # approved template name
TEMPLATE_NAMESPACE="___" # template namespace (required — send fails without it)
TEMPLATE_LANGUAGE="___" # template language code, e.g. "en"
# === Test data ===
TEST_PHONE="___" # client phone in international format
TEST_CUSTOMERNAME="___" # {{1}} customer name
TEST_PROCESS="___" # {{2}} process name
TEST_STATUS="___" # {{3}} status label
PHONE_NORM="$(printf '%s' "$TEST_PHONE" | tr -cd '0-9')"
for pair in "CHANNEL_ID=$CHANNEL_ID" "API_TOKEN=$API_TOKEN" \
"TEMPLATE_NAME=$TEMPLATE_NAME" "TEMPLATE_NAMESPACE=$TEMPLATE_NAMESPACE" \
"TEMPLATE_LANGUAGE=$TEMPLATE_LANGUAGE" "TEST_PHONE=$TEST_PHONE" \
"TEST_CUSTOMERNAME=$TEST_CUSTOMERNAME" \
"TEST_PROCESS=$TEST_PROCESS" \
"TEST_STATUS=$TEST_STATUS"; do
val="${pair#*=}"
if [ -z "$val" ] || [ "$val" = "___" ]; then
echo "Missing configuration value: ${pair%%=*}" >&2
exit 1
fi
done
if [ -z "$PHONE_NORM" ]; then
echo "Error: phone number has no digits after normalization" >&2
exit 1
fi
URL="${API_BASE_URL%/}/${CHANNEL_ID}/sendTemplate"
# params carries body ONLY. Button text is fixed in the Meta template — no button param.
# {{1}} customer name → ${TEST_CUSTOMERNAME}
# {{2}} process name → ${TEST_PROCESS}
# {{3}} status label → ${TEST_STATUS}
read -r -d '' PAYLOAD <<JSON || true
{
"phone": "${PHONE_NORM}",
"template": "${TEMPLATE_NAME}",
"namespace": "${TEMPLATE_NAMESPACE}",
"language": { "policy": "deterministic", "code": "${TEMPLATE_LANGUAGE}" },
"params": [
{
"type": "body",
"parameters": [
{ "type": "text", "text": "${TEST_CUSTOMERNAME}" },
{ "type": "text", "text": "${TEST_PROCESS}" },
{ "type": "text", "text": "${TEST_STATUS}" }
]
}
]
}
JSON
RESPONSE="$(curl -s -w '\n%{http_code}' -X POST "$URL" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${API_TOKEN}" \
-d "$PAYLOAD")"
HTTP_CODE="$(printf '%s' "$RESPONSE" | tail -n1)"
BODY="$(printf '%s' "$RESPONSE" | sed '$d')"
case "$BODY" in
*'"sent":true'*) ok=1 ;;
*) ok=0 ;;
esac
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ] && [ "$ok" -eq 1 ]; then
echo "Message sent to client."
echo "API response: $BODY"
else
echo "Send failed. HTTP status: $HTTP_CODE" >&2
echo "$BODY" >&2
exit 1
fi
Статус отклика и доставки
HTTP 2xx и JSON "sent": true значат, что 1MSG принял сообщение для отправки — но это не значит, что оно уже дошло до телефона клиента. Сохраните id поле (выглядит как wamid.…), чтобы сопоставить обратные вызовы доставки.
{
"sent": true,
"id": "wamid.HBgLMzgwNjM5...",
"message": "Message accepted for delivery"
}sentПринято для отправки — ещё не на устройстве клиента
idСохраните это; обратные вызовы доставки и
hookInfoоснованы на этом
Сообщение о доставке поступает позже, как отдельный вызов обратного вебхука. Зарегистрируйте POST …/webhookвебхук, и 1MSG передаст обновления статусов на ваш HTTPS-эндпоинт в виде основного hooks[]содержимого
{
"hooks": [
{
"id": "gBGGeSaGViBfAgnlzOSHEwK9O6F",
"type": "message",
"status": "sent",
"timestamp": "1654864094",
"recipient_id": "556123122026"
}
]
}statussent,delivered,read— или статус ошибки, если применимоidСвязывает обратный вызов с
idзначением, которое возвращает вызов sendtimestampСекунды Unix в виде строки
Если вы предпочитаете не получать обратных вызовов, вместо этого используйте polling. Однако GET {base}/{channel}/hookInfo?messageId=<id>контракт API не гарантирует доставку в течение нескольких секунд, поэтому никогда не блокируйте процесс в ожидании этого
Распространённые ошибки
| Статус | Ответ | Причина |
|---|---|---|
| 200 | Message was not sent: template is not defined | namespace, template or language missing from the request body. |
| 200 | template name (…) does not exist in <language> | The template is approved in a different language than the one requested. |
| 200 | Message was not sent: provide chatId, phone, bsuid, or username | No recipient the channel could resolve. |
| 403 | access denied | The token is wrong, or belongs to a different channel than the URL. |
| 429 | too many requests. please try later | The channel is over its send rate. |

