Отправляет новый одноразовый код через шаблон аутентификации WhatsApp, когда пользователь подтверждает важное действие в аккаунте. Кнопка «Скопировать код» помогает вставить код в диалог подтверждения.
Пример шаблона
{{1}} — ваш код подтверждения. Для безопасности не делитесь им ни с кем.
Копировать код
{{1}}
одноразовый проверочный код (цифры)
“Копировать код”
кнопка — исправлено в шаблоне Meta
Когда использовать это
Применяйте этот сценарий, когда вошедший пользователь начинает чувствительное изменение в аккаунте, например, обновление электронной почты, настройка выплат или замену API-ключа, и вам нужен новый одноразовый код перед тем, как изменения вступят в силу. Это подойдёт разработчикам, создающим порталы, небольшим командам с высокорисковыми настройками и агентствам, которым нужна дополнительная проверка безопасности и журнал аудита для проверки безопасности.
Усиленные меры безопасности перед внесением критических изменений
Бэкенд генерирует одноразовый код, когда пользователь начинает защищённое изменение, и отправляет его в одной переменной тела через шаблон аутентификации, связывая с ожидаемым действием до завершения проверки.
Быстрый ввод кода на мобильных устройствах
Кнопка «Копировать код» содержит тот же OTP, что и текст сообщения, чтобы пользователь вставлял цифры в диалог подтверждения вместо того, чтобы перепечатывать их из чата.
Проверка без открытого чата
Шаблоны категории «Аутентификация» доставляют OTP даже когда сессия поддержки не открыта, поэтому усиленная аутентификация работает при холодном запуске без необходимости начинать активный диалог.
Доставка OTP для аудита
Каждая отправка добавляет код в тело и кнопку копирования кода в соответствии с правилами шаблона аутентификации, чтобы проверки безопасности могли фиксировать доставку OTP наряду с изменениями настроек с высоким риском.
Как это работает
Триггер
Пользователь начинает защищённое изменение аккаунта.
event · triggered
Собрать и отправить
Бэкенд генерирует усиленный код и отправляет шаблон аутентификации.
#!/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_CODE="___" # {{1}} otp code
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_CODE=$TEST_CODE"; 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 and button blocks.
# {{1}} otp code → ${TEST_CODE}
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_CODE}" }
]
},
{
"type": "button",
"sub_type": "url",
"index": "0",
"parameters": [ { "type": "text", "text": "${TEST_CODE}" } ]
}
]
}
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.…), чтобы сопоставить обратные вызовы доставки.
Принято для отправки — ещёне доставлено на телефон клиента
id
Сохраните это; обратные вызовы доставки и hookInfo привязаны к этому
Доставка поступает позже, отдельным коллбэком. Зарегистрируйте вебхук (POST …/webhook), и 1MSG будет отправлять обновления статуса на ваш HTTPS-эндпоинт в основном hooks[] payload.
200 OKВебхук статуса доставки — данные, которые вы получаете
sent, delivered, read — или статус сбоя в соответствующих случаях
id
Соотносит обратный вызов с id, возвращённым вызовом send
timestamp
Секунды Unix в виде строки
Если вы предпочитаете не получать обратные вызовы, 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.
ЧАСТО ЗАДАВАЕМЫЕ ВОПРОСЫ (FAQ)
Да, для первых сообщений в WhatsApp нужен одобренный Meta шаблон.