Before you begin

This guide assumes that you know how to:

Accept payments with nol Pay

Prepare the client session

nol Pay requires the following data to process a payment successfully. Pass the following data in the client session, or in the payment request (for manual payment creation).
Parameter NameRequiredDescription
currencyCode3-letter currency code in ISO 4217 format, e.g. USD for US dollars
order
↳ lineItems
Details of the line items of the order
orderIdorderId will be passed to Nol as transaction id; it is mandatory, and must be unique. One orderId value cannot be used for multiple payments. Maximum length of orderId is 32 characters.
amountMinimal value (in minor units): 500 Maximal value (in minor units): 200000
paymentMethod
↳ descriptor
A description of the payment, as it would typically appear on a bank statement.

Prepare the SDK for payments

Pre-requisites

Install the nol Pay SDK
With CocoaPods
To integrate the NolPay into your Xcode project using CocoaPods, you can specify it in your Podfile :
RUBY
target 'YourApp' do

  pod 'PrimerSDK'
  pod 'PrimerNolPaySDK'

  post_install do |installer|
    fix_linking(installer)
  end
end

def fix_linking(installer)
    # This script adds linking for all Primer wrapper SDKs. 
    # Failure to include this snippet may result in the "WARNING! Failed to import <Module>" error when initialising the PrimerSDK
    
  installer.generated_projects.each do |project|
    primer_target_names = project.targets.filter { |target|
      !target.name.start_with?("PrimerSDK") && target.name.start_with?("Primer")
    }.map { |t| "\"#{t.name}\"" }
    project.targets.each do |target|
      if target.name == "PrimerSDK"
        framework_flags = primer_target_names.count > 0 ? "-framework #{primer_target_names.join(' -framework ')}" : ""
        target.build_configurations.each do |config|
          puts "Adding framework flags (#{config.name}): #{framework_flags}"
          other_ldflags = "$(inherited) #{framework_flags}"
          config.build_settings['OTHER_LDFLAGS'] = other_ldflags
        end
      end
    end
  end
end
After that, run this command in your terminal:
JSX
$ pod install
Activate the NFC capabilities
To engage with NFC nol payment cards, make sure to first activate the NFC capabilities in your app:
  1. Open your project in Xcode.
  2. Access the target settings.
  3. In the “Signing & Capabilities” section, tap on ”+ Capability”.
  4. Add “Near Field Communication Tag Reading”.
Then, incorporate the following keys into your Info.plist for effective NFC communication and web access:
XML
<key>com.apple.developer.nfc.readersession.formats</key>
<array>
    <string>TAG</string>
</array>
<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
<array>
    <string>D2760000850100</string>
</array>
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>
<key>NFCReaderUsageDescription</key>
<string>We use NFC to scan nol payment card. (Or tailor to your specific usage scenario)</string>
Setting NSAllowsArbitraryLoads to true is mandatory when working on the sandbox environment.

Handle payment method

Integration
PrimerHeadlessNolPayManager is an SDK component designed to streamline the integration of the TransitSDK from nol Pay. This SDK makes it easier to work with NFC nol payment cards.To integrate PrimerHeadlessNolPayManager, follow these steps:
  1. Get the available payment methods using PrimerHeadlessUniversalCheckout.current.start as described here.
  2. For the nol Pay payment method, paymentMethods array will contain PrimerPaymentMethodManagerCategory.NOL_PAY category.
  3. Add implementation of the PrimerHeadlessNolPayManager as described here.
The PrimerHeadlessNolPayManager offers a suite of headless components, each designed to seamlessly guide you through the various steps required for processing nol Pay payments:Link a Nol card
Before allowing a user to make a payment with their Nol card, the Nol card must be linked to their phone number. The user can do so by first scanning the card with their smartphone, and then entering the OTP code sent to their mobile number.To handle this flow, you will have to leverage NolPayLinkCardComponent that manages the process of linking a new Nol card.Get started
Create a new instance of the NolPayLinkCardComponent:
SWIFT
var nolPayLinkComponent = PrimerHeadlessUniversalCheckout.PrimerHeadlessNolPayManager().provideNolPayLinkCardComponent()
Listen for required user steps
As outlined above, the user has to go through multiple steps to successfully link their card. The NolPayLinkCardComponent acts as a state machine enabling you to walk the user through all the steps.Subscribe to the stepDelegate Flow in order to be notified of the next step the user has to go through:
SWIFT
    nolPayLinkComponent.stepDelegate = self

