We are making changes to the WhatsApp Business Platform pricing model. See Pricing Updates on the WhatsApp Business Platform.

Одноразовые пароли в Android SDK доступны в бета-версии. Они предлагают упрощенный рабочий процесс для реализации шаблонов категории "Аутентификация" с кнопкой автоматического заполнения и функцией "Без нажатия". Ниже вы найдете информация о его использовании.

Шаблоны категории "Аутентификация" с кнопкой автоматического заполнения

Шаблоны категории "Аутентификация" с кнопкой автоматического заполнения позволяют отправлять пользователям одноразовый пароль или код вместе с кнопкой автоматического заполнения. Когда пользователь WhatsApp нажимает кнопку автозаполнения, клиент WhatsApp запускает действие, которое открывает ваше приложение и передает ему пароль или код.

Шаблоны категории "Аутентификация" с кнопкой автоматического заполнения состоят из следующих элементов:

  • Предустановленный текст: "Ваш код подтверждения: <VERIFICATION_CODE>".
  • Примечание системы безопасности (необязательно): "Из соображений безопасности никому не сообщайте этот код".
  • Предупреждение об истечении срока действия (необязательно): "Срок действия этого кода истекает через <NUM_MINUTES> мин."
  • Кнопка автоматического заполнения.

Ограничения

Кнопки автоматического заполнения поддерживаются только в Android. Если вы отправите шаблон категории "Аутентификация" пользователю WhatsApp, который использует устройство, отличное от Android, вместо автоматического заполнения клиент WhatsApp отобразит кнопку копирования кода.

URL, медиафайлы и смайлики не поддерживаются.

Создание шаблона

Для создания шаблонов категории "Аутентификация" используйте конечную точку WhatsApp Business Account > Шаблоны сообщений.

Синтаксис запроса

POST /<WHATSAPP_BUSINESS_ACCOUNT_ID>/message_templates

Тело публикации

{
  "name": "<TEMPLATE_NAME>",
  "language": "<TEMPLATE_LANGUAGE>",
  "category": "authentication",
  "message_send_ttl_seconds": <TIME_T0_LIVE>, // Optional
  "components": [
    {
      "type": "body",
      "add_security_recommendation": <SECURITY_RECOMMENDATION> // Optional
    },
    {
      "type": "footer",
      "code_expiration_minutes": <CODE_EXPIRATION> // Optional
    },
    {
      "type": "buttons",
      "buttons": [
        {
          "type": "otp",
          "otp_type": "one_tap",
          "text": "<COPY_CODE_BUTTON_TEXT>",  // Optional
          "autofill_text": "<AUTOFILL_BUTTON_TEXT>", // Optional
          "supported_apps": [
            { 
              "package_name": "<PACKAGE_NAME>",
              "signature_hash": "<SIGNATURE_HASH>"
            }
          ]
        }
      ]
    }
  ]
}

Обратите внимание: в запросе на создание шаблона тип кнопки обозначается как otp, однако после создания для кнопки будет установлен тип url. Чтобы проверить это, выполните запрос GET для только что созданного шаблона и проанализируйте его компоненты.

Свойства

ЗаполнительОписаниеПример значения

<AUTOFILL_BUTTON_TEXT>

Строка

Необязательный параметр.

Текст ярлыка кнопки автоматического заполнения.

Если его не задать, для текста автоматического заполнения по умолчанию будет задано предварительно установленное значение, локализованное в соответствии с языком шаблона. Например, Autofill для английского языка (США).

Максимальное количество символов: 25.

Autofill

<CODE_EXPIRATION>

Целое число

Необязательный параметр.

Срок действия пароля или кода в минутах.

Если этот параметр задан, сообщение будет содержать предупреждения об истечении срока действия кода и это значение. Кнопка будет отключена в доставленном сообщении через указанное количество минут после его отправки.

Если не указывать этот параметр, сообщение не будет содержать предупреждения об истечении срока действия пароля. Вдобавок кнопка будет отключена через 10 минут после отправки сообщения.

Минимальное значение — 1, максимальное — 90.

5

<COPY_CODE_BUTTON_TEXT>

Строка

Необязательный параметр.

Текст ярлыка кнопки копирования кода.

Если его не задать, для текста по умолчанию будет задано предварительно установленное значение, локализованное в соответствии с языком шаблона. Например, Copy Code для английского языка (США).

Если он указан, в сообщении шаблона категории "Аутентификация" будет отображена кнопка копирования кода с этим текстом, если сообщение не пройдет проверку на соответствие правилам.

Максимальное количество символов: 25.

Copy Code

<PACKAGE_NAME>

Строка

Обязательный параметр.

