借助 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(); }