Conform to PrimerHeadlessSteppableDelegate protocol and implement its function:
SWIFT
func didReceiveStep(step: PrimerHeadlessStep) {
  /* Handle the step */
}
Listen to the data validation status
Most steps requires you to collect data from the user. Data validation is automatically performed to ensure the accuracy and completeness of the collected data.Listen to the validationDelegate to handle any validation errors that may occur:
SWIFT
nolPayLinkComponent.validationDelegate = self
Confirm to PrimerHeadlessValidatableDelegate protocol and implement its function:
SWIFT
    
    func didUpdate(validationStatus: PrimerValidationStatus, for data: PrimerCollectableData?) {  /* Handle data validation */}

Start the flow of the component
Call the start function in order to start the flow of the component.
SWIFT
    nolPayLinkComponent.start()
If the call is successful, the component will move to the first required step.Handle the card scanning step
The first step of the card linking process, called NolPayLinkCardStep.collectTagData, consists in having the user scan their Nol cards in order to retrieve the NFC tag.Call submit() to show the NFC scanning UI prompting the user to scan their Nol card.
SWIFT
    
    nolPayLinkComponent.submit()

Handle the phone number step
The second step of the card linking process, called NolPayLinkCardStep.collectPhoneData, consists in collecting the user’s mobile phone number.
SWIFT
var phoneData = NolPayLinkCollectableData.phoneData(mobileNumber: "1234567890")
nolPayLinkComponent.updateCollectedData(collectableData: phoneData)
When the data is valid, as determined by the validationDelegate, call the submit function to process the collected phone number and move the component to the next step:
SWIFT
    nolPayLinkComponent.submit()
If the call to submit() is successful, the user should receive an OTP code via an SMS sent to their phone number.Handle the OTP step
The third step of the card linking process, called NolPayLinkStep.collectOtpData, consists in capturing the OTP code:
SWIFT
    
    var otpData = NolPayLinkCollectableData.otpData(otpCode: "123456")
    nolPayLinkComponent.updateCollectedData(collectableData: otpData)
When the data is valid, as determined by the validationDelegate, call the submit function to process the OTP code and move the component to the next step:
SWIFT
nolPayLinkComponent.submit()
Handle the linked card step
The fourth and final step, called NolPayLinkStep.cardLinked, involves managing the newly linked Nol card. After successfully linking your Nol card, it’s now ready for use in payments.Handle errors
Listen to the errorDelegate to handle any errors that may occur during the linking flow:
SWIFT
    nolPayLinkComponent.errorDelegate = self

Confirm to PrimerHeadlessErrorableDelegate protocol and implement its function:
SWIFT
    
    func didReceiveError(error: PrimerError) {  /* Handle error */}
Check the possible errors that can be returned here.List the linked Nol Cards
Being able to fetch all linked Nol cards gives users a clear overview of their associated cards. This is vital for managing their cards, reviewing details, or even selecting one for further actions such as paying with or unlinking.The NolPayLinkedCardsComponent enables you to fetch the list of the PrimerNolPaymentCard objects, linked to a particular user.Get started
Creating an instance of NolPayLinkedCardsComponent:
SWIFT
    var nolPayLinkedCardsComponent = PrimerHeadlessUniversalCheckout.PrimerHeadlessNolPayManager().provideNolPayGetLinkedCardsComponent()
Get linked cards
Use the getLinkedCards function to get all the linked cards associated with the user’s mobile number:
SWIFT
    
nolPayLinkedCardsComponent.getLinkedCardsFor(mobileNumber: mobileNumber) { result in
            switch result {
                ...
            }
        }
