[Flutter] SMS から認証コード自動取得する方法

こんにちは、株式会社 Pentagon でアプリ開発をしている Kuwano です!

プロジェクトで、「自動で認証コードを取得したい」という要望があったので調べてみました!

【こんな人に読んで欲しい】

  • Flutter で認証コード入力ページを作りたい人
  • Flutter で自動で認証コードを取得したい人

【この記事を読むメリット】

iOS・Android の両方で、自動で SMS 認証コード取得する仕組みがわかる。

目次

注意

sms_retriever は最終更新が 2 年前で、Flutter の非推奨 API を使っているみたいなので新規実装する場合は他のパッケージを使った方が良さそうです。

The plugin sms_retriever uses a deprecated version of the Android embedding.
To avoid unexpected runtime failures, or future build failures, try to see if this plugin supports the Android V2 embedding. Otherwise, consider removing it since a future release of Flutter will remove these deprecated APIs.
If you are plugin author, take a look at the docs for migrating the plugin to the V2 embedding: https://flutter.dev/go/android-plugin-migration.

今回のコードが動作している環境
sms_retriever 1.0.0
pin_code_fields 7.4.0
flutter 2.10.5

実装

sms_retrieverpin_code_fieldsを使用します。

pin_code_fields で、iOS の SMS の自動取得&認証コード入力ウィジェットの作成、
sms_retriever で、Android の SMS の自動取得を行います。

私は flutter_hooks を使用して実装しているので、statefulWidget を使用している方は適宜書き換えてください。

final textEditingController = useTextEditingController();
final isMounted = useIsMounted();
useEffect(
  () {
    // iOSは[PinCodeTextField]で取得するので、ここではAndroidのみ取得する
    if (!Platform.isAndroid) {
      return () {};
    }
    () async {
      final String? comingSms;
      try {
        comingSms = await SmsRetriever.startListening();
      } on PlatformException {
        return;
      }
      if (!isMounted()) {
        return;
      }

      Logger.log('comingSms: $comingSms');

      // 取得したSMSから認証コードを抜き出す
      // 自分の環境に合うように修正してください
      final receivedCode = comingSms.substring(15, 19);
      textEditingController.text = receivedCode;
    }();

    return SmsRetriever.stopListening;
  },
  [],
);

~~~

PinCodeTextField(
  appContext: context,
  controller: textEditingController,
  onChanged: (_) {},
  onCompleted: (text) async {
    process();
  },
),

送信する SMS の注意点

Apple や Google の仕様変更によってアプリ側で SMS が取得できなくなるかもしれません。
その場合は最新の情報をチェックして下さい。

iOS

iOS では特殊なことをせずに認証コードをスペースで区切ると、上記の実装で認識されます。

〇〇の認証コードは 1234 です。

セキュリティ向上策として、ドメイン名を含むこともできるみたいです。
必須ではないので参考リンクだけ置いておきます。
Enhance SMS-delivered code security with domain-bound codes

Android

Android ではこちらの対応が必須になります
アプリのハッシュ文字列の計算

Flutter プロジェクト内の/androidに移動して、以下のコマンドを実行して下さい。
すると 11 桁の文字列が出力されます。

※ 次のコマンドので囲まれた部分を環境に合わせて書き直して下さい。

keytool -exportcert -keystore <keystoreFile> -alias <alias> -storepass <storePass> | xxd -p | tr -d "[:space:]" | xxd -r -p | base64 | cut -c1-11

注: keytool コマンドが失敗した場合(エイリアスがキーストア内に存在しない場合など)、このコマンドはエラーを出力しません。パイプライン全体を実行する前に、keytool コマンドを単独で実行して、有意義な出力を生成することを確認してください。

android 用の SMS は以下になります。

〇〇の認証コードは 1234 です。
<ハッシュ文字列>

iOS と Android に同じ SMS を送信したい場合

こちらを送ると、iOS と Android に同じ SMS を送信しても Flutter アプリで認識されます。

〇〇の認証コードは 1234 です。
<androidのハッシュ文字列>

まとめ

Flutter でより高品質なアプリを作りましょう!

おまけ

Flutterに関する知識を深めたい方には、『Flutterの特徴・メリット・デメリットを徹底解説』という記事がおすすめです。

この記事では、Flutter アプリ開発の基本から、Flutter とは何か、そして実際のFlutter アプリ 事例を通じて、その将来性やメリット、デメリットまで詳しく解説しています。
Flutterを使ったアプリ開発に興味がある方、またはその潜在的な可能性を理解したい方にとって、必見の内容となっています。

ぜひ一度ご覧ください。

採用情報はこちら
目次