如果您的移动应用程序为用户提供通过 WhatsApp 应用程序或 WhatsApp Business 应用程序接收一次性密码或验证码的选项,您必须使用带有一次性密码按钮 (OTP) 的身份验证模板来提供密码或验证码。

带有 OTP 按钮的身份验证模板包含以下内容:
- 预设认证消息模板固定文本:
- <VERIFICATION_CODE> 是您的验证码。
- 安全免责声明(可选):为了您的安全,请勿共享此代码。
- 过期警告(可选):此代码将在 <NUM_MINUTES> 分钟后过期。
- 按钮:复制代码或一键自动填充按钮。
代码长度不能超过 15 个字符。不支持 URL、媒体和表情符号。由于带有 OTP 按钮的身份验证模板仅由预设文本和按钮组成,因此其被暂停的风险显着降低。
按钮
身份验证模板必须包含复制代码或一键自动填充按钮。当用户点击时按钮的行为有所不同:
- 复制代码按钮可将一次性密码或代码复制到用户的剪贴板。然后,用户可以手动切换到您的应用程序并将密码或代码粘贴到您的应用程序界面中。
- 一键式自动填充按钮会自动加载并向您的应用程序传递一次性密码或代码。
一键式按钮是首选解决方案,因为它们提供最佳的用户体验。但是,一键式按钮目前仅在 Android 上受支持,需要更改应用程序的代码才能执行“握手”以及应用程序的签名密钥哈希。请参阅下面的握手和应用程序签名密钥哈希。
最佳实践
- 在向该号码发送一次性密码或代码之前,请先确认用户的 WhatsApp 电话号码。
- 向您的用户明确表示密码或代码将发送至他们的 WhatsApp 电话号码,特别是当您为用户提供多种接收密码或代码发送的方式时。请参阅选择加入以获取更多提示。
- 当用户将密码或代码粘贴到您的应用中,或者您的应用将其作为一键自动填充按钮流程的一部分接收时,请向用户明确该应用已被捕获。
模板创建
使用YCloud template create创建认证模板。或者,您可以使用YCloud background手动创建它们。
组件
Components 属性值必须是一个对象数组,用于描述构成模板的每个组件。身份验证模板必须具有以下组件:
- 单个主体组件
- 单个页脚组件
- 单个OTP 按钮组件
示例请求(一键自动填充)
请求示例(复制代码)
App Signing Key Hash(应用程序签名密钥哈希)
如果您要创建使用一键式自动填充按钮的身份验证模板,则必须在组件数组中包含您的应用程序签名密钥哈希。
要计算您的哈希值,请按照 Google计算应用程序哈希字符串的说明进行操作。
或者,如果您按照 Google 的说明下载应用签名密钥证书(步骤 1),则可以将您的证书与 sms_retriever_hash_v9.sh shell脚本结合使用来计算哈希值。例如:
./sms_retriever_hash_v9.sh --package "com.example.myapplication" --keystore ~/.android/debug.keystore
发送认证模板消息
使用YCloud Whatsapp api发送认证模板消息。
请注意,如果您要发送具有一键式自动填充按钮的身份验证模板,则必须首先在您的应用程序和 WhatsApp Messenger 或 WhatsApp Business 之间发起握手。请参阅下面的握手。
Handshake(握手)
如果您的任何身份验证模板使用一键式自动填充按钮,您的应用程序必须能够启动“握手”。
握手是您实现的 Android 意图和公共类,但我们可以从 WhatsApp 应用程序或 WhatsApp Business 应用程序开始。
当您的应用中的用户请求一次性密码或验证码并选择将其发送到他们的 WhatsApp 号码时,首先执行握手,然后调用我们的 API 发送身份验证模板消息。当 WhatsApp 应用程序或 WhatsApp Business 应用程序收到消息时,它将执行资格检查,如果没有错误,则启动意图并向用户显示消息。最后,当用户点击消息的一键自动填充按钮时,我们会自动加载您的应用程序并向其传递密码或代码。

如果您在发送消息之前未执行握手,或者消息未通过资格检查,则发送的消息将显示复制代码按钮,而不是一键按钮。
资格检查
WhatsApp 应用程序或 WhatsApp Business 应用程序在收到身份验证模板消息时执行以下检查。如果任何检查失败,一键式自动填充按钮将替换为复制代码按钮。
- 握手是在不到10分钟前开始的。
- 消息中的包名称(在创建模板时在组件数组中的package_name属性中定义)与意图上设置的包名称匹配。匹配是通过应用程序提供的PendingIntent对象中调用的getCreatorPackage方法确定的。请参阅组件和公共类。
- 消息中的应用程序签名密钥哈希(在创建模板时在组件数组的signature_hash 属性中定义)与已安装的应用程序的签名密钥哈希相匹配。查看组件
- 该消息包括一键自动填充按钮文本。
- 您的应用程序已定义一个活动来接收密码或代码。请参阅下面的活动。
安卓通知
仅在以下情况下,指示收到 WhatsApp 身份验证模板消息的 Android 通知才会显示在用户的 Android 设备上:
- 用户使用消息发送到的电话号码(帐户)登录 WhatsApp 应用程序或 WhatsApp Business 应用程序。
- 用户已登录到您的应用程序。
- Android 操作系统为 KitKat(4.4、API 19)或更高版本。
- 在 WhatsApp 应用程序或 WhatsApp Business 应用程序中启用显示通知(设置 > 通知)。
- 已为 WhatsApp 应用或 WhatsApp Business 应用启用设备级通知。
- 用户和您的企业之间的 WhatsApp 应用或 WhatsApp Business 应用中之前的消息线程不会被静音。
客户端实施
在您的应用程序中实现以下活动和类。
活动
声明一个可以接收一次性密码或代码的活动和意图过滤器。意图过滤器必须具有操作名称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 应用程序在收到身份验证模板消息并通过所有资格检查后将启动的活动。
公共类
定义为公共活动类,该类在代码传递到您的应用程序后可以接受该代码。
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");
}
}
}
发起握手
此示例演示了与 WhatsApp 应用或 WhatsApp Business 应用发起握手的一种方法。
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);
}