Token Activation in the Mobile Application
The application should support a deeplink configured in MDES. The deeplink should contain a serialNumber parameter in the query string.
Based on this value, the application should find the matching PassKit item using the serialNumber property. Then, it should call the TMP API endpoint:
POST /issuer/push-provisioning/tokens/activations
The request should contain the token identifier. If the response field issuerMobileAppAuthResponse is APPROVED, the card has been successfully activated. For DECLINED or FAILED, the activation was not completed successfully.
Process Overview
- Receive the deeplink from MDES.
- Extract
serialNumberfrom the query string. - Find the matching PassKit item by
serialNumber. - Read its
deviceAccountIdentifier. - Send it to TMP API as
tokenUniqueReference. - Handle the activation response.
Swift Example
import Foundation
import PassKit
enum ActivationStatus: String, Decodable {
case approved = "APPROVED"
case declined = "DECLINED"
case failed = "FAILED"
}
struct TokenActivationRequest: Encodable {
let tokenUniqueReference: String
}
struct TokenActivationResponse: Decodable {
let tokenUniqueReference: String?
let cardLast4Digits: String?
let issuerMobileAppAuthResponse: ActivationStatus
let comment: String?
}
func handleActivationDeeplink(_ url: URL) async throws {
guard
let components = URLComponents(url: url, resolvingAgainstBaseURL: false),
let serialNumber = components.queryItems?.first(where: { $0.name == "serialNumber" })?.value
else {
throw URLError(.badURL)
}
let passLibrary = PKPassLibrary()
guard let pass = passLibrary.passes().first(where: {
$0.serialNumber == serialNumber
}),
let tokenUniqueReference = pass.secureElementPass?.deviceAccountIdentifier
else {
throw URLError(.cannotFindHost)
}
let requestBody = TokenActivationRequest(
tokenUniqueReference: tokenUniqueReference
)
let url = URL(string: "<https://your-tmp-api-base-url/issuer/push-provisioning/tokens/activations>")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try JSONEncoder().encode(requestBody)
let (data, response) = try await URLSession.shared.data(for: request)
guard let httpResponse = response as? HTTPURLResponse,
httpResponse.statusCode == 200 else {
throw URLError(.badServerResponse)
}
let activationResponse = try JSONDecoder().decode(
TokenActivationResponse.self,
from: data
)
switch activationResponse.issuerMobileAppAuthResponse {
case .approved:
// Card has been successfully activated.
break
case .declined, .failed:
// Card activation failed.
break
}
}
Notes
- The deeplink format must match the configuration provided in MDES.
- The
serialNumbervalue is used only to find the correct PassKit item. - The activation request uses the token identifier obtained from the matching pass item.