借记卡和信用卡识别

借助 Google 支付卡识别 API,您可以使用摄像头识别支付卡中的信息。该 API 支持通过光学字符识别 (OCR) 技术识别信用卡或借记卡中的主账号 (PAN) 和失效日期。该 API 会将扫描卡的任务委派给 Google Play 服务。因此,您的应用不需要请求摄像头访问权限,只需接收扫描结果即可。所有图片处理操作都在设备上进行,并且 Google 不会存储结果或共享图片数据。

为了确保最佳的用户体验和功能,该 API 具有以下限制条件:

  • 设备位于以下国家/地区:AU、BR、CA、CH、CZ、DK、ES、FI、FR、GB、HK、IE、JP、KR、NL、NO、NZ、PL、RU、SE、SG、TW、UA、US
  • 设备至少有 1 GB 的 RAM。
  • 设备配有后置摄像头。
  • 设备支持 PORTRAIT 屏幕方向。

创建请求

Activity 中的 onCreate 方法中创建 PaymentsClient 实例。您可以使用 PaymentsClient 与该 Google Pay API 进行互动。

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);
  }

创建响应后,您可以向 PendingIntent 发送异步请求,以启动支付卡识别活动。

请注意,该请求并非总是成功。如果没有启用 API,请求将失败。我们建议您根据请求的响应来调整应用的行为。在示例应用中,系统仅在收到成功响应后显示该按钮。

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);
        });
  }

如需启动支付卡识别活动,请使用以下代码示例:

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);
    }
  }

解读结果

在识别过程中,我们的算法会尝试识别支付卡。如果该 API 成功识别出结果,则会以 PaymentCardRecognitionResult 的形式返回结果。结果始终会包含卡号。如果算法未能检测到失效日期,或者日期表明该卡已失效,则失效日期可能不会显示。卡可能因为多种原因而无法被识别出。这通常是在用户取消流程且 API 返回 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();
  }