Velocity - Android SDK - Integration Guide

1. Document Details

1.1 Scope

This document provides information to assist with the integration of the Velocity Payment Orchestration Platform (POP) software development kit (SDK) with an Android native mobile application.

Note: Integration with an iOS mobile application has a similar workflow, but the details are provided in the Velocity – iOS SDK – Integration Guide v1.12.

1.2 Version

The following table provides details about the various SDKs and features listed in the document.

Document VersionSDK NameSDK VersionAdditional Features
1.04mPoint2.3.1
  • Modirum 2.0
  • Payment Integrations
    • SWISH
    • GRABPAY
    • G-Cash
    • PayMaya
  • HMAC changes
    • Updated Airline Data support
    • Auth-token support
    • FX Service indicator
    • Presentment currency
  • Added support for base SDK v2.0.0
1.05mPoint2.3.2
  • Offline payment card support
  • Handled Sub-Code in URL scheme redirect
  • FX Service based routing support
  • SDK Improvements
1.06mPoint2.3.3
  • Introduced the following:
    • Travel Fund Vouchers
    • Split Payments
  • Enhancements
    • SDK Improvements
    • Added support for base SDK v2.1.0
1.07mPoint2.3.3Introduced the following:
  • Instalments
  • SDK Improvements
1.08mPoint2.4.0Introduced the following:
  • Split Payments
  • SDK Improvements
1.09mPoint2.4.0Updated the template.
1.10mPoint2.5.0Introduced the following:
  • PayU – Online and Offline
  • SDK Improvements
  • Added support for Base SDK 2.2.0
1.11mPoint2.5.0Introduced the following:
  • STRIPE Integration
  • NMI Integration
  • SDK Improvements
1.12mPoint2.6.0Introduced the following:
  • SAFETY PAY Integration
1.13mPoint2.6.0Updated document template.

2. Introduction

Velocity SDK facilitate integration of Velocity POP with native mobile application. SDKs can be integrated with both Android and iOS applications. The SDKs use asynchronous communication when transmitting data to the Velocity server or a Payment Service Provider (PSP).

The following are some features of SDKs:

  • Simple integration with a few calling methods
  • Multiple payment methods such as APM, wallets, mVault or stored card, and cards with 3DS and
    non-3DS
  • Native user interface (UI) elements
  • A familiar technology stack for application developers
  • Capability to control and brand the payment screen
  • Application and POP communication through SDKs

3. Glossary of Terms

The terms used in this document are listed in the table below.

TermsDescription
CPDCellPoint Digital.
POPPayment Orchestration Platform.
HPPHosted Payment Pages.
PSPPayment Service Provider.
ACQAcquirer.
MerchantAny business who sells goods or services and accepts payments from customers;
also referred to as Clients.
CustomersIndividuals who want to buy goods and services from the merchant.
APMAlternative Payment Methods.
SDKSoftware Development Kit.

4. Prerequisites for Integration

After you are onboarded on the Velocity platform, you can start integrating your mobile application with the Velocity SDK.

Before you start the integration process, you must ensure that you have the following:

  • Velocity SDK, which includes the following:
    • Base SDK
    • mPoint SDK
  • Third-party SDK (optional)
  • Nexus URL
  • CPD credentials such as:
    • Username
    • Password
    • Client ID
    • Account ID
    • MESB_URL
  • Country and currency for which transaction is enabled
  • List of CPD country codes
  • Salt values for payment fraud transaction (optional)
  • Sample test application

5. SDK Integration Overview

The Velocity SDK Payment Process Workflow sequential diagram is shown below.

5.1 SDK Integration Workflow

After a customer selects your products or services, they click the payment option to finalize the purchase. Your mobile application Velocity POP enables processing of payments through the Velocity SDK in the following manner:

  1. Your customers click the payment button.
  2. Your application authorizes a payment using the Velocity SDK.
  3. The SDK authorizes the payment through the back end of the Velocity POP.
  4. The back end of the Velocity completes the authorization and returns the payment status response.
  5. The Velocity SDK provides the status back to your mobile application, which processes the payment through the PSS based on the payment status.

Note: Payment cards and card-based forms of payment, such as Google Pay, are authorized through a merchant’s acquirer. Other forms of payments, such as PayPal, are authorized directly with the APM. These processes ensure that the merchant receives settlement directly from the acquirer for the card-based payment.

6. Integrating SDK

Velocity SDK enables asynchronous communication using the delegate/interface pattern. The SDK enables your mobile application to implement the methods defined by mPoint payment interface.

To integrate the payment methods using the Velocity SDK, complete the following steps:

  1. Integrate the SDK using the CPD credentials for communicating with Velocity POP.
    1. Add the SDK path in Gradle file with specific version provided by CPD.

    Note: The versions of these files are updated at regular intervals. Check with the CPD technical team if you have the latest version.

    1. Add nexus repository path in Gradle file
    2. Run Gradle Build command.
  2. allprojects {
                repositories {
    maven {
    url = uri("https://nexus.cellpointmobile.com/content/repositories/internal")
    credentials {
    username = "default-read"
    password = "CPMRead4321"
    }
    }
    }
    }
    
    
  3. Instantiate the SDK using the CPD credentials for communicating with Velocity POP.
  4. Initializing a payment using the SDK involves the following tasks:
    1. Invoke the initialize method on the SDK instance.
    2. Handle the SDK call back through the selected payment method.
    3. Construct the graphical user interface (GUI) for enabling customers to make payment using their selected payment method.
  5. Note: Instantiating and initializing a payment are common to all payment methods such as card payment, save cards, APM, and wallet.

  6. Implement the following interfaces:
    1. mPointWalletDelegate
    2. mPointSchemeOwnerDelegate
    3. mPoint3DSecureDelegate
    4. mPointDelegate
    5. mPointWebViewDelegate
    6. mPointSchemeOwnerDelegate
    7. mPointForeignExchangeDelegate
    8. mPointGetBalanceDelegate

You can authorize a payment with an SDK for one of the following payment methods:

  • Card payment
  • APM
  • Wallet
  • Aggregators
  • Offline Payments
  • Vouchers
  • Split Payment

Note: CPD recommends you implement the following call back error methods for error handling in your application:

  • handleStatus is called for high-level errors when the back-end rejects the request and returns one or more status codes giving the reason, or for operations that do not return any data, where the back-end returns the operation status.
  • handleError is called for low-level errors such as network connectivity problems.

Note: For handling web-view redirects, SDK supports devices with Android 5.0 (application programming interface, or API, level 21) and above only.

6.1 Instantiate SDK

To instantiate the SDK, you must:

  • Implement interfaces.
  • Ensure that you have all the prerequisites.

Instantiate the SDK by providing the appropriate configuration details as shown in the following code sample:

this._mpoint = mPoint(URL ("[CPD provided URL]"),  
        this,  
        "username",[USERNAME]  
        "password", [PASSWORD]  
        clientid, [CLIENT ID]  
        accountid, [ACCOUNT ID]  
        null,  
        context,  
        null, 
        RecordMap<String, String> (), 
        arrayOf(ClientInfo.IDENTIFIERS.DEVICEID) 
this._mpoint.mode = mPoint.OUTPUT_MODE.NONE)

Note: Instantiating the SDK is common for all payment methods.

6.2 Initialize Payment

Initialize the payment transaction by invoking the initialize method of SDK as shown in the following code sample:

var mobile: Long = [MOBILE NUMBER];
var email: String = "[EMAIL ID]";
var countryId = CountryConfig.USA;   //[AMOUNT] for USA
var currencyId = [CURRENCY_ID]
var operatorId = countryId * 100;
var amount = [AMOUNT];
amount= amount*100;
var orderID : String = "[ORDER ID NUMBER]";
var mPointOrderInfo = [ORDER_INFO_AID_DATA]
var txnType: String = mPointTxnInfo.TXN_TYPES. MPOINT_SHOPPING_ONLINE; // An example of Search and Book Flow
mPointClientInfo  clientInfo = mPointClientInfo(appid, appversion, mPoint.LANGUAGES.da) 
.setCountryId(countryId) 
.setMobile(mobile) 
.setEmail(email) 
.setDeviceId(deviceid) 
.setCustomerRef(customerRefId) 
.setProfileId(profileId)

mPointInitializePaymentInfo paymentInfo = mPointInitializePaymentInfo()
                        paymentInfo.amount = amount
                        paymentInfo.country = CountryConfig.COUNTRIES.getValues().get(countryId)
                        paymentInfo.operator = operatorId
                        paymentInfo.mobile = mobile
                        paymentInfo.email = email
                        paymentInfo.language = mPoint.LANGUAGES.us
                        paymentInfo.setOrderno(orderID)
                       paymentInfo.clientinfo = clientInfo
                        paymentInfo.setCurrencyid(currencyId)
 paymentInfo.txnType = txnType
       paymentInfo.setHmac(hmac) // if hmac is available OR
                        paymentInfo.secretSalt = salt // if salt value is available
   paymentInfo.order = mPointOrderInfo
   paymentInfo.authToken = authToken
   paymentInfo.sessionId = sessionId (required during payment retries)
mpoint.initialize(paymentInfo);

Note: Consider the following items:

  • Do not send a float number in the int amount. The SDK handles a float number by multiplying it with 100. For example, the floating digit 100 becomes 10000 and 100.29 becomes 10029.
  • Invoking the initialize method is same for card payments, stored cards, APM, wallets and aggregators.

The following are optional parameters: mPointOrderInfo, authToken, and sessionId.

The following table shows a description of initialize payment parameters.

ParameterTypeRequiredDescription
mobileIntegerYesThe MSISDN of a customer without International Dialling Code.
Note: Mobile number can be mandatory or optional, based on the requirement of a merchant or a PSP.
deviceIdIntegerYesThe identification number of a device from which a customer makes a transaction.
emailStringNoThe email address of a customer.
Note: Email can be mandatory or optional, based on the requirement of a merchant or a PSP.
countryIdIntegerYesThe CPD-specific country code, which is available on request.
currencyIdIntegerYesThe CPD-specific ID of a currency selected for making payment.
amountIntegerYesThe total amount that a customer is charged for a payment transaction in a country’s smallest currency. For example, the smallest currency of USD is penny. If the transaction amount is $120.30, then the amount field contains value 12030.
orderIdStringNoThe alphanumeric order ID that a merchant generates.
Note: Some Payment Providers have strict guidelines for the orderId. The recommended pattern is "[a-zA-Z0-9._-]
operatorIdIntegerYesThe identification number of a customer’s Mobile Network Operator. A typical value is “country id” multiplied by 100.
hmacStringNoIt is deprecated from version 2.3.1 onwards and is applicable only for the mRetail SDK.
mPointOrderInfoObjectNoThe object of mPointOrderInfo. It contains details of order data and is required only for airlines.
authTokenStringNo The token that CPD provides for making payment.
sessionIdIntegerNoThe session ID of a transaction. It is required only for required only if a customer retries making payment.
mPointInitialize
PaymentInfo
ObjectYes The object of mPointInitializePaymentInfo. It contains all details required to construct initialize an API request.
search and bookObjectObjectThis is meant for travel merchants only. Refer to Search and Book Workflow for details.

You can implement the following methods as part of the call back response for initializing a payment. Implement the displayAvailablePayments call back method to display the available payment method as shown in the following code sample:

override fun displayAvailablePayments(availablePayments: mPointAvailablePayments?, mpoint: mPoint?) {}

