Before you begin

This guide assumes that you know how to:

Accept payments with nol Pay

Prepare the API

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
3-letter currency code in ISO 4217 format, e.g. USD for US dollars
  1. order
Details of the line items of the order

orderId 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.

Minimal value (in minor units): 500 Maximal value (in minor units): 200000

  1. paymentMethod

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:

123456789101112131415161718192021222324252627282930
target 'YourApp' do
  pod 'PrimerSDK'  pod 'PrimerNolPaySDK'
  post_install do |installer|    fix_linking(installer)  endend
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  endend
ruby
copy

After that, run this command in your terminal:

1
$ pod install
jsx
copy
Activate the NFC capabilities

To engage with NFC Nol payment cards, make sure to first activate the NFC capabilities in your app:

  1. 1
    Open your project in Xcode.
  2. 2
    Access the target settings.
  3. 3
    In the "Signing & Capabilities" section, tap on "+ Capability".
  4. 4
    Add "Near Field Communication Tag Reading".

Then, incorporate the following keys into your Info.plist for effective NFC communication and web access:

123456789101112131415
<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>
xml
copy

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. 1
    Get the available payment methods using PrimerHeadlessUniversalCheckout.current.start as described here.
  2. 2
    For the Nol Pay payment method, paymentMethods array will contain PrimerPaymentMethodManagerCategory.NOL_PAY category.
  3. 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 payments:


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:

1
var nolPayLinkComponent = PrimerHeadlessUniversalCheckout.PrimerHeadlessNolPayManager().provideNolPayLinkCardComponent()
swift
copy
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:

1
nolPayLinkComponent.stepDelegate = self
swift
copy

Conform to PrimerHeadlessSteppableDelegate protocol and implement its function:

123
func didReceiveStep(step: PrimerHeadlessStep) {  /* Handle the step */}
swift
copy
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:

1
nolPayLinkComponent.validationDelegate = self
swift
copy

Confirm to PrimerHeadlessValidatableDelegate protocol and implement its function:

123
func didUpdate(validationStatus: PrimerValidationStatus, for data: PrimerCollectableData?) {  /* Handle data validation */}
swift
copy
Start the flow of the component

Call the start function in order to start the flow of the component.

1
nolPayLinkComponent.start()
swift
copy

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.

1
nolPayLinkComponent.submit()
swift
copy
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.

12
var phoneData = NolPayLinkCollectableData.phoneData(mobileNumber: "1234567890")nolPayLinkComponent.updateCollectedData(collectableData: phoneData)
swift
copy

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:

1
nolPayLinkComponent.submit()
swift
copy

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:

12
var otpData = NolPayLinkCollectableData.otpData(otpCode: "123456")nolPayLinkComponent.updateCollectedData(collectableData: otpData)
swift
copy

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:

1
nolPayLinkComponent.submit()
swift
copy
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:

1
nolPayLinkComponent.errorDelegate = self
swift
copy

Confirm to PrimerHeadlessErrorableDelegate protocol and implement its function:

123
func didReceiveError(error: PrimerError) {  /* Handle error */}
swift
copy

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:

1
var nolPayLinkedCardsComponent = PrimerHeadlessUniversalCheckout.PrimerHeadlessNolPayManager().provideNolPayGetLinkedCardsComponent()
swift
copy
Get linked cards

Use the getLinkedCards function to get all the linked cards associated with the user's mobile number:

12345
nolPayLinkedCardsComponent.getLinkedCardsFor(mobileNumber: mobileNumber) { result in            switch result {                ...            }        }
swift
copy

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:

1
var nolPayPaymentComponent = PrimerHeadlessUniversalCheckout.PrimerHeadlessNolPayManager(). provideNolPayStartPaymentComponent()
swift
copy
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:

1
nolPayPaymentComponent.stepDelegate = self
swift
copy

Confirm to PrimerHeadlessSteppableDelegate protocol and implement its function:

123
func didReceiveStep(step: PrimerHeadlessStep) {  /* Handle step */}
swift
copy
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:

1
nolPayPaymentComponent.validationDelegate = self
swift
copy

Conform to PrimerHeadlessValidatableDelegate protocol and implement its function:

123
func didUpdate(validationStatus: PrimerValidationStatus, for data: PrimerCollectableData?) {  /* Handle validation */}
swift
copy
Start the flow of the component

Call the start function in order to start the flow of the component.

1
nolPayPaymentComponent.start()
swift
copy

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.

123
var nolPaymentCard = // selected cardvar cardAndPhoneData = NolPayPaymentCollectableData.paymentData(cardNumber: nolPaymentCard.cardNumber, mobileNumber: "1234567890")nolPayPaymentComponent.updateCollectedData(collectableData: phoneData)
swift
copy

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:

1
nolPayPaymentComponent.submit()
swift
copy

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 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:

1
nolPayPaymentComponent.errorDelegate = self
swift
copy

Confirm to PrimerHeadlessErrorableDelegate protocol and implement its function:

123
func didReceiveError(error: PrimerError) {  /* Handle error */}
swift
copy

Check the possible errors that can be returned here


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:

1
var nolPayUnlinkComponent = PrimerHeadlessUniversalCheckout.PrimerHeadlessNolPayManager(). provideNolPayUnlinkCardComponent()
swift
copy
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:

1
nolPayUnlinkComponent.stepDelegate = self
swift
copy

Conform to PrimerHeadlessSteppableDelegate protocol and implement its function:

123
func didReceiveStep(step: PrimerHeadlessStep) {  /* Handle step */}
swift
copy
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:

1
nolPayUnlinkComponent.validationDelegate = self
swift
copy

Confirm to PrimerHeadlessValidatableDelegate protocol and implement its function:

123
func didUpdate(validationStatus: PrimerValidationStatus, for data: PrimerCollectableData?) {  /* Handle validation */}
swift
copy
Start the flow of the component

Call the start function in order to start the flow of the component.

1
nolPayUnlinkComponent.start()
swift
copy

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.

123
var nolPaymentCard = // selected cardvar cardAndPhoneData = NolPayUnlinkCollectableData.cardAndPhoneData(nolPaymentCard: nolPaymentCard, mobileNumber: "1234567890")nolPayUnlinkComponent.updateCollectedData(phoneData)
swift
copy

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:

1
nolPayUnlinkComponent.submit()
swift
copy

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:

12
var otpData = NolPayUnlinkCollectableData.otpData(otpCode: "123456")nolPayUnlinkComponent.updateCollectedData(collectableData: otpData)
swift
copy

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:

1
nolPayUnlinkComponent.submit()
swift
copy
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:

1
nolPayUnlinkComponent.errorDelegate = self
swift
copy

Confirm to PrimerHeadlessErrorableDelegate protocol and implement its function:

123
func didReceiveError(error: PrimerError) {  /* Handle error */}
swift
copy

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.