Skip to main content

IOS

Installation

CocoaPods is a dependency manager for Cocoa projects. For usage and installation instructions, visit their website. To integrate the SDK into your Xcode project using CocoaPods, first add the sources to the top of your `Podfile:

source 'https://bitbucket.org/geopagos-sdk/ios-specs.git'
source 'https://github.com/CocoaPods/Specs.git'

Then add the pod to your target:

pod 'Payments'
  pod 'QPosHardware'

Example

If your target is named MyTarget:

Podfile
source 'https://bitbucket.org/geopagos-sdk/ios-specs.git'
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '10.0'

target 'MyTarget' do
use_frameworks!

# Pods for MyTarget
pod 'Payments'
pod 'QPosHardware'
pod 'MagicPosHardware'

end

Configure the SDK

This consists of initializing the Readers SDK, provide data acording to code documentation.

Create a PaymentsConfiguration object to configure the endpoint and readerInstallers (optionally a logger object and SwipePinDecider implementation)

Call PaymentsSDK.configure(...) to configure the SDK.

        do {
let paymentsConfiguration = try PaymentsConfiguration.Builder(
endpoint: URL(string: "<ENDPOINT>")!,
readerInstallers: [
<QposReaderInstaller>,
<MagicPosReaderInstaller>
]
).setLogger(
logger: self
).setSwipePinDecider(
swipePinDecider: customtSwipePinDecider
).build()

PaymentsSDK.configure(
paymentsConfiguration: paymentsConfiguration
)
} catch {
print("El SDK no pudo ser inicializado correctamente")
}

Note: To create readerInstallers it’s necessary to import the modules corresponding to each Reader.

import QPosHardware

let magicPosReaderInstaller = MagicPosReaderInstaller()

Scan devices

A device is required to make a transaction , at this point you can scan devices.

In order to scan devices(that represent card readers) you must use the DeviceScanService class.

let deviceService = DeviceScanService()

deviceService.scan { (result: DeviceResult) in
switch result {
case .success(let list, let isScanning):
for device: Device in list {
//...
}
case .error(let type, let isScanning):
//handle errors
}
}

To stop the scan call:

deviceService.stopScanning()

Create transaction intent

To start a transaction, a TransactionIntent object is needed, specifying the transaction type (sale, cancel or refund).

To create a TransactionIntent, use the TransactionIntentFactory.createTransactionIntent.

  TransactionIntentFactory.createTransactionIntent(
type: transactionType,
listener: SDKTransactionListenerImplementation,
completion: { [weak self] result in
switch result {
case let .success(aTransaction):
self?.transaction = aTransaction
case let .failure(error):
// Handle TransactionIntentInitializationError
}
}
)

This method receives a TransactionType (.payments, .refund, .cancel) and the class instance that implements the SDKTransactionListener protocol. If a transaction intent is created successfully, it is returned to the integrating app as a successful result of the completion callback, otherwise, a failure result is returned with a TransactionIntentInitializationError.

On successful transaction creation, the class implementing SDKTransactionListener will begin observing changes in the transactin and reader states. Each SDKTransactionState notification will guide you through the transaction life cycle and depending on the state, the SDK may require the integrating app to provide certain data

Provide a device

Provide a device which was previously scanned.

The SDKTransactionState.provideDevice state is broadcasted to the integrating app's listener to request a device to perform the connection to the reader.

   
func onTransactionStateChanged(state: SDKTransactionState) {
switch state {
.
.
case let .provideDevice(provideDeviceCallback: DeviceRequiredCallback):
provideDeviceCallback(aDevice)
.
.
}
}

Provide reader configuration

The SDKTransactionState.onReadConfigRequired state is broadcasted to the integrating app's listener to request a reader configuration (read modes, timeout, ect)

    func onTransactionStateChanged(state: SDKTransactionState) {
switch state {
.
.
case let .provideReadConfig(provideReadConfigCallback: ConfigRequiredCallback):
let transactionTotal = TransactionTotal(...)
let readConfig = ReadConfig(
readModes: [.swipe, .chip, .nfc],
timeout: 10,
transactionTotal: transactionTotal
)
provideReadConfigCallback(readConfig)
.
.
}
)

Select EMV app

There are cards that have more than one EMV application internally in the chip. This allows them to have several logic cards in the same plastic (for example, a credit card and a debit card), In this state the Readers SDK provides the list of available applications and you must choose which one you want to use (if the card only has one emv application, this state is not called).

The SDKTransactionState.onSelectEmvAppRequired state is broadcasted to the integrating app's listener to request an EMB app

    func onTransactionStateChanged(state: SDKTransactionState) {
switch state {
.
.
case selectEMVApp(availableAIDs: [EmvApp], selectEMVAppCallback: EMVAppRequiredCallback):
let anEMVapp = availableAIDs.first
selectEMVAppCallback(anEMVapp)
.
.
}
)

Confirm transaction

When the card is read, this data is provided to the Readers SDK user who decides to confirm or reject the transaction, then online processing is performed. Finally, an approved or declined, or error response is obtained, the data needed to confirm the transaction is documented in required data section.

The SDKTransactionState.confirmPayment , SDKTransactionState.confirmRefund or SDKTransactionState.confirmCancel states may be broadcasted to the integrating app's listener to confirm or reject a transaction

    func onTransactionStateChanged(state: SDKTransactionState) {
switch state {
.
.
case confirmPayment(
card: TransactionCard,
confirmCallback: ConfirmPaymentDataCallback,
rejectCallback: RejectRecoverCallback
):
let confirmation = Confirmation(...)
let paymentConfirmation = PaymentConfirmation(
cnfirmation: confirmation,
installments: nil,
paymentPlan: nil
)
accept(paymentConfirmation)
.
.
}
)

Transaction approved

If the transactions is approved, the response is obtained in the following state.

The SDKTransactionState.approved state is broadcasted to the integrating app's listener to inform the a successful transaction

    func onTransactionStateChanged(state: SDKTransactionState) {
switch state {
.
.
case approved(transactionApproved: TransactionApproved):
switch transactionApproved {
case .sale(_, _, let paymentData):
showTransactionStep("onTransactionApproved \(paymentData.authCode ?? "")")
case .refund(_, _, let paymentData):
showTransactionStep("onTransactionApproved \(paymentData.authCode ?? "")")
case .cancel(_, _, let paymentData):
showTransactionStep("onTransactionApproved \(paymentData.authCode ?? "")")
@unknown default: break
}
.
.
}
)

Transaction error

During a transaction, two kind of errors can occur: recoverable and not recoverable. In the recoverable one, it’s possible to retry the transaction calling the associate callback, in the not recoverable errors, the transaction is concluded and a whole new transaction is needed

The method TransactionIntentDelegate.onRecoverableError is called if a Recoverable Error occurs.

    func onTransactionStateChanged(state: SDKTransactionState) {
switch state {
.
.
case recoverableError(error: TransactionIntentError, recoverCallback: RejectRecoverCallback):
recoverCallback()
.
.
}
)

The method TransactionIntentDelegate.onNonRecoverableError is called if a NonRecoverable error occurs.

    func onTransactionStateChanged(state: SDKTransactionState) {
switch state {
.
.
case nonRecoverableError(error: TransactionIntentError, message: String?):
switch error {
.
.
}
.
.
}
)