Direct Integration to PayPal JS SDK

This guide describes how to add PayPal Smart Button to your payment page by integrating directly to PayPal's JavaScript SDK.

Prerequisites

To offer the PayPal Smart Button as a checkout option to your payers by using PayPal's JavaScript SDK:

  • Ensure tyro has an account with PayPal and has created an application with their PayPal account. Tyro should have received the client ID from PayPal and stored it against your merchant profile in Merchant Manager.
  • Ensure you have configured the PayPal integration in Merchant Administration and have granted the third-party permission to the gateway to transact on your behalf.

Information Flow

The following steps describe the information flow for a direct integration to PayPal JS SDK:

  1. Payer clicks PayPal Smart Button on your payment page.
  2. Javascript in the payer's browser sends a request to your server.
  3. Your server performs the Initiate Browser Payment operation on the gateway to start the payment process with PayPal.
  4. Gateway returns the interaction ID from PayPal to your server.
  5. Your server returns the interaction ID to the Javascript that is running in the payer's browser.
  6. The payer's browser then displays the PayPal UI.
  7. The Javascript in the payer's browser interacts with your server to proceed with the payment process.
  8. Your server performs the Confirm Browser Payment operation on the gateway to complete the payment.

Add Smart Button Using PayPal's JavaScript SDK

Follow the steps outlined below to build your integration to PayPal's JavaScript SDK.

Step 1: Get the Client ID

Get the client ID by submitting the Payment Options Inquiry request to the gateway. The response returns a client ID that you must use in the subsequent steps.

Example Request
https://<your_host_name>/api/rest/version/<api_version>/merchant/<your_gateway_merchantId>/paymentOptionsInquiry
        
Example Response
{
    "merchant": "TESTPP_V2_MER33;",
    "paymentTypes": {
        "paypal": {
            "currencies": [
                {
                    "currency": "AUD"
                },
            ],
            "transactionSources": [
                {
                    "transactionSource": "INTERNET"
                }
            ]
            "clientId": "ARLDC7ynAfGNlnJy8PuLanMRQvteg9RsfxAMLK-43amD5_urCn0Jl1APryAyWEvIm_GY1ippISEwsoza",
            "accountId": "RMU2YU3VN8SUL"
        }
    },
    "result": "SUCCESS",
    "supportedPaymentOperations": [
        {
           "supportedPaymentOperation": "AUTHORIZE"
        }
    ]
}
        

Step 2: Add the PayPal JavaScript SDK to your Web Page

To enable the PayPal Smart Button functionality, add the PayPal JavaScript SDK to your web page. Use the client ID that you have received in the response of Payment Options Inquiry in step 1 as the value of the client-id query parameter.

Example HTML Code

<!DOCTYPE html>

<head>
    <meta name="viewport" content="width=device-width, initial-scale=1"> 
    <meta http-equiv="X-UA-Compatible" content="IE=edge" /> 
</head>

<body>
<script src="https://www.paypal.com/sdk/js?client-id=PayPal_CLIENT_ID and merchant-id=PayPal_MERCHANT_ID">
</script>
</body>
        

For more details on this step, see step 2 in the PayPal Developer guide.

Step 3: Render PayPal Smart Button on your Web Page

To render the PayPal Smart Button on your webpage, add the below code to your webpage. Use the client ID that you have received in the response of Payment Options Inquiry in step 1.

Example
<body>

  <script src="https://www.paypal.com/sdk/js?client-id=PayPal_CLIENT_ID and merchant-id=PayPal_MERCHANT_ID">
  </script>

        <div id="paypal-button-container"></div>

  <script>
          paypal.Buttons().render('#paypal-button-container'); // This function displays Smart Payment Buttons on your web page.
  </script>

</body>
        

For more details on this step, see step 3 in the PayPal Developer guide.

Step 4: Set Up a Transaction

You have to set the createOrder callback to inform your host to submit the Initiate Browser Payment request to the gateway. To set up a transaction from your server or client, see the Set up a Transaction section in the PayPal Developer guide.

The sequence of events differ based on the PayPal Checkout flow.

