Broadleaf Microservices
  • v1.0.0-latest-prod

Frontend Integration

Note
If upgrading from PayPal Checkout JavaScript SDK v1, check out PayPal’s upgrade guide.

Broadleaf provides a PayPal Checkout SDK for common interactions with the PayPal JavaScript SDK.

To use the SDK in your frontend, you will need to handle several interactions. First, you’ll need to include the paypal sdk script during render at the top of your page, or in the App component of your application.

Placing the script in your App component will allow you to render and configure the script with the relevant options, such as page type. PayPal requires that configuration of the PayPal JS SDK uses relevant query parameters, including dataPartnerAttributionId, clientId, merchantId, commit, intent, and currency (defaults to USD, specify if using another currency). PayPal recommends passing the enableFunding to enable venmo and paylater payment methods, dataPageType for the context of the page (i.e. cart, payment, etc.), and components to load buttons, paylater messaing, etc. as options to meet Best Practices. Other options are also available to configure and personalize your checkout experience with PayPal, and can be found on their JavaScript SDK script configuration page.

For example,

const payPalOptions = {
    clientId: PayPalConfig.CLIENT_ID,
    merchantId: PayPalConfig.MERCHANT_ID,
    commit: true,
    enableFunding: ['venmo', 'paylater'],
    disableFunding: ['card'],
    intent: 'authorize',
    components: ['buttons', 'messages'],
    dataCspNonce: nonce,
    dataPageType: pageType,
    dataPartnerAttributionId: 'BroadleafCommerce_SP_PPCP',
  };
...
<PayPalScriptProvider options={payPalOptions}>
  <CurrentLayout>
    <Component {...pageProps} />
  </CurrentLayout>
</PayPalScriptProvider>
...

or

{PayPalConfig.CLIENT_ID && (
  <script
    data-partner-attribution-id="BroadleafCommerce_SP_PPCP"
    data-csp-nonce={this.props.nonce}
    defer
    src={`https://www.paypal.com/sdk/js?client-id=${PayPalConfig.CLIENT_ID}&merchant-id=${PayPalConfig.MERCHANT_ID}&intent=authorize&commit=true`}
  />
)}

Next, you’ll want to define the PayPal button on your site.

  1. Identify the button component after PayPal has loaded and render the button within your PDP, cart, or checkout page.

  2. Include any style or funding properties as needed.

    1. For details on the funding parameters, see Funding Types defined in our PayPal Checkout SDK.

  3. Provide callback functions for createOrder, onApprove, and onError.

    1. For details on createOrder and handleApprove, see Handle Create Order and Handle Approve Order.

    2. If using the Paypal button flow for Payment only, the handleApprove function should be responsible for calling PaymentTransactionServices to create & persist the payment.

      1. In this flow, we render the buttons on the payment stage of checkout, alongside the credit card form & other available payment options.

    3. If using the Complete Payment Paypal button flow, the handleApprove function should be responsible for updating the contact & fulfillment information (i.e. shipping address), and then calling PaymentTransactionServices to create & persist the payment. You may also want to skip the review page and submit the checkout at this stage.

      1. The expectation in the Complete Payment flow is that the checkout process is reduced to the minimum interactions for the customer. To achieve this, we use the shipping address selected within PayPal to populate our shipping & fulfillment information so that the customer can immediately enter checkout. We also support the server-side shipping callbacks from PayPal to save the initial fulfillment address and provide shipping options to the customer within the Complete Payments page.

Below is an example of using the PayPal button as a component within a React TypeScript application.

export const usePayPal = (): PayPalState => {
  const [state, setState] = useState<PayPalState>(
    isPayPalLoaded()
      ? { api: window['paypal'], button: getButtonComponent() }
      : {}
  );

  useEffect(() => {
    setState(
      isPayPalLoaded()
        ? { api: window['paypal'], button: getButtonComponent() }
        : {}
    );
  }, []);

  return state;
};

function isPayPalLoaded() {
  return window && window['paypal'];
}

function getButtonComponent() {
  return window['paypal'].Buttons.driver('react', { React, ReactDOM });
}
const { api, button: Button } = usePayPal();

return (
    <Button
      appSwitchWhenAvailable={true}
      fundingSource={api.FUNDING[funding]}
      funding={api.FUNDING[funding]}
      createOrder={createOrder}
      onApprove={handleApprove}
      onError={error => {
        if (error.message === 'Expected an order id to be passed') {
          // don't want to show this message
          return;
        }

        setError(error.message);
      }}
      style={style}
    />
)

