Headless Universal Checkout has changed to solidify the integration experience and make the interfaces clearer and more consistent.
Below is a summary of the changes and examples of how to migrate to this new integration, however we recommend you consult the full documentation during integration.
Starting Headless Universal Checkout
Like before, you still set Headless Universal Checkout delegate, conform to PrimerHeadlessUniversalCheckoutDelegate
to handle the callbacks that happen during the checkout’s lifecycle, and start headless universal checkout with your client token.
The completion handler returns the available payment methods for the session when you start PrimerHeadlessUniversalCheckout
.
Instead of just a string, each payment method returned contains the following:
paymentMethodType
a unique string identifier for the payment method.paymentMethodManagerCategories
an array that defines the payment method managers that can be used with this payment method (i.e..cardComponents
,.nativeUI
or.rawData
). Use this to know which payment method managers to create.- [Optional]
requiredInputDataClass
this is provided whenpaymentMethodManagerCategories
contains.rawData
and indicates the type of data that should be captured for the payment method. supportedPrimerSessionIntents
an array ofPrimerSessionIntent
which defines what intents can be used with this payment method (i.e..checkout
or.vault
).
See an example below:
12345678910111213141516171819202122232425262728293031323334
import UIKit// 👇 Import the SDKimport PrimerSDK class ViewController: UIViewController { // ... var availablePaymentMethods: [PrimerHeadlessUniversalCheckout.PaymentMethod]? override func viewDidLoad() { super.viewDidLoad() // ... // 👇 Start Headless Universal Checkout with your session's client token PrimerHeadlessUniversalCheckout.current.start(withClientToken: clientToken, delegate: self) { availablePaymentMethods, err in if let err = err { // Handle error } else if let availablePaymentMethods = availablePaymentMethods { // Payment methods that are available for this session self.availablePaymentMethods = availablePaymentMethods } } }} extension ViewController: PrimerHeadlessUniversalCheckoutDelegate { // 👇 [Required] This function will return the checkout data once the payment is finished func primerHeadlessUniversalCheckoutDidCompleteCheckoutWithData(_ data: PrimerCheckoutData) { }}
Building your UI
Before, when building your UI you could create your own buttons using PrimerHeadlessUniversalCheckout.makeButton
like in the example below:
123456789101112131415161718192021222324
extension UIViewController: UITableViewDataSource, UITableViewDelegate { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.paymentMethods.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let paymentMethod = self.paymentMethods[indexPath.row] let cell = tableView.dequeueReusableCell(withIdentifier: "MerchantPaymentMethodCell", for: indexPath) as! MerchantPaymentMethodCell cell.configure(paymentMethodType: paymentMethod) // Primer SDK can provide you with Payment Method buttons that follow // the payment methods UI guidelines. // Example given for Apple Pay payment method // https://developer.apple.com/design/human-interface-guidelines/technologies/apple-pay/introduction // let paymentMethodButton = PrimerHeadlessUniversalCheckout.makeButton(for: paymentMethod) return cell } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { // The user has selected a payment method }}
PrimerHeadlessUniversalCheckout
now includes an AssetsManager
that provides payment method assets per payment method type. See below:
12345
do { let paymentMethodAsset = try PrimerHeadlessUniversalCheckout.AssetsManager.getPaymentMethodAsset(for: paymentMethod.paymentMethodType)} catch { // Handle error}
The payment method asset contains the following:
paymentMethodType
a unique string identifier for the payment method.paymentMethodName
an user friendly English localized string identifier for the payment method (e.g.Apple Pay
)paymentMethodLogo
an instance of thePrimerPaymentMethodLogo
(see more information below)paymentMethodBackgroundColor
an instance of thePrimerPaymentMethodBackgroundColor
The PrimerPaymentMethodLogo
holds UIImage
objects for different scenarios
- [Optional]
colored
aUIImage
to be used anywhere - [Optional]
dark
aUIImage
to be used in dark mode - [Optional]
light
aUIImage
to be used in light mode
The PrimerPaymentMethodBackgroundColor
holds UIColor
objects for different scenarios
- [Optional]
colored
aUIColor
to be used anywhere - [Optional]
dark
aUIColor
to be used in dark mode - [Optional]
light
aUIColor
to be used in light mode
With the above images and colors, you can build your own payment method buttons 💪
Handling Payment Methods
Before you had to call showPaymentMethod
directly for some payment methods while having managers for others. Now each payment method belongs to a payment method manager, as indicated by paymentMethodManagerCategories
on the list of available payment methods.
Native UI Manager
Used for any payment method that needs to present its own UI, like Apple Pay. See an example integration below:
1234567891011121314151617181920
import UIKitimport PrimerSDK class ViewController: UIViewController { // ... @IBAction func paymentMethodButtonTapped(_ sender: UIButton) { do { // 👇 Create the payment method manager let nativeUIPaymentMethodManager = try PrimerHeadlessUniversalCheckout.NativeUIManager(paymentMethodType: paymentMethod.paymentMethodType) // 👇 Show the payment method try nativeUIPaymentMethodManager.showPaymentMethod(intent: .checkout) } catch { // Handle error } }}
Raw Data Manager
Used for payment methods that require you to pass data to the SDK, for example for cards. As before, you have to render your own input elements and capture the required data before finally calling submit()
on the raw data manager. See an example integration below:
1234567891011121314151617181920212223242526272829
import UIKitimport PrimerSDK class ViewController: UIViewController { // ... var rawDataManager: PrimerHeadlessUniversalCheckout.RawDataManager! override func viewDidLoad() { super.viewDidLoad() // ... do { // 👇 Optionally, you can also set its delegate to get notified about data and validation changes self.rawDataManager = try PrimerHeadlessUniversalCheckout.RawDataManager(paymentMethodType: paymentMethod.paymentMethodType) // Capture required inputs... } catch { // Handle error } } @IBAction func payButtonTapped(_ sender: UIButton) { self.rawDataManager.submit() }}
Other changes
PrimerHeadlessUniversalCheckoutUIDelegate addition
New delegates have been introduced to separate payment events from UI events.
You can set the UI delegate in the start
function
1
PrimerHeadlessUniversalCheckout.current.start(..., uiDelegate: self, ...)
PrimerHeadlessUniversalCheckoutDelegate updates
Some delegate functions have been renamed:
Before v2.17.0 | After 2.17.0 |
---|---|
| Renamed to |
| Renamed to |
| Renamed to |
Some delegate functions have been renamed and moved to other delegates:
Before v2.17.0 | After 2.17.0 |
---|---|
| Moved to |
| Moved to |
Resume handler updates
Some listener functions provide a decision handler that you can call with the relevant decision to continue the flow.
The handler class name and signature of the following functions have changed:
Before v2.17.0 | After 2.17.0 |
---|---|
1234 func primerHeadlessUniversalCheckoutDidTokenizePaymentMethod( _ paymentMethodTokenData: PrimerPaymentMethodTokenData, decisionHandler: @escaping (PrimerResumeDecision) -> Void) swift copy | 1234 func primerHeadlessUniversalCheckoutDidTokenizePaymentMethod( _ paymentMethodTokenData: PrimerPaymentMethodTokenData, decisionHandler: @escaping (PrimerHeadlessUniversalCheckoutResumeDecision) -> Void) swift copy |
1234 func primerHeadlessUniversalCheckoutDidResumeWith( _ resumeToken: String, decisionHandler: @escaping (PrimerResumeDecision) -> Void) swift copy | 1234 func primerHeadlessUniversalCheckoutDidResumeWith( _ resumeToken: String, decisionHandler: @escaping (PrimerHeadlessUniversalCheckoutResumeDecision) -> Void) swift copy |
Miscellaneous changes
Models that need to be passed to the SDK when using Raw Data Managers
have changed structures and naming:
Before v2.17.0 | After 2.17.0 |
---|---|
1234567 class PrimerCardData( var cardNumber: String, var expirationMonth: String, var expirationYear: String, var cvv: String, var cardHolderName: String?) swift copy | 123456 class PrimerCardData( var cardNumber: String, var expirationDate: String, var cvv: String, var cardHolderName: String?) swift copy |
123456 class PrimerBancontactCardRedirectData( var cardNumber: String, var expirationMonth: String, var expirationYear: String, var cardHolderName: String) swift copy | 12345 class PrimerBancontactCardData( var cardNumber: String, var expiryDate: String, var cardHolderName: String) swift copy |
123 class PrimerPhoneNumberData( var phoneNumber: String) swift copy | 123 class PrimerPhoneNumberData( var phoneNumber: String) swift copy |
123 class PrimerRawRetailerData( id: String) swift copy | 123 class PrimerRetailerData( id: String) swift copy |