Sequence of Events during Checkout with PayPal

  1. Submit the Initiate Browser Payment request to the gateway with browserPayment.paypal.paymentconfirmation = CONFIRM_AT_MERCHANT
    Example Request
    {
      "apiOperation": "INITIATE_BROWSER_PAYMENT",
      "browserPayment": {
        "operation": "PAY",
        "paypal": {
          "paymentConfirmation": "CONFIRM_AT_MERCHANT"
        }
      },
      "order": {
        "amount": "679.99",
        "currency": "USD"
      },
      "sourceOfFunds": {
        "type": "PAYPAL"
      }
    }
            
    Example Response
    "browserPayment.paypal.interactionId": "EC-8AT72418NV353182U"
            
  2. Implement a callback handler that gets invoked when a payer clicks the PayPal Smart Button (shown as createOrderCallbackHandler in the example in Step 4). This handler must interact with your server to submit the Initiate Browser Payment request to the gateway.
  3. Submit the Initiate Browser Payment request from your server, and then return browserPayment.paypal.interactionId.

    The Initiate Browser Payment response contains the express checkout token in the browserPayment.paypal.interactionId field.

    Example Request
    createOrder: function() {
      return fetch('/my-server/create-paypal-transaction', {
        method: 'post',
        headers: {
          'content-type': 'application/json'
        }
      }).then(function(res) {
        return res.json();
      }).then(function(data) {
        return data.interactionId; // Return the interactionId as provided by the gateway to your server
      });
    }
            
  4. The PayPal JavaScript gets the payment form from PayPal, and then it renders the form on the payer's browser.
  5. Payer logs in to PayPal and submits the payment details to PayPal.
  6. Register the onApprove handler with PayPal.
  7. After the transaction on the PayPal UI is successful, the onApprove handler gets invoked. Now, submit the Update Browser Payment request from your server to the gateway to get the latest payment details.
    approveCallback handler
    onApprove: function (data, actions) {​​
    
        // CALL TO UPDATE_BROWSER_PAYMENT from your server;
    
    }​​;
            
    Sample Update Browser Payment Request
    //URL
    https://<your_host_name>/api/rest/version/latest/merchant/<your_merchant_id>/transaction/151109242cvbnv
    //Body
    { "apiOperation": "UPDATE_BROWSER_PAYMENT" }
    
            
    Sample Update Browser Payment Response
    {
      "device": {
        "browser": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
        "ipAddress": "66.159.204.102"
      },
      "gatewayEntryPoint": "WEB_SERVICES_API",
      "merchant": "TESTMAN1234",
      "order": {
        "amount": 679.99,
        "chargeback": {
          "amount": 0,
          "currency": "USD"
        },
        "creationTime": "2020-09-17T09:38:41.924Z",
        "currency": "USD",
        "id": "421d49456789012345678909234527890",
        "lastUpdatedTime": "2020-09-17T09:40:11.894Z",
        "merchantAmount": 679.99,
        "merchantCurrency": "USD",
        "status": "CAPTURED",
        "totalAuthorizedAmount": 679.99,
        "totalCapturedAmount": 679.99,
        "totalRefundedAmount": 0
      },
      "response": {
        "acquirerCode": "Success",
        "gatewayCode": "APPROVED"
      },
      "result": "SUCCESS",
      "shipping": {
        "address": {
          "city": "Market City",
          "country": "AUS",
          "postcodeZip": "4322",
          "stateProvince": "Queensland",
          "street": "35 Rainbow street",
          "street2": "Floor 5, Apartment 34"
        },
        "contact": {
          "firstName": "John",
          "lastName": "Smith",
          "phone": "0745231111"
        }
      },
      "timeOfLastUpdate": "2020-09-17T09:40:11.894Z",
      "timeOfRecord": "2020-09-17T09:38:41.945Z",
      "transaction": {
        "acquirer": {
          "date": "2020-09-17",
          "id": "PAYPAL",
          "merchantId": "m.m@g.com",
          "time": "09:40:11",
          "transactionId": "SVE2APDYOXKMA7RY0"
        },
        "amount": 679.99,
        "currency": "USD",
        "id": "151109242cvbnv",
        "receipt": "SVE2APDYOXKMA7RY0",
        "source": "INTERNET",
        "stan": "0",
        "type": "PAYMENT",
        "update": [
          {
            "gatewayCode": "SUBMITTED",
            "time": "2020-09-17T09:38:42.054Z"
          },
          {
            "gatewayCode": "APPROVED",
            "time": "2020-09-17T09:40:11.896Z"
          }
        ]
      },
      "version": "59"
    }
            
  8. If there is any change to the amount due to a change in the shipping amount, you display the delta amount to the payer.
  9. Once the payer confirms the payment, submit the CONFIRM_BROWSER_PAYMENT request to finalize the transaction.
    Example Request
    {
        "apiOperation": "CONFIRM_BROWSER_PAYMENT",
        "order": {
            "amount": "779.99", // amount updated as a result of updated shipping and handling charges
            "shippingAndHandlingAmount": "100.00" // updated shipping and handling charges
            ...
        }
    }
            