Building the payload to create the order in PayPal

When interacting with PayPal to create the order via their order create api, we have to consider how to map the data in our system over to a PayPal Order.

PayPal Create Order Request

  1. intent [required]

    1. Type: ENUM string

    2. This can either be set to AUTHORIZE or CAPTURE, which determines which transaction type is executed in our checkout workflow.

  2. purchase_units [required]

    1. Type: Array of purchase unit requests

    2. Each purchase unit is a list of data points that correlates to a payment in Broadleaf.

      1. amount: This is equivalent to the payment amount in Broadleaf. It can be broken down to include totals for items, discounts, shipping, and taxes.

      2. custom_id: This is an external id which Broadleaf populates with the {fulfillmentReference}-{currentTimestamp} by default. This is used by our system as the transaction reference id, which allows us to reference the transaction if we do not receive a response back from the payment gateway during transaction execution.

      3. items: The list of cart items for the order, populated by cart items on Broadleaf’s cart representation.

      4. shipping: The shipping address for the order. By default, this is populated from Broadleaf’s shipping address stored on the fulfillment group. Sending this field to PayPal is required for Complete Payments flow, but optional otherwise.

      5. Refer to PayPal docs for additional fields on purchase unit request which can be populated as your implementation requires.

Venmo vs PayPal Payment Source

In addition to the properties listed on the request above, you’ll also need to populate the payment_source. This varies slightly based on the funding source chosen - i.e. PayPal vs Venmo.

PayPal Request

  1. payment_source

    1. paypal

      1. experience_context: Customizes the payer experience during the approval process for payment with PayPal.

        1. locale: The locale for this request.

        2. shipping_preference

          1. Type: ENUM string

          2. The location from which the shipping address is derived.

        3. contact_preference

          1. Type: ENUM string

          2. The location from which the contact information is derived.

        4. user_action: Configures a Continue or Pay Now checkout flow.

        5. return_url: The URL where the customer is redirected after the customer approves the payment.

        6. cancel_url: The URL where the customer is redirected after the customer cancels the payment.

        7. app_switch_preference: Customizes the payer experience to support app switching.

          1. launch_paypal_app: Whether or not to support launching the PayPal App, if available.

        8. order_update_callback_config: See below section on server-side shipping callback config.

App Switch Config

Of note in the PayPal experience context, there are several properties that can be set for switching to the PayPal App.

  1. app_switch_preference: This can customize whether or not to enable app switching if it’s available.

  2. return_url and cancel_url: These are the URLs to configure where to return when enabling App Switch, so make sure these are set if launch_paypal_app is enabled.

More information on App Switch & setup can be found in the PayPal App Switch docs.

Venmo Request

  1. payment_source

    1. venmo

      1. experience_context: Customizes the payer experience during the approval process for payment with Venmo.

        1. shipping_preference

          1. Type: ENUM string

          2. The location from which the shipping address is derived.

        2. order_update_callback_config: See below section on server-side shipping callback config.

Server-Side Shipping Callback Config

Within the PayPal or Venmo request if you’re also supporting sever-side shipping callbacks, you’ll want to build out the following config:

  1. order_update_callback_config: The callback configuration for fulfillment address & fulfillment options. Should only be included if using server-side shipping callbacks & when the shipping_preference is `GET_FROM_FILE.

    1. callback_events: A list of events to be supported by the shipping callback.

    2. callback_url: The URL to call for the shipping callback.

More information on the Shipping Callbacks can be found at PayPal’s Shipping Module documentation.

Enabling PayLater Messaging

PayPal supports & encourages use of messaging for their PayLater funding source. To enable PayLater messaging, you can add messages to the list of components when setting the options in the PayPal script. Then, you just need to include snippets of HTML that include the data-pp-placement and data-pp-amount properties.

For example,

<div
  className="mb-2"
  data-pp-message
  data-pp-style-layout="text"
  data-pp-style-logo-type="inline"
  data-pp-style-text-color="black"
  data-pp-style-text-size="12"
  data-pp-amount={cart?.cartPricing?.total?.amount}
  data-pp-placement="payment"
></div>

For a complete reference of the options available to integrate and customize the PayLater messaging, see the PayLater messaging documentation.