Проблема с verifiyPhoneNumber в приложении Flutter/Firebase: ‘несоответствие токена’

Вопросы и ответы

Я пытаюсь заставить работу ‘signinwithphonenumber’ на протяжении нескольких ДНЕЙ, но, похоже, у меня ничего не получается на iOS. Он работает отлично на Android, но, как бы я ни старался, не могу заставить работать версию для iOS.

Вот как я выполняю вход в firebase:

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // Инициализация Firebase
  await Firebase.initializeApp(
    name: '<имя приложения>',
    options: DefaultFirebaseOptions.currentPlatform,
  ).then((_) {
    print("Firebase успешно инициализирован.");
  }).catchError((error) {
    print("Ошибка инициализации Firebase: $error");
  });

// Очистка кеша Firestore
  try {
    await FirebaseFirestore.instance.clearPersistence();
    print('Кеш Firestore очищен.');
  } catch (e) {
    print('Ошибка очистки кеша Firestore: $e');
  }

  // Настройка Firestore
  try {
    FirebaseFirestore.instance.settings = const Settings(
      persistenceEnabled: false,
      sslEnabled: false,
      cacheSizeBytes: Settings.CACHE_SIZE_UNLIMITED,
    );
    print('Настройки Firestore обновлены.');
  } catch (e) {
    print('Ошибка настройки Firestore: $e');
  }

  globals.fbdb = FirebaseFirestore.instance;
  globals.fbauth = FirebaseAuth.instance;
  globals.fbs = FirebaseStorage.instance;

  // Запуск приложения
  runApp(const <имя приложения>());
}

Вот где я пытаюсь подтвердить номер телефона:

  static Future<void> verifyPhoneNumber(String phoneNumber) async {
    await FirebaseMessaging.instance.getToken();

    print("+++ phoneNumber = ${phoneNumber}");
    await globals.fbauth.verifyPhoneNumber(
      phoneNumber: phoneNumber,
      verificationCompleted: (PhoneAuthCredential credential) async {
        // Автополучение кода подтверждения
        print("Подтверждение завершено по какой-то причине!");
      },
      verificationFailed: (FirebaseAuthException e) {
        // Подтверждение не удалось
        print('+++ Подтверждение не удалось. Ошибка = ${e}');
      },
      codeSent: (String verificationId, int? resendToken) async {
        // Сохраните идентификатор подтверждения для дальнейшего использования
        print('дошел до секции codeSent');
      },
      codeAutoRetrievalTimeout: (String verificationId) {},
      timeout: Duration(seconds: 60),
    );
  }
}

И это всегда активирует секцию ‘verificationFailed’ с ошибкой ‘Несоответствие токена’.

Это AppDelegate.swift:

import UIKit
import Firebase
import Flutter
import FirebaseMessaging
import FirebaseAuth

@main
@objc class AppDelegate: FlutterAppDelegate {
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        // Инициализация Firebase
        GeneratedPluginRegistrant.register(with: self)
        Messaging.messaging().delegate = self
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }

    override func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        if Auth.auth().canHandleNotification(userInfo) {
            print(userInfo)
            return
        }
        completionHandler(.newData)
    }

    override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        Auth.auth().setAPNSToken(deviceToken, type: AuthAPNSTokenType.unknown)
    }
}

extension AppDelegate: MessagingDelegate {
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
        print("Токен регистрации Firebase: \(String(describing: fcmToken))")
    }
}

Версия Flutter = 3.24.3 <> Стабильный канал
Dart 3.5.3
Devtools 2.37.3

Xcode: Версия 15.4 (15F31d)

Android Studio Koala Feature Drop | 2024.1.2

Mac mini M2 Pro – 32 ГБ

Тестирование на iPhone 13 (реальное устройство)

  • Нет проблем с компиляцией
  • Все плагины обновлены (все Firebase версии последние доступные)
  • Файл ‘firebase-options.dart’ настроен и правильный (проверено)
  • URL Type с REVERSE_CLIENT_ID правильный
  • Я проверил и перепроверил все сертификаты от Apple, и ключ .p8 был сгенерирован около 4 раз, чтобы убедиться, что у меня не было какого-то сбоя (!) при его генерации или что-то подобное
  • ‘Аутентификация’ в консоли Firebase настроена с ‘Вход с помощью Google’, ‘Вход с помощью номера телефона’ и ‘вход с адресом электронной почты и паролем’ – все включено.
  • Имена пакетов все правильные, так же как и имя приложения Firebase, где оно упоминается
  • Я переключил ‘Автоматически сгенерированный ключ для iOS’ в Google Cloud Platform на блокировку для приложений iOS
  • Я являюсь платным разработчиком Apple
  • Правильный профиль поставки настроен
  • Файл GoogleService-Info.plist находится в правильном месте и все содержимое правильное
  • Режимы работы в разделе ‘signing & capabilities’ установлены на ‘Фоновая выборка’ и ‘Удаленные уведомления’