Decline Recovery is not supported in CONFIRM_AT_MERCHANT (that is, Checkout with PayPal).

Sequence of Events during Pay with PayPal

  1. Submit the Initiate Browser Payment request to the gateway with browserPayment.paypal.paymentconfirmation = CONFIRM_AT_PROVIDER
    Example Request
    {
      "apiOperation": "INITIATE_BROWSER_PAYMENT",
      "browserPayment": {
        "operation": "PAY",
        "paypal": {
          "paymentConfirmation": "CONFIRM_AT_PROVIDER"
        }
      },
      "order": {
        "amount": "679.99",
        "currency": "USD"
      },
      "sourceOfFunds": {
        "type": "PAYPAL"
      }
    }
            
    Example Response
    "browserPayment.paypal.interactionId": "EC-8AT72418NV353182U"
            
  2. Implement the createOrder callback in the PayPal Smart Button code. When a payer clicks the PayPal Smart Button, PayPal will execute this code.
  3. Submit the Initiate Browser Payment request, from your server and then return browserPayment.paypal.interactionId.

    The Initiate Browser Payment response contains the field browserPayment.paypal.interactionId.

    Example
    createOrder: function() {
      return fetch('/my-server/create-paypal-transaction', {
        method: 'post',
        headers: {
          'content-type': 'application/json'
        }
      }).then(function(res) {
        return res.json();
      }).then(function(data) {
        return data.interactionId; // Return the interactionId as provided by the gateway to your server
      });
    }
            
  4. The PayPal JavaScript gets the payment form from PayPal, and then it renders the form on the payer's browser.
  5. Payer logs in to PayPal and submits the payment details to PayPal.
  6. Register the onApproveCallback handler with PayPal.
  7. After the transaction on the PayPal UI is successful, the onApprove handler gets invoked. Now, submit the CONFIRM_BROWSER_PAYMENT request from your server to the gateway to finalize the payment.
    approveCallback handler
    onApprove: function (data, actions) {​​
    
        // CALL TO CONFIRM_BROWSER_PAYMENT from your server;
    }​​;
            
    Example Request
    {
        "apiOperation": "CONFIRM_BROWSER_PAYMENT"
    }
            
  8. (Optional) If the instrument is declined, PayPal sends the INSTRUMENT_DECLINED response to the Execute Payment request.

    A payer gets three attempts in total to make the payment. For more information, see Decline Recovery.

    You must do action.restart() to support DECLINE_RECOVERY.

Decline Recovery

Decline recovery is supported only using PayPal. During the transaction process if the instrument gets declined then the payer gets two more attempts to make the payment. For all the three attempts, a payer can use the same or any another instrument which is registered with PayPal to proceed with the payment. If it is a new instrument, a payer must register it with PayPal before proceeding wth the payment. A payer gets three attempts in total to make the payment. If even after the third attempt the instrument gets declined, tyro will send the TRANSACTION_REFUSED or the INSTRUMENT_DECLINED response. Henceforth, the payer will not be able to proceed with the transaction process.

