Reconhecimento de cartão de crédito e débito

A API Payment Card Recognition do Google possibilita o uso de uma câmera para reconhecer as informações dos cartões de pagamento. A API é compatível com o reconhecimento do número da conta principal (PAN, na sigla em inglês) e da data de validade de um cartão de crédito ou débito por meio do reconhecimento óptico de caracteres (OCR). A API delega a tarefa de verificação do cartão para os serviços do Google Play. Portanto, seu app não precisa solicitar a permissão da câmera e recebe apenas os resultados da verificação. Todo o processamento de imagens ocorre no dispositivo, e o Google não armazena os resultados nem compartilha os dados das imagens.

Para garantir a melhor funcionalidade e experiência do usuário, a API tem as seguintes restrições:

  • O dispositivo precisa estar disponível em países específicos (AU, BR, CA, CH, CZ, DK, ES, FI, FR, GB, HK, IE, JP, KR, NL, NO, NZ, PL, RU, SE, SG, TW, UA, US)
  • O dispositivo deve ter pelo menos 1 GB de RAM.
  • O dispositivo deve ter uma câmera traseira.
  • O dispositivo deve ser compatível com a orientação PORTRAIT.

Criar uma solicitação

Crie uma instância PaymentsClient no método onCreate em Activity. Use PaymentsClient para interagir com a API Google Pay.

Kotlin

    fun createPaymentsClient(activity: Activity): PaymentsClient {
        val walletOptions = Wallet.WalletOptions.Builder()
                .setEnvironment(Constants.PAYMENTS_ENVIRONMENT)
                .build()

        return Wallet.getPaymentsClient(activity, walletOptions)
    }

Java

  public static PaymentsClient createPaymentsClient(Activity activity) {
    Wallet.WalletOptions walletOptions =
        new Wallet.WalletOptions.Builder().setEnvironment(Constants.PAYMENTS_ENVIRONMENT).build();
    return Wallet.getPaymentsClient(activity, walletOptions);
  }

Depois de criar a resposta, é possível enviar uma solicitação assíncrona para um PendingIntent, que pode ser usado para iniciar a atividade de reconhecimento do cartão de pagamento.

Não se esqueça de que a solicitação nem sempre dá certo. Se a API não for ativada, a solicitação vai apresentar problemas. Recomendamos que você ajuste o comportamento do app de acordo com a resposta à solicitação. No app de exemplo, o botão aparece somente após o recebimento de uma resposta bem-sucedida.

Kotlin

    private fun possiblyShowPaymentCardOcrButton() {
        // The request can be used to configure the type of the payment card recognition. Currently
        // the only supported type is card OCR, so it is sufficient to call the getDefaultInstance()
        // method.
        val request = PaymentCardRecognitionIntentRequest.getDefaultInstance()
        paymentsClient
            .getPaymentCardRecognitionIntent(request)
            .addOnSuccessListener { intentResponse ->
                cardRecognitionPendingIntent = intentResponse.paymentCardRecognitionPendingIntent
                paymentCardOcrButton.visibility = View.VISIBLE
            }
            .addOnFailureListener { e ->
                // The API is not available either because the feature is not enabled on the device
                // or because your app is not registered.
                Log.e(TAG, "Payment card ocr not available.", e)
            }
    }

Java

  public void possiblyShowPaymentCardOcrButton() {
    // The request can be used to configure the type of the payment card recognition. Currently the
    // only supported type is card OCR, so it is sufficient to call the getDefaultInstance() method.
    PaymentCardRecognitionIntentRequest request =
        PaymentCardRecognitionIntentRequest.getDefaultInstance();
    paymentsClient
        .getPaymentCardRecognitionIntent(request)
        .addOnSuccessListener(intentResponse -> {
          cardRecognitionPendingIntent = intentResponse.getPaymentCardRecognitionPendingIntent();
          paymentCardOcrButton.setVisibility(View.VISIBLE);
        })
        .addOnFailureListener(e -> {
          // The API is not available either because the feature is not enabled on the device
          // or because your app is not registered.
          Log.e(TAG, "Payment card ocr not available.", e);
        });
  }

Para iniciar a atividade de reconhecimento do cartão de pagamento, use o exemplo de código a seguir:

Kotlin

    private fun startPaymentCardOcr() {
        try {
            ActivityCompat.startIntentSenderForResult(
                this@CheckoutActivity,
                cardRecognitionPendingIntent.intentSender,
                PAYMENT_CARD_RECOGNITION_REQUEST_CODE,
                null, 0, 0, 0, null
            )
        } catch (e: SendIntentException) {
            throw RuntimeException("Failed to start payment card recognition.", e)
        }
    }

Java

  public void startPaymentCardOcr(View view) {
    try {
      ActivityCompat.startIntentSenderForResult(
          CheckoutActivity.this, cardRecognitionPendingIntent.getIntentSender(),
          PAYMENT_CARD_RECOGNITION_REQUEST_CODE,
          null, 0, 0, 0, null);
    } catch (SendIntentException e) {
      throw new RuntimeException("Failed to start payment card recognition.", e);
    }
  }

Interpretar o resultado

Durante o processo de reconhecimento, nosso algoritmo tenta reconhecer o cartão de pagamento. Se ele reconhecer um resultado, a API vai dar um retorno como PaymentCardRecognitionResult. O resultado sempre contém um número de cartão. O algoritmo não vai detectar uma data de validade, caso ela não esteja presente ou se já tiver passado do vencimento. Por vários motivos, um cartão pode não ser reconhecível. Isso geralmente acontece quando um usuário cancela um fluxo e a API retorna o código Activity.RESULT_CANCELLED.

Kotlin

    private fun handlePaymentCardRecognitionSuccess(
        cardRecognitionResult: PaymentCardRecognitionResult
    ) {
        val creditCardExpirationDate = cardRecognitionResult.creditCardExpirationDate
        val expirationDate = creditCardExpirationDate?.let { "%02d/%d".format(it.month, it.year) }
        val cardResultText = "PAN: ${cardRecognitionResult.pan}\nExpiration date: $expirationDate"
        Toast.makeText(this, cardResultText, Toast.LENGTH_LONG).show()
    }

Java

  private void handleCardRecognitionSuccess(PaymentCardRecognitionResult cardResult) {

    String expirationDate = null;
    Locale locale = Locale.getDefault();
    CreditCardExpirationDate cardExpirationDate = cardResult.getCreditCardExpirationDate();
    if(cardExpirationDate != null) {
      expirationDate = String.format(locale,
          "%02d/%d", cardExpirationDate.getMonth(), cardExpirationDate.getYear());
    }

    String cardResultString = String.format(locale,
        "PAN: %s\nExpiration date: %s", cardResult.getPan(), expirationDate);
    Toast.makeText(this, cardResultString, Toast.LENGTH_LONG).show();
  }