Имя пакета приложения Android.

В строке должно быть как минимум два сегмента (одна или несколько точек). Каждый сегмент должен начинаться с буквы.

Можно использовать буквы, цифры и символ подчеркивания [a-zA-Z0-9_].

При использовании Graph API версии 20.0 или более ранней вы можете определить имя пакета приложения вне массива supported_apps, однако такой подход не рекомендуется. См. раздел Поддерживаемые приложения ниже.

Максимальное количество символов: 224.

com.example.luckyshrub

<SECURITY_RECOMMENDATION>

Логическое значение

Необязательный параметр.

Если шаблон должен содержать строку Из соображений безопасности никому не сообщайте этот код, установите значение true. В противном случае задайте значение false.

true

<SIGNATURE_HASH>

Строка

Обязательный параметр.

Хэш ключа подписи приложения. См. раздел Хэш ключа подписи приложения ниже.

Можно использовать буквы, цифры, символы +, / и = (a-zA-Z0-9+/=).

При использовании Graph API версии 20.0 или более ранней вы можете определить хэш подписи приложения вне массива supported_apps, однако такой подход не рекомендуется. См. раздел Поддерживаемые приложения ниже.

Ровно 11 символов.

K8a/AINcGX7

<TEMPLATE_LANGUAGE>

Строка

Обязательный параметр.

Язык и код региона, используемые в шаблоне.

en_US

<TEMPLATE_NAME>

Строка

Обязательный параметр.

Название шаблона.

Максимальное количество символов: 512.

verification_code

<TIME_TO_LIVE>

Целое число

Необязательный параметр.

Время жизни сообщения категории "Аутентификация" в секундах. См. раздел Настройка времени жизни.

60

Пример запроса

В этом примере создается шаблон с именем "authentication_code_autofill_button", категорией authentication, всеми необязательными текстовыми строками и кнопкой автоматического заполнения.

curl 'https://graph.facebook.com/v21.0/102290129340398/message_templates' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer EAAJB...' \
-d '
{
  "name": "authentication_code_autofill_button",
  "language": "en_US",
  "category": "authentication",
  "message_send_ttl_seconds": 60,
  "components": [
    {
      "type": "body",
      "add_security_recommendation": true
    },
    {
      "type": "footer",
      "code_expiration_minutes": 10
    },
    {
      "type": "buttons",
      "buttons": [
        {
          "type": "otp",
          "otp_type": "one_tap",
          "text": "Copy Code",
          "autofill_text": "Autofill",
          "package_name": "com.example.luckyshrub",
          "signature_hash": "K8a/AINcGX7"
        }
      ]
    }
  ]
}'

Пример ответа

{
  "id": "594425479261596",
  "status": "PENDING",
  "category": "AUTHENTICATION"
}

Хэш ключа подписи приложения

You must include your app signing key hash in your post body.

To calculate your hash, follow Google's instructions for computing your app's hash string.

Alternatively, if you follow Google's instructions and download your app signing key certificate (step 1), you can use your certificate with the sms_retriever_hash_v9.sh shell script to compute the hash. For example:

./sms_retriever_hash_v9.sh --package "com.example.myapplication" --keystore ~/.android/debug.keystore

Поддерживаемые приложения

The supported_apps array allows you define pairs of app package names and signing key hashes for up to 5 apps. This can be useful if you have different app builds and want each of them to be able to initiate the handshake:

"buttons": [
  {
    "type": "otp",
    ...
    "supported_apps": [
      { 
        "package_name": "<PACKAGE_NAME_1>",
        "signature_hash": "<SIGNATURE_HASH_1>"
      },
      { 
        "package_name": "<PACKAGE_NAME_2>",
        "signature_hash": "<SIGNATURE_HASH_2>"
      },
      ...
    ]
  }
]

Alternatively, if you have only a single app, you can define the app's package name and signing key hash as buttons object properties, but this is not recommened as we will stop supporting this method at a future date:

"buttons": [
  {
    "type": "otp",
    ...
    "package_name": "<PACKAGE_NAME>",
    "signature_hash": "<SIGNATURE_HASH>"
  }
]

Подтверждение подключения

Вы должны сообщить клиенту WhatsApp о скорой доставке пароля или кода. Вы можете сделать это, инициировав подтверждение подключения.

Подтверждение подключения — это намерение Android и общедоступный класс, который реализуете вы, но который может запустить клиент WhatsApp.

