Shipping module

Current

Last updated: Jan 15th, 5:00pm

The PayPal shipping module presents shipping details to a buyer during the PayPal flow. The merchant has several options available for controlling how shipping addresses and shipping options are handled. The server-side shipping callbacks allow you to update the shipping and order amount information as buyers make changes on the PayPal review page.

Merchant and buyer interaction

Buyers can use the shipping module to specify the shipping address and shipping options on the PayPal review page. The system sends a callback to the merchant's URL with the updated shipping information.

When the buyer provides their shipping address, PayPal sends a callback to the merchant server with the buyer's address using the server-side shipping callbacks. In response, the merchant can send PayPal the shipping options and updated order cost amounts.

You can use server-side callbacks to:

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

Although both server-side and client-side callbacks are possible, PayPal recommends server-side callbacks because the client-side callbacks may be unavailable in all situations. For example, client-side callbacks using JS-SDK are designed primarily for web-based integrations. They may not be suitable for native mobile applications that often require different APIs or SDKs tailored for mobile platforms.

The following sample PayPal review page shows a buyer's shipping address and options:

image

How it works

The shipping address and options callback process involves the following steps:

  1. A buyer clicks on the PayPal button displayed on the merchant site.
  2. The merchant makes a Create Order API request to PayPal to set up the PayPal flow, including the parameters needed to enable the server-side callbacks.
  3. The buyer is taken to the PayPal flow where they are authenticated and shown the PayPal review page.
  4. PayPal makes a server-side callback to the merchant's server with the default shipping address from the buyer's PayPal wallet.
  5. The merchant processes the callback and responds with shipping options for the address and updated order amount.
  6. PayPal updates the review page to reflect the merchant's revised order amount and shipping options.
  7. If the buyer changes the shipping address or shipping options, a callback is made to the merchant. The merchant's response updates the PayPal review page.
  8. The buyer clicks the pay button on the PayPal review page to complete the transaction, which is returned to the merchant.
  9. The merchant may make a Show Order Details API call to get the final PayPal order information and verify it still matches the information in their system.
  10. The merchant captures the PayPal order to complete the transaction.

Create order

PayPal uses the PayPal Orders v2 API Create Order request to set up the PayPal flow used by the buyer to approve a PayPal transaction. There are several ways to determine how the shipping address and options are displayed on the PayPal review page and which events create callbacks when the buyer interacts with them.

Enabling server-side callbacks

The payment_source.paypal.experience_context.order_update_callback_config object is used to enable and configure server-side callbacks during the PayPal flow. The callback_url field specifies the endpoint on your servers where PayPal sends the callback request. The callback_events array specifies which callback events you support. The PayPal flow supports the following events:

  • SHIPPING_ADDRESS: This event happens when the PayPal review page loads for the first time and when the buyer changes their shipping address. We recommend merchants to subscribe only to SHIPPING_ADDRESS. This requires a merchant to respond with all the shipping options and amounts calculated on the initial callback. Since all options have been returned, the merchant callback does not have to be called when the selection option changes. This method reduces delays and the number of requests for PayPal.
  • SHIPPING_OPTION: This event happens when the buyer selects new shipping options and when they change shipping options. We recommend merchants subscribe to this if they want to be notified or need to recalculate amounts with their callback URL when a selected shipping option changes for the current address. If SHIPPING_OPTION is not needed by the merchant, they should subscribe to SHIPPING_ADDRESS.

Configuring shipping preferences

The shipping preference is a set using the payment_source.paypal.experience_context.shipping_preference field. There are 3 possible values:

  • GET_FROM_FILE: This default preference retrieves the customer-provided shipping address from PayPal.
  • NO_SHIPPING: This option removes the shipping address information from the PayPal review page and the API response. However, the shipping.phone_number and shipping.email_address fields are returned for digital goods delivery.
  • SET_PROVIDED_ADDRESS: The PayPal review page shows the shipping address provided by the merchant in the create order request. The buyer cannot change this address on the PayPal site. If the merchant does not pass an address, the buyer can choose the address on PayPal.

