Rubean Transaction iOS API(under construction)
The Rubean Transaction API is an iOS Framework which simplifies the communication with PhonePOS to ensure easy implementation of complicated payment features. iOS api is newly in
Setup
The Transaction API library is available on CocoaPods and can be accessed only with given credentials given by Rubean.
Please contact us Rubean support team if none of the above was provided, or in case you have troubles downloading the library.
Usage
Obtaining the Transaction API class
The TransactionApi class is encapsulating the main logic of the library.
You can instantiate it with:
class MainController: UIViewController {
private let PHONEPOS_APPLICATION_NAME = "your.phonepos.name"
var transactionApi: TransactionApi = PhonePosFactory.getTransactionApi(PHONEPOS_APPLICATION_NAME, UIViewController: self)
}
Initiating a Payment
To start a transaction you need to call the function below:
transactionApi.startTransaction(transactionRequest: transactionRequest, transactionCallback: TransactionCallback)
The function takes two parameters:
TransactionRequest: This object contains information about the type of the transaction, amount, etc.
Please do NOT create an instance of this class directly. Use theTransactionDataFactoryclass for getting an instance.TransactionCallback: The result of the transaction is delivered to this interface.
Please take a look at the factory methods that you can use to generate a TransactionRequest:
class TransactionDataFactory {
/*
This function creates objects describing a card payment operation.
You will only use this for payments. For refunds and reversals please
refer to the functions below.
money - Money object which describes the amount and currency you would like to collect.
*/
static func getPaymentData(money: Money) -> TransactionRequest {
// Implementation goes here
}
/*
Extends the standard getPaymentData for the field additionalHostData which is forwarded to the Host.
The format of the content is always a JSON string.
Depending on the Host the following fields can be supported:
- merchantReference
- externalReference
As the names already indicates, this data is used to set a reference by the payment initiator.
Hint: You can build a JSON string by either crafting a POJO and serializing it, or:
String additionalHostData = new JSONObject().put("KEY", "VALUE").toString();
*/
static func getPaymentData(money: Money, additionalHostData: String?) -> TransactionRequest {
// Implementation goes here
}
/*
This function creates objects describing a refund operation.
traceNumber - The id of the transaction you would like to refund or reverse.
If your PhonePOS terminal supports general refunds without a reference
you can pass a nil value here. This setting is controlled by the terminal configuration.
money - Money object which describes the amount and currency you would like to refund.
NOTE: depending on the configuration of our PhonePOS terminal, refund or reversal transactions
might NOT be supported.
*/
static func getRefundData(money: Money, traceNumber: String?) -> TransactionRequest {
// Implementation goes here
}
/*
This function creates objects that describe a reversal operation.
traceNumber - The id of the transaction you would like to reverse.
NOTE: depending on the configuration of our PhonePOS terminal, refund or reversal transactions might NOT be supported.
*/
static func getReversalData(traceNumber: String?) -> TransactionRequest {
// Implementation goes here
}
}
Example
An example on how to initiate a payment, a refund or a reversal is shown here:
class MainController: UIViewController {
private func startPayment(amount: NSDecimalNumber) {
let money = getMoneyWithPreferredCurrency(amount: amount)
transactionApi.startTransaction(
data: TransactionDataFactory.getPaymentData(money: money),
callback: getTransactionCallback(),
)
}
private func startRefund(amount: NSDecimalNumber) {
let money = getMoneyWithPreferredCurrency(amount: amount)
transactionApi.startRefund(
data: TransactionDataFactory.getPaymentData(money: money),
callback: getTransactionCallback(),
)
}
private func startReversal(amount: NSDecimalNumber) {
let money = getMoneyWithPreferredCurrency(amount: amount)
transactionApi.startReversal(
data: TransactionDataFactory.getPaymentData(money: money),
callback: getTransactionCallback(),
)
}
private func getTransactionCallback() -> TransactionCallback {
return TransactionCallback(
onTransactionSuccess: { result in
// The operation ended successfully.
// In case of a payment, the amount was charged.
// In case of a refund, the amount was refunded.
// In case of a reversal, the transaction was voided.
// You can use the result object for extracting the desired information,
// e.g., receipts and payment information.
},
onTransactionFailed: { result in
// This callback means that the operation failed.
// In case of a card payment, no amount was charged.
// In case of a refund, no amount was returned.
// In case of a reversal, the transaction was not voided.
// You do not need to recover this operation.
// It failed for a defined reason.
// The result object can be used to identify the problem that occurred.
},
onTransactionResultUnknown: { error in
// The transaction did not succeed and the result is unknown.
// This can happen for multiple reasons.
// Connection problems, server problems,...
// It is important to you run a recover operation as it is unclear
// if your operation was fulfilled.
// Proceeding without recovery can lead to double payments.
// -> Connection was lost and no success is shown but payment was fulfilled
// Another payment is initiated and also fulfilled.
}
)
}
}
In case you receive onTransactionResultUnknown callback, it is required to perform a recovery.
Unless you perform a recovery and get the status of the last transaction, any following attempt of payments will automatically fail.
The API is implemented in this way to prevent hidden payments (server did register payment, app does not display payment).
Hidden payments are mostly caused by bad internet connections.
You should always try unblocking this state by recovery, although in rare case, if you would like to ignore the result you can use
TransactionApi.cancelMandatoryRecovery() api.
TransactionStatus processing
Every kind of result received in the callback will contain the ENUM TransactionStatus, where you can check the overall result of the transaction. You can see the explanations for each of them here:
- TransactionStatus.SUCCESS: Success always means that the transaction was successful and everything is in order. You can proceed further with the processing of the response.
In the case that the transaction did not succeed we grouped the possible causes into the following states:
- TransactionStatus.FAILURE -> This means that the transaction itself has failed. The action point from here would be to retry with a NEW transaction You can see the exact reason in detail inside the response.
- TransactionStatus.UNKNOWN -> This means that the transaction status is unclear. This can happen due to loss of connection to the server or other issues. The only action point here is that you should perform the [TransactionRecovery] operation.
- TransactionStatus.RECOVERY_REQUIRED -> Transaction API is caching the result of last transaction and in case the last Transaction was UNKNOWN, it will not perform the next operation, until a TransactionRecovery is successfully performed. This state is intentionally triggered to avoid double payments for merchants. Nevertheless, if you would like to ignore the last result, which we DO NOT recommend, you can forcefully recover from this case by calling TransactionApi.cancelMandatoryRecovery().
- TransactionStatus.ANOTHER_OPERATION_IN_PROGRESS -> We do NOT allow 2 parallel terminal operations. If you receive this status it means that there was another operation triggered before and you must wait for it to finish.
enum TransactionStatus {
FAILURE,
SUCCESS,
UNKNOWN,
ANOTHER_OPERATION_IN_PROGRESS,
RECOVERY_REQUIRED
}
Receipts
Every transaction generates two receipts. One for the merchant and one for the customer. To obtain these receipts implement the following logic in the callback.
func onTransactionSuccess(result: TransactionResponse) {
let merchantReceipt = result.merchantReceipt
let customerReceipt = result.customerReceipt
}
JSON receipts
If the JSON receipt option is enabled for a terminal, it can be fetched from the first line of the TransactionReceipt object as per the below example.
func onTransactionSuccess(result: TransactionResponse) {
let merchantReceiptJson = result.merchantReceipt[0]
let customerReceiptJson = result.customerReceipt[0]
}
Initiate a Transaction Recovery
A Transaction Recovery must be used in case you do NOT know the result of the last transaction.
i.e., when you get an UNKNOWN result from an operation in the onTransactionResultUnknown method of the callback.
You can also use this method to receive the last transaction details.
To start a Transaction Recovery you need to use the TransactionApi.startTransactionRecovery(..) function:
It takes two parameters:
TransactionRecoveryRequest: This class can be instantiated by calling:TransactionDataFactory.getLastTransactionRecoveryRequest().
The last transaction will automatically be picked. Please do NOT directly create an instance of this class.TransactionRecoveryCallback: The result of the transaction recovery is delivered to this interface.
Example:
class MainController: UIViewController {
private let phonePosApplicationName = "your.phonepos.name"
private var transactionApi: TransactionApi?
private func setupTransactionApi() {
transactionApi = PhonePosFactory.getTransactionApi(applicationName: phonePosApplicationName, context: self)
}
private func recoverLastOperation() {
guard let transactionApi = transactionApi else { return }
let lastTransactionRequest = transactionApi.provideAdministrationApi().getLastTransactionRequest()
transactionApi.startTransactionRecovery(
request: lastTransactionRequest,
callback: getTransactionRecoveryCallback(),
context: applicationContext()
)
}
private func getTransactionRecoveryCallback() -> TransactionRecoveryCallback {
return TransactionRecoveryCallback(
onLastTransactionSucceeded: { result in
// Handle success
},
onLastTransactionFailed: { error in
// Handle failure
},
onRecoveryResultUnknown: { error in
// Handle unknown result
}
)
}
private func applicationContext() -> AnyObject {
// Return application context, adapt as needed
}
}
Cancel Mandatory Recovery
In case you receive UNKNOWN result during the payment, you will be FORCED to perform a recovery.
Unless you perform a recovery and retrieve the status of the last transaction, every following attempt of payments will automatically fail.
You should always try unblocking this state by recovery, although in rare case if you would like to ignore the result you can use
this api to drop the mandatory request.
TransactionApi.startTransactionRecovery(..) function takes
It takes three parameters:
TransactionRecoveryRequest:TransactionDataFactory.getLastTransactionRecoveryRequest(),should be used to retrieve the last transaction that was done.ForceCancelRecoveryCallback: The result of the cancellation is delivered to this interface.Context: Regular Android context. Used to send the configuration calls and startup the transaction screen.
Example:
class MainController: UIViewController {
private var transactionApi: TransactionApi?
// ...
// Instantiate transactionApi here
// ...
private func onRecoveryCanceledRequested() {
guard let transactionApi = transactionApi else { return }
let lastTransactionRequest = transactionApi.provideAdministrationApi().getLastTransactionRequest()
transactionApi.cancelMandatoryRecovery(
request: lastTransactionRequest,
callback: ForceCancelRecoveryCallback(onRecoveryCanceled: { originalRequest in
// Handle the original request of recovery
})
)
}
}