Use digital wallets with Issuing
Learn how to use Issuing to add cards to digital wallets.
Issuing allows users to add cards to digital wallets like Apple Pay and Google Pay.
You can’t test this feature in a sandbox, because digital wallet tokens are only available in live mode. To test using digital wallet tokens, you must be approved for live use cases and use real cards. Stripe supports the following provisioning methods:
- Manual provisioning: cardholders enter their card details into a phone’s wallet application to add it to their digital wallets.
- Push provisioning: mobile applications and websites allow users to add cards directly to their digital wallets.
When a card is added to a digital wallet, a tokenized 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 and CA
US-issued stablecoin programs currently follow the US enablement process.
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. After the application is submitted, approval can take 1-2 weeks.
Google Pay and Samsung Pay have no additional required steps.
EU and 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
Push provisioning allows cardholders to add Stripe Issuing cards to their digital wallets directly from your app or website by selecting an “add to wallet” button.
Users must first complete manual provisioning steps to enable push provisioning in the US. In addition to manual provisioning approval, push provisioning requires an integration with each wallet platform. You can integrate directly with the wallet platform or use a Stripe SDK.
This requires both approval processes through Stripe and code integration for each platform where you want to support push provisioning. Platform approvals cascade down to all of their connected accounts.
Samsung Pay push provisioning isn’t supported with our SDKs.
Request access
Warning
You must get accesss to manual provisioning before you can request push provisioning.
Push provisioning requires a special entitlement from Apple called com.apple.developer.payment-pass-provisioning. You can request it by emailing . In your email, include your:
- Card network : Visa or Mastercard.
- Card name : 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 ).
- the related setting 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. the relevant part of the product ).
- 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
If you use the Stripe iOS SDK, integrate its latest version with your app.
Determine if the device is eligible to use push provisioning.
- Check that the value of wallets[apple _ pay][eligible] in the issued card is true .
- 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.
Select a language
Swift
Objective C
No results
import PassKit
import UIKit
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.
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.
Select a language
Swift
Objective C
No results
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 initializer 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.
Select a language
Swift
Objective C
No results
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.
Select a language
Swift
Objective C
No results
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
Your push provisioning integration communicates with your backend to create a Stripe Ephemeral Key and return its JSON to your app. This key is a short-lived API credential that you can use to retrieve the encrypted card details for a single card object.
You must explicitly set an API version when creating the key. If you use a Stripe SDK, use the API version that the SDK provides. For a direct integration, return the version used to create the key with its secret, and use that same version for requests authenticated with the key.
Command Line
Select a language
curl
Ruby
Python
PHP
Node.js
Java
Go
.NET
No results
{
"id": "ephkey_1G4V6eEEs6YsaMZ2P1diLWdj",
"object": "ephemeral_key",
"associated_objects": [
{
"id": "{{CARD_ID}}",
"type": "issuing.card"
}
],
"created": 1586556828,
"expires": 1586560428,
"livemode": false,
"secret": "ek_test_YWNjdF8xRmdlTjZFRHelWWxwWVo5LEtLWFk0amJ2N0JOa0htU1JzEZkd2RpYkpJdnM_00z2ftxCGG",
"api_version": "{{API_VERSION}}"
}
For more context, see how the sample backend creates a Stripe Ephemeral Key.
Testing
The com.apple.developer.payment-pass-provisioning entitlement only works with distribution provisioning profiles. To test a direct integration end to end, distribute your app with TestFlight or the App Store and use a live card.
If you use the Stripe iOS SDK, you can test with a mock version of PKAddPaymentPassViewController called STPFakeAddPaymentPassViewController. This only works in a sandbox using test cards.
Select a language
Swift
Objective C
No results
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.