Sequence of Events during Decline Recovery

  1. Submit the Initiate Browser Payment request to the gateway with browserPayment.paypal.paymentconfirmation = CONFIRM_AT_PROVIDER.

    The PayPal's payment form is displayed.

  2. A payer logs in to the PayPal's payment form, selects the payment instrument, and then clicks Pay Now.
  3. Submit the CONFIRM_BROWSER_PAYMENT request to invoke the PayPal's Execute Payment request.
  4. If the instrument is declined, PayPal sends the INSTRUMENT_DECLINED response to the Execute Payment request.

    A payer gets three attempts in total to make the payment.

  5. After the onApprove event handler receives the INSTRUMENT_DECLINED response, call the actions.restart() function to allow a payer to choose a different instrument.
Decline Recovery is not supported in CONFIRM_AT_MERCHANT (Checkout with PayPal).
action.restart()
const restartPaymentOnInstrumentDeclined = (resp, actions) => {
  if (isInstrumentDeclined(resp)) {
    return actions.restart();
  } else {
    gatewaySuccessCallbackBP(resp);
  }
}

INSTRUMENT_DECLINED

{
  "browserPayment": {
    "interaction": {
      "status": "INITIATED",
      "timeInitiated": "2021-07-15T07:10:16.176Z"
    },
    "operation": "PAY",
    "paypal": {
      "displayShippingAddress": true,
      "interactionId": "EC-9SH774983H4356451",
      "overrideShippingAddress": true,
      "paymentConfirmation": "CONFIRM_AT_PROVIDER"
    }
  },
  "gatewayEntryPoint": "WEB_SERVICES_API",
  "merchant": "PP_POI_1",
  "order": {
    "amount": 931,
    "chargeback": {
      "amount": 0,
      "currency": "USD"
    },
    "creationTime": "2021-07-15T07:10:16.152Z",
    "currency": "USD",
    "id": "vcc-206",
    "item": [
      {
        "brand": "MC",
        "category": "NA",
        "detail": {
          "unitDiscountRate": 0
        },
        "name": "name",
        "quantity": 1,
        "sku": "sku",
        "unitDiscountAmount": 0,
        "unitPrice": 931
      }
    ],
    "itemAmount": 931,
    "lastUpdatedTime": "2021-07-15T07:12:19.571Z",
    "merchantAmount": 931,
    "merchantCurrency": "USD",
    "reference": "my order",
    "status": "INITIATED",
    "taxAmount": 0,
    "totalAuthorizedAmount": 0,
    "totalCapturedAmount": 0,
    "totalDisbursedAmount": 0,
    "totalRefundedAmount": 0
  },
  "response": {
    "acquirerCode": "INSTRUMENT_DECLINED",
    "acquirerMessage": "",
    "debugInformation": "INSTRUMENT_DECLINED, The instrument presented  was either declined by the processor or bank, or it can't be used for this payment., e5a837ee6834",
    "gatewayCode": "SUBMITTED"
  },
  "result": "SUCCESS",
  "shipping": {
    "address": {
      "city": "Los Angeles",
      "company": "Google",
      "country": "USA",
      "postcodeZip": "90001",
      "stateProvince": "CA",
      "street": "2nd Main",
      "street2": "lane 2"
    },
    "contact": {
      "email": "ramakanth@gmail.com",
      "firstName": "Ramakanth",
      "lastName": "Kulkarni",
      "mobilePhone": "9999999999",
      "phone": "9999999999"
    }
  },
  "sourceOfFunds": {
    "provided": {
      "paypal": {
        "accountEmail": "johnsmith@paypal.com",
        "accountHolder": "Paul Levetsky",
        "payerId": "LM9AM5Y34N3X8"
      }
    },
    "type": "PAYPAL"
  },
  "timeOfLastUpdate": "2021-07-15T07:12:19.571Z",
  "timeOfRecord": "2021-07-15T07:10:16.171Z",
  "transaction": {
    "acquirer": {
      "date": "15 Jul 2021",
      "id": "PAYPAL",
      "merchantId": "NDXE9MFKNPCUA",
      "time": "07:12:19"
    },
    "amount": 931,
    "currency": "USD",
    "id": "1",
    "source": "INTERNET",
    "stan": "0",
    "type": "PAYMENT",
    "update": [
      {
        "gatewayCode": "SUBMITTED",
        "time": "2021-07-15T07:10:17.280Z"
      }
    ]
  },
  "version": "62"
}