Successfull result should return array of PrimerNolPaymentCard objects.Pay using a linked Nol card
After the Nol card has been linked, it can be used for payments. The user can do so by first selecting the linked card, and then by scanning the card with their smartphone.To handle this flow, you will have to leverage NolPayPaymentComponent that manages the process of creating a payment using linked Nol card.Get started
Create a new instance of the NolPayPaymentComponent:
SWIFT
var nolPayPaymentComponent = PrimerHeadlessUniversalCheckout.PrimerHeadlessNolPayManager(). provideNolPayStartPaymentComponent()
Listen for required user steps
As outlined above, the user has to go through multiple steps to successfully pay using their card. The NolPayPaymentComponent acts as a state machine enabling you to walk the user through all the steps.Subscribe to the stepDelegate Flow in order to be notified of the next step the user has to go through:
SWIFT
nolPayPaymentComponent.stepDelegate = self
Confirm to PrimerHeadlessSteppableDelegate protocol and implement its function:
SWIFT
    func didReceiveStep(step: PrimerHeadlessStep) {  /* Handle step */}
Listen to the data validation status
Most steps requires you to collect data from the user. Data validation is automatically performed to ensure the accuracy and completeness of the collected data.Listen to the validationDelegate to handle any validation errors that may occur:
SWIFT
    
    nolPayPaymentComponent.validationDelegate = self

Conform to PrimerHeadlessValidatableDelegate protocol and implement its function:
SWIFT
    
    func didUpdate(validationStatus: PrimerValidationStatus, for data: PrimerCollectableData?) {  /* Handle validation */}

Start the flow of the component
Call the start function in order to start the flow of the component.
SWIFT
    nolPayPaymentComponent.start()

If the call is successful, the component will move to the first required step.Handle the collect card data & phone number step
The first step of the card payment process, called NolPayPaymentStep.collectCardAndPhoneData, consists in collecting the Nol card retrieved using getLinkedCards that user wants to pay with, and the user’s mobile phone number.
SWIFT
    
    var nolPaymentCard = // selected card
    var cardAndPhoneData = NolPayPaymentCollectableData.paymentData(cardNumber: nolPaymentCard.cardNumber, mobileNumber: "1234567890")
    nolPayPaymentComponent.updateCollectedData(collectableData: phoneData)

When the data is valid, as determined by the validationDelegate, call the submit function to process the collected card and phone number and move the component to the next step:
SWIFT
    
    nolPayPaymentComponent.submit()

If the call to submit() is successful, the SDK will automatically show the NFC scanning UI prompting the user to scan the selected Nol card.Handle the requested payment step
The third and final step, called NolPayPaymentStep.paymentRequested, consists in handling the end of the payment flow.This step will be triggered when a nol Pay payment was requested using the TransitSDK from nol Pay. When this step is reached, the user is successfully charged on the Nol card they scanned during the previous step.Just like any other Primer payment, make sure to listen for the final Primer payment result using the primerHeadlessUniversalCheckoutDidCompleteCheckoutWithData or primerHeadlessUniversalCheckoutDidFail callbacks as described here.Handle errors
You can listen to the errorDelegate to handle any errors that may occur during the linking flow:
SWIFT
    nolPayPaymentComponent.errorDelegate = self

Confirm to PrimerHeadlessErrorableDelegate protocol and implement its function:
SWIFT
    func didReceiveError(error: PrimerError) {  /* Handle error */}
Check the possible errors that can be returned hereUnlink a linked Nol card
Unlinking a Nol card allows users to disassociate a card from their account. This may be necessary if the card is lost, stolen, or simply no longer in use. The user can do so by first selecting the linked card, and then entering the OTP code sent to their mobile number.To handle this flow, you will have to leverage NolPayLinkedCardsComponent to get linked Nol cards and NolPayUnlinkCardComponent that manages the process of unlinking of linked Nol card.Get started
Create a new instance of the NolPayUnlinkCardComponent:
SWIFT
    
    var nolPayUnlinkComponent = PrimerHeadlessUniversalCheckout.PrimerHeadlessNolPayManager(). provideNolPayUnlinkCardComponent()