In availablePayments, the following sub-objects are available:

  • Card
  • Stored card
  • APM
  • Third-party wallet
  • Aggregators
  • Offline payment
  • Vouchers
  • Split Payment

7. Integration for Card Payment

To integrate the SDK for a card transaction, complete the following steps:

  1. Add the SDK path in Gradle file.
  2. Add nexus repository path in Gradle file.
  3. Run the Gradle Build command.

7.1 Instantiate SDK

You can Instantiate SDK as shown in the previous section.

7.2 Initialize Payment

You can Initialize Payment as shown in the previous section.

Note: If you have subscribed for Foreign Exchange (FX) Service, the FX API is called. To get the subscription of FX, sales team/system admin.

7.3 Foreign Exchange Service

FX Service provides an omnichannel solution for facilitating the payment of products and/or services in multiple currencies. The service helps to reduce the rate of drop-offs as customers can make payment in the currency they prefer.

The SDK fetches the amount in available card currency, which enables customers to see the option to make payment in multiple currencies. The FX API is called after the initialize API is successful.

Note: FX is available for Mastercard and Visa card transactions only for customers of merchants who subscribe to this service.

The following diagram shows how to integrate FX with the assumption that the communication with Velocity backend is successful.

To retrieve all available currencies of a card, use the getForeignExchangeOffer method. To use this method, refer to the following code sample.

var  saleAmount: mPointAmountInfo = mPointAmountInfo().setCurrency(currency).setPrice(amount)

Use the following code sample to create the mPointExchangeOfferCriteria object for making payment with a new card:

var offerCriteria = mPointExchangeOfferCriteria()
                    .setOrderNumber(orderId)
                    .setCardNumber(cardnumber.toString())
                    .setCardType(cardtype)                                                  .setCountry(CountryConfig.COUNTRY_CODES.getValues()
                               .get(countryid)) 
                    .setSaleAmount(saleAmount) 
                    .setTransactionId(_mPoint.txnInfo.id)                                   .setClientId(CLIENT_ID)
                    .setAccountId(ACCOUNT_ID)
                    .setClientInfo(clientInfo)

_mPoint.getForeignExchangeOffer(offerCriteria)

To handle the response of exchange offer, override the displayForeignExchangeOffers method and implement the mPointForeignExchangeDelegate interface as follows:

override fun displayForeignExchangeOffers (offer: mPointExchangeOffer?, mpoint: mPoint?) {
}

To consume a specific mPointExchangeOffer, use this exchange offer and create mPointForeignExchangeInfo as shown in the following code sample:

  var foreignExchangeInfo 
  = mPointForeignExchangeInfo()
  .setId(offer?.foreignExchangeOfferId!!)                  
         .setExchangeAmount(offer.paymentCurrencyOffers[0]
    .exchangeAmount.price)                           .setExchangeCurrencyId(offer.paymentCurrencyOffers[0]
                                                                            .exchangeCurrency.isoNumericCode)           .setSaleCurrencyId(offer.paymentCurrencyOffers[0]
                                                                                                                                           .saleCurrency.isoNumericCode)                    .setSaleAmount(offer.paymentCurrencyOffers[0]
  .saleAmount.price)
      .setConversionRate(offer.paymentCurrencyOffers[0]
                         .offeredExchangeRate)
      .setHmac(offer.paymentCurrencyOffers[0].validationHmac)

7.4 Authorize Payment

To retrieve specific mPoint cardinfoobject, use the following method. You must provide the card number which your customer enters in the text field; it is an on-click event. This cardinfoobject gives information regarding the card type, such as Visa, Mastercard, and American Express; and maximum and minimum length of the card and card verification value (CVV) number. Based on this information, add validation and modification on your payment screen.

var cardtype = _mPoint.getCardFromPrefix(java.lang.Long.valueOf(cardNumer)!!)

7.4.1 FX Opt-in Transaction

An opt-in transaction is when a customer is making a payment with a new card and selects a card currency other than the original sale currency. The flow of an opt-in transaction is as follows:

  1. Complete the initialize payment successfully.
  2. Consume the FX API successfully.
  3. Finalize the payment offer and invoke the auth API.
  1. Customers opted to make payment in currency other than the sale currency.
  2. Send Opt-in as a Boolean flag as true.
  3. Send standard authorize parameters.

Note: The Opt-in and SetDccOpted depends on a merchant’s requirement.
Refer to Dynamic Currency Conversion to create the mPointForeignExchangeInfo object. For opt-in transactions, refer to the following code:

foreignExchangeInfo?.setDccOpted(true)

To support FX-based routing, send the service-type-id field in the foreign-exchange info node as it enables you to offer various services such as FX and PCC. Send the following ID in service-type-id field.

foreignExchangeInfo?.serviceTypeId = mPointForeignExchangeInfo.SERVICE_TYPE_ID.DCC_OPT_IN

7.4.2 FX Opt-out Transaction

In opt-out transactions, the customer has the option to make payment in available card currencies,
but chooses to make payment in the sale currency. The flow of an opt-out transaction is as follows:

  1. Complete the initialize payment successfully.
  2. Consume the FX API successfully.
  3. Finalize the payment offer and invoke the auth API.
  1. a. Customers opted to make payment using sale currency.
  2. Send Opt-in as a Boolean flag as false.
  3. Send standard authorize parameters.

Refer to Dynamic Currency Conversion to create the mPointForeignExchangeInfo object. For opt-in transactions, refer to the following code:

foreignExchangeInfo?.setDccOpted(false)

For FX opt-out transactions, send the following ID in the service-type-id field:

foreignExchangeInfo?.serviceTypeId =  mPointForeignExchangeInfo.SERVICE_TYPE_ID.DCC_OPT_OUT

7.4.3 ID Values

The values for service-type-id field ID used for a transaction are double-digit numbers - XY in which:

  • X represents the exchange service applicable for a transaction.
  • Y represents the any one of the following types of exchange:
  • 1, which means Opted
  • 2, which means Not-opted

The following table shows the possible values of service-type-id number and how it is derived.

ID (XY)Service (X)Opted (Y)
11FXOpted
12FXNot opted
41PCCOpted
42PCCNot opted

Authorize the payment for a transaction for a card by invoking the authorize method of SDK as shown in the following code sample:

mPoint.authorize(mPointAuthorizeInfo(cardtype)
.setCardNo(java.lang.Long.valueOf(cardNumer))
.setCardExpMonth(Integer.parseInt(expiryMonth))
.setCardExpYear(Integer.parseInt(expiryYear))
.setCvc(tempCvv.toString())
.setNameOnCard(cardName)
.setStoreCard(isSaveCard)
.setCardValidFromMonth(validMonth.toInt())
.setCardValidFromYear(validYear.toInt())
.setClientInfo(clientInfo)
.setAddressInfo(addressInfo))
.setForeignExchangeOffer(foreignExchangeInfo)

.setViaAuthToken(true).setPassword(authToken)

Note: The setViaAuthToken parameter is required only if the authToken parameter is sent in request.

7.4.4 Sending FX Indicator

When the FX API gives an error, a status tag is returned in handleStatus method. As per regulatory requirements, send this status code in authorize API request.
Refer to the following code sample to fetch the status codes in handleStatus method:

var additionalData: RecordMap<String, String>? = null
….
override fun handleStatus(statusInfo: mPointStatusInfo?, client: Client?, p2: mPoint?) {
runOnUiThread {
if(statusInfo.statuses.size > 0 && statusInfo.statuses[0].containsKey("status")){
    val status = statusInfo.statuses[0]["status"] as RecordMap<*, *>
    val code : String = status["@code"] as String
additionalData = RecordMap()
    additionalData!!["cfx_status_code"] = code
}
 	   }
}

Refer to the following code sample to send FX indicator in authorize API request:

_mPoint.authorize(mPointAuthorizeInfo(cardtype)
.setCardNo(java.lang.Long.valueOf(cardNumer))
.setCardExpMonth(Integer.parseInt(expiryMonth))
.setCardExpYear(Integer.parseInt(expiryYear))
.setCvc(tempCvv.toString())
.setNameOnCard(cardName)
.setStoreCard(isSaveCard)
.setCardValidFromMonth(validMonth.toInt())
.setCardValidFromYear(validYear.toInt())
.setClientInfo(clientInfo)
.setAddressInfo(addressInfo))
.setForeignExchangeOffer(foreignExchangeInfo)
.addAdditionalData(additionalData))
.setViaAuthToken(true).setPassword(authToken)

Note: The setViaAuthToken parameter is required only if the authToken parameter is sent in request.

7.5 3DS Redirection

Implement the displayWebView method for 3DS redirection. This method generates a one-time password for a card transaction and provides a WebView instance. 3DS provides an additional layer of security.
The displayWebView method is used in all types of payment such as a stored card, wallet, and APM.
Note: Implementing 3DS redirection depends on the PSP you select for conducting transactions.

override fun displayRaw3DSecureChallenge(mpoint: mPoint): WebView

7.6 Instalments

Customers can use the Instalments feature to make payment in instalments, which is payable in set intervals over a defined period. To add support for card payment with instalments, implement the mPointGetInstallmentPlansDelegate interface.

After customers enter the 11-digit card number, call the getInstallmentPlans API to fetch the available instalment plans for that card shown as follows:

var cardNumber : Long
var cardInfo : mPointCardInfo
cardInfo = _mPoint.getCardFromPrefix(cardNumber)

val installmentPlansSearchCriteria = mPointInstallmentPlansSearchCriteria()
installmentPlansSearchCriteria.binNumber = cardNumber 
installmentPlansSearchCriteria.cardInfo = cardInfo
_mPoint.getInstallmentPlans(installmentPlansSearchCriteria)

To receive result for the getInstallmentPlans API, call in the previous code sample and implement the mPointGetInstallmentPlansDelegate method. The result is returned in the following method:

override fun displayInstallmentPlans(arrListInstallments: java.util.ArrayList<String>?, p1: mPoint?) {
}

Note: The arrListInstallments parameter contains the list of all the Instalment Plans that are available. Populate this data in a drop-down widget so that a customer can select an instalment plan.

To pass the value of the selected instalment, send it in the authorize API in the setInstallmentValue(installmentValue) parameter as shown in the following code sample:

var installmentValue : String  // The Selected Installment Plan

_mPoint.authorize(mPointAuthorizeInfo(cardInfo)
.setCardNo(java.lang.Long.valueOf(cardNumer))
.setCardExpMonth(Integer.parseInt(expiryMonth))
.setCardExpYear(Integer.parseInt(expiryYear))
.setCvc(tempCvv.toString())
.setNameOnCard(cardName)
.setStoreCard(isSaveCard)
.setCardValidFromMonth(validMonth.toInt())
.setCardValidFromYear(validYear.toInt())
.setClientInfo(clientInfo)
.setForeignExchangeOffer(foreignExchangeInfo)
.setViaAuthToken(true)
.setPassword(authToken)
.setAddressInfo(addressInfo)
.addAdditionalData(additionalData)
.setInstallmentValue(installmentValue))

7.7 Split Payment

The split payment option allows customers to split the payment into equal amounts or to enter amounts to split the payment. To allow split payments, you need to check initialize payment response. If a split payment is available, you get split payment node in the response with all required details. You need to read the details from the initialize-payment response. See func override fun displayAvailablePayments(availablePayments: mPointAvailablePayments?, mpoint: mPoint?) {} for how to read split payment node.

