@paypal/checkout-server-sdk vs @paypal/react-paypal-js vs @stripe/stripe-js vs react-payment-inputs
Architecting Payment Flows in React Applications
@paypal/checkout-server-sdk@paypal/react-paypal-js@stripe/stripe-jsreact-payment-inputs

Architecting Payment Flows in React Applications

These packages cover different layers of payment integration, ranging from server-side transaction validation to client-side UI components. @paypal/checkout-server-sdk handles backend logic for PayPal, while @paypal/react-paypal-js provides React components for PayPal buttons. @stripe/stripe-js is the core library for integrating Stripe payments in the browser, and react-payment-inputs offers generic UI hooks for building custom credit card forms. Understanding where each tool fits ensures secure and compliant payment architectures.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
@paypal/checkout-server-sdk0---5 years agoSEE LICENSE IN https://github.com/paypal/Checkout-NodeJS-SDK/blob/master/LICENSE
@paypal/react-paypal-js0337706 kB233 days agoApache-2.0
@stripe/stripe-js07521.02 MB58 days agoMIT
react-payment-inputs0-267 kB-2 years agoMIT

Architecting Payment Flows: Server SDKs vs Frontend Libraries

Integrating payments requires mixing server-side security with client-side interactivity. The packages listed here serve different roles — some run on your backend to protect secrets, while others run in the browser to handle user input. Let's compare how they tackle common integration tasks.

🖥️ Runtime Environment: Backend vs Frontend

@paypal/checkout-server-sdk runs on your Node.js server.

  • Keeps secret keys safe from public view.
  • Validates transactions before capturing money.
// server-sdk: Node.js backend controller
const client = new paypal.core.PayPalEnvironment(clientId, clientSecret);
const request = new paypal.orders.OrdersCreateRequest();
request.prefer("return=representation");
request.requestBody({ intent: "CAPTURE", purchase_units: [{ amount: { currency_code: "USD", value: "100.00" } }] });
const response = await client.execute(request);

@paypal/react-paypal-js runs in the browser within React.

  • Loads PayPal scripts dynamically.
  • Renders buttons for user interaction.
// react-paypal-js: React component
import { PayPalScriptProvider, PayPalButtons } from "@paypal/react-paypal-js";
<PayPalScriptProvider options={{ clientId: "..." }}>
  <PayPalButtons createOrder={(data, actions) => {...}} />
</PayPalScriptProvider>

@stripe/stripe-js runs in the browser.

  • Loads Stripe.js securely.
  • Handles tokenization of card data.
// stripe-js: Client-side initialization
import { loadStripe } from "@stripe/stripe-js";
const stripe = await loadStripe("pk_test_...");
const result = await stripe.confirmCardPayment(clientSecret);

react-payment-inputs runs in the browser.

  • Provides UI hooks for card inputs.
  • Does not process payments itself.
// react-payment-inputs: Custom form hook
import { usePaymentInputs } from "react-payment-inputs";
const { getCardNumberProps } = usePaymentInputs();
<input {...getCardNumberProps()} />

🚀 Initializing the SDK

@paypal/checkout-server-sdk requires credentials in code.

  • You pass Client ID and Secret directly.
  • Never expose this to the browser.
// server-sdk: Secure server setup
const client = new paypal.core.PayPalEnvironment(clientId, clientSecret);

@paypal/react-paypal-js uses a Context Provider.

  • Wraps your app to manage script loading state.
  • Handles reloads and errors automatically.
// react-paypal-js: Provider wrapper
<PayPalScriptProvider options={{ clientId: "..." }}>
  <App />
</PayPalScriptProvider>

@stripe/stripe-js uses a standalone loader function.

  • Returns a promise that resolves to the stripe object.
  • Often wrapped in a React provider (react-stripe-js).
// stripe-js: Async loader
const stripe = await loadStripe("pk_test_...");

react-payment-inputs uses a React hook.

  • No external script loading required.
  • Manages local input state only.
// react-payment-inputs: Hook usage
const { getCardNumberProps, getExpiryDateProps } = usePaymentInputs();

🔒 Security & PCI Compliance

@paypal/checkout-server-sdk is fully secure by design.

  • Secrets stay on your server.
  • You control the entire flow.
// server-sdk: Server-side validation
const response = await client.execute(request);
// Validate response.status === "COMPLETED"

@paypal/react-paypal-js offloads security to PayPal.

  • Users log in to PayPal directly.
  • Your server never sees card details.
// react-paypal-js: OnApprove callback
onApprove={(data, actions) => {
  return actions.order.capture().then((details) => {
    // Send details to your server for verification
  });
}}

@stripe/stripe-js reduces PCI scope significantly.

  • Card data goes straight to Stripe.
  • You only handle tokens or payment intents.