Listen for required user steps
As outlined above, the user has to go through multiple steps to successfully unlink their card. The NolPayUnlinkCardComponent acts as a state machine enabling you to walk the user through all the steps.Subscribe to the stepDelegate Flow in order to be notified of the next step the user has to go through:
SWIFT
    nolPayUnlinkComponent.stepDelegate = self
Conform to PrimerHeadlessSteppableDelegate protocol and implement its function:
SWIFT
    func didReceiveStep(step: PrimerHeadlessStep) {  /* Handle step */}
Listen to the data validation status
Most steps requires you to collect data from the user. Data validation is automatically performed to ensure the accuracy and completeness of the collected data.Listen to the validationDelegate to handle any validation errors that may occur:
SWIFT
    nolPayUnlinkComponent.validationDelegate = self
Confirm to PrimerHeadlessValidatableDelegate protocol and implement its function:
SWIFT
    func didUpdate(validationStatus: PrimerValidationStatus, for data: PrimerCollectableData?) {  /* Handle validation */}
Start the flow of the component
Call the start function in order to start the flow of the component.
SWIFT
    nolPayUnlinkComponent.start()
If the call is successful, the component will move to the first required step.Handle the collect card data & phone number step
The first step of the card unlinking process, called NolPayUnlinkCardStep.collectCardAndPhoneData, consists in collecting the Nol card retrieved using getLinkedCards that user wants to unlink and the user’s mobile phone number and country dialling code.
SWIFT
    var nolPaymentCard = // selected cardvar cardAndPhoneData = NolPayUnlinkCollectableData.cardAndPhoneData(nolPaymentCard: nolPaymentCard, mobileNumber: "1234567890")nolPayUnlinkComponent.updateCollectedData(phoneData)
When the data is valid, as determined by the validationDelegate, call the submit function to process the collected card and phone number and move the component to the next step:
SWIFT
    nolPayUnlinkComponent.submit()
If the call to submit() is successful, the user should receive an OTP code via an SMS sent to their phone number.Handle the OTP step
The third step of the card linking process, called NolPayUnlinkStep.collectOtpData, consists in capturing the OTP code:
SWIFT
    var otpData = NolPayUnlinkCollectableData.otpData(otpCode: "123456")
    nolPayUnlinkComponent.updateCollectedData(collectableData: otpData)
When the data is valid, as determined by the validationDelegate, call the submit function to process the OTP code and move the component to the next step:
SWIFT
    nolPayUnlinkComponent.submit()
Handle the unlinked card step
The third and final step, called NolPayUnlinkStep.cardUnlinked, involves managing the unlinked Nol card. After successfully ulinking your Nol card, it can be safely removed from the list of the linked Nol cards.Handle errors
You can listen to the errorDelegate to handle any errors that may occur during the linking flow:
SWIFT
    nolPayUnlinkComponent.errorDelegate = self
Confirm to PrimerHeadlessErrorableDelegate protocol and implement its function:
SWIFT
    func didReceiveError(error: PrimerError) {
          /* Handle error */
          }
Check the possible errors that can be returned here

Limitations

The following requirements must be met in order to use nol Pay:
  • iOS : Version 13.1.
  • Devices : Should support NFC (Near Field Communication).

Troubleshooting

  • Nol test cards can be only used in Sandbox
  • Real Nol cards can be only used in Production
  • the error codes that the TransitSDK can return can be found here
  • If the SDK returns error with code A3313, make sure not to remove the Nol card until the scanning is completed
  • If the card is already linked to a specific mobile number, and user tries to link it again, SDK will return appropriate error during the card scanning step

Test

  • in sandbox environment, you can use OTP code: 987123
  • in sandbox environment, you must use a test card provided by Nol

Go live

You don’t need to do anything particular to go live — just make sure to use production credentials.