TRANSACTION_REFUSED

{
  "browserPayment": {
    "interaction": {
      "status": "COMPLETED",
      "timeCompleted": "2021-07-20T09:17:27.128Z",
      "timeInitiated": "2021-07-20T09:15:56.313Z"
    },
    "operation": "PAY",
    "paypal": {
      "displayShippingAddress": true,
      "interactionId": "EC-74C02380KE247305K",
      "overrideShippingAddress": true,
      "paymentConfirmation": "CONFIRM_AT_PROVIDER"
    }
  },
  "gatewayEntryPoint": "WEB_SERVICES_API",
  "merchant": "PP_POI_1",
  "order": {
    "amount": 1.28,
    "chargeback": {
      "amount": 0,
      "currency": "USD"
    },
    "creationTime": "2021-07-20T09:15:56.278Z",
    "currency": "USD",
    "description": "Ordered goods",
    "id": "testsdkhco33",
    "item": [
      {
        "brand": "MC",
        "category": "NA",
        "name": "name",
        "quantity": 1,
        "sku": "sku",
        "unitPrice": 1.28
      }
    ],
    "itemAmount": 1.28,
    "lastUpdatedTime": "2021-07-20T09:17:27.136Z",
    "merchantAmount": 1.28,
    "merchantCurrency": "USD",
    "reference": "my order",
    "status": "FAILED",
    "taxAmount": 0,
    "totalAuthorizedAmount": 0,
    "totalCapturedAmount": 0,
    "totalDisbursedAmount": 0,
    "totalRefundedAmount": 0
  },
  "response": {
    "acquirerCode": "TRANSACTION_REFUSED",
    "acquirerMessage": "",
    "debugInformation": "TRANSACTION_REFUSED, The request was refused, cae635b964420",
    "gatewayCode": "DECLINED"
  },
  "result": "FAILURE",
  "shipping": {
    "address": {
      "city": "Los Angeles",
      "country": "USA",
      "postcodeZip": "90001",
      "stateProvince": "CA",
      "street": "2nd Main",
      "street2": "lane 2"
    },
    "contact": {
      "firstName": "Ramakanth",
      "lastName": "Kulkarni"
    }
  },
  "sourceOfFunds": {
    "provided": {
      "paypal": {
        "accountEmail": "CCREJECT-REFUSED@paypal.com",
        "accountHolder": "Paul Levetsky",
        "payerId": "LM9AM5Y34N3X8"
      }
    },
    "type": "PAYPAL"
  },
  "timeOfLastUpdate": "2021-07-20T09:17:27.136Z",
  "timeOfRecord": "2021-07-20T09:15:56.308Z",
  "transaction": {
    "acquirer": {
      "date": "20 Jul 2021",
      "id": "PAYPAL",
      "merchantId": "NDXE9MFKNPCUA",
      "time": "09:17:27"
    },
    "amount": 1.28,
    "currency": "USD",
    "id": "1",
    "source": "INTERNET",
    "stan": "0",
    "type": "PAYMENT",
    "update": [
      {
        "gatewayCode": "SUBMITTED",
        "time": "2021-07-20T09:15:57.482Z"
      },
      {
        "gatewayCode": "DECLINED",
        "time": "2021-07-20T09:17:27.128Z"
      }
    ]
  },
  "version": "62"
}

Testing your Integration

When you have completed your integration with the PayPal, you can test it by using the PayPal sandbox.

To begin the test, create an account with PayPal and use those credentials while setting up your merchant profile with tyro. Ensure you use the non-TEST merchant for these transactions.

  • Use the aforementioned steps for the integration.
  • Ensure you submit the Payment Options Inquiry request to receive the client ID of tyro in the response.
  • Ensure you have configured the PayPal integration in Merchant Administration, and have granted the third-party permission to the gateway to transact on your behalf.

Copyright © 2023 Tyro Payments