// stripe-js: Confirming payment
const { error, paymentIntent } = await stripe.confirmCardPayment(clientSecret, {
  payment_method: { card: elements.getElement(CardElement) }
});

react-payment-inputs increases PCI scope.

  • You handle raw card numbers in your inputs.
  • Requires strict PCI DSS compliance on your server.
// react-payment-inputs: Handling raw data
const { meta } = usePaymentInputs();
// meta.number contains the raw card number - handle with care

📊 Summary Table

PackageEnvironmentPrimary RolePCI Scope
@paypal/checkout-server-sdkNode.js ServerTransaction ValidationLow (Server-side)
@paypal/react-paypal-jsReact BrowserPayPal ButtonsNone (Hosted Fields)
@stripe/stripe-jsBrowserStripe LogicLow (Elements)
react-payment-inputsBrowserUI Input MaskingHigh (Raw Data)

💡 Final Recommendation

@paypal/checkout-server-sdk is mandatory for any PayPal integration that validates payments on your backend. Pair it with @paypal/react-paypal-js for the frontend buttons.

@stripe/stripe-js is the standard for Stripe integrations. Use it with Stripe Elements to keep PCI compliance simple.

react-payment-inputs should only be used if you need a fully custom card form design and cannot use Stripe Elements. Be aware of the security burden.

Overall: Prefer provider-specific SDKs (react-paypal-js, stripe-js) over generic UI libs (react-payment-inputs) to reduce security risk and maintenance work.

How to Choose: @paypal/checkout-server-sdk vs @paypal/react-paypal-js vs @stripe/stripe-js vs react-payment-inputs

  • @paypal/checkout-server-sdk:

    Choose this package for Node.js backend services that need to create, validate, or capture PayPal orders securely. It keeps your client secrets off the client side and is essential for verifying transaction status before fulfilling orders. Do not use this in the browser as it exposes sensitive credentials.

  • @paypal/react-paypal-js:

    Choose this package when building React frontends that require PayPal checkout buttons or smart payment fields. It manages script loading states and provides ready-made components that reduce boilerplate code. It is the official way to integrate PayPal UIs into a React application.

  • @stripe/stripe-js:

    Choose this package for integrating Stripe payments into any JavaScript application, especially when paired with React. It loads the secure Stripe.js library and enables tokenization of card data without handling raw numbers. It is the foundation for using Stripe Elements or Payment Intents.

  • react-payment-inputs:

    Choose this package only if you need a fully custom credit card form design and cannot use provider-specific components like Stripe Elements. Be aware that using this increases your PCI compliance burden because you handle raw card data. It is best suited for projects where design control outweighs security convenience.

README for @paypal/checkout-server-sdk

PayPal Checkout API SDK for NodeJS

PayPal Developer

To consolidate support across various channels, we have currently turned off the feature of GitHub issues. Please visit https://www.paypal.com/support to submit your request or ask questions within our community forum.

Welcome to PayPal NodeJS SDK. This repository contains PayPal's NodeJS SDK and samples for v2/checkout/orders and v2/payments APIs.

This is a part of the next major PayPal SDK. It includes a simplified interface to only provide simple model objects and blueprints for HTTP calls. This repo currently contains functionality for PayPal Checkout APIs which includes Orders V2 and Payments V2.

Please refer to the PayPal Checkout Integration Guide for more information. Also refer to Setup your SDK for additional information about setting up the SDK's.

Usage

Binaries

It is not mandatory to fork this repository for using the PayPal SDK. You can refer PayPal Checkout Server SDK for configuring and working with SDK without forking this code.

For contributing or referring the samples, you can fork/refer this repository.

Examples

Creating an Order

Code to Execute:

const paypal = require('@paypal/checkout-server-sdk');
  
// Creating an environment
let clientId = "<<PAYPAL-CLIENT-ID>>";
let clientSecret = "<<PAYPAL-CLIENT-SECRET>>";

// This sample uses SandboxEnvironment. In production, use LiveEnvironment
let environment = new paypal.core.SandboxEnvironment(clientId, clientSecret);
let client = new paypal.core.PayPalHttpClient(environment);

// Construct a request object and set desired parameters
// Here, OrdersCreateRequest() creates a POST request to /v2/checkout/orders
let request = new paypal.orders.OrdersCreateRequest();
request.requestBody({
    "intent": "CAPTURE",
    "purchase_units": [
        {
            "amount": {
                "currency_code": "USD",
                "value": "100.00"
            }
        }
     ]
});

// Call API with your client and get a response for your call
let createOrder  = async function() {
    let response = await client.execute(request);
    console.log(`Response: ${JSON.stringify(response)}`);
    
    // If call returns body in response, you can get the deserialized version from the result attribute of the response.
    console.log(`Order: ${JSON.stringify(response.result)}`);
}
createOrder();

