Skip to content
Create account
or
Sign in
The Stripe Docs logo
/
Ask AI
Create account
Sign in
Get started
Payments
Finance automation
Platforms and marketplaces
Money management
Developer tools
Get started
Payments
Finance automation
Get started
Payments
Finance automation
Platforms and marketplaces
Money management
Overview
Start an integration
Products
Global Payouts
Capital
Issuing cards
    Overview
    How Issuing works
    Global availability
    Manage fraud
    Cards
    Choose your card type
    Virtual cards
    Issue virtual cards
    Physical cards
    Manage cards
    Digital wallets
    Replacement cards
    Card programmes
    Programme management
    Customise your card programme
    Add funds to your card programme
    Credit Consumer Issuing
    Controls
    Spending controls
    Advanced fraud tools
    3DS
    Fraud challenges
    Real-time authorisations
    PIN management
    Issuing Elements
    Token Management
    Funding
    Balance
    Post-fund your integration with Stripe
    Post-fund your integration with Dynamic Reserves
    Purchases
    Authorisations
    Transactions
    Disputes
    Testing
    Merchant categories
    ATM Usage
    Issuing with Connect
    Set up an Issuing and Connect integration
    Update terms of service acceptance
    Connect funding
    Connected accounts, cardholders, and cards
    Embed card management UI
    Credit
    Overview
    Set up connected accounts
    Manage credit terms
    Report other credit decisions and manage AANs
    Report required regulatory data for credit decisions
    Manage account obligations
    Test credit integration
    Additional information
    Choose a cardholder type
    Customer support for Issuing and Treasury
    Issuing watchlist
    Marketing guidance (Europe/UK)
    Product and marketing compliance guidance (US)
Treasury
Manage money
HomeMoney managementIssuing cards

Use digital wallets with Issuing

Learn how to use Issuing to add cards to digital wallets.

Copy page

Issuing allows users to add cards to digital wallets such as Apple Pay and Google Pay. Stripe supports the addition of cards through two methods:

  1. Manual Provisioning: cardholders enter their card details into a phone’s wallet application to add it to their digital wallets.
  2. Push Provisioning: mobile applications allow users to add cards to their digital wallets straight from the app.

When a card is added to a digital wallet, a tokenised representation of that card is created. Network tokens are managed separately from cards. For more information about network tokens and how they work, see Token Management.

Manual Provisioning

Cardholders can add Stripe Issuing virtual cards and physical cards to their Apple Pay, Google Pay, and Samsung Pay wallets through manual provisioning.

To do so, cardholders open the wallet app on their phone and enter their card details. Stripe then sends a 6-digit verification code to the phone_number or email of the cardholder associated with the card.

A card not supported error displays if neither field is set on the cardholder when the card was provisioned.

No code is required to implement manual provisioning, but the process to set it up can vary depending on the digital wallet provider and the country you’re based in:

US

Apple Pay wallets require approval from Apple. Check your digital wallets settings to view the status of Apple Pay in your account. You might need to submit an application before using Apple Pay.

Google Pay and Samsung Pay have no additional required steps.

EU/UK

Digital wallet integrations require additional approval from the Stripe partnership team. Get in touch with your account representative or contact Stripe for more information.

Apple Pay wallets require additional approval. Check your digital wallets settings to view the status of Apple Pay in your account. You might need to submit an application before using Apple Pay.

Push Provisioning

With push provisioning, cardholders can add their Stripe Issuing cards to their digital wallets using your app, by pressing an “add to wallet” button like the ones shown below.

Users must first complete manual provisioning steps to enable push provisioning in the US. In addition to manual provisioning approval, push provisioning requires you to integrate with the Stripe SDK.

This requires both approval processes through Stripe and code integration with the Stripe SDK for each platform you wish to support push provisioning on. Platform approvals cascade down to all their connected accounts.

Samsung Pay push provisioning isn’t supported with our SDKs.

A black UI button that says Add to Apple Wallet. There is an Apple Wallet logo image to the left of the text. It is a grey wallet with blue, yellow, green, and red cards stacked slightly offset.

Request Access

Push provisioning requires a special entitlement from Apple called com.apple.developer.payment-pass-provisioning. You can request it by emailing support-issuing@stripe.com. In your email, include your:

  • Card network – Visa or MasterCard.
  • Card name – This is the name of the card displayed in the wallet.
  • App name – Your app’s name.
  • Developer team ID—Found in your Apple Developer account settings under membership (for example, 2A23JCNA5E).
  • ADAM ID – Your app’s unique numeric ID. Found in App Store Connect, or in the App Store link to your app (for example, https://apps.apple.com/app/id123456789).
  • Bundle ID – Your app’s bundle identifier, also found in App Store Connect (for example, com.example.yourapp).

If you have multiple apps (such as for testing), that have any different fields for the above attributes, you’ll need to request access for each of these.

After we approve and apply your request, your app appears on the details page of a provisioned card in the Wallet app, and the PKSecureElementPass object is available in your app by calling PKPassLibrary().passes(). You might need to remove and re-provision the card for the change to take effect.

Check eligibility
Client-side

Make sure you’ve integrated the latest version of the Stripe iOS SDK with your app.

Determine if the device is eligible to use push provisioning.

  1. Check that the value of wallets[apple_pay][eligible] in the issued card is true.
  2. Call PKPassLibrary().canAddSecureElementPass(primaryAccountIdentifier:) with the wallets[primary_account_identifier] from your card, and check that the result is true. If the primary_account_identifier is empty, pass an empty string to canAddSecureElementPass().

Retrieve these values on your back end, then pass them to your app for the eligibility check.

Warning

You must check the server-side wallets[apple_pay][eligible] flag and the result of canAddSecureElementPass() before showing the PKAddPassButton. If you show an Add to Apple Wallet button without checking these values, App Review might reject your app.

Swift
import Stripe class MyViewController: UIViewController { @IBOutlet weak var addPassButton: PKAddPassButton! // ... func handleEligibilityResponse(eligible: Bool, primaryAccountIdentifier: String?) { if eligible && PKPassLibrary().canAddSecureElementPass(primaryAccountIdentifier: primaryAccountIdentifier ?? "") { addPassButton.isHidden = false } else { addPassButton.isHidden = true } } }

For more context, see the code snippets and references to the sample app at each step. For this step, see how the sample app checks eligibility.

Provision a card
Client-side

When the user taps the PKAddPassButton, create and present a PKAddPaymentPassViewController, which contains Apple’s UI for the push provisioning flow.

Note

PKAddPaymentPassViewController can use the primaryAccountIdentifier from the previous step to determine if a card has already been provisioned on a specific device. For example, if the card has already been added to an iPhone, Apple’s UI offers to add it to a paired Apple Watch.

Swift
import Stripe class MyViewController: UIViewController { // ... func beginPushProvisioning() { let config = STPPushProvisioningContext.requestConfiguration( withName: "Jenny Rosen", // the cardholder's name description: "RocketRides Card", // optional; a description of your card last4: "4242", // optional; the last 4 digits of the card brand: .visa, // optional; the brand of the card primaryAccountIdentifier: self.primaryAccountIdentifier // the primary_account_identifier value from the previous step ) let controller = PKAddPaymentPassViewController(requestConfiguration: config, delegate: self) self.present(controller!, animated: true, completion: nil) } }

For more context, see how the sample app uses a PKAddPaymentPassViewController.

The PKAddPaymentPassViewController’s initialiser takes a delegate that you need to implement – typically this can just be the view controller from which you’re presenting it. We provide a class called STPPushProvisioningContext to help you implement these methods.

Swift
class MyViewController: UIViewController { var pushProvisioningContext: STPPushProvisioningContext? = nil // ... } extension MyViewController: PKAddPaymentPassViewControllerDelegate { func addPaymentPassViewController(_ controller: PKAddPaymentPassViewController, generateRequestWithCertificateChain certificates: [Data], nonce: Data, nonceSignature: Data, completionHandler handler: @escaping (PKAddPaymentPassRequest) -> Void) { self.pushProvisioningContext = STPPushProvisioningContext(keyProvider: self) // STPPushProvisioningContext implements this delegate method for you, by retrieving encrypted card details from the Stripe API. self.pushProvisioningContext?.addPaymentPassViewController(controller, generateRequestWithCertificateChain: certificates, nonce: nonce, nonceSignature: nonceSignature, completionHandler: handler); } func addPaymentPassViewController(_ controller: PKAddPaymentPassViewController, didFinishAdding pass: PKPaymentPass?, error: Error?) { // Depending on if `error` is present, show a success or failure screen. self.dismiss(animated: true, completion: nil) } }

For more context, see how the sample app implements PKAddPaymentPassViewControllerDelegate.

You can see that the STPPushProvisioningContext’s initializer expects a keyProvider. This is an instance of a class that implements the STPIssuingCardEphemeralKeyProvider protocol.

This protocol defines a single required method, createIssuingCardKeyWithAPIVersion:completion. To implement this method, make an API call to your backend. Your backend creates an Ephemeral Key object using the Stripe API, and returns it to your app. Your app then calls the provided completion handler with your backend’s API response.

Swift
extension MyViewController: STPIssuingCardEphemeralKeyProvider { func createIssuingCardKey(withAPIVersion apiVersion: String, completion: @escaping STPJSONResponseCompletionBlock) { // This example uses Alamofire for brevity, but you can make the request however you want AF.request("https://myapi.com/ephemeral_keys", method: .post, parameters: ["api_version": apiVersion]) .responseJSON { response in switch response.result { case .success: if let data = response.data { do { let obj = try JSONSerialization.jsonObject(with: data, options: []) as! [AnyHashable: Any] completion(obj, nil) } catch { completion(nil, error) } } case .failure(let error): completion(nil, error) } } } }

For more context, see how the sample app implements STPIssuingCardEphemeralKeyProvider.

Update your backend
Server-side

The push provisioning implementation exposes methods that expect you to communicate with your own backend to create a Stripe Ephemeral Key and return a JSON of it to your app. This key is a short-lived API credential that you can use to retrieve the encrypted card details for a single instance of a card object.

To make sure that the object returned by the Stripe API is compatible with the version of the iOS or Android SDK you’re using, the Stripe SDK lets you know what API version it prefers. You must explicitly pass this API version to our API when creating the key.

Command Line
curl
curl https://api.stripe.com/v1/ephemeral_keys \ -u
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:
\ -d "issuing_card"="{{ISSUING_CARD_ID}}" \ -H "Stripe-Version: {{API_VERSION}}"
{ "id": "ephkey_1G4V6eEEs6YsaMZ2P1diLWdj", "object": "ephemeral_key", "associated_objects": [ { "id": "ic_1GWQp6EESaYspYZ9uSEZOcq9", "type": "issuing.card" } ], "created": 1586556828, "expires": 1586560428, "livemode": false, "secret": "ek_test_YWNjdF8xRmdlTjZFRHelWWxwWVo5LEtLWFk0amJ2N0JOa0htU1JzEZkd2RpYkpJdnM_00z2ftxCGG" }

For more context, see how the sample back end creates a Stripe Ephemeral Key.

Testing

The com.apple.developer.payment-pass-provisioning entitlement only works with distribution provisioning profiles, meaning even after you obtain it, the only way to test the end-to-end push provisioning flow is by distributing your app with TestFlight or the App Store.

To help with testing, we provide a mock version of PKAddPaymentPassViewController called STPFakeAddPaymentPassViewController that can be used interchangeably during testing.

Swift
import Stripe class MyViewController: UIViewController { // ... func beginPushProvisioning() { let config = STPPushProvisioningContext.requestConfiguration( withName: "Jenny Rosen", // the cardholder's name description: "RocketRides Card", // optional; a description of your card last4: "4242", // optional; the last 4 digits of the card brand: .visa // optional; the brand of the card ) let controller = STPFakeAddPaymentPassViewController(requestConfiguration: config, delegate: self) self.present(controller!, animated: true, completion: nil) } }

To build the sample app, follow the steps in the readme. You don’t need to build the app to follow the instructions above.

Was this page helpful?
YesNo
Need help? Contact Support.
Join our early access programme.
Check out our changelog.
Questions? Contact Sales.
LLM? Read llms.txt.
Powered by Markdoc