--- title: "Apple Pay in-app provisioning" description: "Learn how to integrate Apple Pay in-app provisioning." url: "https://docs.adyen.com/issuing/tokens-digital-wallet/apple-pay-provisioning" source_url: "https://docs.adyen.com/issuing/tokens-digital-wallet/apple-pay-provisioning.md" canonical: "https://docs.adyen.com/issuing/tokens-digital-wallet/apple-pay-provisioning" last_modified: "2023-03-28T14:00:00+02:00" language: "en" --- # Apple Pay in-app provisioning Learn how to integrate Apple Pay in-app provisioning. [View source](/issuing/tokens-digital-wallet/apple-pay-provisioning.md) This page is a work in progress. Some of the APIs, documentation, and processes may change. If you have any feedback, reach out to your Adyen contact. Apple Pay in-app provisioning enables cardholders to add their payment cards to Apple Wallet directly from within your app. With this feature, cardholders can quickly and securely add their payment information to their Apple Wallet, without having to manually enter their card details. This page explains how to integrate Apple Pay in-app provisioning using the **Adyen Apple Pay Provisioning SDK**. ## Get the Adyen Apple Pay Provisioning SDK Download the Adyen Apple Pay Provisioning SDK from [Adyen's GitHub repository](https://github.com/Adyen/adyen-apple-pay-provisioning-ios/). The repository also includes a [README](https://github.com/Adyen/adyen-apple-pay-provisioning-ios/blob/main/README.md) with the instructions for installing the SDK. ### System requirements Before you install and start using the **Adyen Apple Pay Provisioning SDK**, ensure that your system follows the requirements: * Your application targets iOS 13.4 or later. * Your developer environment runs Xcode 14 or later. * Your developer environment runs Swift 5.7 or later (pre-installed with Xcode 13.2). ## In-app provisioning If you have an iOS app for your business, you **must** use the in-app provisioning flow described in this section. With Apple Pay in-app provisioning, your cardholders can tap **Add to Apple Wallet** directly within your iOS app. That tap starts an in-app provisioning flow. When the process is complete, they have their card data stored within their Apple Wallet, allowing them to make charges on that card from their Apple device. The following diagram walks you through the in-app provisioning flow. Green labels correspond to the steps described further on the page: 1. [Get activation data](#app-get-activation-data) 2. [Check for a card to add to Wallet](#app-check-card) 3. [Initiate card provisioning](#app-initiate-provisioning) 4. [Provision the card](#app-provision-card) 5. [Finalize card provisioning](#app-finalize-provisioning) ![](/user/pages/docs/07.issuing/18.tokens-digital-wallet/02.apple-pay-provisioning/in-app-flow.svg?decoding=auto\&fetchpriority=auto) ### Get activation data Before you start card provisioning, you must get activation data for the specified payment instrument. 1. From your server, make a GET `/paymentInstruments/{id}/networkTokenActivationData` request and specify the `id` of the payment instrument in the path. To make this request, your [API credential](/issuing/manage-access/api-credentials-web-service) needs the following role: * **Bank Issuing PaymentInstrument Network Token Activation Data role** **Get activation data** ```bash curl https://balanceplatform-api-test.adyen.com/bcl/v2/paymentInstruments/PI00000000000000000000001/networkTokenActivationData \ -H 'x-api-key: ADYEN_BALANCE_PLATFORM_API_KEY' \ -H 'content-type: application/json' \ -X GET ``` The response contains the `sdkInput` object that you need to initialize the provisioning service in the next step. 2. Pass the `sdkInput` to your app. ### Check for a card to add to Wallet Initialize the `ProvisioningService` class that is used to check if the cardholder can add a payment card to their Apple Wallet. **Check card eligibility** ```swift import AdyenApplePayProvisioning let provisioningService = ProvisioningService(sdkInput: sdkInput) let canAddCard = await provisioningService.canAddCard() // Show or hide the Add card to Apple Wallet button ``` Use the value returned by the `canAddCard` method to show or hide the **Add card to Apple Wallet** button. If available, you can add a payment card to both iPhone and Apple Watch. To determine the compatibility of the card with a particular device, use the `canAddCardDetails()` function. ### Initiate card provisioning When the cardholder selects **Add card to Apple Wallet**, use the **Adyen Apple Pay Provisioning SDK** to initiate provisioning by calling the `start()` function with two parameters: `delegate` and `presentingViewController`. **Initiate card provisioning** ```swift try provisioningService.start( delegate: self, presentingViewController: viewController ) ``` ### Provision the card Implement `ProvisioningServiceDelegate` to receive the `provision(sdkOutput)` callback from the **Adyen Apple Pay Provisioning SDK**. In the callback: 1. From your back end, make a POST `paymentInstruments/{id}/networkTokenActivationData` request and pass `sdkOutput` to provision the payment instrument. The response contains the `sdkInput` object. 2. Return `sdkInput` from the `provision` method. **Provision the card** ```swift func provision(sdkOutput: Data) async -> Data? { let sdkInput = // POST `sdkOutput` to server return sdkInput } ``` ### Finalize card provisioning After the provisioning is complete, the Adyen Apple Pay Provisioning SDK calls the delegate method `didFinishProvisioning`. This callback can be used to update your UI and show **Added to Apple Wallet** or **Available in Apple Wallet**. **Finalize card provisioning** ```swift func didFinishProvisioning(with pass: PKPaymentPass?, error: Error?) { // Update your UI } ``` ## Wallet provisioning You must also support card provisioning directly from Apple Wallet. After implementing the Apple Wallet extension, your app's name and icon appears in the **From Apps on Your iPhone** list of cards available to add to the Wallet. In addition to [in-app provisioning](#in-app-provisioning), you must also support card provisioning directly from Apple Wallet. ### Requirements Before you start implementing the Wallet provisioning flow: 1. [Add the Apple Wallet extension](#add-wallet-extension). 2. [Add Authentication UI extension](#add-auth-extension). #### Add the Apple Wallet extension To add the Apple Wallet extension: 1. Add a new target to your Xcode project with any Extension template. Then, change the values under the `NSExtension` dictionary in the `Info.plist` as follows: | Key | Type | Value | | --------------------------- | ------ | --------------------------------------------- | | `NSExtension` | String | **com.apple.PassKit.issuer-provisioning** | | `NSExtensionPrincipalClass` | String | **$(PRODUCT\_MODULE\_NAME).ExtensionHandler** | 2. Create an `ExtensionHandler` class that implements the `PKIssuerProvisioningExtensionHandler` protocol. This class manages the issuer-provided extension that is used during the card provisioning process. **Add Wallet extension** ```swift import PassKit class ExtensionHandler: PKIssuerProvisioningExtensionHandler { } ``` #### Add the Authentication UI extension The Apple Wallet authenticates cardholders before allowing them to provision cards. You can implement this authentication process in your UI by adding the Authentication UI extension. To add this extension: 1. Add another target to your Xcode project with any Extension template. Change the values under the `NSExtension` dictionary in the `Info.plist` as follows: | Key | Type | Value | | --------------------------- | ------ | ------------------------------------------------------- | | `NSExtension` | String | **com.apple.PassKit.issuer-provisioning.authorization** | | `NSExtensionPrincipalClass` | String | **$(PRODUCT\_MODULE\_NAME).AuthorizationProvider** | 2. Create an `AuthorizationProvider` class that is a subclass of `UIViewController` and implements the `PKIssuerProvisioningExtensionAuthorizationProviding` protocol. Use the `completionHandler` to communicate if the authentication was successful. ### Extension provisioning flow The following sequence diagram shows the flow to provision a card in an Apple Wallet. ![](/user/pages/docs/07.issuing/18.tokens-digital-wallet/02.apple-pay-provisioning/extension-flow.svg?decoding=auto\&fetchpriority=auto) As shown in the diagram, the provisioning flow is the following: 1. [Show your app on Apple Wallet](#show-your-app-on-wallet) 2. [Show card passes](#show-card-passes) 3. [Generate a request to add a card](#ext-generate-request) 4. [Provision the card](#ext-provision-card) #### Initialize the Adyen Apple Pay Provisioning SDK At the beginning of each step of the provisioning flow, you must initialize the **Adyen Apple Pay Provisioning SDK**, so you can call the SDK's methods. The following sequence diagram shows the flow to initialize the SDK. ![](/user/pages/docs/07.issuing/18.tokens-digital-wallet/02.apple-pay-provisioning/initialize-sdk.svg?decoding=auto\&fetchpriority=auto) As shown in the diagram, the initialization flow is the following: 1. Make a GET `/paymentInstruments/{id}/networkTokenActivationData` request. 2. Receive an `sdkInput` from Adyen. 3. Initialize the `ExtensionProvisioningService` using the `sdkInput`. The following sections explain the steps for the provisioning flow, including the steps to initialize the SDK. ### Show your app on Apple Wallet When your user tries to add their Adyen-issued card to Apple Wallet, Apple Wallet must show your app as an option for provisioning. To do this, Apple Wallet uses the [Apple Wallet extension](#add-wallet-extension) to check if your app can provision card data. If your app is available for provisioning, then Apple Wallet shows it as an option. You can provide the provisioning status of your app by using the **Adyen Apple Pay Provisioning SDK**. Do this as follows: 1. From your server, make a GET `/paymentInstruments/{id}/networkTokenActivationData` request and specify the `id` of the payment instrument in the path.\ If your user has multiple payment instruments, make a request for each payment instrument. **Get activation data** ```bash curl https://balanceplatform-api-test.adyen.com/bcl/v2/paymentInstruments/PI00000000000000000000001/networkTokenActivationData \ -H 'x-api-key: ADYEN_BALANCE_PLATFORM_API_KEY' \ -H 'content-type: application/json' \ -X GET ``` The response contains the `sdkInput` string that you need to initialize the provisioning service in the next step. 2. Initialize the `ExtensionProvisioningService` class, which manages the [Apple Wallet extension](#add-wallet-extension). Pass the `sdkInput` to the class as a parameter. **Initiate card provisioning for one payment instrument** ```swift import AdyenApplePayExtensionProvisioning let provisioningService = ExtensionProvisioningService(sdkInput: sdkInput) ``` If you requested multiple `sdkInput` strings, pass them to the class in an array. **Initiate card provisioning for multiple payment instruments** ```swift import AdyenApplePayExtensionProvisioning let provisioningService = ExtensionProvisioningService(sdkInputs: [sdkInput1, sdkInput2, ...]) ``` 3. From the **Adyen Apple Pay Provisioning SDK**, call `extensionStatus` to implement the `status` method of the `PKIssuerProvisioningExtensionHandler` protocol. Consider including the following parameters: * `requiresAuthentication`: A boolean that specifies whether you provide [authentication through the UI extension](#add-auth-extension). * `entriesUnavailableExtensionStatus`: If the `ExtensionProvisioningService` could not be initialized, return this parameter to indicate that the provisioning service is not available. **Get current status** ```swift func status() async -> PKIssuerProvisioningExtensionStatus { // Initialize the service return provisioningService.extensionStatus(requiresAuthentication: true) // If service could not be initialized return ExtensionProvisioningService.entriesUnavailableExtensionStatus } ``` After completing these steps, the **Adyen Apple Pay Provisioning SDK** sends the status to the Apple Wallet extension. If your provisioning service is available, the `status` object contains information about the available [card passes](#show-card-passes) in your app. The time limit for your app to complete these steps is 100 milliseconds. If your app exceeds this limit, make a new GET `/paymentInstruments/{id}/networkTokenActivationData` request to refresh the `sdkInput`. ### Show card passes To enable your user to add their card to their Apple Wallet, you must show the cards as available card passes. You can do this by providing the card data and card art to **Adyen Apple Pay Provisioning SDK**. With this information, the SDK generates a preview of the card passes to the user. The SDK uses two different methods to generate the available card passes: * `passEntries`: This method shows card passes on the Wallet app on iPhone. * `remotePassEntries`: This method shows card passes on: * The Watch app on iPhone. * The Wallet app on Apple Watch. To implement `passEntries` and `remotePassEntries`: 1. From your server, make a GET `/paymentInstruments/{id}/networkTokenActivationData` request and specify the `id` of the payment instrument in the path. **Get activation data** ```bash curl https://balanceplatform-api-test.adyen.com/bcl/v2/paymentInstruments/PI00000000000000000000001/networkTokenActivationData \ -H 'x-api-key: ADYEN_BALANCE_PLATFORM_API_KEY' \ -H 'content-type: application/json' \ -X GET ``` The response contains the `sdkInput` string that you need to initialize the provisioning service in the next step. If the extension needs to show multiple payment instruments, request an `sdkInput` string for each payment instrument. 2. Initialize the `ExtensionProvisioningService` class, which manages the [Apple Wallet extension](#add-wallet-extension). Pass the `sdkInput` to the class as a parameter. **Initiate card provisioning for one payment instrument** ```swift import AdyenApplePayExtensionProvisioning let provisioningService = ExtensionProvisioningService(sdkInput: sdkInput) ``` If you requested multiple `sdkInput`, pass these to the class in an array. **Initiate card provisioning for multiple payment instruments** ```swift import AdyenApplePayExtensionProvisioning let provisioningService = ExtensionProvisioningService(sdkInputs: [sdkInput1, sdkInput2, ...]) ``` 3. Implement `ExtensionProvisioningServiceDelegate` to receive the `cardArt(forBrand: String)` callback from the **Adyen Apple Pay Provisioning SDK**. This callback returns the card art that corresponds to each available card pass. **Provide card art** ```swift extension ExtensionHandler: ExtensionProvisioningServiceDelegate { func cardArt(forBrand brand: String) -> CGImage { return UIImage(named: "card_art")!.cgImage! } } ``` 4. From the SDK, call `passEntries` and `remotePassEntries` and pass the delegate that you created in the previous step. **Get pass entries** ```swift func passEntries() async -> [PKIssuerProvisioningExtensionPassEntry] { return provisioningService.passEntries(withDelegate: self) } func remotePassEntries() async -> [PKIssuerProvisioningExtensionPassEntry] { return provisioningService.remotePassEntries(withDelegate: self) } ``` Now, the Apple Wallet or Watch app shows the available card passes to your user. The time limit for your app to complete these steps is 20 seconds. If your app exceeds this limit, make a new GET `/paymentInstruments/{id}/networkTokenActivationData` request to refresh the `sdkInput`. ### Generate a request to provision a card After your user selects to add a card to Apple Wallet, the Apple Wallet extension calls **Adyen Apple Pay Provisioning SDK** to generate a request to provision the card pass. To generate a request for adding a card: 1. From your server, make a GET `/paymentInstruments/{id}/networkTokenActivationData` request and specify the `id` of the payment instrument in the path.\ If your user has multiple payment instruments, make a request for each payment instrument. **Get activation data** ```bash curl https://balanceplatform-api-test.adyen.com/bcl/v2/paymentInstruments/PI00000000000000000000001/networkTokenActivationData \ -H 'x-api-key: ADYEN_BALANCE_PLATFORM_API_KEY' \ -H 'content-type: application/json' \ -X GET ``` The response contains the `sdkInput` string that you need to initialize the provisioning service in the next step. 2. Initialize the `ExtensionProvisioningService` class, which manages the [Apple Wallet extension](#add-wallet-extension). Pass the `sdkInput` to the class as a parameter. **Initiate card provisioning for one payment instrument** ```swift import AdyenApplePayExtensionProvisioning let provisioningService = ExtensionProvisioningService(sdkInput: sdkInput) ``` If you requested multiple `sdkInput` strings, pass these to the class in an array. **Initiate card provisioning for multiple payment instruments** ```swift import AdyenApplePayExtensionProvisioning let provisioningService = ExtensionProvisioningService(sdkInputs: [sdkInput1, sdkInput2, ...]) ``` 3. From the SDK, call the `generateAddPaymentPassRequestForPassEntryWithIdentifier` method to obtain a pass request. In this call, include the `delegate` parameter to handle [card provisioning](#ext-provision-card). **Generate a request for adding a card pass** ```swift func generateAddPaymentPassRequestForPassEntryWithIdentifier( _ identifier: String, configuration: PKAddPaymentPassRequestConfiguration, certificateChain certificates: [Data], nonce: Data, nonceSignature: Data ) async -> PKAddPaymentPassRequest? { try? await provisioningService.generateAddPaymentPassRequestForPassEntryWithIdentifier( identifier, configuration: configuration, certificateChain: certificates, nonce: nonce, nonceSignature: nonceSignature, delegate: self ) } ``` 4. Send the pass request to the extension. ### Provision the card After the SDK sends the pass request to the Apple Wallet extension, the extension requests from Adyen the [network token](/issuing/manage-network-tokens) data of the card. The extension uses this data to provision the card in Apple Wallet. To provision the card when the extension requests it: 1. Implement `ExtensionProvisioningServiceDelegate` to receive the `provision(paymentInstrumentId, sdkOutput)` callback from the **Adyen Apple Pay Provisioning SDK**. 2. In the callback, make a POST `paymentInstruments/{id}/networkTokenActivationData` request and specify the following parameters: | Parameter | Type | Description | | ----------- | ---- | ------------------------------------------------------------------------------------------------------------------------- | | `id` | Path | The `paymentInstrumentId` of the card you want to provision. | | `sdkOutput` | Body | Data automatically generated and provided by the SDK. The extension must send this data to Adyen to validate the request. | The response contains the `sdkInput` string that the SDK needs to provision the card. 3. Return the `sdkInput` string from the response back to the SDK. The following example shows how to implement these steps. **Provision the card** ```swift extension ExtensionHandler: ExtensionProvisioningServiceDelegate { func provision(paymentInstrumentId: String, sdkOutput: Data) async -> Data? { let sdkInput = // POST `sdkOutput` to server return sdkInput } } ``` After these steps are completed, the SDK returns the delegate to the Apple Wallet extension. Then, the extension provisions the card on Apple Wallet. ## Next steps [required](/issuing/manage-network-tokens) [Manage network tokens](/issuing/manage-network-tokens) [Learn how to manage network tokens for cards added to digital wallets.](/issuing/manage-network-tokens)