If you do not pass a shipping preference, the default behavior is GET_FROM_FILE. The PayPal review page shows the default shipping address from the buyer's PayPal wallet. The buyer can select a different shipping address from their wallet or add a new address.

Callbacks happen if the shipping preference is GET_FROM_FILE.

Passing a shipping address

If you have a shipping address from the buyer, pass it to PayPal on the create order request. If you pass a shipping address with a shipping preference of GET_FROM_FILE, it will display on the PayPal review page, where the buyer can change the shipping address. You can use the shipping preference SET_PROVIDED_ADDRESS to prevent the buyer from changing the shipping address on the PayPal review page.
If your transaction does not involve shipping, you can pass the shipping preference SET_PROVIDED_ADDRESS, and no shipping information will be displayed on the PayPal review page.

Here is a sample Create Order API request to a merchant with callback config:

1curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders \
2-H 'Content-Type: application/json' \
3-H 'PayPal-Request-Id: 7b92603e-77ed-4896-8e78-5dea2050476a' \
4-H 'Authorization: Bearer 6V7rbVwmlM1gFZKW_8QtzWXqpcwQ6T5vhEGYNJDAAdn3paCgRpdeMdVYmWzgbKSsECednupJ3Zx5Xd-g' \
5-d '{
6 "intent": "CAPTURE", "payment_source": {
7 "paypal": {
8 "experience_context": {
9 "user_action": "PAY_NOW",
10 "shipping_preference": "GET_FROM_FILE",
11 "return_url": "https://example.com/returnUrl",
12 "cancel_url": "https://example.com/cancelUrl",
13 "order_update_callback_config": {
14 "callback_events": ["SHIPPING_ADDRESS", "SHIPPING_OPTIONS"],
15 "callback_url": "https://example.com/orders?cart_id=h98h98h&session_id=89h788fg8"
16 }
17 }
18 }
19 }, "purchase_units": [{
20 "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",
21 "items": [{
22 "name": "T-Shirt",
23 "description": "Super Fresh Shirt",
24 "unit_amount": {
25 "currency_code": "USD",
26 "value": "50.00"
27 },
28 "quantity": "1",
29 "category": "PHYSICAL_GOODS",
30 "sku": "sku01",
31 "image_url": "https://example.com/static/images/items/1/tshirt_green.jpg",
32 "url": "https://example.com/url-to-the-item-being-purchased-1",
33 "upc": {
34 "type": "UPC-A",
35 "code": "123456789012"
36 }
37 }, {
38 "name": "Shoes",
39 "description": "Running, Size 10.5",
40 "sku": "sku02",
41 "unit_amount": {
42 "currency_code": "USD",
43 "value": "25.00"
44 },
45 "quantity": "2",
46 "category": "PHYSICAL_GOODS",
47 "image_url": "https://example.com/static/images/items/1/shoes_running.jpg",
48 "url": "https://example.com/url-to-the-item-being-purchased-2",
49 "upc": {
50 "type": "UPC-A",
51 "code": "987654321012"
52 }
53 }],
54 "amount": {
55 "currency_code": "USD",
56 "value": "100.00",
57 "breakdown": {
58 "item_total": {
59 "currency_code": "USD",
60 "value": "100.00"
61 }
62 }
63 }
64 }]
65 }

Server-side shipping callbacks

The Server-Side Callback API request to a merchant is consistent with GET orders and includes selected addresses and options outside of the order object.

  • Sending order data is structurally similar to making a GET request.
  • PayPal will send updated shipping addresses and options separately from the order to avoid confusion.
  • If the address or option is incomplete, PayPal will not set it in order to prevent misunderstandings.
  • PayPal will embed the cart identifier in the callback URL if merchants cannot associate their shopping cart with the order.
  • Merchants with client-side shopping carts should include item details when they create the order for server-side shipping callbacks.

Callback request to merchant for shipping address event

The following sample is a PayPal server-side callback request to the merchant for a shipping event. The callback identifies the order, shipping_address, shipping_option, and purchase_units.

The initial callback to the merchant does not include the "shipping_option" section

