Debit and credit card recognition

The Google payment card recognition API provides the ability to use a camera to recognize information from payment cards. The API supports recognition of the primary account number (PAN) and the expiration date from a credit card or a debit card through optical character recognition (OCR). The API delegates the task of scanning the card to Google Play services. Therefore, your app doesn't need to request camera permission and only receives the scan results. All image processing occurs on the device and Google doesn't store the results or share the image data.

To ensure the optimal user experience and functionality, the API has the following constraints:

  • The device has a Google account logged in.
  • The device has at least 1 GB of RAM.
  • The device has a back facing camera.
  • The device has the latest Google Play services version.
  • The device supports PORTRAIT orientation.

Create a request

Create a PaymentsClient instance in the onCreate method in your Activity . You can use PaymentsClient to interact with the 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 
 ); 
  
 } 
  

After you create the response, you can then send an asynchronous request for a PendingIntent , which you can use to start the payment card recognition activity.

Keep in mind that the request doesn't always succeed. If there is no API enablement, the request fails. We suggest that you adjust your app's behavior according to the response to the request. In the sample app, we display the button only after we receive a successful response.

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

To start the payment card recognition activity, use the following code sample:

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

Interpret the result

During the recognition process, our algorithm attempts to recognize the payment card. If it successfully recognizes a result, then the API returns the result as a PaymentCardRecognitionResult . The result always contains a card number. The expiration date might not be present if the algorithm fails to detect one, or if the date shows that the card is past its expiration date. For various reasons, a card might not be recognizable. This usually results when a user cancels a flow and the API returns 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 
 (); 
  
 } 
  
Create a Mobile Website
View Site in Mobile | Classic
Share by: