Set up advanced credit and debit card payments

Create a customized checkout experience by adding credit card fields that align with your brand.

Know before you code

  • Integrate advanced credit and debit card payments if you want a customized card form. If you are looking for a quicker way to accept payments and are not concerned with customization, see our Set up standard payments integration.
  • See the country and currency availability list to see where advanced credit and debit card payments is available.
  • Complete the steps in Get started to get the following sandbox account information from the Developer Dashboard:

    • Your sandbox account login information
    • Your access token
  • Advanced credit and debit cards requires that your business account be evaluated and approved by PayPal. You'll complete this process when you onboard in Step 1.
  • (UK merchants) Credit is a regulated activity in the UK. Before integrating a PayPal Credit button, you must be authorized to act as a credit broker and have a credit agreement with PayPal. For more information, contact business customer support through paypal.com or by calling 0800 358 7929.

  • This client-side and server-side integration uses the following:

How it works

This demo shows a checkout flow that integrates advanced credit and debit card payments to customize the credit card fields.

Custom Card Fields demo

1. Enable your account

Before you can accept card payments on your website, your account has to be enabled. The process includes completing information about your business before PayPal can approve you.

For this step, you'll request the feature for your sandbox business account as you're building your integration on the sandbox. Sandbox requests are automatically approved so you can build and test your integration. Before you test and go live, you'll request the feature for your merchant account in the production environment.

Important: The code for the integration checks eligibility requirements, so the payment card fields won't display if the sandbox or production request isn't successful.

Request advanced debit and credit card processing for your sandbox business account.

Tip: When prompted for required data like a phone number for the sandbox business request, enter any number that fits the required format. Since this is a sandbox request, the data doesn't have to be factual.

2. Generate client token

Generate a client token to uniquely identify your buyer. The client token is required and without it, the card fields won't accept a card.

The following request generates a client token that you'll use for data-client-token when you add the JavaScript SDK script to your web page in Step 3.

Copy the following code and modify it.

Sample client token request

curl -X POST https://api-m.sandbox.paypal.com/v1/identity/generate-token \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <ACCESS-TOKEN>' \
-H 'Accept-Language: en_US' \

Modify the code

  1. Copy the sample request code.
  2. Change Access-Token to your access token.

Step result

A successful request results in a client token and the number of seconds the token is valid. You can generate a new client token if the current token expires.

Tip: Because each buyer session is unique, set up your server to generate a new client token each time the card fields render on your page.

Sample client token response

{
  "client_token": "eyJicmFpbnRyZWUiOnsiYXV0aG9yaXphdGlvbkZpbmdlcnByaW50IjoiYjA0MWE2M2JlMTM4M2NlZGUxZTI3OWFlNDlhMWIyNzZlY2FjOTYzOWU2NjlhMGIzODQyYTdkMTY3NzcwYmY0OHxtZXJjaGFudF9pZD1yd3dua3FnMnhnNTZobTJuJnB1YmxpY19rZXk9czlic3BuaGtxMmYzaDk0NCZjcmVhdGVkX2F0PTIwMTgtMTEtMTRUMTE6MTg6MDAuMTU3WiIsInZlcnNpb24iOiIzLXBheXBhbCJ9LCJwYXlwYWwiOnsiYWNjZXNzVG9rZW4iOiJBMjFBQUhNVExyMmctVDlhSTJacUZHUmlFZ0ZFZGRHTGwxTzRlX0lvdk9ESVg2Q3pSdW5BVy02TzI2MjdiWUJ2cDNjQ0FNWi1lTFBNc2NDWnN0bDUyNHJyUGhUQklJNlBBIn19",
  "expires_in": 3600
}

3. Add JavaScript SDK and card form

To accept payments on your website, add the PayPal JavaScript SDK code with card form elements to your checkout page.

Sample JavaScript SDK code

This fully-styled sample code adds payment buttons and card fields to your website that capture the payment immediately.

<html>
<head>

  <meta charset="utf-8"/>
  <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Optimal rendering on mobile devices. -->
  <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <!-- Optimal Internet Explorer compatibility -->
  <script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
  <link rel="stylesheet" type="text/css" href="cardfields.css"/>

</head>
<body>

<!-- JavaScript SDK -->
 <script src="https://www.paypal.com/sdk/js?components=hosted-fields,buttons&client-id=<YOUR-CLIENT-ID>" data-client-token="<YOUR-CLIENT-TOKEN>"></script>

   <!-- Buttons container -->
   <table border="0" align="center" valign="top" bgcolor="#FFFFFF" style="width:39%">
     <tr>
       <td colspan="2">
         <div id="paypal-button-container"></div>
       </td>
     </tr>
     <tr><td colspan="2">&nbsp;</td></tr>
   </table>

   <div align="center"> or </div>

   <!-- Advanced credit and debit card payments form -->
   <div class='card_container'>
     <form id='my-sample-form'>

       <label for='card-number'>Card Number</label><div id='card-number' class='card_field'></div>
       <div>
         <label for='expiration-date'>Expiration Date</label><div id='expiration-date' class='card_field'></div>
       </div>
       <div>
         <label for='cvv'>CVV</label><div id='cvv' class='card_field'></div>
       </div>
       <label for='card-holder-name'>Name on Card</label><input type='text' id='card-holder-name' name='card-holder-name' autocomplete='off' placeholder='card holder name'/>
       <div>
         <label for='card-billing-address-street'>Billing Address</label><input type='text' id='card-billing-address-street' name='card-billing-address-street' autocomplete='off' placeholder='street address'/>
       </div>
       <div>
         <label for='card-billing-address-unit'>&nbsp;</label><input type='text' id='card-billing-address-unit' name='card-billing-address-unit' autocomplete='off' placeholder='unit'/>
       </div>
       <div>
         <input type='text' id='card-billing-address-city' name='card-billing-address-city' autocomplete='off' placeholder='city'/>
       </div>
       <div>
         <input type='text' id='card-billing-address-state' name='card-billing-address-state' autocomplete='off' placeholder='state'/>
       </div>
       <div>
         <input type='text' id='card-billing-address-zip' name='card-billing-address-zip' autocomplete='off' placeholder='zip / postal code'/>
       </div>
       <div>
         <input type='text' id='card-billing-address-country' name='card-billing-address-country' autocomplete='off' placeholder='country code' />
       </div>
       <br><br>
       <button value='submit' id='submit' class='btn'>Pay</button>
     </form>
   </div>

   <!-- Implementation -->
   <script>
     //Displays PayPal buttons
     paypal.Buttons({
       commit: false,
          createOrder: function(data, actions) {
           // This function sets up the details of the transaction, including the amount and line item details
           return actions.order.create({
             purchase_units: [{
               amount: {
                 value: '2'
               }
             }]
           });
         },
         onCancel: function (data) {
             // Show a cancel page, or return to cart
          },
         onApprove: function(data, actions) {
           // This function captures the funds from the transaction
           return actions.order.capture().then(function(details) {
             // This function shows a transaction success message to your buyer
             alert('Thanks for your purchase!');
           });
         }
     }).render('#paypal-button-container');
     // Eligibility check for advanced credit and debit card payments
     if (paypal.HostedFields.isEligible()) {
       paypal.HostedFields.render({
         createOrder: function () {return "order-ID";}, // replace order-ID with the order ID
         styles: {
           'input': {
             'font-size': '17px',
             'font-family': 'helvetica, tahoma, calibri, sans-serif',
             'color': '#3a3a3a'
           },
           ':focus': {
             'color': 'black'
           }
         },
         fields: {
           number: {
             selector: '#card-number',
             placeholder: 'card number'
           },
           cvv: {
             selector: '#cvv',
             placeholder: 'card security number'
           },
           expirationDate: {
             selector: '#expiration-date',
             placeholder: 'mm/yy'
           }
         }
       }).then(function (hf) {
         $('#my-sample-form').submit(function (event) {
           event.preventDefault();
           hf.submit({
             // Cardholder Name
             cardholderName: document.getElementById('card-holder-name').value,
             // Billing Address
             billingAddress: {
               streetAddress: document.getElementById('card-billing-address-street').value,      // address_line_1 - street
               extendedAddress: document.getElementById('card-billing-address-unit').value,       // address_line_2 - unit
               region: document.getElementById('card-billing-address-state').value,           // admin_area_1 - state
               locality: document.getElementById('card-billing-address-city').value,          // admin_area_2 - town / city
               postalCode: document.getElementById('card-billing-address-zip').value,           // postal_code - postal_code
               countryCodeAlpha2: document.getElementById('card-billing-address-country').value   // country_code - country
             }
           // redirect after successful order approval
           }).then(function () {
        window.location.replace('http://www.somesite.com/review');
      }).catch(function (err) {
        console.log('error: ', JSON.stringify(err));
        document.getElementById("consoleLog").innerHTML = JSON.stringify(err);
           });
         });
       });
     }
     else {
       $('#my-sample-form').hide();  // hides the advanced credit and debit card payments fields if merchant isn't eligible
     }
   </script>

   </body>
   </html>

