- Australia
- Austria
- Belgium
- Bulgaria
- Canada
- China
- Cyprus
- Czech Republic
- Denmark
- Estonia
- Finland
- France
- Germany
- Hong Kong
- Hungary
- Ireland
- Italy
- Japan
- Latvia
- Liechtenstein
- Lithuania
- Luxembourg
- Malta
- Netherlands
- Norway
- Poland
- Portugal
- Romania
- Singapore
- Slovakia
- Slovenia
- Spain
- Sweden
- United Kingdom
- United States
Save cards with the Android SDK
CurrentLast updated: November 7th 2023, @ 9:47:43 am
Allow customers to save their credit or debit cards in order to eliminate the need to re-enter payment details on subsequent purchases - leading to a faster checkout experience.
Use cases
Businesses save payment methods if they want customers to:
- Check out without re-entering a payment method
- Pay after use, for example, ride-sharing and food delivery
Availability
How it works
PayPal encrypts payment method information and stores it in a digital vault for that customer.
- The payer saves their payment method.
- For a first-time payer, PayPal creates a customer ID. Store this within your system for future use.
- The customer ID can be used to save another payment method for an existing customer or to display saved payment methods for a customer in your application.
The checkout process is now shorter because it uses saved payment information.
Know before you code
- This integration requires a PayPal Developer account.
- You'll need to have an existing advanced credit and debit card payments integration. PayPal must approve your account to process advanced credit and debit card payments.
- Complete the steps in Get started to get the following sandbox account information from the Developer Dashboard:
- The sandbox client ID and secret of .
- An access token to use the PayPal REST API server.
- This client-side and server-side integration uses the following:
1. Set up sandbox to save payment methods
Set up your sandbox and live business accounts to save payment methods:
- Log in to the Developer Dashboard.
- Under REST API apps, select your app name.
- Under Sandbox App Settings > App Feature Options, check Accept payments.
- Expand Advanced options. Confirm that Vault is selected.
2. Add checkbox for payers to save card
Add a checkbox
element grouped with your card collection fields to give payers the option to save their card.
1@Composable2fun CheckoutScreen() {3 var shouldSaveCard by remember { mutableStateOf(false) }4 Column {5 ...6 Row {7 Checkbox(8 checked = shouldSaveCard,9 onCheckedChange = { value -> shouldSaveCard = value }10 )11 Text("Save your card")12 }13 }14}
3. Create order and save card
Set up your server to call the Orders API. Use the Orders API request to add attributes needed to save a card.
- First-time payer
- Returning payer
Save payment method for first-time payers
This request is for payers who:
- Don't have a payment source saved into the vault.
To run 3D Secure on the card, set the payment_source.card.attributes.verification.method
to SCA_ALWAYS
or SCA_WHEN_REQUIRED
.
SCA_ALWAYS
triggers an authentication for every transaction, while SCA_WHEN_REQUIRED
triggers an authentication only when a regional compliance mandate such as PSD2 is required. 3D Secure is supported only in countries with a PSD2 compliance mandate.Note: In the following request, the
payment_source.attributes.vault.store_in_vault
with the valueON_SUCCESS
means the card is saved with a successful authorization or capture.
1curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders \2 -H "Content-Type: application/json" \3 -H "Authorization: Bearer 'ACCESS-TOKEN'" \4 -d '{5 "intent": "CAPTURE",6 "purchase_units": [{7 "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",8 "amount": {9 "currency_code": "USD",10 "value": "100.00"11 }12 }],13 "payment_source": {14 "card": {15 "attributes": {16 "vault": {17 "store_in_vault": "ON_SUCCESS"18 }19 }20 }21 }22 }
Response
Pass the order id
and card details to the Android SDK. Calling CardClient.approveOrder()
updates the order with the new card details. PayPal handles any PCI compliance issues.
When approveOrder()
succeeds, you can then authorize or capture the order using the orderID
.
Note: The request to save a payment method is made when an order is created with the
payment_source.attributes.vault.store_in_vault
property set totrue
. Vault details are available only after an order is authorized or captured.
1{2 "id": "5O190127TN364715T",3 "status": "CREATED",4 "intent": "CAPTURE",5 "payment_source": {6 "card": {7 "brand": "VISA",8 "last-digits": "1881",9 "billing_address": {10 "address_line_1": "123 Main St.",11 "address_line_2": "Unit B",12 "admin_area_2": "Anytown",13 "admin_area_1": "CA",14 "postal_code": "12345",15 "country_code": "US"16 }17 }18 },19 "purchase_units": [{20 "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",21 "amount": {22 "currency_code": "USD",23 "value": "100.00"24 }25 }],26 "create_time": "2021-10-28T21:18:49Z",27 "links": [{28 "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T",29 "rel": "self",30 "method": "GET"31 },32 {33 "href": "https://www.sandbox.paypal.com/checkoutnow?token=5O190127TN364715T",34 "rel": "approve",35 "method": "GET"36 },37 {38 "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T",39 "rel": "update",40 "method": "PATCH"41 },42 {43 "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T/capture",44 "rel": "capture",45 "method": "POST"46 }47 ]48 }
4. Approve order using SDK
Use the orderId
along with the customer's Card
information to approve the order using the PayPal SDK:
1@Composable2fun CheckoutScreen(card: Card) {3 Column {4 ...5 Button(6 onClick = { approveCardOrder(card) }7 ) {8 Text("Complete Purchase")9 }10 }11}1213fun approveCardOrder(card: Card) {1415 // Set up CardClient16 val coreConfig = CoreConfig("CLIENT_ID")17 val cardClient = CardClient(activity, coreConfig)1819 // setup CardListener20 cardClient.approveOrderListener = object : ApproveOrderListener {21 override fun onApproveOrderSuccess(result: CardResult) {22 // Capture or authorize order (see next step)23 }24 override fun onApproveOrderFailure(error: PayPalSDKError) {25 // Handle error26 }27 override fun onApproveOrderCanceled() {28 // 3DS canceled by the user29 }30 override fun onApproveOrderThreeDSecureWillLaunch() {31 // 3DS will launch32 }33 override fun onApproveOrderThreeDSecureDidFinish() {34 // 3DS finished35 }36 }3738 val returnUrl = "com.myapp.package://example.com/return_url""39 val request = CardRequest("ORDER_ID", card, returnUrl)40 cardClient.approveOrder(activity, request)41}
5. Authorize or capture order and save card
Server side
Set up your server to call the v2 Orders API:
- Call the authorize order endpoint if the
intent
passed wasAUTHORIZE
. - Call the capture order endpoint if the
intent
passed wasCAPTURE
.
Request
Authorize or capture order request
- Authorize
- Capture
1curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T/authorize \2 -H "Content-Type: application/json" \3 -H "Authorization: Bearer 'ACCESS-TOKEN'" \4 -d '{}'
Response
1{2 "id": "5O190127TN364715T",3 "status": "COMPLETED",4 "payment_source": {5 "card": {6 "brand": "VISA",7 "last_digits": "4949"8 "attributes": {9 "vault": {10 "id": "nkq2y9g",11 "customer": {12 "id": "695922590"13 },14 "status": "VAULTED",15 "links": [{16 "href": "https://api-m.sandbox.paypal.com/v3/vault/payment-tokens/nkq2y9g",17 "rel": "self",18 "method": "GET"19 },20 {21 "href": "https://api-m.sandbox.paypal.com/v3/vault/payment-tokens/nkq2y9g",22 "rel": "delete",23 "method": "DELETE"24 },25 {26 "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T",27 "rel": "up",28 "method": "GET"29 }30 ]31 }32 }33 }34 },35 "purchase_units": [{36 "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",37 "payments": {38 "captures": [{39 "id": "3C679366HH908993F",40 "status": "COMPLETED",41 "amount": {42 "currency_code": "USD",43 "value": "100.00"44 },45 "seller_protection": {46 "status": "NOT_ELIGIBLE"47 },48 "final_capture": true,49 "seller_receivable_breakdown": {50 "gross_amount": {51 "currency_code": "USD",52 "value": "100.00"53 },54 "paypal_fee": {55 "currency_code": "USD",56 "value": "3.00"57 },58 "net_amount": {59 "currency_code": "USD",60 "value": "97.00"61 }62 },63 "create_time": "2022-01-01T21:20:49Z",64 "update_time": "2022-01-01T21:20:49Z",65 "processor_response": {66 "avs_code": "Y",67 "cvv_code": "M",68 "response_code": "0000"69 },70 "links": [{71 "href": "https://api-m.sandbox.paypal.com/v2/payments/captures/3C679366HH908993F",72 "rel": "self",73 "method": "GET"74 },75 {76 "href": "https://api-m.sandbox.paypal.com/v2/payments/captures/3C679366HH908993F/refund",77 "rel": "refund",78 "method": "POST"79 }80 ]81 }]82 }83 }],84 "links": [{85 "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T",86 "rel": "self",87 "method": "GET"88 }]89}
In the response from the Authorize or Capture request, the Orders v2 API interacts with the Payment Method Tokens v3 API to save the card.
The payment_source.card.attributes.vault
stores the card information as the vault.id
, which can be used for future payments when the vault.status
is VAULTED
.
Save approved payment source
If the payment has been authorized or captured, the payer does not need to be present to save a payment_source
. To keep checkout times as short as possible, the Orders API responds as soon as payment is captured.
If the attributes.vault.status
returned after payment is APPROVED
, you won't have a vault.id
yet. An example of the attributes
object from this scenario is in the following sample:
1"attributes": {2 "vault": {3 "status": "APPROVED",4 "links": [5 {6 "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T",7 "rel": "up",8 "method": "GET"9 }10 ]11 }12 }
The Payment Method Tokens API still saves the payment source even after the Orders API returns its response and sends a webhook after the payment source is saved.
In order to retrieve a vault_id
when an APPROVED
status is returned, you'll need to subscribe to the VAULT.PAYMENT-TOKEN.CREATED
webhook.
The Payment Method Tokens API sends a webhook after the payment source is saved. An example of the VAULT.PAYMENT-TOKEN.CREATED
webhook payload is shown in the following sample:
1{2 "id":"WH-1KN88282901968003-82E75604WM969463F",3 "event_version":"1.0",4 "create_time":"2022-08-15T14:13:48.978Z",5 "resource_type":"payment_token",6 "resource_version":"3.0",7 "event_type":"VAULT.PAYMENT-TOKEN.CREATED",8 "summary":"A payment token has been created.",9 "resource":{10 "time_created":"2022-08-15T07:13:48.964PDT",11 "links":[12 {13 "href":"https://api-m.sandbox.paypal.com/v3/vault/payment-tokens/9n6724m",14 "rel":"self",15 "method":"GET",16 "encType":"application/json"17 },18 {19 "href":"https://api-m.sandbox.paypal.com/v3/vault/payment-tokens/9n6724m",20 "rel":"delete",21 "method":"DELETE",22 "encType":"application/json"23 }24 ],25 "id":"nkq2y9g",26 "payment_source":{27 "card":{28 "last_digits":"1111",29 "brand":"VISA",30 "expiry":"2027-02",31 "billing_address":{32 "address_line_1":"123 Main St.",33 "address_line_2":"Unit B",34 "admin_area_2":"Anytown",35 "admin_area_1":"CA",36 "postal_code":"12345",37 "country_code":"US"38 }39 }40 },41 "customer":{42 "id":"695922590"43 }44 },45 "links":[46 {47 "href":"https://api-m.sandbox.paypal.com/v1/notifications/webhooks-events/WH-1KN88282901968003-82E75604WM969463F",48 "rel":"self",49 "method":"GET"50 },51 {52 "href":"https://api-m.sandbox.paypal.com/v1/notifications/webhooks-events/WH-1KN88282901968003-82E75604WM969463F/resend",53 "rel":"resend",54 "method":"POST"55 }56 ]57 }
In this example, the resource.id
field is the vault ID, and resource.customer.id
is the PayPal-generated customer ID.
You can now style your card fields and test a purchase.
Payment processor codes
Payment processors return the following codes when they receive a transaction request. For advanced card payments, the code displays in the authorization object under the response_code
field.
The following sample shows the processor response codes returned in an authorization (avs_code
) and capture call (cvv_code
) response:
1"processor_response": {2 "avs_code": "Y",3 "cvv_code": "S",4 "response_code": "0000"5 }
See the Orders API response_code
object to get the processor response code for the non-PayPal payment processor errors.
6. Pay with saved payment methods
When a payer returns to your site, you can show the payer's saved payment methods with the Payment Method Tokens API.
List all saved payment methods
Make the server-side list all payment tokens API call to retrieve payment methods saved to a payer's PayPal-generated customer ID. Based on this list, you can show all saved payment methods to a payer to select during checkout.
Show saved card to payer
Display the saved card to the payer and use the Orders API to make another transaction. Use the vault ID the payer selects as an input to the Orders API.
7. Test your integration
Test your vault integration in the PayPal sandbox.
- Copy the sample request code.
- Change
'ACCESS_TOKEN'
to your access token.
Save payment method
- On the checkout page, enter the card information and select the option to save the card. You can use test card numbers from this page for testing.
- Capture the transaction.
- Log in to sandbox with your merchant account and verify the transaction.
Pay with a saved payment method
- Use the list all payment tokens API to retrieve all the payment methods saved for the payer.
- Capture the payment by passing the payer-selected vault ID to the Orders API.
- Log in to the sandbox with your merchant account and verify the transaction.
Next steps
- Test and go live with this integration.
- Complete production onboarding to be eligible to process cards with your live PayPal account.
- Be sure to swap the credentials and API URL from sandbox to production when going live with your integration.
- Follow Use payment method token with checkout for subsequent or recurring transactions.
- You can get a payment token, list all payment tokens, delete a payment token, and more with the Payment Method Tokens API.
- Keep saved cards up-to-date with the real-time account updater.