Integre o reCAPTCHA com apps iOS

Esta página explica como integrar o reCAPTCHA na sua app iOS.

Devido à variação nos dispositivos móveis em termos de tamanho do ecrã, desempenho e interfaces do utilizador das apps, o desafio reCAPTCHA de caixa de verificação visual (Não sou um robô) não está disponível para apps móveis iOS. Em alternativa, pode implementar a sua própria estratégia de aplicação em camadas, como um fluxo de MFA, para fornecer um caminho de resgate alternativo para tráfego suspeito.

O SDK usa a reflexão e o código dinâmico para permitir a atualização e o refinamento do sistema de deteção em aplicações ou SDKs já implementados. Para evitar interferências com a aplicação, o conjunto de classes disponíveis no sistema está restrito a uma lista cuidadosamente controlada.

Antes de começar

  1. Defina o SDK mínimo da sua app para iOS 12 ou crie uma nova app para dispositivos móveis.

  2. Prepare o seu ambiente para o reCAPTCHA.

  3. Crie uma chave do reCAPTCHA para a plataforma de apps iOS.

    Em alternativa, pode copiar o ID de uma chave do reCAPTCHA existente para iOS através de um dos seguintes passos:

    • Para copiar o ID de uma chave existente a partir da Google Cloud consola, faça o seguinte:

      1. Aceda à página reCAPTCHA.

        Aceder ao reCAPTCHA

      2. Na lista de chaves do reCAPTCHA, mantenha o ponteiro sobre a chave que quer copiar e, de seguida, clique em .
    • Para copiar o ID de uma chave existente através da API REST, use o método projects.keys.list.
    • Para copiar o ID de uma chave existente através da CLI gcloud, use o comando gcloud recaptcha keys list.

  4. Ter uma conta do GitHub.

  5. Leia os detalhes de privacidade da Apple.

Prepare o seu ambiente iOS

Para preparar o ambiente de programação, faça o seguinte:

  1. Transfira e instale a versão mais recente do Xcode e crie uma nova aplicação iOS de visualização única em branco.

  2. Transfira o SDK através de uma das seguintes opções:

    CocoaPods

    1. Transfira e instale o CocoaPods.
    2. Crie um Podfile e adicione as seguintes linhas ao seu Podfile:

      source "https://github.com/CocoaPods/Specs.git"
      
      target 'AppTarget' do
      
        # Podfiles must include use_frameworks! or
        # use_frameworks! :linkage => :static
        use_frameworks!
      
        pod "RecaptchaEnterprise", "18.8.0"
        ...
      
      end
      
    3. Instale as dependências necessárias executando pod update.

    Swift Package Manager

    1. No Xcode, selecione File > Add Packages e introduza o seguinte URL no campo Search ou Enter Package URL: https://github.com/GoogleCloudPlatform/recaptcha-enterprise-mobile-sdk
    2. Na caixa de diálogo Xcode, introduza os seguintes detalhes:

      • Nome de utilizador do GitHub.
      • Um token de acesso pessoal que criou através das instruções do GitHub. O token de acesso pessoal tem de ter os âmbitos indicados na caixa de diálogo Iniciar sessão com o XCode.

      O Xcode instala o SDK e as respetivas dependências necessárias.

    Flutter

    Para ver instruções detalhadas sobre a utilização do reCAPTCHA através do Flutter, consulte a documentação do Flutter.

    ReactNative

    Para ver instruções detalhadas sobre a utilização do reCAPTCHA através do React Native, consulte a documentação do React Native.

    Transferência direta

    1. Se quiser transferir o SDK e as respetivas dependências como xcframeworks, transfira o cliente.

Integre o reCAPTCHA com a sua app iOS

Para integrar o reCAPTCHA com a sua app iOS, siga estes passos no Xcode:

  1. Para instanciar o SDK com a chave do reCAPTCHA (KEY_ID) que criou, atualize a app com o seguinte código:

    Swift com guião gráfico

    1. Atualize o ViewController.swift.

      import RecaptchaEnterprise
      
      class ViewController: UIViewController {
        var recaptchaClient: RecaptchaClient?
      
        override func viewDidLoad() {
          super.viewDidLoad()
          Task {
            do {
              self.recaptchaClient = try await Recaptcha.fetchClient(withSiteKey: "KEY_ID")
            } catch let error as RecaptchaError {
               print("RecaptchaClient creation error: \(String(describing: error.errorMessage)).")
            }
          }
        }
      }
      

      Se a versão mínima do SO da sua aplicação for inferior a 13, use um fecho final:

      import RecaptchaEnterprise
      
      class ViewController: UIViewController {
        var recaptchaClient: RecaptchaClient?
      
        override func viewDidLoad() {
          super.viewDidLoad()
          Recaptcha.fetchClient(withSiteKey: "KEY_ID") { client, error in
            guard let client = client else {
                print("RecaptchaClient creation error: \(error).")
              return
            }
            self.recaptchaClient = client
          }
        }
      }
      

    Swift com SwiftUI

    1. Crie uma turma ViewModel.

      import RecaptchaEnterprise
      
      @MainActor class ViewModel: ObservableObject {
        private var recaptchaClient: RecaptchaClient?
      
        init() {
           Task {
            do {
              self.recaptchaClient = try await Recaptcha.fetchClient(withSiteKey: "KEY_ID")
            } catch let error as RecaptchaError {
               print("RecaptchaClient creation error: \(String(describing: error.errorMessage)).")
            }
          }
        }
      }
      

      Se a versão mínima do SO da sua aplicação for inferior a 13, use um fecho final:

      import RecaptchaEnterprise
      
      class ViewController: UIViewController {
        var recaptchaClient: RecaptchaClient?
      
        override func viewDidLoad() {
          super.viewDidLoad()
          Recaptcha.fetchClient(withSiteKey: "KEY_ID") { client, error in
            guard let client = client else {
                print("RecaptchaClient creation error: \(error).")
              return
            }
            self.recaptchaClient = client
          }
        }
      }
      
    2. Instancie ViewModel em ContentView.swift.

      import SwiftUI
      import RecaptchaEnterprise
      
      struct ContentView: View {
        @StateObject private var viewModel = ViewModel()
      
        var body: some View {
        }
      }
      
      struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
          ContentView()
        }
      }
      

    Objective-C

    1. Se a sua app estiver escrita em Objective-C, crie um ficheiro Swift fictício e inclua a seguinte importação para se certificar de que o Xcode consegue encontrar e associar as bibliotecas Swift.

      import Foundation
      
    2. Para garantir que o código Swift está associado corretamente, navegue para Target > Build Settings > Always Embed Swift Standard Libraries e verifique se a opção está definida como Yes.

    3. Atualize o ViewController.h.

      #import <RecaptchaEnterprise/RecaptchaEnterprise.h>
      
      @interface ViewController : UIViewController
      @property (strong, atomic) RecaptchaClient *recaptchaClient;
      @end
      
    4. Atualize o ViewController.m.

      @implementation ViewController
      [Recaptcha fetchClientWithSiteKey:@"KEY_ID"
            completion:^void(RecaptchaClient* recaptchaClient, NSError* error) {
              if (!recaptchaClient) {
                NSLog(@"%@", (RecaptchaError *)error.errorMessage);
                return;
              }
              self->_recaptchaClient = recaptchaClient;
            }
      ];
      @end
      

    A inicialização do SDK pode demorar vários segundos a ser concluída. Para mitigar esta latência, inicialize o cliente o mais cedo possível, como durante a chamada onCreate() de uma classe Application personalizada. Não deve fazer com que os elementos da IU bloqueiem no SDK reCAPTCHA.

  2. Crie um botão para chamar o reCAPTCHA e acionar execute().

    Swift com guião gráfico

    1. No guião ilustrado, crie um botão.
    2. Crie uma ação em ViewController associada ao botão que criou.
    3. Chame o método execute() transmitindo uma ação Login para devolver um token do reCAPTCHA através do seguinte fragmento de código:

      guard let recaptchaClient = recaptchaClient else {
        print("RecaptchaClient creation failed.")
        return
      }
      Task {
        do {
          let token = try await recaptchaClient.execute(withAction: RecaptchaAction.login)
          print(token)
        } catch let error as RecaptchaError {
          print(error.errorMessage)
        }
      }
      

      Se a versão mínima do SO da sua aplicação for inferior a 13, use um fecho final:

      guard let recaptchaClient = recaptchaClient else {
        print("RecaptchaClient creation failed.")
        return
      }
      recaptchaClient.execute(withAction: RecaptchaAction.login) { token, error in
        if let token = token {
          print(token)
        } else {
          print(error)
        }
      }
      

    Swift com SwiftUI

    1. Atualize o ficheiro ViewModel.swift com o código de execução:

      import RecaptchaEnterprise
      
      @MainActor class ViewModel: ObservableObject {
      
        func execute() {
          guard let recaptchaClient = self.recaptchaClient else {
            print("Client not initialized correctly.")
            return
          }
      
          Task {
            do {
              let token = try await recaptchaClient.execute(withAction: RecaptchaAction.login)
              print(token)
            } catch let error as RecaptchaError {
              print(error.errorMessage)
            }
          }
        }
      }
      

      Se a versão mínima do SO da sua aplicação for inferior a 13, use um fecho final:

      guard let recaptchaClient = recaptchaClient else {
        print("RecaptchaClient creation failed.")
        return
      }
      recaptchaClient.execute(withAction: RecaptchaAction.login) { token, error in
        if let token = token {
          print(token)
        } else {
          print(error)
        }
      }
      
    2. Atualize o ficheiro ContentView.swift.

      import SwiftUI
      import RecaptchaEnterprise
      
      struct ContentView: View {
        @StateObject private var viewModel = ViewModel()
      
        var body: some View {
      
          Button {
            viewModel.execute()
          } label: {
            Text("Execute")
          }.padding()
      
          Spacer()
        }
      }
      
      struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
          ContentView()
        }
      }
      

    Objective-C

    1. No guião ilustrado, crie um botão.
    2. Crie uma ação em ViewController associada ao botão que criou.
    3. Chame o método execute() transmitindo uma ação Login para devolver um token reCAPTCHA:

      if (!self->_recaptchaClient) {
        return;
      }
      
      [recaptchaClient execute:RecaptchaAction.login
          completion:^void(NSString* _Nullable  token, NSError* _Nullable error) {
        if (!token) {
          NSLog (@"%@", (RecaptchaError *)error.errorMessage);
          return;
        }
        NSLog (@"%@", token);
      }];
      

    A API execute do cliente pode demorar vários segundos a ser concluída, por exemplo, em condições de rede lentas ou se estiver a aguardar a conclusão da inicialização em segundo plano. Certifique-se de que as chamadas execute() não bloqueiam um evento da IU, como premir um botão.

  3. Teste a sua aplicação:

    1. O reCAPTCHA usa a App Attest da Apple como parte do respetivo motor de deteção. Se não planeia usar uma chave de teste com uma pontuação fixa para o desenvolvimento local, faça o seguinte:

      1. No Xcode, adicione a capacidade App Attest à sua app.

      2. No ficheiro .entitlements do seu projeto, defina o ambiente do App Attest como production.

    2. Para limpar o ambiente de compilação do Xcode, no menu Product, clique em Clean Build Folder.

    3. Para executar a aplicação, no menu Produto, clique em Executar.

    4. Na aplicação carregada, clique no botão que criou anteriormente.

    5. Observe a janela de saída de depuração para ver um token do reCAPTCHA (string alfanumérica), que é devolvido se a integração for bem-sucedida.

