npm.io
10.0.1 • Published 3d ago

@paypal/paypal-js

Licence
Apache-2.0
Version
10.0.1
Deps
1
Size
654 kB
Vulns
0
Weekly
0

paypal-js

Loading wrapper and TypeScript types for the PayPal JS SDK

build status npm version npm downloads apache license

Why use paypal-js?

The default JS SDK code snippet blocks page rendering:

<script src="https://www.paypal.com/sdk/js?client-id=test"></script>
<script>
  paypal.Buttons().render("body");
</script>

The above snippet can be difficult to implement in a non-blocking way, especially in single page web apps. This is where the paypal-js library comes in. It provides the following benefits over the above snippet:

  • Async script loading to ensure page rendering isn't blocked.
  • A Promise API to know when script loading is complete.
  • A convenient way to reload the script when query parameters or data attributes change.

Installation

To get started, install paypal-js with npm.

npm install @paypal/paypal-js

Usage

Import the loadScript function for asynchronously loading the Paypal JS SDK.

loadScript(options)
  • accepts an object for passing query parameters and attributes to the JS SDK.
  • returns a Promise that resolves with window.paypal after the JS SDK is finished loading.
Async/Await
import { loadScript } from "@paypal/paypal-js";

let paypal;

try {
  paypal = await loadScript({ clientId: "test" });
} catch (error) {
  console.error("failed to load the PayPal JS SDK script", error);
}

if (paypal) {
  try {
    await paypal.Buttons().render("#your-container-element");
  } catch (error) {
    console.error("failed to render the PayPal Buttons", error);
  }
}
Promises
import { loadScript } from "@paypal/paypal-js";

loadScript({ clientId: "test" })
  .then((paypal) => {
    paypal
      .Buttons()
      .render("#your-container-element")
      .catch((error) => {
        console.error("failed to render the PayPal Buttons", error);
      });
  })
  .catch((error) => {
    console.error("failed to load the PayPal JS SDK script", error);
  });
Passing Arguments

The loadScript function accepts an object for configuring the JS SDK. It's used for setting query parameters and script attributes. It accepts parameters in camelCase or kebab-case.

Query Parameters

The following example adds client-id and currency as query string parameters:

loadScript({ clientId: "YOUR_CLIENT_ID", currency: "EUR" });

Which will load the following <script> asynchronously:

<script src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID&currency=EUR"></script>

By default, the JS SDK only loads the buttons component. The components query string parameter can be used to load multiple components:

loadScript({
  clientId: "YOUR_CLIENT_ID",
  components: ["buttons", "marks", "messages"],
});

Which will load the following <script> asynchronously:

<script src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID&components=buttons,marks,messages"></script>

View the full list of supported query parameters.

Data Attributes

All options prefixed with data are considered attributes. The following example adds data-page-type as an attribute:

loadScript({
  clientId: "YOUR_CLIENT_ID",
  dataPageType: "checkout",
});

Which will load the following <script> asynchronously:

<script
  data-page-type="checkout"
  src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID"
></script>

View the full list of supported script parameters.

Merchant Id Array

The merchantId option accepts an array to simplify the implementation for Multi-Seller Payments. With this approach the caller doesn't have to worry about managing the two different merchant id values (data-merchant-id and merchant-id).

Here's an example with multiple merchantId values:

loadScript({
  clientId: "YOUR_CLIENT_ID",
  merchantId: ["123", "456", "789"],
});

Which will load the following <script> and use merchant-id=* to properly configure the edge cache:

<script
  data-merchant-id="123,456,789"
  src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID&merchant-id=*"
></script>

Here's an example with one merchant-id value:

loadScript({
  clientId: "YOUR_CLIENT_ID",
  merchantId: ["123"],
});

When there's only one, the merchant-id is passed in using the query string.

<script src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID&merchant-id=123"></script>
sdkBaseUrl

For local development, the sdkBaseUrl option can be used to set the base url of the JS SDK:

loadScript({
  clientId: "YOUR_CLIENT_ID",
  sdkBaseUrl: "http://localhost.paypal.com:8000/sdk/js",
});
Legacy Browser Support

This library relies on JavaScript Promises. To support legacy browsers like IE 11, you must provide your own Promise polyfill. With a Promise polyfill this library will support the same browsers as the JS SDK.

The loadScript() function takes in a second parameter for providing a Promise ponyfill. It defaults to the global Promise object if it exists. There are two options for polyfilling the Promise object:

  1. Use a global polyfill strategy that monkey patches the window.Promise API implementation.
  2. Use a ponyfill strategy that passes a Promise library into loadScript() without affecting other code:
import { loadScript } from "@paypal/paypal-js";
import PromisePonyfill from "promise-polyfill";

loadScript(options, PromisePonyfill).then((paypalObject) => {});

We also provide a legacy build that includes the promise-polyfill library. You can reference it from the CDN here:

<script src="https://unpkg.com/@paypal/paypal-js@9.4.0/dist/iife/paypal-js.legacy.min.js"></script>
Using a CDN