Example Output:

{
    "id": "4VW45368HJ294683Y",
    "links": [
        {
            "href": "https://api.sandbox.paypal.com/v2/checkout/orders/4VW45368HJ294683Y",
            "method": "GET",
            "rel": "self"
        },
        {
            "href": "https://www.sandbox.paypal.com/checkoutnow?token=4VW45368HJ294683Y",
            "method": "GET",
            "rel": "approve"
        },
        {
            "href": "https://api.sandbox.paypal.com/v2/checkout/orders/4VW45368HJ294683Y",
            "method": "PATCH",
            "rel": "update"
        },
        {
            "href": "https://api.sandbox.paypal.com/v2/checkout/orders/4VW45368HJ294683Y/capture",
            "method": "POST",
            "rel": "capture"
        }
    ],
    "status": "CREATED"
}

Capturing an Order

Before Capturing an order, it should be approved by the buyer using approve link in the create order response.

Code to Execute:

let captureOrder =  async function(orderId) {
    request = new paypal.orders.OrdersCaptureRequest(orderId);
    request.requestBody({});
    // Call API with your client and get a response for your call
    let response = await client.execute(request);
    console.log(`Response: ${JSON.stringify(response)}`);
    // If call returns body in response, you can get the deserialized version from the result attribute of the response.
    console.log(`Capture: ${JSON.stringify(response.result)}`);
}

let capture = captureOrder('REPLACE-WITH-APPROVED-ORDER-ID'); 

Example Output:

{
    "id": "96J43722461654618",
    "links": [
        {
            "href": "https://api.sandbox.paypal.com/v2/checkout/orders/96J43722461654618",
            "method": "GET",
            "rel": "self"
        }
    ],
    "payer": {
        "address": {
            "country_code": "US"
        },
        "email_address": "byer@example.com",
        "name": {
            "given_name": "John",
            "surname": "Doe"
        },
        "payer_id": "XXXXXXXXXXX",
        "phone": {
            "phone_number": {
                "national_number": "111-111-1111"
            }
        }
    },
    "purchase_units": [
        {
            "payments": {
                "captures": [
                    {
                        "amount": {
                            "currency_code": "USD",
                            "value": "100.00"
                        },
                        "create_time": "2019-02-05T02:44:14Z",
                        "final_capture": true,
                        "id": "7XU44982RK2157057",
                        "links": [
                            {
                                "href": "https://api.sandbox.paypal.com/v2/payments/captures/7XU44982RK2157057",
                                "method": "GET",
                                "rel": "self"
                            },
                            {
                                "href": "https://api.sandbox.paypal.com/v2/payments/captures/7XU44982RK2157057/refund",
                                "method": "POST",
                                "rel": "refund"
                            },
                            {
                                "href": "https://api.sandbox.paypal.com/v2/checkout/orders/96J43722461654618",
                                "method": "GET",
                                "rel": "up"
                            }
                        ],
                        "seller_protection": {
                            "dispute_categories": [
                                "ITEM_NOT_RECEIVED",
                                "UNAUTHORIZED_TRANSACTION"
                            ],
                            "status": "ELIGIBLE"
                        },
                        "seller_receivable_breakdown": {
                            "gross_amount": {
                                "currency_code": "USD",
                                "value": "100.00"
                            },
                            "net_amount": {
                                "currency_code": "USD",
                                "value": "96.80"
                            },
                            "paypal_fee": {
                                "currency_code": "USD",
                                "value": "3.20"
                            }
                        },
                        "status": "COMPLETED",
                        "update_time": "2019-02-05T02:44:14Z"
                    }
                ]
            },
            "reference_id": "default",
            "shipping": {
                "address": {
                    "address_line_1": "1 Main St",
                    "admin_area_1": "CA",
                    "admin_area_2": "San Jose",
                    "country_code": "US",
                    "postal_code": "95131"
                },
                "name": {
                    "full_name": "John Doe"
                }
            }
        }
    ],
    "status": "COMPLETED"
}

Running tests

To run integration tests using your client id and secret, clone this repository and run the following command:

$ npm install
$ PAYPAL_CLIENT_ID=YOUR_SANDBOX_CLIENT_ID PAYPAL_CLIENT_SECRET=YOUR_SANDBOX_CLIENT_SECRET npm test

Samples

You can start off by trying out creating and capturing an order

To try out different samples for both create and authorize intent check this link

Note: Update the payPalClient.js with your sandbox client credentials or pass your client credentials as environment variable while executing the samples.

Note

PayPalHttpClient used as part of this project returns Promises

You can read more about Promises here: https://www.promisejs.org/

License

Code released under SDK LICENSE