Modify the code

  1. Download the sample CSS file, cardfields.css, and save it in the same directory as your Checkout JavaScript SDK code.
  2. Copy the sample JavaScript SDK code and paste it into the code of your checkout page. This sample code is optimized for JavaScript performance. To learn more about this and other optimization considerations, see JavaScript SDK performance optimization.
  3. In the SDK code, replace YOUR_SB_CLIENT_ID with your client ID and data-client-token with the client token that you generated in the previous step.

    • The components=hosted-fields,buttons parameter displays the PayPal buttons and card fields component.
    • The client token is required in the JavaScript SDK and without it, the card fields won't accept a card.
  4. Explicitly pass parameters to override the default values the PayPal JavaScript SDK uses. Review the JavaScript SDK reference to learn about these default values. Example: currency defaults to USD.
  5. Find createOrder: function () {return "order-ID";}, and change order -ID to your order ID.
  6. Create JavaScript or server-side code to pass purchase variables, like amount: value, to the JavaScript SDK code. Your implementation varies based on the other systems and integrations you're using to manage inventory and order details. Refer to the Orders REST API to learn more about the values you can pass as you build your code.
  7. If you process payments that require Strong Customer Authentication (SCA), you must provide additional context about the transaction with payment indicators.

Step result

Working buttons and card fields display on your checkout page. Refresh the webpage to see the payment buttons and card fields. The payment buttons send your buyer to PayPal to complete a purchase. The card fields transaction completes when the buyer approves the payment on your checkout page.

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.

This sample represents the processor response codes that are returned in the response of authorization and capture calls:

"processor_response": {
    "avs_code": "Y",
    "cvv_code": "S",
    "payment_advice_code": "",
    "response_code": "0000"
}

If an external payment processor declines a transaction, PayPal returns a HTTP 201 Created status code and a status of DECLINED in the capture status.

See the Orders API response_code object to get the processor response code for the non-PayPal payment processor errors.

4. Capture order

If you're not redirecting your buyer to a review page after a successful approval, make sure you have logic in your server-side code that can immediately capture the order when a buyer pays with a credit or debit card. Server-side code keeps you from exposing your access token on the client.

curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders/ <order-id>/capture \
-H "Content-Type: application/json" \
-H "Authorization: Bearer Access-Token" \
-H "PayPal-Request-Id: 7b92603e-77ed-4896-8e78-5dea2050476a"

See also

You can move on to styling your card fields and testing a purchase.

5. Style card fields

Style the card fields to align with your brand using the CSS properties supported by this integration.

Next steps

See also