1{
2 "title": "Shipping Options Callback Request - Shipping Address and Shipping Options Event",
3 "description": "The PayPal callback server sends request with a buyer's shipping address, the shipping option the buyer selected, and the purchase_units of the order, to the merchant listener URL. The merchant responds with a the appropriate tax calculation and breakdown for the given address and shipping option combination.",
4 "runnable": true,
5 "operationId": "server.callback",
6 "request": {
7 "method": "POST",
8 "path": "v2/checkout/orders/order-update-callback",
9 "headers": {
10 "Content-Type": "application/json"
11 },
12 "body": {
13 "id": "5O190127TN364715T",
14 "shipping_address": {
15 "country_code": "US",
16 "admin_area_1": "TX",
17 "admin_area_2": "Dallas",
18 "postal_code": "75001"
19 },
20 "shipping_option": {
21 "id": "2",
22 "amount": {
23 "currencyCode": "USD",
24 "value": "20.00"
25 },
26 "type": "SHIPPING",
27 "label": "Free Shipping"
28 },
29 "purchase_units": [{
30 "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",
31 "amount": {
32 "currency_code": "USD",
33 "value": "100.00"
34 }
35 }]
36 }
37 },

Callback request fields

Field

Description

Data type

idstringUnique identifier for the shipping order. For example, 5O190127TN364715T.
shipping_addressobjectShipping address information. Includes country_code, admin_area_1, admin_area_2, and postal_code.
country_codestringIdentifies the shipping address country. For example, US.
admin_area_1stringIdentifies the shipping address state or region. For example, TX.
admin_area_2stringIdentifies the shipping address, city, or municipality. For example, Dallas.
postal_codenumberIdentifies the postal code. For example, 7500.
shipping_optionstringShipping option information. Includes id, amount, type, and label.
idnumberIndicates the type of shipping option. For example, 2.
amountobjectShipping option amount. Includes currencyCode and value.
currencyCodestringIndicates the type of currency. For example, USD.
valuenumberString denoting the shipping option price, formatted as X.XX. For example, 20.00.
typestringAn enum that indicates the type of shipping. For example, SHIPPING or PICKUP.
labelstringDropdown menu option selected by the buyer. Indicates whether the shipping is free or not. For example, Free Shipping.
purchase_unitsobjectDefines the purchase unit. Includes reference_id and amount.
reference_idstringIdentifier associated with the purchase units. For example, d9f80740-38f0-11e8-b467-0ed5f89f718b.
amountobjectPurchase amount. Includes currency_code and value.
currency_codestringIndicates the type of currency. For example, USD.
valuenumberString denoting the purchase price, formatted as X.XX. For example, 100.00.

Merchant response

The merchant response to a PayPal server-side callback request is similar to an order. A change to the customer’s shipping address or options can affect the following fields within the data structure:

  • purchase_units[].shipping.options represent the shipping modules associated with the purchase units within the order. The purchase order field includes contact and delivery information, including phone number, PayPal account email address, order ID, and reference ID.
  • purchase_units[].amount represents the purchase unit amount in the order.

PayPal can handle these changes by taking one of the following approaches:

  • Asking the merchant to return an updated order limited to the fields that can be changed.
  • Asking the merchant to return a list of patch operations.

Merchant success response

When the order request is acceptable, the merchant responds with a success message that contains amount and shipping option changes.

Here is a sample HTTP 200 OK callback response from a merchant with shipping options and amount updates.

1{
2 "id": "8HFTASDATTV",
3 "purchase_units": [{
4 "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",
5 "amount": {
6 "currency_code": "USD",
7 "value": "105.00",
8 "breakdown": {
9 "item_total": {
10 "currency_code": "USD",
11 "value": "100.00"
12 },
13 "tax_total": {
14 "currency_code": "USD",
15 "value": "5.00"
16 },
17 "shipping": {
18 "currency_code": "USD",
19 "value": "0.00"
20 }
21 }
22 },
23 "shipping_options": [{
24 "id": "1",
25 "amount": {
26 "currencyCode": "USD",
27 "value": "0.00"
28 },
29 "type": "SHIPPING",
30 "label": "Free Shipping",
31 "selected": true
32 }, {
33 "id": "2",
34 "amount": {
35 "currencyCode": "USD",
36 "value": "7.00"
37 },
38 "type": "SHIPPING",
39 "label": "USPS Priority Shipping",
40 "selected": false
41 }, {
42 "id": "3",
43 "amount": {
44 "currencyCode": "USD",
45 "value": "10.00"
46 },
47 "type": "SHIPPING",
48 "label": "1-Day Shipping",
49 "selected": false
50 }]
51 }]
52}

Merchant success response fields

A merchant response can include the fields identified in the following table.

Field

Description

Data type

idstringIdentifies the merchant. For example, 8HFTASDATTV.
purchase_unitsobjectPurchase unit information. Includes reference_id and amount.
reference_idstringUniquely identifies the purchase transaction. For example, d9f80740-38f0-11e8-b467-0ed5f89f718b.
amountobjectPurchase unit amount in the order. Includes currency_code,value, and breakdown.
currency_codestringCode indicating the amount currency type. For example, USD.
valuenumberString denoting the purchase unit amount in the order, formatted as X.XX. For example, 105.00.
breakdownobjectAmount breakdown. Includes item_total, tax_total, and shipping.
item_totalstringAmount item breakdown. Includes currency_code, and value.
currency_codestringAmount item total currency type. For example, USD.
valuenumberAmount item value. For example, 100.0.
tax_totalobjectAmount tax breakdown. Includes currency_code, and value.
currency_codestringCurrency type of the amount tax total. For example, USD.
valuenumberString denoting thetax_total amount, formatted as X.XX. For example, 5.00.
shippingobjectAmount shipping breakdown. Includes currency_code, and value.
currency_codestringAmount shipping currency type. For example, USD.
valuenumber

String denoting the value. amount, formatted as X.XX. For example, 0.00.

In this example, there are no shipping costs associated with the purchase unit.

shipping_optionsobjectShipping option details. Includes id, amount, type, label, and selected.
idnumberShipping option identifier. For example, 1.
amountobjectAmount for the selected shipping option. For example, currency_code and value.
currencyCodestringType of currency required for the selected shipping option. For example, USD.
valuenumberString denoting the value. amount for the selected shipping option, formatted as X.XX. For example, 0.00. The value depends upon the selected label.
typestringAn enum that indicates the type of delivery for the selected option. For example, SHIPPING or PICKUP.
labelstring

Dropdown menu option selected by the buyer. Indicates the type of SHIPPING. For example, Free Shipping.

Other labels include USPS Priority Shipping and 1-Day Shipping.

selectedbooleanDetermines which option is selected by default. Possible values are true or false.

The order amount is automatically updated based on the options chosen by the buyers. You can use the onShippingOptionsChange() callback to update your own database with the new cost amount.

Merchant decline response

A merchant can issue a 422 error to decline a callback event. This could occur when:

  • The merchant rejects a shipping address.
  • A server-side callback request to a merchant fails or times out.
  • The merchant returns a poorly formatted response.

PayPal mechanisms handle these issues, minimizing disruptions throughout the process. Here are a few examples of merchant-declined callback events and associated descriptions:

Callback event type

Error

Description

Shipping addressADDRESS_ERRORYour order can't be shipped to this address.
Shipping addressCOUNTRY_ERRORYour order can't be shipped to this country.
Shipping addressSTATE_ERRORYour order can't be shipped to this state.
Shipping addressZIP_ERRORYour order can't be shipped to this zip.
Shipping optionMETHOD_UNAVAILABLEThe shipping method you selected is unavailable. To continue, choose another way to get your order.
Shipping optionSTORE_UNAVAILABLEPart of your order isn't available at this store.

Here is a sample decline callback from the merchant. In this case, there is an HTTP 422 Unprocessable Entity response, which is a country error.

1{
2 "name": "UNPROCESSABLE_ENTITY",
3 "details": [{
4 "issue": "COUNTRY_ERROR"
5 }]
6}