After you read the split payment node as shown in above method, you have an array of split payment combinations of type mPointSplitCombination. Store that array for later use. It is the responsibility of the front end to give a UI which provides the customer a toggle switch to choose to split a payment or not. The front end also has to filter and select an appropriate combination object from the combinations array to perform a split payment transaction using the appropriate payment type.

The table below lists the payment type IDs for various form of payments.

Payment methodPayment Type ID
Card1
Voucher2
Wallet3
APM4

The following options are currently available combinations to perform split payment:

  • Card + Card
  • Voucher + Card
  • Voucher + APM
  • Voucher + Wallet

The combination object has an array of mPointSplitPaymentType which includes payment type ID, sequence, and a boolean property is_one_step_authorization. To perform a split payment with Card + Card,

the front end needs to filter and send a combination object with Payment Type ID as 1 for both the sequences. Similarly, the front end needs to filter and send an appropriate combination object in the authorize request to perform a split payment with other forms of payments.

The is_one_step_authorization property has an important role to play in a split payment ecosystem. If is_one_step_authorization value is true, the authorize request needs to include details of both forms of payment. If it is false, the authorize request needs to be called separately for both forms of payment.

After the completion of the first authorize request, the front end needs to call getTxnStatus api, from override fun displayPaymentConfirmation(txn: mPointTxnInfo?, code: Int, mpoint: mPoint) {} method. The response is returned in handleTxnStatus method shown below. If the is_one_step_authorization value is true, you need to poll getTxnStatus api until it returns a success or failure. If value of is_one_step_authorization is false, you need to read the pending amount from the response and make an initialise payment request with that pending amount and session ID.

Refer to the below sample code sample to understand how to call authorize, getTxnStatus and initialise methods.

Note: This code sample is taken from our application to give you an idea of how to integrate or call any given method on mPoint SDK. You need to implement your own classes wherever required.

The code show below is a sample of the calling authorize with split payment method with Card + Card.

var mPointSplitCombination: mPointSplitCombination? = null
var priceInfo: PriceInfo? = null
 
for(splitCombination in this.splitPayment!!.splitCombinations){
    for(paymentType in splitCombination.paymentType){
        if(paymentType.id == mPointCardInfo.PAYMENT_TYPES.CARD.id ){
            mPointSplitCombination = splitCombination
        }
    }
}
 
 
priceInfo = PriceInfo(getCountryCode(country),
                    (((tempAmount.toFloat()) * getDecimalPointMultiplierFromCurrencyId(currencyCode)).roundToLong()),
                    null, null, null, currencyCode,  -1)
                    
                                       
if(null != mPointSplitCombination && null != priceInfo && isSplit){
        _mPoint.authorize(mPointAuthorizeInfo(cardtype)
            .setClientInfo(clientInfo)
            .setViaAuthToken(true)
            .setPassword(authToken)
            .setCardNo(java.lang.Long.valueOf(cardNumer))
            .setCardExpMonth(Integer.parseInt(expiryMonth))
            .setCardExpYear(Integer.parseInt(expiryYear))
            .setCvc(tempCvv).setNameOnCard(cardName)
            .setStoreCard(isSaveCard)
            .setCardValidFromMonth(validMonth.toInt())
            .setCardValidFromYear(validYear.toInt())
            .setForeignExchangeOffer(foreignExchangeInfo)
            .setAddressInfo(addressInfo)
            .addAdditionalData(additionalData)
            .setInstallmentValue(installmentValue)
            .setPendingSplitAmount(priceInfo)
            .setSplitCombinations(mPointSplitCombination))
}               

7.8 Payment Confirmation

Implement the displayPaymentConfirmation call back method to receive the transaction status as shown in the following code sample:

Implement the displayPaymentConfirmation call back method to receive the transaction status as shown in the following code sample:

When using the split payment option, after getting callback in displayPaymentConfirmation you need to call getTxnStatus method to retrieve status of the transactions. When calling the getTxnStatus pass session ID (available in mPoint class) to retrieve all transactions from the current session. To call getTxnStatus, use the following code sample:

if(isSplitPaymentApplicable){
    	if(mpoint!!.sessionId != null && mpoint.sessionId.isNotEmpty()){
   		mPoint.delegate = this
              mPoint.getTxnStatus(-1, "", mpoint.sessionId, clientInfo)
  	  }
}

To get transaction statuses response implement following delegate method:

override fun handleTxnStatus(arrListTxnStatusInfo: ArrayList<mPointTxnStatusInfo>?, paymentStatus: Int, arrListLinkedTransactions: ArrayList<mPointLinkedTransactions>?, mPoint: mPoint?) {
 
            runOnUiThread {
                var pendingAmount: Long = 0
 
                if(null != arrListTxnStatusInfo && arrListTxnStatusInfo.size > 0){
                    for (txnStatusInfo : mPointTxnStatusInfo in arrListTxnStatusInfo){
                        // Retrieve Pending Amount
                        pendingAmount = txnStatusInfo.pendingAmount
                    }
                }
 
                when (paymentStatus) {
                    com.cellpointmobile.sdk.mPoint.PAYMENT_STATUS.MPOINT_PAYMENT_STATUS_PENDING.id -> 
                    // Poll getTxnStatus()
                    getTxnStatus(mPoint!!.sessionId)
                    com.cellpointmobile.sdk.mPoint.PAYMENT_STATUS.MPOINT_PAYMENT_STATUS_COMPLETE.id -> {
                        if(pendingAmount == 0L)
                            // Split Payment Successful
                        else
                            // Retry Payment with Pending Amount
                    }
                    com.cellpointmobile.sdk.mPoint.PAYMENT_STATUS.MPOINT_PAYMENT_STATUS_FAILED.id -> {
                        // Retry Payment with Pending Amount
                    }
                }
            }
    }               

The merchant front end reads the response received to know the payment status. Read the paymentStatus parameter to know the status of the payment. If a transaction status has payment status as:

  • • Pending: call the getTxnStatus API again until you get the payment status either as Successful or Failed.
  • Complete: the payment is successful.
  • Failed: retry the payment.

To retry the payment, initialize the payment with the pending amount. This action helps a customer complete the payment using any option.

Send the pending amount you received from back end in the initialize request. After you initialize, a customer can complete the payment using any available payment option or can split the payment. This process repeats until the transaction is successful, fails, or maximum retries are attempted.

Note: If a customer decides not to retry a failed payment, call the Post-Status API as shown in the following code sample to notify that the session is complete:

mPoint.postStatus(mPoint.sessionId)

7.9 Handle Error

A handle error occurs when there an error in parsing. The status code reveals the type of error that has occurred in the SDK. For details of the status code, refer to Status Codes.

override fun handleError(errorInfo: mPointErrorInfo, client: Client, mpoint: mPoint) {}

7.10 Handle Status

The status codes are returned by the SDK in a call back to the handleStatus method. The method enables the application to handle the status appropriately by implementing the method as shown in the following code sample:

The handleStatus method shows an error in the CPD server.

if(isSplitPaymentApplicable){
    if(statusInfo!!.sessionId != null && statusInfo.sessionId.isNotEmpty()){
   	
        mPoint.delegate = this
  mPoint.getTxnStatus(-1, "", statusInfo.sessionId, clientInfo)

  	  }
}
To get transaction statuses response implement handleTxnStatus delegate method and repeat the same steps as mentioned above in handleTxnStatus method.

8. Integration for Stored Card

To opt for the save card feature, you can contact the CPD team during the onboarding process. You can select the either the CPD card vault or a third-party vault. You need to send an authentication token for a single sign-on.

  • When the SDK receives an initialize response, it checks if the response contains an mPoint Store-card. If it contains a store card
    • The SDK notifies the application that the store cards are available.
    • The SDK provides a callback in the displayAvailablePayments method.
  • You can authorize transactions for which customers use a stored card by providing CVV. If the transaction is successful, you receive a callback in displaPaymentConfirmation.

8.1 Initialize Request

You can Initialize Payment as given in the previous section.
Note: In initialize request for cards stored in Velocity wallet, you need to send an auth token or SSO token to authenticate a customer.

Initialize Response

To initialize a payment using stored cards, show the cards stored in a wallet. Implement the displayAvailablePayments call back method to display the available wallets as shown in the following code sample:

override fun displayAvailablePayments(availablePayments: mPointAvailablePayments?, mpoint: mPoint?) {}

In the availablePayments, the following sub-objects are available:

  • Card
  • Stored card
  • APM
  • Third-party wallet
  • Aggregators
  • Offline Payment
  • Vouchers

8.2 Dynamic Currency Conversion

To make payment for a stored card, create the mPointExchangeOfferCriteria object; instead of card number, send card ID as shown in the following code sample:

var offerCriteria = mPointExchangeOfferCriteria()
                    .setOrderNumber(orderId)
                    .setCardId(selectedCard.id)                                             .setCardType(cardtype)                                                  .setCountry(CountryConfig.COUNTRY_CODES.getValues()
                               .get(countryid)) 
                    .setSaleAmount(saleAmount) 
                    .setTransactionId(_mPoint.txnInfo.id)                                   .setClientId(CLIENT_ID)
                    .setAccountId(ACCOUNT_ID)
                    .setClientInfo(clientInfo)
_mPoint.getForeignExchangeOffer(offerCriteria)

8.3 Authorize Card

You authorize payment either by showing a new card or a stored card. To authorize a card payment, show the cards stored in the vault, provide auth token, billing address, and client information. You can enable customers to provide their card CVV, depending on the PSP for a transaction.

8.3.1 FX Opt-in

An opt-in transaction is when a customer is making a payment with a new card and selects a card currency other than the original sale currency. The flow of the opt-in transaction is as follows:

  1. Complete the initialize payment successfully.
  2. Consume the FX API successfully.
  3. Finalize the payment offer and invoke the auth API as follows:
    1. Customers opted to make payment in currency other than the sale currency.
    2. Send opt-in as a Boolean flag as true.
    3. Send standard authorize parameters.

Note: The opt-in and SetDccOpted depends on a merchant’s requirement.

Refer to Dynamic Currency Conversion to create the mPointForeignExchangeInfo object. For opt-in transactions, refer to the following code.

foreignExchangeInfo?.setDccOpted (true)

8.3.2 FX Opt-out

In opt-out transactions, the customer has the option to make payment in available card currencies but chooses to make payment in the sale currency. The flow of an opt-out transaction is as follows:

  1. Complete the initialize payment successfully.
  2. Consume the FX API successfully.
  3. Finalize the payment offer and invoke the auth API as follows:
    1. Customers opted to make payment using sale currency.
    2. b. Send opt-in as a Boolean flag as false.
    3. Send standard authorize parameters.

Refer to Dynamic Currency Conversion to create the mPointForeignExchangeInfo object. For opt-in transactions, refer to the following code.

foreignExchangeInfo?.setDccOpted(false)

The following code is an example of making payment with a new card with an option to save the card. To save a card set the value of setStoreCard as true, else set it as false. When the next payment is made, the stored cards are displayed.

_mPoint.authorize(mPointAuthorizeInfo(cardtype)
.setCardNo(java.lang.Long.valueOf(cardNumer))
.setCardExpMonth(Integer.parseInt(expiryMonth))
.setCardExpYear(Integer.parseInt(expiryYear))
.setCvc(tempCvv.toString())
.setNameOnCard(cardName)
.setStoreCard(false)
.setCardValidFromMonth(validMonth.toInt())
.setCardValidFromYear(validYear.toInt())
.setClientInfo(clientInfo)
.setAddressInfo(addressInfo))
.setForeignExchangeOffer(foreignExchangeInfo)

