InApp Provisioning — Customization [EN]

David Martinez
4 min readOct 3, 2021

--

In this article we will continue to apply changes to our enrollment process that started in the previous episode about InApp provisioning with the goal of improving user experience.

To do so, we will explore alternatives offered by the PassKit API and we will review some of the problems that we may encounter when developing our main functionality.

Customization

One of Apple’s recommendations is to display the button or change it to a static banner or image depending on whether the card is already included in ApplePay or not. To do this we will initially focus on the following PassKit API methods:

/// A Boolean value that indicates whether the pass library is available.
class func isPassLibraryAvailable() -> Bool
/// Returns the passes of the specified pass type.
func passes(of passType: PKPassType) -> [PKPass]

The first one will tell us if we have access to the device’s Passes library and the second one will return an array with pkpasses currently registered for the requested type.

A pkpass object can be anything from a wallet-linked card to an airline ticket.

With these ideas, we will built an interface that expose us some useful features.

// 1

At first, we must check if the PassKit library is available for our device.

// 2

Second, we request to PassKit library for all secureElements. These elements may be representing secure items and transactions in which we could find our bank cards. This API was suffer a mandatory mayor update at iOS 13.4 so we have preferred to include the code with both implementations to increase compatibility to older iOS versions.

// 3

We extract from the PKPass the suffix of the card (if it exists) that we will use to make a relationship and checks if this cards exists or not (comparing with our server card data information). Note: For the card identification we also have the primaryAccountIdentifier, but in our example we not use it.

// 4

Extract from the PKPass the deviceAccountIdentifier too. This object is not necessary for this example but it is usually necessary for your own bank api services.

// 5

Finally, we filter from the list those PKPass items that have these values (primaryAccountNumberSuffix and deviceAccountIdentifer) and ignore the others. An enrolled card always have both of them.

// 6
In the same way that in step 5, we obtain the passes linked with our linked devices such as, an AppleWatch. Using that information we will keep showing the “Add to Apple Wallet” button until all our devices has configured our selected card.

With all this code, we must perform a final step, we will create a piece of code that manage if we must show, or not, the AppleWallet button.

// 1

At first we must check (as always) if our card is already enrolled with our device.

// 2

We check if we have a remote device linked with our phone such as our AppleWatch

// 3

… If so, we must evaluate if our selected card is enrolled with this remote device.

// 4

With this information we can state that our card is completely link with ApplePay if all our devices are linked.

// 5

This is a helper repository that evaluate if we have (or not) linked devices.

And … that’s all! from our view we could have something like that:

let isEnroll: IsCardRegisterAtApplePayInteractorfunc setupApplePay(card: Card) {
if isEnroll.execute() {
// todo: Display a banner or not display Add To Apple Wallet button
} else {
let passKitButton = PKAddPassButton(addPassButtonStyle: .blackOutline)
// todo: Display passKitButton into the screen
}
}

Frequent problems and doubts

The API says that my card is not linked

I was already register mi card into my AppleWallet (natively) but the PassKit API says that i haven’t any card enrolled so … what’s could be the problem?
To avoid “InApp” enrollment malfunctions it’s so important that the servers involved with the sign up process send all the information involves with this process such as the bundle application id (eg: com.mycompany.myapp). With this Apple relations the card <-> device <-> AppleWallet. Without this information PassKit never could stablish a relation between the card added to AppleWallet with our application. For more information, read chapter II. Prerequisites, from user manual include in the bibliography at the bottom of this article.

Another possible error derived from this could be the following one, imagine this flow:
1. The server is configured without including the bundle-id
2. A user links it card using ApplePay
3. The servers add the bundle-id implementation
4. The user install our app and navigate to the detail card landing page
5. The API indicates that card is not added to ApplePay :(

In this case if the user tries to add again it will receive an error due to this card is already added to our device.
For this case ask to your issuer-host if offers any possibility to update automatically this information across all platforms

What if I register my card using Wallet native app?

No problem, if you registered or remove your card from or inside your application or your wallet app, the PassKit library always return the single and unique state for the card enroll status across all your single device.

Note: Remember that the enroll process works for a single device not across all your physical devices. So if you enroll your card to your iPhone, not be available into your iPad too, not works like other iCloud features.

Thanks for reading!

Bibliography

Utilities

--

--