The paypal-js script is also available on the unpkg CDN. The iife/paypal-js.js build assigns the loadScript function to the window object as window.paypalLoadScript. Here's an example:

<!doctype html>
<html lang="en">
  <head>
    <script src="https://unpkg.com/@paypal/paypal-js@9.4.0/dist/iife/paypal-js.min.js"></script>
  </head>
  <body>
    <div id="paypal-buttons"></div>
    <script>
      window.paypalLoadScript({ clientId: "test" }).then((paypal) => {
        paypal.Buttons().render("#paypal-buttons");
      });
    </script>
  </body>
</html>
loadCustomScript(options)

The loadCustomScript function is a generic script loader function that works with any url.

  • accepts an object for defining the script url and attributes.
  • returns a promise to indicate if the script was successfully loaded.
Async/Await
import { loadCustomScript } from "@paypal/paypal-js";

try {
  await loadCustomScript({
    url: "https://www.example.com/index.js",
    attributes: {
      id: "custom-id-value",
      "data-foo": "custom-data-attribute",
    },
  });

  console.log("successfully loaded the custom script");
} catch (error) {
  console.error("failed to load the custom script", error);
}
Promises
import { loadCustomScript } from "@paypal/paypal-js";

loadCustomScript({
  url: "https://www.example.com/index.js",
  attributes: { id: "custom-id-value", "data-foo": "custom-data-attribute" },
})
  .then(() => {
    console.log("successfully loaded the custom script");
  })
  .catch((err) => {
    console.error("failed to load the custom script", err);
  });

TypeScript Support

This package includes TypeScript type definitions for the PayPal JS SDK. This includes types for the window.paypal namespace. We support projects using TypeScript versions >= 3.8.

V6 SDK Support

The PayPal Web SDK V6 introduces a modern, component-based architecture with a createInstance() pattern, explicit component loading, and built-in eligibility checking.

Loading the V6 SDK

Use loadCoreSdkScript() to asynchronously load the V6 SDK:

import { loadCoreSdkScript } from "@paypal/paypal-js/sdk-v6";

const paypal = await loadCoreSdkScript({
  environment: "sandbox", // "sandbox" | "production"
  debug: true, // optional
});

Options:

Important: environment is required. The clientId does not determine which environment is loaded in v6 — environment does. A live clientId will still load the sandbox SDK if environment: "sandbox" is passed.

Option Type Description
environment "sandbox" | "production" Required. Target environment. clientId does not select the environment in v6 — this option does.
debug boolean Enable debug mode
dataNamespace string Custom global namespace
Creating an SDK Instance

After loading, create an instance with createInstance():

const sdkInstance = await paypal.createInstance({
  clientId: "YOUR_CLIENT_ID",
  components: ["paypal-payments", "venmo-payments"],
  locale: "en-US",
  pageType: "checkout",
});
V6 Components

These are the components that currently support the TypeScript types offered for the V6 PayPal JS SDK via paypal-js.

Component Description
paypal-payments PayPal payment sessions (one-time, save, Pay Later)
paypal-guest-payments Guest checkout with credit/debit cards
venmo-payments Venmo payment integration
card-fields Customizable card field components
paypal-messages PayPal messaging component
paypal-subscriptions Subscription payment handling
paypal-legacy-billing-agreements Legacy billing support
V6 TypeScript Types

Import types from the @paypal/paypal-js/sdk-v6 subpath:

import type {
  PayPalV6Namespace,
  LoadCoreSdkScriptOptions,
  Components,
  CreateInstanceOptions,
  SdkInstance,
  OnApproveDataOneTimePayments,
  OnShippingAddressChangeData,
} from "@paypal/paypal-js/sdk-v6";
Complete V6 Example
import { loadCoreSdkScript } from "@paypal/paypal-js/sdk-v6";
import type { OnApproveDataOneTimePayments } from "@paypal/paypal-js/sdk-v6";

async function initPayPal() {
  const paypal = await loadCoreSdkScript({ environment: "sandbox" });

  if (!paypal) {
    console.error("Failed to load PayPal SDK");
    return;
  }

  const sdkInstance = await paypal.createInstance({
    clientId: "YOUR_CLIENT_ID",
    components: ["paypal-payments"],
  });

  // Check eligibility before rendering
  const eligibility = await sdkInstance.findEligibleMethods();

  if (eligibility.isEligible("paypal")) {
    const session = sdkInstance.createPayPalOneTimePaymentSession({
      onApprove: async (data: OnApproveDataOneTimePayments) => {
        // Capture payment on your server
        await fetch("/api/capture", {
          method: "POST",
          body: JSON.stringify({ orderId: data.orderId }),
        });
      },
    });

    // Start payment when user clicks
    await session.start({ presentationMode: "popup" }, createOrderOnServer);
  }
}

async function createOrderOnServer() {
  const response = await fetch("/api/create-order", { method: "POST" });
  return response.json(); // { orderId: "..." }
}

Keywords