To authorize a transaction using stored card, implement the following code:

mPoint.authorize(mPointAuthorizeInfo(cardtype)
.setTypeId(mPoint.AUTH_CARD)
.setPassword(authToken)
.setCvc(cvc)
.setViaAuthToken(true)
.setAuthToken(authToken)
.setForeignExchangeOffer(foreignExchangeInfo)
.setAddressInfo(addressInfo)
.setClientInfo(clientInfo))

To send authentication token during a transaction, set the value of setViaAuthToken to true. If you set it as false, the authentication token is not sent.

8.4 3DS Redirection

Implement the displayWebView method for 3DS redirection. This method generates a one-time password for a card transaction and provides a WebView instance. 3DS provides an additional layer of security. The displayWebView method is used in all types of payment such as stored card, wallet, and APM.

Note: Implementing 3DS redirection depends on the PSP you select for conducting transactions.

override fun displayRaw3DSecureChallenge(mpoint: mPoint?): WebView

8.5 Payment Confirmation

Implement the displayPaymentConfirmation call back method to receive the transaction status as shown in the following code sample:

override fun displayPaymentConfirmation(txn: mPointTxnInfo?, code: Int, mpoint: mPoint) {
        Log.d(TAG, "displayPaymentConfirmation")
    }

8.6 Create Account

Invoke the saveAccount call to receive a callback in display to create, and then save an account.

Invoke the saveAccount call to receive a callback in display to create, and then save an account.

You must configure at least one of the following parameters to enable customers to create a profile:

  • Mobile
  • Email address
  • Customer reference or customer ID

Note: A customer ID is unique and depends on the configured identification parameter.

You can configure this API in the following manner:

  • Store account of customers directly in mPoint, which users can access using a password.
  • Use single sign-on to verify a profile:
    • Valid for both mProfile and third-party profile (mandatory)
    • You must share authorization token with request if you are using an external CRM.
  • You can authorize transactions for which customers use a stored card by providing CVV. If the transaction is successful, you receive a callback in displaPaymentConfirmation.

An eua-id is created after the profile of your customer is saved with Velocity. The following table provides the values of eua-id used to identify APIs that are called.

Eua-idAPU method used
-1Save account
Greater than 0Save account

The descriptions of the parameters are listed in the table below.

ParameterTypeDescription
fullnameStringThe full name of the customer; pass this value as null to avoid collecting this information.
cardIntegerThe full name of the customer; pass this value as null to avoid collecting this information.
cardnameStringThe card name entered by a customer; pass it as null if the does not name the card.
addressStringThe billing address of a customer.
authTokenStringThe authentication token generated when a customer logs in.

8.7 Save Card

When you receive callback in the display save card method, invoke the following method to save the profile of a customer. You must configure at least one of the following parameters to enable customers to create a profile:

  • Mobile
  • Email address
  • Customer reference or customer ID

Note: A customer ID is unique and depends on the configured identification parameter.

You can configure this API in the following manner:

  • Store account of customers directly in mPoint, which users can access using a password.
  • Use single sign on to verify a profile: Valid for both mProfile and third-party profile (mandatory)
  • You must share authorization token with request if you are using an external CRM. An eua-id is created after the profile of your customer is saved with Velocity.

The following table provides the values of eua-id used to identify APIs that are called.

Note: Invoke the save card payment flow only.

public void _saveCard(card : mPointCardInfo, name : String, clientinfo : mPointClientInfo, preferred : Boolean, address : mPointAddressInfo, authToken : String, cardHolderName : String)

The descriptions of the parameters are listed in the table below.

ParameterTypeDescription
cardIntegerThe payment card which was used for an authorization.
nameStringThe card name entered by a customer; the value is Null if no changes are made to the card name.
clientinfoStringThe clientinfo object used for identifying a customer.
preferredStringThe value for this parameter can be one of the following:

  • True- if a card is preferred
  • False- if card Is not preferred
  • Null- if the setting is not changed

addressStringThe billing address of a customer.
authTokenStringThe authentication token generated to enable a customer to log in.

8.8 Log in to Velocity Wallet

Your customers can log in to their profile using their credentials. You need to send an authentication token or SSO token to mPoint login API to authenticate them.

Note: The profile system can be of Velocity, merchant, or third-party.

You can use the following code sample for an SSO token:

public void loginViaToken(authToken: String, clientinfo : mPointClientInfo)

8.9 Update Card

You can implement the updateCard method to update the

  • Cards of your customers’ accounts
  • Details of the customers’ stored cards

The descriptions of the parameters are listed in the table below.

Parameter Type Description
card Integer The card used for the authorization of payment.
name String The name that a customer enters for a card. This value is null if no changes are made to the card name.
cardHolderName String The name that a customer enters for a card holder. This value is null if no changes are made to the card name.
expiryMonth String The month in which a card expires.
expiryYear String The year in which a card expires.
preferred String The value of the parameter can be one of the following: True if a card is preferred. False if a card is not preferred. Null if the setting is not changed.
address String The address of the card holder.
authToken String The authentication token from the mProfile.
clientinfo Object The clientinfo object that specifies a customer.

8.10 Delete a Card

If you use Delete a Card using auth token/access token/SSO token from the wallet, you must call the login API when a customer logs in. You can invoke the delete Card API only after the customer logs in.

You must send the following para card ID received in login API and set through viaAuthToken.

Use following method to delete card from a wallet:

public void deleteCard(cardid: Int, String : accessToken, clientinfo : mPointClientInfo, viaAuthToken : Boolean)

The descriptions of the parameters are listed in the table below.

ParameterTypeDescription
cardidIntegerThe identification number of the card that will be deleted.
accessTokenAlphanumeric stringA customer's authentication token or password.
clientinfoObjectThe client information that needs to be included in a request.
viaAuthTokenBooleanDefines if the access is through an authentication token or a password.

8.11 Delete Account

You can use the following code sample to enable customers to delete their account.

public void deleteAccount(password : String, accessToken : String, account : mPointAccountInfo, clientinfo : mPointClientInfo)

The descriptions of the parameters are listed in the table below.

ParameterTypeDescription
passwordStringUser password to log in.
accessTokenAlphanumeric stringThe customer’s authentication token or password.
accountObjectThe mPoint user account information.
clientinfoObjectThe client information that needs to be included in the request.

8.12 Handle Error

When using the split payment option, after getting callback in displayPaymentConfirmation you need to call getTxnStatus method to retrieve status of the transactions. When calling getTxnStatus pass session ID (available in mPoint class) to retrieve all transactions from the current session. To call getTxnStatus, use the following code sample:

if(isSplitPaymentApplicable){
    	if(mpoint!!.sessionId != null && mpoint.sessionId.isNotEmpty()){
   		mPoint.delegate = this
              mPoint.getTxnStatus(-1, "", mpoint.sessionId, clientInfo)
  	  }
}

To get transaction statuses response implement following delegate method:

override fun handleTxnStatus(arrListTxnStatusInfo: ArrayList<mPointTxnStatusInfo>?, paymentStatus: Int, arrListLinkedTransactions: ArrayList<mPointLinkedTransactions>?, mPoint: mPoint?) {
 
            runOnUiThread {
                var pendingAmount: Long = 0
 
                if(null != arrListTxnStatusInfo && arrListTxnStatusInfo.size > 0){
                    for (txnStatusInfo : mPointTxnStatusInfo in arrListTxnStatusInfo){
                        // Retrieve Pending Amount
                        pendingAmount = txnStatusInfo.pendingAmount
                    }
                }
 
                when (paymentStatus) {
                    com.cellpointmobile.sdk.mPoint.PAYMENT_STATUS.MPOINT_PAYMENT_STATUS_PENDING.id -> 
                    // Poll getTxnStatus()
                    getTxnStatus(mPoint!!.sessionId)
                    com.cellpointmobile.sdk.mPoint.PAYMENT_STATUS.MPOINT_PAYMENT_STATUS_COMPLETE.id -> {
                        if(pendingAmount == 0L)
                            // Split Payment Successful
                        else
                            // Retry Payment with Pending Amount
                    }
                    com.cellpointmobile.sdk.mPoint.PAYMENT_STATUS.MPOINT_PAYMENT_STATUS_FAILED.id -> {
                        // Retry Payment with Pending Amount
                    }
                }
            }
    }  

The merchant front end reads the response received to know the payment status. Read the paymentStatus parameter to know the status of the payment. If a transaction status has payment status as:

  • Pending: call the getTxnStatus API again until you get the payment status either as Successful or Failed.
  • Complete: the payment is successful.
  • Failed: retry the payment.

To retry the payment, initialize the payment with the pending amount. This action helps a customer complete the payment using any option.

Send the pending amount you received from back end in the initialize request. After you initialize, a customer can complete the payment using any available payment option or can split the payment. This process repeats until the transaction is successful, fails, or maximum retries are attempted.

Note: If a customer decides not to retry a failed payment, call the Post-Status API as shown in the following code sample to notify that the session is complete:

mPoint.postStatus(mPoint.sessionId)

Refer to Handle Error for details.

8.13 Handle Status

Refer to Handle Status for details.

8.14 Sending FX Indicator

Refer to Sending FX Indicator for details.

9. Integration for APM

You can easily integrate SDK with an Android device for an APM. However, the integration workflow depends on an APM used for a transaction. This section provides an example for PayPal.

9.1 Application Configurations

Before you start integrating the SDK for APM transactions, you need to make the following configurations in your mobile application. To integrate the SDK with an Android device for an APM, complete the following steps:

  1. Add the following line to build.gradle file of your app:implementation "com.cellpointmobile.mpoint:mPoint:2.5.0@aar"
  2. Copy PPFraud.jar file into libs folder of your application.

    Note: Include this jar only if you opt for fraud detection feature.

  3. Add the following line to build.gradle file of your application:compile 'com.android.support:customtabs:28.0.0'
  4. Add the following intent filters to the activity to implement mPoint initialization and authorization. This is achieved using deep linking.<intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <!—the following host and scheme is required to return call back from Paypal--> <data android:host="[MERCHANT URL].<CLIENT_HOST_DOMAIN_PREFIX>.PayPalReturn" android:scheme="cellpoint" /> </intent-filter>

9.2 Instantiate SDK

See Instantiate SDK for details.

9.3 Initialize Payment for APM

When you initialize a payment for APM, a call is sent to the SDK to authorize the payment. The following code sample shows the authorize call that you need to send to the SDK:

var addressInfo = [mPointAddressInfo]  
var authToken = [AUTH_TOKEN] 

mPoint.authorize(mPointAuthorizeInfo(cardInfo) 
.setActivity(activity) 
.setAddressInfo(addressInfo) 
.setClientInfo(clientInfo) 
.setAuthToken(authToken))

Note: The setAuthToken parameter can be optional or required, depending on merchant requirement.

9.4 Presentment Currency

This is a subscription-based feature. You can show the price of your product or services on your website or app-in presentment currencies. However, you cannot make settlement in that currency. Velocity enables you to make the settlement in the configured currency.

When making payments, customers select a currency in which they want to make payment. On the payment page, Velocity converts this currency into the settlement currency and facilitates the payment in the configured settlement currency

This feature is enabled for APM and wallet. It utilizes the FX flow in Velocity. In the initialize payment response, in the card node, if FX and presentment flags are true, call the FX API to fetch available currencies. To call the FX API, refer to the following code sample