Migrar da API method para o método fetchClient

O método fetchClient devolve um RecaptchaClient que tenta novamente a inicialização em caso de falhas de rede. Se a app não tiver acesso à rede quando o cliente é criado, o cliente continua a tentar e é inicializado com êxito quando é adquirida uma rede.

Se chamar execute(timeout) e o cliente ainda não estiver pronto, tenta inicializar antes de devolver um token ou um RecaptchaErrorCode.

O exemplo seguinte mostra como migrar de getClient para fetchClient.

Swift com guião gráfico

// Migrate from getClient
func initializeWithGetClient() {
  Task {
    do {
      self.recaptchaClient = try await Recaptcha.getClient(withSiteKey: "KEY_ID")
    } catch let error as RecaptchaError {
        print("RecaptchaClient creation error: \(String(describing: error.errorMessage)).")
    }
  }
}

// Migrate to fetchClient
func initializeWithFetchClient() {
  Task {
    do {
      self.recaptchaClient = try await Recaptcha.fetchClient(withSiteKey: "KEY_ID")
    } catch let error as RecaptchaError {
        print("RecaptchaClient creation error: \(String(describing: error.errorMessage)).")
    }
  }
}

Se a versão mínima do SO da sua aplicação for inferior a 13, use um fecho final:

// Migrate from getClient
override func initializeWithGetClient() {
  Recaptcha.getClient(withSiteKey: "KEY_ID") { client, error in
    guard let client = client else {
        print("RecaptchaClient creation error: \(error).")
      return
    }
    self.recaptchaClient = client
  }
}

