Listen for Shipping Changes

SDKLegacyLast updated: June 20th 2023, @ 6:44:12 pm


The Shipping Change callback is a feature of Smart Payment Buttons that extends your Smart Payment Buttons integration. While the buyer is on the PayPal site, you can update the contents of their shopping cart to reflect the shipping address they chose on PayPal.

You can also use the callback to:

  • Validate that you support the shipping address.
  • Update shipping costs.
  • Change the line items in the cart.
  • Inform the buyer that you do not support their shipping address.

To integrate the callback, pass the onShippingChange function to your paypal.Buttons component. For example:

paypal.Buttons({
    onShippingChange: function(data, actions) {
        // ...
    }
}).render('#paypal-button-container');

PayPal calls your onShippingChange function when:

  • The buyer initially logs into their account (if the buyer already has a PayPal account).
  • The buyer submits their billing/payment information (if the buyer does not have a PayPal account).
  • The buyer makes a change to their shipping address on the review your payment page.

PayPal provides the following parameters to your onShippingChange function:

  • data: An object containing the buyer’s shipping address. Consists of the following fields:
    • orderID: The ID represents an order.
    • paymentID: The ID represents a payment.
    • paymentToken: The ID/token which represents the resource.
    • shipping_address: The buyer's selected city, state, and postal code.
    • selected_shipping_option: Shipping option selected by the buyer.
  • actions: An object that contains methods to update the contents of the buyer’s cart and interact with PayPal Checkout. Consists of the following methods:
    • resolve: Indicates to PayPal that you do not need to make any changes to the buyer’s cart.
    • reject: Indicates to PayPal that you will not support the shipping address provided by the buyer.
    • order: Client-side order API method:
      • PATCH: To make the update, pass an array of change operations in the request, as described in the order update API reference. The response returns a promise.

Examples

Consider a use case where you do not support international transactions:

paypal.Buttons({
    onShippingChange: function(data, actions) {
        if (data.shipping_address.country_code !== 'US') {
            return actions.reject();
        }

        return actions.resolve();
    }
}).render('#paypal-button-container');

A more complex example could be free shipping in California, but flat-rate shipping everywhere else in the United States:

const baseOrderAmount = '15.00';

paypal.Buttons({
    onShippingChange: function(data, actions) {
        // Reject non-US addresses
        if (data.shipping_address.country_code !== 'US') {
            return actions.reject();
        }

        // Patch the shipping amount
        const shippingAmount = data.shipping_address.state === 'CA' ? '0.00' : '5.00';
        return actions.order.patch([
            {
                op: 'replace',
                path: '/purchase_units/@reference_id==\'default\'/amount',
                value: {
                    currency_code: 'USD',
                    value: (parseFloat(baseOrderAmount) + parseFloat(shippingAmount)).toFixed(2),
                    breakdown: {
                        item_total: {
                            currency_code: 'USD',
                            value: baseOrderAmount
                        },
                        shipping: {
                            currency_code: 'USD',
                            value: shippingAmount
                        }
                    }
                }
            }
        ]);
    }
}).render('#paypal-button-container');

For other requests, such as changing the country where you are shipping or validating the state in the shipping address, you can make a callback to your server and perform any necessary validation and patching operations from there. For example:

paypal.Buttons({
    onShippingChange: function(data, actions) {
        return fetch('/my-backend/service', {
            method: 'post',
            headers: {
                'content-type': 'application/json'
            },
            body:    JSON.stringify(data)
        }).then(res => {
            if (!res || res.error) {
                return actions.reject();
            }

            return actions.resolve();
        });            
    }
}).render('#paypal-button-container');