var cardInfo : mPointCardInfo
    if(cardInfo.isDcc && cardInfo.isPresentmentCurrency){
// Fetch settlement currencies from initialize response and send it in Fx Service api request
        val settlementCurrencies = cardInfo.settlementCurrencies
        if(settlementCurrencies != null && settlementCurrencies.size > 0){
  
Call Fx API for Presentment Currency to fetch available currencies
        val amount : Long  
val currency : Int 
     val saleAmount: mPointAmountInfo = mPointAmountInfo().setCurrency(currency).setPrice(amount)

        val offerCriteria: mPointExchangeOfferCriteria =
                mPointExchangeOfferCriteria().setOrderNumber(orderID)
                        .setCardType(cardInfo.type)
                        .setCountry(CountryConfig.COUNTRY_CODES.getValues().get(countryCode)).country)
                        .setSaleAmount(saleAmount)
                        .setTransactionId(mPoint.txnInfo.id)
                        .setClientId(clientId)
                        .setClientInfo(clientInfo)
                        .setSettlementCurrencies(settlementCurrencies)
         
  _mPoint.delegate = context        _mPoint.getForeignExchangeOffer(offerCriteria)   

}

After receiving the FX API response, create mPointForeignExchangeInfo object. Display the available currency and exchange amount to the customer. Refer to Dynamic Currency Conversion for details. Refer to the following code sample:

override fun displayForeignExchangeOffers(offer: mPointExchangeOffer?, mpoint: mPoint?) {
var fxInfo : mPointForeignExchangeInfo = mPointForeignExchangeInfo()
.setId(offer?.foreignExchangeOfferId!!)
.setExchangeAmount(offer.paymentCurrencyOffers[0].exchangeAmount.price)
        .setExchangeCurrencyId(offer.paymentCurrencyOffers[0].exchangeCurrency.isoNumericCode)
.setSaleCurrencyId(offer.paymentCurrencyOffers[0].saleCurrency.isoNumericCode)
        .setSaleAmount(offer.paymentCurrencyOffers[0].saleAmount.price)
.setConversionRate(offer.paymentCurrencyOffers[0].offeredExchangeRate)
.setHmac(offer.paymentCurrencyOffers[0].validationHmac)


fxInfo.isDccOpted = true
fxInfo?.serviceTypeId = mPointForeignExchangeInfo.SERVICE_TYPE_ID.PCC_OPT_IN
}

Note: Consider the following items:

  • The mPointForeignExchangeInfo object might be required for the subsequent API calls.
  • When creating mPointForeignexchangeinfo object, set isDccOpted as true for presentment currencies.
  • Set the value service type ID for the mPointForeignexchangeinfo object, as PCC_OPT_IN as mentioned in the previous code sample. The process is similar to FX opt-in.

9.5 Authorize Payment

After you invoke the authorize the authorization of PayPal transaction. Override the following method in that activity and authorize mPoint.

var txnTypeId = [mPointTxnInfo.TXN_TYPES.MPOINT_SHOPPING_ONLINE.id]
var addressInfo = [mPointAddressInfo]  
var authToken = [AUTH_TOKEN] 

override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)
     var params : List<String> = intent.data.pathSegments
    if (params.get(0).equals("return")) {
        // complete PayPal checkout
                 mPoint.authorizeWallet(cardInfo, clientInfo, txnTypeId, authToken, addressInfo)

    } else {
        // cancel PayPal checkout
          }
}

Note: Consider the following items:
• The authToken parameter is required only if it is present in the initialize request.
• It is important that the activity must include in the manifest android:launchMode="singleTask" //singleTop to activate onNewIntent.

9.6 Payment Confirmation

Implement the displayPaymentConfirmation call back method to receive the transaction status as shown in the following code sample:

override fun displayPaymentConfirmation(txn: mPointTxnInfo?, code: Int, mpoint: mPoint) {
        Log.d(TAG, "displayPaymentConfirmation")
    }

9.7 Initialize Payment for APM

When you initialize a payment for APM, a call is sent to the SDK to authorize the payment. Refer to the following code sample to make the authorize call, which you need to send to the SDK with the mPointForeignExchangeInfo object in authorize API request for presentment currency:

mPoint.authorize(mPointAuthorizeInfo(cardInfo)
        .setActivity(context)
        .setAddressInfo(addressInfo)
        .setClientInfo(clientInfo)
        .setAuthToken(authToken)
        .setForeignExchangeOffer(fxInfo))

9.8 Authorize Payment

After you invoke the authorize the authorization of PayPal transaction. Override the following method in that activity and authorize mPoint.

_mPoint.authorizeWallet(mPointAuthorizeWalletInfo()
        .setWallet(cardInfo)
        .setClientInfo(clientInfo)
        .setTxnTypeId(mPointTxnInfo.TXN_TYPES.MPOINT_SHOPPING_ONLINE.id)
        .setAuthToken(authToken)
        .setAddressInfo(addressInfo)
        .setForeignExchangeOffer(fxInfo))

9.9 Payment Confirmation

Implement the displayPaymentConfirmation call back method to receive the transaction status as shown in the following code sample:

Implement the displayPaymentConfirmation call back method to receive the transaction status as shown in the following code sample:

9.10 Handle Error

When using the split payment option, after getting callback in displayPaymentConfirmation you need to call getTxnStatus method to retrieve status of the transactions. When calling the getTxnStatus pass session ID (available in mPoint class) to retrieve all transactions from the current session. To call getTxnStatus, use the following code sample:

if(isSplitPaymentApplicable){
    	if(mpoint!!.sessionId != null && mpoint.sessionId.isNotEmpty()){
   		mPoint.delegate = this
              mPoint.getTxnStatus(-1, "", mpoint.sessionId, clientInfo)
  	  }
}

To get transaction statuses response implement following delegate method:

override fun handleTxnStatus(arrListTxnStatusInfo: ArrayList<mPointTxnStatusInfo>?, paymentStatus: Int, arrListLinkedTransactions: ArrayList<mPointLinkedTransactions>?, mPoint: mPoint?) {
 
            runOnUiThread {
                var pendingAmount: Long = 0
 
                if(null != arrListTxnStatusInfo && arrListTxnStatusInfo.size > 0){
                    for (txnStatusInfo : mPointTxnStatusInfo in arrListTxnStatusInfo){
                        // Retrieve Pending Amount
                        pendingAmount = txnStatusInfo.pendingAmount
                    }
                }
 
                when (paymentStatus) {
                    com.cellpointmobile.sdk.mPoint.PAYMENT_STATUS.MPOINT_PAYMENT_STATUS_PENDING.id -> 
                    // Poll getTxnStatus()
                    getTxnStatus(mPoint!!.sessionId)
                    com.cellpointmobile.sdk.mPoint.PAYMENT_STATUS.MPOINT_PAYMENT_STATUS_COMPLETE.id -> {
                        if(pendingAmount == 0L)
                            // Split Payment Successful
                        else
                            // Retry Payment with Pending Amount
                    }
                    com.cellpointmobile.sdk.mPoint.PAYMENT_STATUS.MPOINT_PAYMENT_STATUS_FAILED.id -> {
                        // Retry Payment with Pending Amount
                    }
                }
            }
    }   

The merchant front end reads the response received to know the payment status. Read the paymentStatus parameter to know the status of the payment. If a transaction status has payment status as:

  • Pending: call the getTxnStatus API again until you get the payment status either as Successful or Failed.
  • Complete: the payment is successful.
  • Failed: retry the payment.

To retry the payment, initialize the payment with the pending amount. This action helps a customer complete the payment using any option.

Send the pending amount you received from back end in the initialize request. After you initialize, a customer can complete the payment using any available payment option or can split the payment. This process repeats until the transaction is successful, fails, or maximum retries are attempted.

Note: If a customer decides not to retry a failed payment, call the Post-Status API as shown in the following code sample to notify that the session is complete:

mPoint.postStatus(mPoint.sessionId)

Refer to Handle Error for details.

9.11 Handle status

Refer to Handle Status for details.

10. SDK Integration for Wallets

The integration workflow of an Android device with SDK for a wallet transaction depends on the wallet used for a transaction. This section provides an example of Google Pay wallet integration.

Before you start integrating a wallet, go through the list of prerequisites.

To integrate the SDK for a wallet payment, check for the following:

10.1 SDK Integration Checklist

Before you start the SDK integration process, ensure you have the following details:

10.2 Application Configurations

Make the following configurations in your mobile application before you start integrating the SDK for wallet transactions.

10.2.1 Organize the Setup

To organize the setup, complete the following steps:

  1. Add dependencies in build.gradle file.
implementation 'com.google.android.gms:play-services-wallet:18.0.0'
implementation 'com.android.support:appcompat-v7:24.1.1'
  1. Update AndroidManifest.xml to enable Google Pay API.
<application
    ...
    ...
    <!-- Enables the Google Pay API -->
    <meta-data
        android:name="com.google.android.gms.wallet.api.enabled"
        android:value="true" />

10.2.2 Create Request Object

The mPoint SDK provides mPoint class to create request object based on the client configuration details. The request object is required to initiate the payment process.

this._mpoint = mPoint(URL ("[CPD provided URL]"), 
        this, 
        "username",[USERNAME] 
        "password", [PASSWORD] 
        clientid, [CLIENT ID] 
        accountid, [ACCOUNT ID] 
        null, 
        context, 
        null,
        RecordMap<String, String> (),
arrayOf(ClientInfo.IDENTIFIERS.DEVICEID)
 this._mpoint.mode = mPoint.OUTPUT_MODE.NONE)

10.3 Instantiate Payment

See Instantiate SDK for details.

10.4 Initialize Payment

To initialize a wallet payment, use the following code sample:

var mobile: Long = [MOBILE NUMBER];
var email: String = "[EMAIL ID]";
var countryId = CountryConfig.USA;   //[AMOUNT] for USA
var currencyId = [CURRENCY_ID]
var operatorId = countryId * 100;
var amount = [AMOUNT];
amount= amount*100;
var orderID : String = "[ORDER ID NUMBER]";
var mPointOrderInfo = [ORDER_INFO_AID_DATA]
var txnType: String = mPointTxnInfo.TXN_TYPES. MPOINT_SHOPPING_ONLINE; // Example of Search and Book Flow

mPointClientInfo  clientInfo = mPointClientInfo(appid, appversion, mPoint.LANGUAGES.da) 
.setCountryId(countryId) 
.setMobile(mobile) 
.setEmail(email) 
.setDeviceId(deviceid) 
.setCustomerRef(customerRefId) 
.setProfileId(profileId)

mPointInitializePaymentInfo paymentInfo = mPointInitializePaymentInfo()
                        paymentInfo.amount = amount
                        paymentInfo.country = CountryConfig.COUNTRIES.getValues().get(countryId)
                        paymentInfo.operator = operatorId
                        paymentInfo.mobile = mobile
                        paymentInfo.email = email
                        paymentInfo.language = mPoint.LANGUAGES.us
                        paymentInfo.setOrderno(orderID)
                       paymentInfo.clientinfo = clientInfo
                        paymentInfo.setCurrencyid(currencyId)
 paymentInfo.txnType = txnType
       paymentInfo.setHmac(hmac) OR
                        paymentInfo.secretSalt = salt


   paymentInfo.order = mPointOrderInfo
   paymentInfo.authToken = authToken
   paymentInfo.sessionId = sessionId 
     
