PayPal v6 SDK with Braintree
Last updated: Jun 17th, 3:24pm
Overview
PayPal Web SDK v6 handles the button and PayPal flow.
-
Braintree Web SDK is used to create the payment and generate a payment method nonce to securely complete the transaction.
-
You will:
-
Initialize PayPal and Braintree clients
-
Render a PayPal button
-
Start a one-time payment flow
-
Capture the payment on your server
-
Set up your HTML file
Create an index.html file to structure your payment interface. Include the necessary scripts for Braintree and PayPal.
1<!doctype html>2<html lang="en">3<head>4 <meta charset="UTF-8" />5 <title>Braintree One-Time Payment - Recommended Integration - PayPal Web SDK</title>6 <meta name="viewport" content="width=device-width, initial-scale=1" />7 <style>8 .buttons-container {9 display: flex;10 flex-direction: column;11 gap: 12px;12 }13 </style>14</head>15<body>16 <h1>Braintree One-Time Payment Recommended Integration</h1>1718 <div class="buttons-container">19 <paypal-button id="paypal-button" type="pay" hidden></paypal-button>20 </div>21 <script src="app.js"></script>22 <script src="https://js.braintreegateway.com/web/3.111.0/js/client.min.js"></script>23 <script src="https://js.braintreegateway.com/web/3.111.0/js/paypal-checkout.min.js"></script>24 <script25 async26 src="https://www.sandbox.paypal.com/web-sdk/v6/core"27 onload="onPayPalLoaded()"28 ></script>29</body>30</html>
Create Your JavaScript File
Create an app.js file to set up the SDK and connect to your APIs. This file will include functions to manage the PayPal integration and Braintree payments.
1async function onPayPalLoaded() {2 try {3 const clientToken = await getBrowserSafeClientToken();4 const paypalInstance = await window.paypal.createInstance({5 clientToken,6 components: ["paypal-payments"],7 pageType: "checkout",8 });910 const braintreeInstance = await window.braintree.client.create({11 authorization: clientToken,12 });1314 const braintreeCheckout = await window.braintree.paypalCheckout.create({15 client: braintreeInstance,16 });1718 setupPayPalButton({ paypalInstance, braintreeCheckout });19 } catch (error) {20 console.error(error);21 }22}2324async function setupPayPalButton({ paypalInstance, braintreeCheckout }) {25 const paypalPaymentSession = paypalInstance.createPayPalOneTimePaymentSession({26 async onApprove(data) {27 const { nonce } = await braintreeCheckout.tokenizePayment({28 payerID: data.payerId,29 paymentID: data.orderId,30 });31 const orderData = await completePayment(nonce);32 console.log("Capture result", orderData);33 },34 onCancel(data) {35 console.log("onCancel", data);36 },37 onError(error) {38 console.log("onError", error);39 },40 });4142 const paypalButton = document.querySelector("#paypal-button");43 paypalButton.removeAttribute("hidden");4445 async function createOrder() {46 const orderId = await braintreeCheckout.createPayment({47 flow: "checkout",48 amount: 10.0,49 currency: "USD",50 intent: "capture",51 });52 return { orderId };53 }5455 paypalButton.addEventListener("click", async () => {56 try {57 await paypalPaymentSession.start(58 { presentationMode: "auto" },59 createOrder()60 );61 } catch (error) {62 console.error(error);63 }64 });65}6667async function getBrowserSafeClientToken() {68 const response = await fetch("/braintree-api/auth/browser-safe-client-token", {69 method: "GET",70 headers: {71 "Content-Type": "application/json",72 },73 });74 const { accessToken } = await response.json();75 return accessToken;76}7778async function completePayment(paymentMethodNonce) {79 const response = await fetch("/braintree-api/checkout/transaction/sale", {80 method: "POST",81 headers: {82 "Content-Type": "application/json",83 },84 body: JSON.stringify({85 paymentMethodNonce,86 amount: 10.0,87 }),88 });89 const result = await response.json();90 return result;91}
Constant & Function Reference Table
| Constant / Function Name | Description |
| onPayPalLoaded() | Main entry point. Called when the PayPal SDK is loaded. Initializes PayPal + Braintree instances and sets up the PayPal button. |
| getBrowserSafeClientToken() | Calls your server to get a Braintree browser-safe client token, used to authorize both PayPal and Braintree SDK instances. This can be done server-side and hydrated into your frontend if using a SSR set up. |
| paypalInstance | Instance of PayPal SDK v6, initialized using paypal.createInstance(). Used to create the PayPal one-time payment session. |
| braintreeInstance | Instance of Braintree Client SDK (braintree.client.create()), used as the base client for PayPal Checkout. |
| braintreeCheckout | Instance of Braintree PayPal Checkout integration (braintree.paypalCheckout.create()), used to create Braintree PayPal transactions and tokenize them. |
| setupPayPalButton({ ... }) | Sets up PayPal button click behavior, and registers callbacks for approval, cancel, and error events in the PayPal payment session. |
| paypalPaymentSession | PayPal one-time payment session created by paypalInstance.createPayPalOneTimePaymentSession(). Starts the payment flow when invoked. |
| createOrder() | Function to create a PayPal order via braintreeCheckout.createPayment(). Returns orderId, which is passed to PayPal payment session. |
| paypalButton | DOM element reference to your PayPal button. The hidden attribute is removed once the button is ready. |
| paypalButton.addEventListener("click", ...) | Click listener that starts the PayPal payment session when the user clicks the button. |
| onApprove(data) (callback) | Called when the user approves the PayPal payment. Tokenizes the PayPal payment via Braintree and sends it to the server to complete the transaction. |
| onCancel(data) (callback) | Called if the user cancels the PayPal payment. Logs cancel data. |
| onError(error) (callback) | Called if an error occurs during the PayPal flow. Logs the error. |
| completePayment(paymentMethodNonce) | Sends the tokenized payment nonce to your server endpoint /braintree-api/checkout/transaction/sale to complete the transaction with Braintree. Returns the result. |
Implementing the server code
This server-side example uses Node.js but you are free to use any backend language you choose. This file sets up the Express server and defines API endpoints that the frontend relies on to successfully process a one time payment.
1import express, { Request, Response } from "express";2import cors from "cors";34import {5 getBrowserSafeClientToken,6 completeTransactionSale,7} from "./braintreeServerSdk";89const app = express();1011app.use(cors());12app.use(express.json());1314/* ######################################################################15 * API Endpoints for the client-side JavaScript Braintree Integration code16 * ###################################################################### */1718app.get(19 "/braintree-api/auth/browser-safe-client-token",20 async (_req: Request, res: Response) => {21 try {22 const accessToken = await getBrowserSafeClientToken();23 res.status(200).json({ accessToken });24 } catch (error) {25 res.status(500).json({26 errorMessage: `failed to create the braintree client token: '${(error as Error).message}'`,27 });28 }29 },30);3132app.post(33 "/braintree-api/checkout/transaction/sale",34 async (req: Request, res: Response) => {35 const { amount, paymentMethodNonce } = req.body;36 const result = await completeTransactionSale({37 amount,38 paymentMethodNonce,39 });4041 const statusCode = result.errors ? 500 : 200;42 res.status(statusCode).json(result);43 },44);4546const port = process.env.PORT ?? 8080;4748app.listen(port, () => {49 console.log(`API server listening at https://localhost:${port}`);50});
Implementing Braintree Server SDK Functions
This file configures the Braintree SDK and includes functions for token generation and transaction processing.
1import { config } from "dotenv";2import { join } from "path";3import braintree from "braintree";4import type { BraintreeGateway } from "braintree";56const envFilePath = join(__dirname, "../../../", ".env");7config({ path: envFilePath });89let gateway: BraintreeGateway;1011function getGateway() {12 if (!gateway) {13 if (!process.env.BRAINTREE_SANDBOX_MERCHANT_ID || !process.env.BRAINTREE_SANDBOX_MERCHANT_PUBLIC_KEY || !process.env.BRAINTREE_SANDBOX_MERCHANT_PRIVATE_KEY) {14 throw new Error("Required Braintree credentials are not defined in the .env file.");15 }16 gateway = new braintree.BraintreeGateway({17 environment: braintree.Environment.Sandbox,18 merchantId: process.env.BRAINTREE_SANDBOX_MERCHANT_ID,19 privateKey: process.env.BRAINTREE_SANDBOX_MERCHANT_PUBLIC_KEY,20 publicKey: process.env.BRAINTREE_SANDBOX_MERCHANT_PRIVATE_KEY,21 });22 }23 return gateway;24}2526export async function getBrowserSafeClientToken() {27 const clientTokenResponse = await getGateway().clientToken.generate({});28 return clientTokenResponse.clientToken;29}3031export async function completeTransactionSale({ paymentMethodNonce, amount }: { paymentMethodNonce: string; amount: string; }) {32 const result = await getGateway().transaction.sale({33 amount,34 paymentMethodNonce,35 });36 return result;37}
Configure Environment Variables
The example above uses enviroment variables to generate tokens for order processing. Make sure you create a .env file with the values below.
1BRAINTREE_SANDBOX_MERCHANT_ID=your_merchant_id2BRAINTREE_SANDBOX_MERCHANT_PUBLIC_KEY=your_public_key3BRAINTREE_SANDBOX_MERCHANT_PRIVATE_KEY=your_private_key