Это от многих часов изучения StackOverflow, чтения и перепроверки документации от Google и делания всего, что я мог придумать, чтобы это заработало…

…но весь тот же код (точно) работает отлично на Android.

ПОМОГИТЕ! Я теряю желание жить!

Ответ

Проблема с ошибкой "Token mismatch" при использовании метода verifyPhoneNumber в приложении Flutter/Firebase на iOS может быть вызвана различными факторами. Давайте пройдемся по шагам, которые помогут решить вашу проблему.

1. Проверьте конфигурацию Firebase

Убедитесь, что ваши настройки Firebase для iOS выполнены правильно:

  • GoogleService-Info.plist: Проверьте, что файл действительно находится в папке iOS вашего проекта и что он корректен (с правильными идентификаторами).
  • URL Type: Проверьте, что URL Type в настройках вашего проекта iOS содержит правильное значение REVERSE_CLIENT_ID.
  • Push Notifications: Убедитесь, что включены push-уведомления и что ваше приложение имеет соответствующие разрешения.

2. Настройка AppDelegate.swift

Ваш код в AppDelegate.swift выглядит в целом правильно, но добавьте обработку уведомлений при инициализации Firebase. Убедитесь, что вы правильно инициализируете Firebase и его настройки. Например:

import UserNotifications

@main
@objc class AppDelegate: FlutterAppDelegate {
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        // Инициализация Firebase
        FirebaseApp.configure()

        // Настройка push-уведомлений
        UNUserNotificationCenter.current().delegate = self

        GeneratedPluginRegistrant.register(with: self)
        Messaging.messaging().delegate = self
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }

    // Имplement other methods...
}

Также убедитесь, что вы вызываете FirebaseApp.configure() только один раз, чтобы избежать конфликтов.

3. Настройка аутентификации

Проверьте, что в разделе Authentication консоли Firebase у вас действительно активированы все нужные способы входа, включая Sign in with Phone. Перепроверьте настройки и, при необходимости, отключите и снова включите.

4. Обновление Firebase и других зависимостей

Убедитесь, что все плагины Firebase обновлены до последней версии. Это можно сделать с помощью команды:

flutter pub upgrade

5. Отладка кода

Измените функцию verifyPhoneNumber так, чтобы в случае возникновения ошибок вы могли легче отладить проблему. Например, добавьте больше логирования, чтобы вы могли видеть все шаги выполнения:

static Future<void> verifyPhoneNumber(String phoneNumber) async {
    print("Attempting to verify phone number: $phoneNumber");

    await globals.fbauth.verifyPhoneNumber(
      phoneNumber: phoneNumber,
      verificationCompleted: (PhoneAuthCredential credential) async {
          print("Verification completed. Credential: $credential");
          // Здесь можно выполнить аутентификацию с использованием credential
      },
      verificationFailed: (FirebaseAuthException e) {
          print('Verification failed. Error: ${e.code} - ${e.message}');
      },
      codeSent: (String verificationId, int? resendToken) async {
          print('Code sent. Verification ID: $verificationId');
          // Сохраните verificationId для дальнейшей обработки
      },
      codeAutoRetrievalTimeout: (String verificationId) {
          print('Code auto retrieval timeout. Verification ID: $verificationId');
      },
      timeout: Duration(seconds: 60),
    );
}

6. Проверка телефонного номера

Убедитесь, что формат телефонного номера правильный и включает код страны. Например, для России это будет выглядеть так: +79123456789.

7. Разрешения на устройствах

Убедитесь, что ваше приложение имеет разрешения на отправку SMS на устройства iOS. Убедитесь, что вы не сбрасываете настройки устройства или эмитируете его, так как это может повлиять на аутентификацию.

8. Используйте real device

Убедитесь, что вы тестируете на реальном устройстве, так как тестирование на симуляторе не всегда может дать корректные результаты для функций, связанных с SMS.

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

Оцените материал
Добавить комментарий

Капча загружается...