mpoint.initialize(paymentInfo);

Note: Consider the following items:

  • The mPointOrderInfo is required only for order data.
  • The authToken can be made optional, depending on a merchant’s requirement.
  • The sessionId is required only for payment retries.

10.5 Presentment Currency

See Presentment Currency for details.

10.6 Initialize Payment

Call the following method to initialize the payment when a customer selects a third-party wallet for payment such as Google Pay.

var addressInfo = [mPointAddressInfo]   
var authToken = [AUTH_TOKEN] 
 

mPoint.authorize(mPointAuthorizeInfo(cardInfo)  
.setActivity(activity)  
.setAddressInfo(addressInfo)  
.setClientInfo(clientInfo)  
.setAuthToken(authToken))

Note: The authToken parameter can be optional or required, depending on the merchant requirement.

10.7 Authorize Payment

After the authorize method is called, customers can see their Google Pay accounts and cards stored in the wallet. When they select a card for payment, you get response in the following method:

override fun displayPaymentConfirmation(txn: mPointTxnInfo?, code: Int, mpoint: mPoint?)

10.8 Handle Error

When using the split payment option, after getting callback in displayPaymentConfirmation you need to call getTxnStatus method to retrieve status of the transactions. When calling the getTxnStatus pass session ID (available in mPoint class) to retrieve all transactions from the current session. To call getTxnStatus, use the following code sample:

if(isSplitPaymentApplicable){
    	if(mpoint!!.sessionId != null && mpoint.sessionId.isNotEmpty()){
   		mPoint.delegate = this
              mPoint.getTxnStatus(-1, "", mpoint.sessionId, clientInfo)
  	  }
}

To get transaction statuses response implement following delegate method:

override fun handleTxnStatus(arrListTxnStatusInfo: ArrayList<mPointTxnStatusInfo>?, paymentStatus: Int, arrListLinkedTransactions: ArrayList<mPointLinkedTransactions>?, mPoint: mPoint?) {
 
            runOnUiThread {
                var pendingAmount: Long = 0
 
                if(null != arrListTxnStatusInfo && arrListTxnStatusInfo.size > 0){
                    for (txnStatusInfo : mPointTxnStatusInfo in arrListTxnStatusInfo){
                        // Retrieve Pending Amount
                        pendingAmount = txnStatusInfo.pendingAmount
                    }
                }
 
                when (paymentStatus) {
                    com.cellpointmobile.sdk.mPoint.PAYMENT_STATUS.MPOINT_PAYMENT_STATUS_PENDING.id -> 
                    // Poll getTxnStatus()
                    getTxnStatus(mPoint!!.sessionId)
                    com.cellpointmobile.sdk.mPoint.PAYMENT_STATUS.MPOINT_PAYMENT_STATUS_COMPLETE.id -> {
                        if(pendingAmount == 0L)
                            // Split Payment Successful
                        else
                            // Retry Payment with Pending Amount
                    }
                    com.cellpointmobile.sdk.mPoint.PAYMENT_STATUS.MPOINT_PAYMENT_STATUS_FAILED.id -> {
                        // Retry Payment with Pending Amount
                    }
                }
            }
    }

The merchant front end reads the response received to know the payment status. Read the paymentStatus parameter to know the status of the payment. If a transaction status has payment status as:

  • Pending: call the getTxnStatus API again until you get the payment status either as Successful or Failed.
  • Complete: the payment is successful.
  • Failed: retry the payment.

To retry the payment, initialize the payment with the pending amount. This action helps a customer complete the payment using any option.

Send the pending amount you received from back end in the initialize request. After you initialize, a customer can complete the payment using any available payment option or can split the payment. This process repeats until the transaction is successful, fails, or maximum retries are attempted.

Note: If a customer decides not to retry a failed payment, call the Post-Status API as shown in the following code sample to notify that the session is complete:

mPoint.postStatus(mPoint.sessionId)

Refer to Handle Error for details.

10.9 Handle status

The status codes are returned by the SDK in a call back to the handleStatus method. This method enables the application to handle the status appropriately by implementing the method as shown in the following code sample:

The handleStatus method shows an error in the CPD server.

override fun handleStatus(statusInfo: mPointStatusInfo, client: Client, mpoint: mPoint) {}

11. SDK Integration for Offline Payment

Some merchants facilitate customers to make offline payment at their partner establishments. This section provides integration details for such offline payments.

11.1 Instantiate SDK

See Instantiate SDK for details.

11.2 Initialize payment

See Initialize Payment for details.

Note: For offline payment, if holding fee is applicable, send it in initialize-payment request. Refer to the following code sample to see how to send holding fee. Front end needs to have a provision to accept
holding fee.

// Set holding fee to mPointInitializePaymentInfo builder if holding fee is present
paymentInfo.holdingFees = Holding Fee amount

When creating Airline Data or Order Info for offline payment, pass the holding fee details as shown in the following code:

var lineItem = mPointLineItem(...)

lineItem.addAdditionalData("session_token", sessionToken)
lineItem.addAdditionalData("hold_fee_amount", holdFee)
lineItem.addAdditionalData("hold_fee_currency_code", currencyCode)
lineItem.addAdditionalData("hold_period", holdPeriod)

Note: The setAuthToken parameter can be optional or required, depending on merchant requirement.

11.3 Authorize Payment

When you initialize a payment for offline methods, send the authorize call to the SDK to process payment as shown in the following sample:

var addressInfo = [mPointAddressInfo]  
var authToken = [AUTH_TOKEN] 

mPoint.authorize(mPointAuthorizeInfo(cardInfo)  
.setActivity(activity)  
.setAddressInfo(addressInfo)  
.setClientInfo(clientInfo)  
.setAuthToken(authToken))

Note: The setAuthToken parameter can be optional or required, depending on merchant requirement.

11.4 Presentment Currency

See Presentment Currency for details.

Note: Consider the following items:

  • If you use FX opt-in and FX opt-out, send the mPointForeignExchangeInfo object in subsequent calls such as authorize.
  • To create mPointForeignexchangeinfo object for offline method flow, set isDccOpted as false.
  • For mPointForeignexchangeinfo object, set value for service type id as PCC_OPT_OUT. The process is similar to FX Opt-out Transaction.

11.5 Payment Confirmation

Implement the displayPaymentConfirmation call back method to receive the transaction status as shown in the following code sample:

override fun displayPaymentConfirmation(txn: mPointTxnInfo?, code: Int, mpoint: mPoint) {
        Log.d(TAG, "displayPaymentConfirmation")
    }

11.5.1 Handle Error

When using the split payment option, after getting callback in displayPaymentConfirmation you need to call getTxnStatus method to retrieve status of the transactions. When calling the getTxnStatus pass session ID (available in mPoint class) to retrieve all transactions from the current session. To call getTxnStatus, use the following code sample:

if(isSplitPaymentApplicable){
    	if(mpoint!!.sessionId != null && mpoint.sessionId.isNotEmpty()){
   		mPoint.delegate = this
              mPoint.getTxnStatus(-1, "", mpoint.sessionId, clientInfo)
  	  }
}

To get transaction statuses response implement following delegate method:

override fun handleTxnStatus(arrListTxnStatusInfo: ArrayList<mPointTxnStatusInfo>?, paymentStatus: Int, arrListLinkedTransactions: ArrayList<mPointLinkedTransactions>?, mPoint: mPoint?) {
 
            runOnUiThread {
                var pendingAmount: Long = 0
 
                if(null != arrListTxnStatusInfo && arrListTxnStatusInfo.size > 0){
                    for (txnStatusInfo : mPointTxnStatusInfo in arrListTxnStatusInfo){
                        // Retrieve Pending Amount
                        pendingAmount = txnStatusInfo.pendingAmount
                    }
                }
 
                when (paymentStatus) {
                    com.cellpointmobile.sdk.mPoint.PAYMENT_STATUS.MPOINT_PAYMENT_STATUS_PENDING.id -> 
                    // Poll getTxnStatus()
                    getTxnStatus(mPoint!!.sessionId)
                    com.cellpointmobile.sdk.mPoint.PAYMENT_STATUS.MPOINT_PAYMENT_STATUS_COMPLETE.id -> {
                        if(pendingAmount == 0L)
                            // Split Payment Successful
                        else
                            // Retry Payment with Pending Amount
                    }
                    com.cellpointmobile.sdk.mPoint.PAYMENT_STATUS.MPOINT_PAYMENT_STATUS_FAILED.id -> {
                        // Retry Payment with Pending Amount
                    }
                }
            }
    }  

The merchant front end reads the response received to know the payment status. Read the paymentStatus parameter to know the status of the payment. If a transaction status has payment status as:

  • Pending: call the getTxnStatus API again until you get the payment status either as Successful or Failed.
  • Complete: the payment is successful.
  • Failed: retry the payment.

To retry the payment, initialize the payment with the pending amount. This action helps a customer complete the payment using any option.

Send the pending amount you received from back end in the initialize request. After you initialize, a customer can complete the payment using any available payment option or can split the payment. This process repeats until the transaction is successful, fails, or maximum retries are attempted.

Note: If a customer decides not to retry a failed payment, call the Post-Status API as shown in the following code sample to notify that the session is complete:

mPoint.postStatus(mPoint.sessionId)

Refer to Handle Error for details.

11.5.2 Handle Status

Refer to Handle Status for details.

12. SDK Integration for Vouchers

The integration of an Android device with an SDK for a voucher transaction depends on the voucher used for a transaction. The following is an example of Travel Fund integration with Velocity SDK.

12.1 Travel Fund

Travel Fund (TF) acts as a virtual wallet and stores a customer’s cash refund. The amount is attributed to a PNR as a record locator and an expiry date, which can be retrieved and redeemed using the PNR. Merchants can configure the currencies for which TF is shown as a payment method during a transaction.

When customers select TF to make payment:

  • Travel Fund is shown on the page for making payment.
  • Customers enter their PNR number to know the voucher details such as:
  • Balance amount
  • Currency
  • Expiry date

12.2 Instantiate SDK

See Instantiate SDK for details.

12.3 Initialize Payment for Travel Fund

See Initialize Request for details.

Additionally, send the session token in the initialize payment request. The following code sample shows how to send session token in the initialize-payment request:

var paymentInfo :mPointInitializePaymentInfo
var sessionToken: String // Session Token
…

paymentInfo.addAdditionalData("session_token", sessionToken)

…

mPoint.initialize(paymentInfo)