// Migrate to fetchClient
override func initializeWithFetchClient() {
  Recaptcha.fetchClient(withSiteKey: "KEY_ID") { client, error in
    guard let client = client else {
        print("RecaptchaClient creation error: \(error).")
      return
    }
    self.recaptchaClient = client
  }
}

Swift com SwiftUI

// Migrate from getClient
initializeWithGetClient() {
    Task {
    do {
      self.recaptchaClient = try await Recaptcha.getClient(withSiteKey: "KEY_ID")
    } catch let error as RecaptchaError {
        print("RecaptchaClient creation error: \(String(describing: error.errorMessage)).")
    }
  }
}

// Migrate to fetchClient
initializeWithFetchClient() {
    Task {
    do {
      self.recaptchaClient = try await Recaptcha.fetchClient(withSiteKey: "KEY_ID")
    } catch let error as RecaptchaError {
        print("RecaptchaClient creation error: \(String(describing: error.errorMessage)).")
    }
  }
}

Se a versão mínima do SO da sua aplicação for inferior a 13, use um fecho final:

// Migrate from getClient
func initializeWithGetClient() {
  super.viewDidLoad()
  Recaptcha.getClient(withSiteKey: "KEY_ID") { client, error in
    guard let client = client else {
        print("RecaptchaClient creation error: \(error).")
      return
    }
    self.recaptchaClient = client
  }
}

// Migrate to fetchClient
func initializeWithFetchClient() {
  super.viewDidLoad()
  Recaptcha.fetchClient(withSiteKey: "KEY_ID") { client, error in
    guard let client = client else {
        print("RecaptchaClient creation error: \(error).")
      return
    }
    self.recaptchaClient = client
  }
}

Objective-C

// Migrate from getClient
@implementation ViewController
[Recaptcha getClientWithSiteKey:@"KEY_ID"
      completion:^void(RecaptchaClient* recaptchaClient, NSError* error) {
        if (!recaptchaClient) {
          NSLog(@"%@", (RecaptchaError *)error.errorMessage);
          return;
        }
        self->_recaptchaClient = recaptchaClient;
      }
];
@end

// Migrate to fetchClient
@implementation ViewController
[Recaptcha fetchClientWithSiteKey:@"KEY_ID"
      completion:^void(RecaptchaClient* recaptchaClient, NSError* error) {
        if (!recaptchaClient) {
          NSLog(@"%@", (RecaptchaError *)error.errorMessage);
          return;
        }
        self->_recaptchaClient = recaptchaClient;
      }
];
@end

Defina um limite de tempo para chamadas API

Pode especificar um valor de tempo limite para as APIs execute através da propriedade withTimeout.

Swift

  1. Defina o limite de tempo ao ligar para execute.

      Task {
        do {
          let token = try await recaptchaClient.execute(
            withAction: RecaptchaAction.login,
            withTimeout: 10000)
          print(token)
        } catch let error as RecaptchaError {
          print(error.errorMessage)
        }
      }
    

    Se a versão mínima do SO da sua aplicação for inferior a 13, use um fecho final:

      recaptchaClient.execute(
        withAction: RecaptchaAction.login,
        withTimeout: 10000
      ) { token, error in
        if let token = token {
          print(token)
        } else {
          print(error)
        }
      }
    

Objective-C

  1. Defina o limite de tempo ao ligar para execute.

      [recaptchaClient execute:RecaptchaAction.login
          witTimeout:10000.0
          completion:^void(NSString* _Nullable  token, NSError* _Nullable error) {
        if (!token) {
          NSLog (@"%@", (RecaptchaError *)error.errorMessage);
          return;
        }
        NSLog (@"%@", token);
      }];
    

Processar erros

Se a sua app não conseguir comunicar com o serviço reCAPTCHA, tal pode dever-se a um erro da API. Tem de adicionar lógica na sua app para processar estes erros de forma adequada.

Para mais detalhes sobre mitigações de erros comuns da API, consulte o artigo RecaptchaErrorCode.

Referência da API

Para uma referência completa da API reCAPTCHA para iOS, consulte RecaptchaEnterprise.

O que se segue?

  • Para avaliar o token de resposta do reCAPTCHA, crie uma avaliação.