Когда пользователь в вашем приложении запрашивает одноразовый пароль или код и выбирает получение на свой номер WhatsApp, нужно выполнить подтверждение подключения, а затем вызвать наш API для отправки шаблона сообщения категории "Аутентификация". Когда клиент WhatsApp получит сообщение, он проверит его на соответствие правилам. Если ошибок нет, он запустит намерение и покажет сообщение пользователю. Когда пользователь нажмет кнопку автоматического заполнения, мы автоматически загрузим ваше приложение и передадим ему пароль или код.

Если не выполнить подтверждение подключения перед отправкой сообщения или сообщение не пройдет проверку на соответствие правилам, в доставленном сообщении будет отображаться кнопка копирования, а не автоматического заполнения.

Проверка на соответствие правилам

При получении шаблона сообщения категории "Аутентификация" клиент WhatsApp выполняет следующие проверки. Если хотя бы одна проверка не будет пройдена, кнопка автоматического заполнения будет заменена кнопкой копирования кода.

  • Подтверждение подключения инициировано не более 10 минут назад (или не более количества минут, указанного в свойстве code_expiration_minutes шаблона, если оно задано).
  • Имя пакета в сообщении (определяется в свойстве package_name массива components при создании шаблона) совпадает с именем пакета, заданным в намерении. Совпадение определяется методом getCreatorPackage, вызываемым в объекте PendingIntent, который предоставляет ваше приложение.
  • Никакое другое приложение из числа включенных вами в список supported_apps шаблона не инициировало подтверждение подключения в течение последних 10 минут (или в течение времени в минутах, указанного в свойстве code_expiration_minutes шаблона, если таковое имеется).
  • Хэш ключа подписи приложения (определяется в свойстве signature_hash массива компонентов при создании шаблона) совпадает с хэшем ключа подписи вашего установленного приложения.
  • В сообщении есть кнопка автоматического заполнения.
  • В вашем приложении определены действия для получения пароля или кода.

Уведомления на устройствах Android

Уведомления Android о том, что получен шаблон сообщения категории "Аутентификация" в WhatsApp, будут появляться на Android-устройстве пользователя, только если:

  • пользователь вошел в приложение WhatsApp или WhatsApp Business, используя номер телефона (аккаунт), на который отправлено сообщение;
  • пользователь вошел в ваше приложение;
  • используется Android версии KitKat (4.4, API 19) или более поздней;
  • в приложении WhatsApp или WhatsApp Business включен показ уведомлений (Настройки > Уведомления);
  • уведомления для приложения WhatsApp или WhatsApp Business включены на уровне устройства;
  • для предыдущих переписок в приложении WhatsApp или WhatsApp Business между пользователем и вашей компанией не отключены уведомления.

Использование SDK (бета-версия)

OTP Android SDK доступен в бета-версии. Его можно использовать для подтверждения подключения, а также других функций в шаблонах категории "Аутентификация" как с одним касанием, так и без касания.

Чтобы получить доступ к функциям SDK, добавьте следующую конфигурацию в файл Gradle:

dependencies {
  …
  implementation 'com.whatsapp.otp:whatsapp-otp-android-sdk:0.1.0'
  …
}

В свои репозитории добавьте mavenCentral():

repositories {
  …
  mavenCentral()
  …
}

Действия

Укажите фильтр действий и намерений, который может получить одноразовый пароль или код. Фильтр намерений должен иметь имя действия com.whatsapp.otp.OTP_RETRIEVED.

<activity
   android:name=".ReceiveCodeActivity"
   android:enabled="true"
   android:exported="true"
   android:launchMode="standard">
   <intent-filter>
       <action android:name="com.whatsapp.otp.OTP_RETRIEVED" />
   </intent-filter>
</activity>

Это действие, которое приложение WhatsApp или WhatsApp Business начнет после получения шаблона сообщения категории "Аутентификация" и прохождения всех проверок на соответствие правилам.

Класс действия

Использование SDK (предпочтительно)

Определите общедоступный класс действия и создайте экземпляр объекта WhatsAppOtpIncomingIntentHandler для обработки намерения, проверки кода одноразового пароля и обработки ошибок.

public class ReceiveCodeActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      WhatsAppOtpIncomingIntentHandler incomingIntentHandler = new WhatsAppOtpIncomingIntentHandler();
      incomingIntentHandler.processOtpCode(
                             intent,
                             // call your function to validate
                             (code) -> validateCode(code),
                             // call your function to handle errors
                             (error, exception) -> handleError(error, exception));
}

Без SDK

Определите общедоступный класс для действий, который сможет принять код после передачи вашему приложению.