Add the following in displayAvailablePayments (availablePayments: mPointAvailablePayments?, mpoint: mPoint? method to read voucher cards.

override fun displayAvailablePayments(availablePayments: mPointAvailablePayments?, mpoint: mPoint?) {

if(availablePayments!!.vouchers != null && availablePayments.vouchers.size > 0){
   // Read Vouchers
   }
}

After reading the vouchers, the system can identify voucher as a payment method. To check the balance in the voucher, complete the following steps:

  1. Retrieve TF. To retrieve the TF balance, call the getBalance method shown as follows.
var voucherId: String // 6-digit Booking Ref. No or PNR

var sessionToken: String
var clientInfo: mPointClientInfo 

val getBalanceCriteria = mPointGetBalanceCriteria()
getBalanceCriteria.voucherId = voucherId
getBalanceCriteria.addAdditionalData("session_token", sessionToken)
getBalanceCriteria.clientInfo = clientInfo
mPoint.delegate = this
mPoint.getBalance(getBalanceCriteria)

The previous code sample provides the response for which you need to implement displayBalance method from mPointGetBalanceDelegate interface.

override fun displayBalance(balanceDetails: mPointBalanceDetails?, p1: mPoint?) { 
// balanceDetails instance has properties amount, currency and  expiryDate. Use them to display information about Travel Fund.

}

  1. Redeem TF by using the authorize method. TF redemption has following scenarios:
  • TF amount is more than booking amount- customers can utilize the entire TF amount to pay the booking amount.
  • TF amount is less than booking amount- The UI shows that the balance amount is less than the booking amount and enables customers to make payment using another method. In this case, customers can use split payment method.

12.3.1 Authorize Payment for Voucher

To redeem the voucher, call the authorize method shown as follows:

var voucherId: String // 6-digit Booking Ref. No or PNR

var sessionToken: String

var countryCode: Int
var amount: Long 

var currencyCode:  Int

var clientInfo : mPointClientInfo

var authToken: String
var additionalData: RecordMap<String, String>

var addressInfo: mPointAddressInfo


val travelFundVoucher = mPointTravelFundVoucher()
travelFundVoucher.voucherId = voucherId
travelFundVoucher.amount = PriceInfo(countryCode,amount,
        null, null, null, currencyCode,  -1)

mPoint.authorize(mPointAuthorizeInfo()
        .setClientInfo(clientInfo)
        .setViaAuthToken(true)
        .setPassword(authToken)
        .setVoucherInfo(travelFundVoucher)
        .addAdditionalData(additionalData)
        .setAddressInfo(addressInfo))

12.4 Display Payment Confirmation

Implement the displayPaymentConfirmation callback method to receive confirmation of payment as shown in the following sample:

override fun displayPaymentConfirmation(txnInfo: mPointTxnInfo?, code: Int, mpoint: mPoint?) {
}

12.5 Split Payment

If the retrieved TF amount is less than the booking amount, the customer can opt to split the payment.
The payment can be split with the Card & Travel Fund balance. The customer can pay the remaining amount by card after the redemption of the TF balance.

If FX is enabled on the selected card for split payment, then the FX flow execution remains the same.

12.5.1 Authorize Payment for Card and Voucher

Call authorize method as shown below to pay using split option.

var voucherId: String // 6-digit Booking Ref. No or PNR

var sessionToken: String

var countryCode: Int
var travelFundBalanceAmount: Long   // Travel Fund Balance to be redeemed
var cardPendingAmount: Long   // Remaining Balance to be paid through card payment

var currencyCode:  Int

var clientInfo : mPointClientInfo

var authToken: String
var additionalData: RecordMap<String, String>

var addressInfo: mPointAddressInfo
var cardType: mPointCardInfo
var cardNumber: Long
var expMonth: Int

var expYear: Int

var cvv: String

var cardName: String 

var validFromExpMonth: Int

var validFromExpYear: Int

var isSaveCard: Boolean

var foreignExchangeInfo: mPointForeignExchangeInfo




// Voucher
var travelFundVoucher = mPointTravelFundVoucher()
    travelFundVoucher.voucherId = voucherId
 travelFundVoucher.amount = PriceInfo(countryCode, travelFundBalanceAmount, null, null, null, currencyCode,  -1)
}

// Card - Pending Amount
var priceInfo: PriceInfo? = null
    priceInfo = PriceInfo(countryCode, cardPendingAmount, null, null, null, currencyCode,  -1)



mPoint.authorize(mPointAuthorizeInfo(cardType)
        .setClientInfo(clientInfo)
        .setViaAuthToken(true)
        .setPassword(authToken)
        .setVoucherInfo(travelFundVoucher)
        .addAdditionalData(additionalData)
        .setCardNo(cardNumber)
        .setCardExpMonth(expMonth)
        .setCardExpYear(expYear)
        .setCvc(cvv)
        .setNameOnCard(cardName)
        .setCardValidFromMonth(validFromExpMonth)
        .setCardValidFromYear(validFromExpYear)
        .setStoreCard(isSaveCard)
        .setForeignExchangeOffer(foreignExchangeInfo)
        .setAddressInfo(addressInfo)
        .setPendingSplitAmount(priceInfo))

12.5.2 Authorize Payment for APM and Voucher

var mPointSplitCombination: mPointSplitCombination? = null
 
// Voucher
val travelFundVoucher = mPointTravelFundVoucher()
if(remainingBalanceToBePaidByTravelFund > 0)
{
    travelFundVoucher.voucherId = etBookingReferenceNumber.text.toString()
    travelFundVoucher.amount = PriceInfo(AppConstants.getCountryCode(country),
    (((remainingBalanceToBePaidByTravelFund.toFloat()) * getDecimalPointMultiplierFromCurrencyId(currencyCode)).roundToLong()),
    null, null, null, currencyCode,  -1)
}
 
// APM - Pending Amount
var priceInfo: PriceInfo? = null
if(remainingBalanceToBePaidByAPM > 0)
priceInfo = PriceInfo(AppConstants.getCountryCode(country),
    (((remainingBalanceToBePaidByAPM.toFloat()) * getDecimalPointMultiplierFromCurrencyId(currencyCode)).roundToLong()),
    null, null, null, currencyCode,  -1)
                
                
for(splitCombination in this.splitPayment!!.splitCombinations){
    for(paymentType in splitCombination.paymentType){
        if(paymentType.id == paymentTypeId){
            mPointSplitCombination = splitCombination
        }
    }
}                
 
mPoint.authorize(mPointAuthorizeInfo(cardType)
    .setActivity(this)
    .setAddressInfo(addressInfo)
    .setClientInfo(clientInfo)
    .setAuthToken(authToken)
    .setForeignExchangeOffer(fxInfo)
    .setPendingSplitAmount(priceInfo)
    .setVoucherInfo(travelFundVoucher)
    .addAdditionalData(additionalData)
    .setSplitCombinations(mPointSplitCombination))

12.5.3 Authorize Payment for eWallet and Voucher

var mPointSplitCombination: mPointSplitCombination? = null
 
// Voucher
val travelFundVoucher = mPointTravelFundVoucher()
if(remainingBalanceToBePaidByTravelFund > 0)
{
    travelFundVoucher.voucherId = etBookingReferenceNumber.text.toString()
    travelFundVoucher.amount = PriceInfo(AppConstants.getCountryCode(country),
    (((remainingBalanceToBePaidByTravelFund.toFloat()) * getDecimalPointMultiplierFromCurrencyId(currencyCode)).roundToLong()),
    null, null, null, currencyCode,  -1)
}
 
// eWallet- Pending Amount
var priceInfo: PriceInfo? = null
if(remainingBalanceToBePaidByWallet> 0)
priceInfo = PriceInfo(AppConstants.getCountryCode(country),
    (((remainingBalanceToBePaidByWallet.toFloat()) * getDecimalPointMultiplierFromCurrencyId(currencyCode)).roundToLong()),
    null, null, null, currencyCode,  -1)
                
                
for(splitCombination in this.splitPayment!!.splitCombinations){
    for(paymentType in splitCombination.paymentType){
        if(paymentType.id == paymentTypeId){
            mPointSplitCombination = splitCombination
        }
    }
}                
 
mPoint.authorize(mPointAuthorizeInfo(cardType)
    .setActivity(this)
    .setAddressInfo(addressInfo)
    .setClientInfo(clientInfo)
    .setAuthToken(authToken)
    .setForeignExchangeOffer(fxInfo)
    .setPendingSplitAmount(priceInfo)
    .setVoucherInfo(travelFundVoucher)
    .addAdditionalData(additionalData)
    .setSplitCombinations(mPointSplitCombination))

12.6 Display Payment Confirmation

Implement the displayPaymentConfirmation callback method to receive confirmation of payment as shown in the following sample.

override fun displayPaymentConfirmation(txnInfo: mPointTxnInfo?, code: Int, mpoint: mPoint?) {
}

When using split payment option and after getting callback in displayPaymentConfirmation, you need to call getTxnStatus method to retrieve status of the transactions. When calling the getTxnStatus, pass session ID (available in mPoint class) to retrieve all transactions from the current session.

To call getTxnStatus, use the following code sample:

if(isSplitPaymentApplicable){
    	if(mpoint!!.sessionId != null && mpoint.sessionId.isNotEmpty()){
   		mPoint.delegate = this
mPoint.getTxnStatus(-1, "", mpoint.sessionId, clientInfo)
  	  }
}

To get transaction statuses response implement following delegate method:

override fun handleTxnStatus(arrListTxnStatusInfo: ArrayList<mPointTxnStatusInfo>?, paymentStatus: Int, arrListLinkedTransactions: ArrayList<mPointLinkedTransactions>?, mPoint: mPoint?) {
        when (paymentStatus) {
           MPOINT_PAYMENT_STATUS_PENDING.id -> // Payment is Pending
           MPOINT_PAYMENT_STATUS_COMPLETE.id -> // Payment is Successful
           MPOINT_PAYMENT_STATUS_FAILED.id -> { // Payment is Failed
                        var pendingAmount: Long = 0
                        if(null != arrListTxnStatusInfo && arrListTxnStatusInfo.size > 0){
                        for (txnStatusInfo : mPointTxnStatusInfo in arrListTxnStatusInfo){
                                // Retrieve Pending Amount
                                pendingAmount = txnStatusInfo.pendingAmount
                            }
                        }
                      }
    }

The merchant front end reads the response received to know the payment status. Read the paymentStatus parameter to know the status of the payment. If a transaction status has payment status as:

  • Pending: call the getTxnStatus API again till you get the payment status either as Successful or Failed.
  • Complete: the payment is successful.
  • Failed: retry the payment.

To retry the payment, initialize the payment with the pending amount. This helps a customer complete the payment using any option.

Send the pending amount you received from back end in the initialize request. After you initialize, a customer can complete the payment using any available payment option or can split the payment. This process repeats until the transaction is successful, fails, or maximum retry is attempted.

Note: If a customer decides not to retry a failed payment, call the Post-Status API as shown in the following code sample to notify that the session is complete.

mPoint.postStatus(mPoint.sessionId

12.7 Handle Error

When using the split payment option, after getting callback in displayPaymentConfirmation you need to call getTxnStatus method to retrieve status of the transactions. When calling the getTxnStatus pass session ID (available in mPoint class) to retrieve all transactions from the current session. To call getTxnStatus, use the following code sample:

if(isSplitPaymentApplicable){
    	if(mpoint!!.sessionId != null && mpoint.sessionId.isNotEmpty()){
   		mPoint.delegate = this
              mPoint.getTxnStatus(-1, "", mpoint.sessionId, clientInfo)
  	  }
}

To get transaction statuses response implement following delegate method:

override fun handleTxnStatus(arrListTxnStatusInfo: ArrayList<mPointTxnStatusInfo>?, paymentStatus: Int, arrListLinkedTransactions: ArrayList<mPointLinkedTransactions>?, mPoint: mPoint?) {
 
            runOnUiThread {
                var pendingAmount: Long = 0
 
                if(null != arrListTxnStatusInfo && arrListTxnStatusInfo.size > 0){
                    for (txnStatusInfo : mPointTxnStatusInfo in arrListTxnStatusInfo){
                        // Retrieve Pending Amount
                        pendingAmount = txnStatusInfo.pendingAmount
                    }
                }
 
                when (paymentStatus) {
                    com.cellpointmobile.sdk.mPoint.PAYMENT_STATUS.MPOINT_PAYMENT_STATUS_PENDING.id -> 
                    // Poll getTxnStatus()
                    getTxnStatus(mPoint!!.sessionId)
                    com.cellpointmobile.sdk.mPoint.PAYMENT_STATUS.MPOINT_PAYMENT_STATUS_COMPLETE.id -> {
                        if(pendingAmount == 0L)
                            // Split Payment Successful
                        else
                            // Retry Payment with Pending Amount
                    }
                    com.cellpointmobile.sdk.mPoint.PAYMENT_STATUS.MPOINT_PAYMENT_STATUS_FAILED.id -> {
                        // Retry Payment with Pending Amount
                    }
                }
            }
    }  

The merchant front end reads the response received to know the payment status. Read the paymentStatus parameter to know the status of the payment. If a transaction status has payment status as:

  • Pending: call the getTxnStatus API again till you get the payment status either as Successful or Failed.
  • Complete: the payment is successful.
  • Failed: retry the payment.

To retry the payment, initialize the payment with the pending amount. This action helps a customer complete the payment using any option.

Send the pending amount you received from back end in the initialize request. After you initialize, a customer can complete the payment using any available payment option or can split the payment. This process repeats until the transaction is successful, fails, or maximum retries are attempted.

Note: If a customer decides not to retry a failed payment, call the Post-Status API as shown in the following code sample to notify that the session is complete:

mPoint.postStatus(mPoint.sessionId)

Refer to Handle Error for details.

12.8 Handle Status

Refer to Handle Status for details.

Note: You should verify in handle status method if the customer is trying to make a payment using split payment. If yes, you should give a call to getTxnStatus method with session ID. See the example code sample below.

if(isSplitPaymentApplicable){
    if(statusInfo!!.sessionId != null && statusInfo.sessionId.isNotEmpty()){
   	
        mPoint.delegate = this
  mPoint.getTxnStatus(-1, "", statusInfo.sessionId, clientInfo)

  	  }
}
To get transaction statuses response implement handleTxnStatus delegate method and repeat the same steps as mentioned above in handleTxnStatus method.

13. SDK Integration for Aggregators

This section provides integration details for aggregators.

13.1 Instantiate SDK

See Instantiate SDK for details.

13.2 Initialize payment

See Initialize Payment for details.

13.3 Authorize Payment

The front-end application needs to display the available list of payment methods. After the you select a particular payment method out of the list, you can initialize a payment for aggregators by sending the authorize call to the SDK to process payment as shown in the following sample:

var addressInfo = [mPointAddressInfo]  
var authToken = [AUTH_TOKEN] 
var paymentMethod = [mPointCardPaymentMethod] // Selected Payment Method	

                                                  
mPoint.authorize(mPointAuthorizeInfo(cardInfo)  
.setCardPaymentMethod(paymentMethod)
.setActivity(activity)  
.setAddressInfo(addressInfo)  
.setClientInfo(clientInfo)  
.setAuthToken(authToken))

Note: The setAuthToken parameter can be optional or required depending on merchant requirements.

13.4 Payment Confirmation

Implement the displayPaymentConfirmation call back method to receive the transaction status as shown in the following code sample:

override fun displayPaymentConfirmation(txn: mPointTxnInfo?, code: Int, mpoint: mPoint) {
        Log.d(TAG, "displayPaymentConfirmation")
    }

13.5 Handle Error

A handle error occurs when there an error in parsing. The status code reveals the type of error that has occurred in the SDK. For details of the status code, refer to Status Codes.

override fun handleError(errorInfo: mPointErrorInfo, client: Client, mpoint: mPoint) {}

13.6 Handle status

The status codes are returned by the SDK in a call back to the handleStatus method. This method enables the application to handle the status appropriately by implementing the method as shown in the following code sample:

The handleStatus method shows an error in the CPD server.

override fun handleStatus(statusInfo: mPointStatusInfo, client: Client, mpoint: mPoint) {}

14. Description of Parameters

14.1 Search and Book Workflow

ParameterTypeRequiredDescription
mobileIntegerNoThe mobile number of a customer.
emailStringNoThe email address of a customer.
countryIdIntegerNoThe CPD-specific country code, made available on request.
currencyIdIntegerNoThe CPD-specific ID of a currency selected for making payment.
operatorIdIntegerNoThe identification number of a customer’s Mobile Network Operator. A typical value is “country id” multiplied by 100.
amountStringNoThe amount for a product or services that a customer pays.
orderIDIntegerNoThe order ID details, required for airlines.
mPointOrder
Info
ObjectNoThe object of mPointOrderInfo, which contains details of order data.
txnTypeStringNo

The type of transaction. The following table shows the transaction types.







Txn TypeTransaction flow that a customer uses for making payment
1 Search and book
2 Search and book, pay later
3
  • Manage your booking for:
    • Ancillary Purchase
    • Change itinerary payment
  • Online check in for ancillary purchase
  • 4 Manage your booking, pay later

    14.2 FX Service Parameters

    The description of parameters for the FX Service transaction is listed in the table below.

    Object NameDescription
    OrderNumberThe order number of a transaction.
    CardNumberThe card used in a transaction.
    CardTypeThe type of card used in a transaction such as Visa or Mastercard.
    orderIdThe order ID of a transaction.
    amountThe amount that a customer pays for a transaction.
    SaleAmountThe mpoint amount info object. It shows the amount and currency against which you want to offer exchange price.
    TransactionIdThe transaction ID generated during a transaction.
    AccountIdThe account ID of a transaction.
    ClientIdThe client ID.
    clientinfoThe client info object.
    CardIdThe ID number of a stored card.

    15. Status Codes

    15.1 Status Codes

    The status codes are listed in the table below.

    CodeCategoryTypeDescription
    1001PaymentPayment Initialized with VelocityThe payment transaction is created in the Velocity database.
    1009PaymentPayment Initialized with PSPThe payment processor responsible for authorizing the payment has been initialized.
    1991CallbackMerchant Callback ConstructedThe callback to the merchant application sent to callback-url has been constructed.
    1992CallbackCallback ConnectedThe connection with the merchant callback URL is established.
    1993CallbackCallback Connection FailedThe connection with the merchant callback URL failed.
    1990CallbackCallback AcceptedThe merchant system returned an HTTP 200 OK and received the callback.
    1995CallbackCallback RejectedThe merchant system returned an HTTP $XX/5XX Error and rejected the callback.
    2000PaymentAuthorizedThe payment has been authorized successfully by the PSP.
    2002PaymentCancelledThe authorized payment has been cancelled successfully by the PSP.
    2003PaymentRefundedThe captured payment refunded successfully (full / partial) by the PSP. The manual operation / delayed refund - pending states, initiated.
    2008PaymentPayment via StoredInitialized payment with a stored card.
    2009PaymentAuthorized and Card StoredThe payment has been authorized successfully by the PSP and the card stored on a successful authorization.
    2001PaymentCapturedThe payment has been captured successfully by the PSP initiated for refund.
    2010PaymentRejectedThe payment was rejected by the PSP or Acquirer
    • Need more granular states - message
    • tbl Front end can continue handling the generic state.
    20109PaymentRejected sub state on timeoutIssuer down time; SDK returns this to the Velocity core.
    20108PaymentRejected sub state on timeoutPSP down time; SDK returns this to the Velocity core.
    2011refund PaymentDeclinedThe payment was declined by the PSP / Acquirer while performing capture, refund, or cancel.
    No Vision impact; however, all declines have common state 2011.
    4020SessionSession FailedThe session failed or declined. One or more transactions in the session failed.
    4021SessionSession FailedThe session failed (maximum attempt exceeds). One or more transaction attempts failed.
    4030SessionSession CompleteThe session completed successfully. The transactions in the session are complete and successful.
    4031SessionSession PartialThe session was partially completed. One or more transactions in the session were incomplete.
    4020SessionSession FailedThe session failed or declined. One or more transactions in the session failed.
    CodeDescription
    0Payment not made.
    1003Card expired.
    1005Invalid card number
    1011Invalid card name.
    1012Invalid card address.
    1013Invalid card date of birth.
    1014Card is inactive.
    2007Payment processed.
    2019Payment duplicated.
    2084Card not found.
    4030Payment success.
    40031Partial payment success.
    200Request validated and accepted by back end.
    400Request rejected by back end because of validation error.
    401Authentication required.
    403Access denied.
    415Message transmitted in an unknown format or by using an unsupported content type.
    500Velocity server error.
    502PSP returned an unknown error.
    504A timeout occurred while communicating with the PSP.

    15.2 Initialize Payment

    The following table lists and describes the codes that you can receive after you initialize a payment:

    CodeDescription
    1Undefined client ID
    1Client ID / Account doesn't match.
    2Invalid client ID
    3Unknown client ID
    4Client disabled
    11Undefined account
    12Invalid account
    13Unknown account
    14Account disabled
    401Authentication required.
    1002Internal database error - Unable to create a new Transaction.
    Contact [email protected]
    1003Internal database error - Unable to insert new message for Transaction.
    Contact [email protected]
    1004Internal database error - Unable to update Transaction.
    Contact [email protected]

    15.3 Authorize Payment

    The following table lists and describes the codes that you can receive after a payment is authorized:

    Code Description
    1Undefined client ID
    1Client ID / Account doesn't match.
    2Invalid client ID
    3Unknown client ID
    4Client disabled
    11Undefined account
    12Invalid account
    13Unknown account
    14Account disabled
    26Undefined password.
    27 Password is too short; min length is 6 characters.
    28Password is too long; max length is 50 characters.
    29Password contains invalid characters or
    31 Authentication failed.
    32Authentication failed – Next invalid attempt will delete the account.
    33Authentication failed – Account deleted.
    34Authentication rejected by the single sign-on server.
    35User account not found.
    36A timeout occurred while communicating with the single sign-on server.
    37Mobile number not verified.
    38Unable to perform single sign-on due to invalid Security Token or Authentication URL.
    39User account disabled.
    41Undefined card ID.
    42ID for the stored card is too small, min value is 1.
    43Stored card not found.
    43Insufficient balance on voucher.
    44Stored card disabled.
    51Insufficient balance on e-money account.
    52Insufficient balance on loyalty account.
    59Authorization type not supported for Transaction
    90The connection timed out while authorizing the payment with the PSP.
    91Internal Error: Unable to debit account
    92Authorization rejected by PSP / Acquirer.
    99Unknown PSP / Acquirer.
    100Payment Authorized using stored card.
    101Payment authorized using e-money account.
    102Payment authorized using loyalty account.
    103Authorization already in progress.
    400Wrong operation: authorization.
    401Authentication required.
    1002Internal database error - Unable to create a new Transaction. Contact [email protected]
    1003Internal database error - Unable to insert new message for Transaction. Contact [email protected]
    99Unknown PSP / Acquirer
    1004Internal database error - Unable to update Transaction.
    Contact [email protected]

    15.4 Capture Payment

    The following table lists and describes the codes that you may receive after you initialize payment.

    CodeDescription
    1000Transaction captured successfully
    999Declined
    400Invalid Request
    998Network Error
    997Capture not supported

    15.5 Refund Payment

    The following table lists and describes the codes that you may receive after you initialize a refund request.

    CodeDescription
    51The amount is undefined
    52The amount is too small
    53The amount greater than the authorized amount
    1000Transaction Refunded successfully
    1001Transaction Cancelled successfully
    999Declined
    9400Invalid Request
    9502Bad Gateway
    9500Internal Sever Error
    998Network Error