# PayPal JS SDK
source: https://developer.mastercard.com/mastercard-gateway/documentation/payment-methods/digital-wallets/paypal/paypal-js-sdk/index.md

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

## Prerequisites {#prerequisites}

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

* Ensure that your payment service provider has an account with PayPal and has created an application with their PayPal account. Your payment service provider 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 {#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](https://developer.mastercard.com/mastercard-gateway/documentation/api-reference/v100/rest/api-ops/index.md#browser-payment) operation on the gateway to start the payment process with PayPal.
4. The 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](https://developer.mastercard.com/mastercard-gateway/documentation/api-reference/v100/rest/api-ops/index.md#browser-payment) operation on the gateway to complete the payment.

## Add smart button using PayPal's JavaScript SDK {#add-smart-button-using-paypals-javascript-sdk}

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

### Step 1: Get the Client ID {#step-1-get-the-client-id}

Get the client ID by submitting the [Payment Options Inquiry](https://developer.mastercard.com/mastercard-gateway/documentation/api-reference/v100/rest/api-ops/index.md#gateway) request to the gateway. The response returns a client ID that you must use in the subsequent steps.

#### Example Request {#example-request}

```h
https://<your_host_name>/api/rest/version/<api_version>/merchant/<your_gateway_merchantId>/paymentOptionsInquiry
```

#### Example Response {#example-response}

```json
{
    "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 {#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 {#example-html-code}

```html
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
</head>
<body>
    https://www.paypal.com/sdk/js?client-id=PayPal_CLIENT_ID and merchant-id=PayPal_MERCHANT_ID
</body>
</html>
```

For more details on this step, see step 2 in the [PayPal Developer](https://developer.paypal.com/docs/checkout/integrate#2-add-the-paypal-javascript-sdk-to-your-web-page) guide.

### Step 3: Render a PayPal Smart Button on your web page {#step-3-render-a-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 the Payment Options Inquiry in step 1.

#### Example {#example}

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

    <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](https://developer.paypal.com/docs/checkout/integrate/#3-render-the-smart-payment-buttons) guide.

### Step 4: Set up a transaction {#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 [Setup a Transaction](https://developer.paypal.com/docs/checkout/reference/server-integration/set-up-transaction/) section in the PayPal Developer guide.

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

* For Checkout with PayPal, see the [Sequence of Events during Checkout with PayPal](https://developer.mastercard.com/mastercard-gateway/documentation/payment-methods/digital-wallets/paypal/paypal-js-sdk/index.md#sequence-of-events-during-checkout-with-paypal) section.
* For Pay with PayPal, see the [Sequence of Events in the Pay with PayPal](https://developer.mastercard.com/mastercard-gateway/documentation/payment-methods/digital-wallets/paypal/paypal-js-sdk/index.md#sequence-of-events-during-pay-with-paypal) section.

##### Sequence of Events during Checkout with PayPal {#sequence-of-events-during-checkout-with-paypal}

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

   ```json
   {
     "apiOperation": "INITIATE_BROWSER_PAYMENT",
     "browserPayment": {
       "operation": "PAY",
       "paypal": {
         "paymentConfirmation": "CONFIRM_AT_MERCHANT"
       }
     },
     "order": {
       "amount": "679.99",
       "currency": "USD"
     },
     "sourceOfFunds": {
       "type": "PAYPAL"
     }
   } 
   ```

   ```json
   "browserPayment.paypal.interactionId": "EC-8AT72418NV353182U" 
   ```

   <br />

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 {#example-request-1}

```js
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](https://developer.mastercard.com/mastercard-gateway/documentation/api-reference/v100/rest/api-ops/index.md#browser-payment) request from your server to the gateway to get the latest payment details.

#### approveCallback handler {#approvecallback-handler}

```js
onApprove: function (data, actions) {
    // CALL TO UPDATE_BROWSER_PAYMENT from your server
    return fetch('/my-server/update-browser-payment', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            interactionId: data.orderID // or data.interactionId depending on your flow
        })
    })
    .then(function(res) {
        return res.json();
    })
    .then(function(response) {
        // Handle response from your server
        console.log('Payment updated:', response);
    });
}
```

#### Sample Update Browser Payment Request {#sample-update-browser-payment-request}

```h
https://<your_host_name>/api/rest/version/latest/merchant/<your_merchant_id>/transaction/151109242cvbnv
```

#### Sample Update Browser Payment Response {#sample-update-browser-payment-response}

```json
{
  "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 {#example-request-2}

```json
{
  "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
    // ...
  }
}
```

Warning: Decline Recovery is not supported in **CONFIRM_AT_MERCHANT** (that is, Checkout with PayPal).

##### Sequence of Events during Pay 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.

```json
{
  "apiOperation": "INITIATE_BROWSER_PAYMENT",
  "browserPayment": {
    "operation": "PAY",
    "paypal": {
      "paymentConfirmation": "CONFIRM_AT_PROVIDER"
    }
  },
  "order": {
    "amount": "679.99",
    "currency": "USD"
  },
  "sourceOfFunds": {
    "type": "PAYPAL"
  }
} 
```

```json
"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 {#example-1}

```js
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 {#approvecallback-handler-1}

```js
onApprove: function (data, actions) {
  // CALL TO CONFIRM_BROWSER_PAYMENT from your server
}
```

#### Example Request {#example-request-3}

```json
{
  "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](https://developer.mastercard.com/mastercard-gateway/documentation/payment-methods/digital-wallets/paypal/paypal-js-sdk/index.md#decline-recovery).  

Do `action.restart()` to support `DECLINE_RECOVERY`.

### 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 with the payment. A payer gets three attempts in total to make the payment. If even after the third attempt the instrument gets declined, your payment service provider 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 {#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.

Warning: Decline Recovery is not supported in **CONFIRM_AT_MERCHANT** (Checkout with PayPal).

#### action.restart() {#actionrestart}

```js
const restartPaymentOnInstrumentDeclined = (resp, actions) => {
  if (isInstrumentDeclined(resp)) {
    return actions.restart();
  } else {
    gatewaySuccessCallbackBP(resp);
  }
};
```

#### INSTRUMENT_DECLINED {#instrument_declined}

```json
{
  "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": "",
```

#### TRANSACTION_REFUSED {#transaction_refused}

```json
{
  "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 {#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 your payment service provider. 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 your payment service provider 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.