public class ReceiveCodeActivity extends AppCompatActivity {

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       Intent intent = getIntent();
       // retrieve PendingIntent from extras bundle
       PendingIntent pendingIntent = intent.getParcelableExtra("_ci_");
       // verify source of the pendingIntent
       String pendingIntentCreatorPackage = pendingIntent.getCreatorPackage();
       // check if creatorPackage is "com.whatsapp" -> WA consumer app Or
       // "com.whatsapp.w4b" -> WA business app
       if ("com.whatsapp".equals(creatorPackage) || "com.whatsapp.w4b".equals(creatorPackage)) {
         // use OTP code
         String otpCode = intent.getStringExtra("code");
       }
   }
}

Инициализация подтверждения подключения

Использование SDK (предпочтительно)

Проверку подключения можно выполнить путем создания экземпляра объекта WhatsAppOtpHandler и передачи вашего контекста методу .sendOtpIntentToWhatsApp():

WhatsAppOtpHandler whatsAppOtpHandler = new WhatsAppOtpHandler();
whatsAppOtpHandler.sendOtpIntentToWhatsApp(context);

Без SDK

В этом примере демонстрируется один из способов инициировать подтверждение подключения с клиентом WhatsApp.

public void sendOtpIntentToWhatsApp() {
   // Send OTP_REQUESTED intent to both WA and WA Business App
   sendOtpIntentToWhatsApp("com.whatsapp");
   sendOtpIntentToWhatsApp("com.whatsapp.w4b");
}

private void sendOtpIntentToWhatsApp(String packageName) {

  /**
  * Starting with Build.VERSION_CODES.S, it will be required to explicitly
  * specify the mutability of  PendingIntents on creation with either
  * (@link #FLAG_IMMUTABLE} or FLAG_MUTABLE
  */
  int flags = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ? FLAG_IMMUTABLE : 0;
  PendingIntent pi = PendingIntent.getActivity(
      getApplicationContext(),
      0,
      new Intent(),
      flags);


  // Send OTP_REQUESTED intent to WhatsApp
  Intent intentToWhatsApp = new Intent();
  intentToWhatsApp.setPackage(packageName);
  intentToWhatsApp.setAction("com.whatsapp.otp.OTP_REQUESTED");
  // WA will use this to verify the identity of the caller app.
  Bundle extras = intentToWhatsApp.getExtras();
  if (extras == null) {
     extras = new Bundle();
  }
  extras.putParcelable("_ci_", pi);
  intentToWhatsApp.putExtras(extras);
  getApplicationContext().sendBroadcast(intentToWhatsApp);
}

Проверка установки клиента WhatsApp

Вы можете проверить установку клиента WhatsApp до того, как предлагать WhatsApp в качестве опции, если предполагаете, что WhatsApp и ваше приложение будут использоваться на одном устройстве.

Сначала вам необходимо добавить следующее в свой файл AndroidManifest.xml:

<queries>
    <package android:name="com.whatsapp"/>
    <package android:name="com.whatsapp.w4b"/>
</queries>

Использование SDK (предпочтительно)

Создайте экземпляр объекта WhatsAppOtpHandler:

WhatsAppOtpHandler whatsAppOtpHandler = new WhatsAppOtpHandler();

Проверьте, установлен ли клиент WhatsApp, передав метод isWhatsAppInstalled в качестве условия в заявлении If:

If (whatsAppOtpHandler.isWhatsAppInstalled(context)) {
    // ... do something
}

Без SDK

if (this.isWhatsAppInstalled(context)) {
    // ... do something
} 

public boolean isWhatsAppInstalled(final @NonNull Context context){
    return isWhatsAppInstalled(context, "com.whatsapp") || 
           isWhatsAppInstalled(context, "com.whatsapp.w4b");
  }

  public boolean isWhatsAppInstalled(final @NonNull Context context,
      final @NonNull String type){
    final Intent intent = new Intent();
    intent.setPackage(type);
    intent.setAction("com.whatsapp.otp.OTP_REQUESTED");
    PackageManager packageManager = context.getPackageManager();
    List<ResolveInfo> receivers = packageManager.queryBroadcastReceivers(intent, 0);
    return !receivers.isEmpty();
  }
}

Отправка шаблонов сообщений категории "Аутентификация"

Для отправки шаблонов сообщений категории "Аутентификация" используйте облачный или локальный API.

Обратите внимание: сначала вы должны инициировать подтверждение подключения между своим приложением и клиентом WhatsApp. См. раздел Подтверждение подключения выше.

Сигналы ошибок

См. раздел Сигналы ошибок, что может помочь с отладкой.

Пример приложения

См. наш пример приложения с одноразовым паролем (OTP) в WhatsApp для Android на Github. В этом примере показано, как отправлять и получать одноразовые пароли и коды через API, интегрировать автоматическое заполнение одним нажатием и кнопки копирования кода, создавать шаблоны, а также запускать сервер.