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'
- QPOS
- MagicPOS
pod 'QPosHardware'
pod 'MagicPosHardware'
Example
If your target is named MyTarget:
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.
- QPOS
- MagicPOS
import QPosHardware
let magicPosReaderInstaller = MagicPosReaderInstaller()
import MagicPosHardware
let qposReaderInstaller = QposReaderInstaller()
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 {
.
.
}
.
.
}
)