Overview
This page demonstrates the Order Tracking feature available in Apple Pay using the Payment Request API or the Apple Pay JS APIs. Order Tracking with Apple Pay provides users with an itemized breakdown of purchased items along with any shipping or pickup information. Orders can be updated by the merchant on user device to reflect the latest order state such as shipping or pickup fulfillments.
This is an interactive playground that shows examples for each step of implementing Order Tracking. You can modify the payloads in the code editor blocks throughout the page to customize the orders and explore how the changes impact the functionality.
This demo displays a transcript of server responses after each order creation and update. Click or tap Show Transcript tab to view the transaction transcript.
To implement Order Tracking, you must first have set up your service to process Apple Pay transactions. See the main Apple Pay Demo page for detailed implementation guidance.
This demo generates source code that you can copy into your own project. Click or tap the Show Source tab to view the source code. The source code updates as you change values in the code editor blocks throughout the page. You can click or tap the Copy button inside the Show Source tab to copy the source code to your clipboard.
Implementation Variations
As with baseline Apple Pay, you may be a developer who is implementing this functionality on your own site, you may be a developer working on a shopping or logistics platform that serves many merchants, or you may be a developer implementing order creation on your site, but relying on a logistics partner for serving order updates to your customers.
Depending on your use case, you would need to implement all, or only a subset of the APIs. If you are planning to to use a third party to serve your order updates to your customers, please refer to your shopping platform or logistic partner documentation for integration instructions .
Requirements
This demo uses Apple Pay JS version 13. To run this demo, use
- iOS devices running iOS 16.0 or later
- Safari 14 on macOS 13.0 or later
- Have a payment card provisioned in Wallet
- Have the same card and Apple ID across all devices
Create an order
As the merchant, you create the order when a customer purchases products on your website. When the customer authorizes the transaction with Apple Pay, you must send the initial order details to Wallet running on their device.
After the payment is processed for the transaction Wallet receives initial order details that
include the unique orderID
and the webServiceURL
.
Wallet then calls the webServiceURL
requesting the order package,
identified by the unique orderID
.
Sending order details to Wallet
When the customer initiates a transaction you, as the merchant start an
ApplePaySession
.
When the customer authorizes the payment as part of the session the browser triggers the
onpaymentauthorized
event handler. In your implementation of this event handler you, as the merchant need to generate the initial
order details and send them as part of the payload to the
completePayment
session handler function.
Below you can see an example implementation of this handler that includes the new payload data that needs to be included to enable order tracking.
session = new ApplePaySession(version, request); session.onpaymentauthorized = (payment) => { // ... // ... After merchant validation and payment request build // ... let paymentStatus = ApplePaySession.STATUS_SUCCESS // Can be "ApplePaySession.STATUS_SUCCESS" or "ApplePaySession.STATUS_FAILURE" let data = { status: paymentStatus, // Additional fields for order tracking orderDetails: { orderIdentifier: // The ID of the order of type DOMString. orderTypeIdentifier: // The order type ID of the order of type DOMString. webServiceURL: // The base URL of type DOMString to where Wallet can request for orders. authenticationToken: // Randomly generated alpha-numeric token of type DOMString. } } session.completePayment(data); }
For more information see orderDetails
.
Note
The Order Details payload documented above is different from an Order Package. The Order Details payload is how you, as the merchant, tell Wallet where to fetch the Order Package. The Order Package documented below is what Wallet will actually fetch and parse to display the order information.
If you are a merchant implementing the Order Tracking functionality on your site (or you are
a merchant platform that serves many merchants) and are planning to serve order updates to the
user devices directly, you would point webServiceURL
to a new API endpoint on your own domain.
You should then implement the Web Service API.
Alternatively, if you rely on a third party logistics partner that will be generating the
order payloads and sending updates to user on your behalf, refer to the
documentation of your logistics partner to determine the correct value to specify for the
webServiceURL
.
Now that Wallet has obtained the webServiceURL
from orderDetails
via completePayment
, Wallet makes a request to fetch the Order Package from the URL in this format:
GET https://your-web-service.com/v1/orders/{orderTypeIdentifier}/{orderIdentifier}
In the GET request, the "your-web-service.com" is the webServiceURL
specified in orderDetails
.
Wallet will send the authenticationToken
that you generated for the order and included in the orderDetails
as the Authorization
header with the request.
The web service needs to return an order package as a response to the request above. The next section details how to build a distributable order package.
For more information, see Retrieve the latest version of an order.
Build a distributable order package
An order package is a compressed zip archive that contains
a order.json
file with the detailed order information,
a manifest.json
file, localization string files, any media
files, and a signature file.
See Creating the source for an order for the detailed explanation of the schema.
You can use the JSON editor in the create an order section’s below
to validate the order json against the JSON 2020-12
schema.
Here is an example of a manifest.json
contents:
{ "icon.png" : "2a1625e1e1b3b38573d086b5ec158f72f11283a0", "icon@2x.png" : "7321a3b7f47d1971910db486330c172a720c3e4b", "icon@3x.png" : "7321a3b7f47d1971910db486330c172a720c3e4b", "order.json" : "ef3f648e787a16ac49fff2c0daa8615e1fa15df9", "strip.png" : "25b737727194b5c7b26a86d57e859a054eada240", "en.lproj/logo.png" : "cff02680b9041b7bf637960f9f2384738c935347", "en.lproj/logo@2x.png" : "0e12af882204c3661fd937f6594c6b5ffc6b8a49", "en.lproj/logo@3x.png" : "1f103c8a07fb979ea33adfbfd031e26305fd616b", "en.lproj/order.strings" : "aaf7d9598f6a792755be71f492a3523d507bc212", "zh-Hans.lproj/logo.png" : "eca86d8a474ccd33978f6aaf98a564669d45c7ae", "zh-Hans.lproj/logo@2x.png" : "b6556bc2fa795d11262f17cdff04f80350398f5f", "zh-Hans.lproj/logo@3x.png" : "124f8381721b44b2b57bf33e30b8a9a2e0404bce", "zh-Hans.lproj/order.strings" : "b0b4499ba7369e4cc15bad45c251e7b9bbcad6a4", }
Note
Don’t include metadata files that aren’t part of the order format, such as
the .DS_Store
file, in the manifest or distributable order package.
To sign the order package, see Sign and compress order package.
Now, you have a distributable .order
package you can send to Wallet.
Note
See the Track in Wallet button documentation to allow users to download the order package directly from their browser.
For more information, see Building a distributable order package.
Try it: create an order
Modify the values of the different JSON payloads to simulate an order creation as part of a customer-initiated transaction. Click or tap Pay button to make a dummy transaction and see the order in Wallet on your test device.
Note
Orders can be ingested on macOS 13.0 Ventura, but are not visible in the macOS UI — you must look for the order to appear in Wallet on your device running iOS 16.
If your customer makes a transaction using an earlier version of macOS or iOS, their device will simply ignore the order payload information.
To try this demo, open this page in Safari.
(See Requirements.)
Register a device for updates
While the simple examples above allow for static order receipts, you may want to provide updates to the user over the lifetime of the order. For example, you may want to update the order with shipping or pickup fulfillment status, shipping tracking number and status, or other information. To support this use case, Wallet can register for update notifications.
Wallet sends a registration request to the webServiceURL
that you
specify in the order.json
.
Note
Multiple unique devices may register for updates on the same order because as the initial order receipt syncs between all of user’s devices, each device subscribes for updates individually.
Wallet builds the URL to send the subscription request to according to the following schema:
POST https://your-web-service.com/v1/devices/{deviceIdentifier}/registrations/{orderTypeIdentifier}/{orderIdentifier}
The request has an Authorization field in the header that contains the authenticationToken
that was generated for the order for verification. The header field for Authorization is in
the form AppleOrder {authenticationToken}
.
The body of the request contains the device-specific APNs
pushToken
that you will use to send notifications to Wallet.
The pushToken
is a unique key for app-device combination. Your web service
should store the association between all four fields to send updates to Wallet.
Note
The POST
request to register device for order updates will only be made to your web service if the
webServiceURL
and authenticationToken
fields are included
in the top-level of the order.json
.
Take a look at the examples below to make a transaction for orders with the webServiceURL
,
and the authenticationToken
present.
Try it: create an order with status
Modify the values of the different JSON payloads to simulate updatable orders.
To try this demo, open this page in Safari.
(See Requirements.)
For more information, see Register a device for update notifications.
Updating an order
When the logistic provider or the merchant updates the order, the web service should send an APNs notification to notify Wallet that there are changes to the orders from this merchant.
When Wallet receives the notification, it makes a call to your web service requesting a list of order identifiers of orders associated with the device, that have been modified since the last time Wallet and your web service communicated.
GET https://your-web-service.com/v1/devices/{deviceIdentifier}/registrations/{orderTypeIdentifier}?ordersModifiedSince={lastModified}
The ordersModifiedSince
query parameter contains whatever the
lastModified
field value was provided by your web service last time
Wallet made this request. If this is the first time Wallet makes the request, the value will be empty.
Note
We advise you to use a standard timestamp for this field, in
ISO8601
format, but you can choose to use any identifier that
works best for your circumstances.
The web service should return a list of order identifiers that have been modified, and an updated
lastModified
value in the response body using the following schema:
{ "orderIdentifiers": [ "orderid1", "orderid2", "..." ], "lastModified": "new current timestamp or other identifier" }
Once Wallet receives the list of orders to fetch, it makes an individual request to fetch each order from
GET https://your-web-service.com/v1/orders/{orderTypeIdentifier}/{orderIdentifier}
For more information, see Retrieve the registrations for a device.
Try it: update sample orders
Once you have placed at least one sample updatable order in this session, it will be visible in the list below.
There are no orders in this session. Please place an updatable order to edit and update it.
After you select the order, scroll down to view the order json in the editor.
You may modify fields such as status
,
pickupAt
, estimatedDeliveryAt
, etc.
Then, click Update button below the editor to send an APNs notification to Wallet, and see the
order state change on your test device.
Send APNs push notification
When the logistic provider or the merchant updates the order, they need to send an APNs notification
using the pushToken
associated with the
order when Wallet registered for update notifications.
The apns-topic
for the push notification needs to be set to the
orderTypeIdentifier
specified in the initial order payload.
The body of the notification is empty — Wallet will reach out to the associated
webServiceURL
to fetch the list of all recently updated orders
for this merchant Order Type Identifier when it receives the notification as described above in
the Updating an order section.
In order to send the push notification, you need a few items from the Apple Developer APNs Portal:
kid
: APNs Key ID (certificate ID generated in Apple Developer Portal)
iss
: Issuer (the team ID in Apple Developer Portal)
auth-key
: APNs Authentication Key (certificate file generated in Apple Developer Portal)
All APNs notifications must be sent over HTTP/2 and TLS 1.2 connections.
- Development server: api.sandbox.push.apple.com:443
- Production server: api.push.apple.com:443
For more information, see Sending Notification Requests to APNs.
Important
The web service API MUST implement the logging endpoint at
POST https://your-web-service.com/v1/logto accept log entries from user devices.
This endpoint is how Wallet notifies the API about any problems processing order packages. If the endpoint is not implemented, or doesn’t return a 200 response, Wallet will not process the push notifications for this order type id.
For more information, see Receive log messages.
Unregistering from updates
When a user deletes an order in Wallet, or disables update notifications on an order, Wallet sends a request to the web service to unregister the device from any updates to this order.
It’s the merchant’s responsibility to delete the device push token from their database. The request is made to:
DELETE https://your-web-service.com/v1/devices/{deviceIdentifier}/registrations/{orderTypeIdentifier}/{orderIdentifier}
The request has an Authorization field in the header that contains the
authenticationToken
that was generated for the order for verification. The header field for Authorization is in
the form AppleOrder {authenticationToken}
.For more information, see Unregister a device from update notifications.
Additional Resources
Ready to integrate Apple Pay into your website? Here are a few links you may find useful:
Questions or Feedback
Check out our developer forums or reach out to us.