Consumer Wallet

SDK Documentation

The Horizon Wallet SDK for Android makes it quick and easy to build an excellent payment experience in your Android app. We provide a powerful workflow and APIs that enables your UI to complete the full customer experience.

How to add library build file to the project

Open your app’s build.gradle file and add a declaration similar to the following:

// Gradle Groovy DSL install command

implementation 'io.vipaso.horizon:walletSdk:1.0.4'

// Add Gradle Groovy DSL repository command

maven {
  url 'https://gitlab.com/api/v4/projects/39115928/packages/maven'
}
// Gradle Kotlin DSL install command

implementation("io.vipaso.horizon:walletSdk:1.0.4")

// Add Gradle Kotlin DSL repository command

maven("https://gitlab.com/api/v4/projects/39115928/packages/maven")

Check this documentation for more details about libraries: https://developer.android.com/studio/projects/android-library

Library packages and classes structure

  • API package contains:
    • DTO package that contains a request package with api requests ordered by purpose packages(bonusProgram, payment, transaction, user and wallet). The DTO package also includes response packages ordered by purpose. There you can see in more detail the response values of all API calls.
    • Interfaces package contains interfaces with API calls named after the purpose they have(BonusProgramApi, PaymentApi, RedemptionApi, TransactionApi, UserApi, WalletDataApi).
    • Repositories package contains classes ordered by purpose that use API interfaces to make API requests(BonusProgramRepository, PaymentRepository, RedemptionRepository, TransactionRepository, UserRepository, WalletRepository).
    • Storage package is the most important package because it contains use case classes that you will be calling directly from your project. The storage package contains a use case class with one function for each API call or calls for payment, redemption and wallet clients(Please follow instructions below for each use case function with call examples and also see comments in code for more details about parameters and responses).
  • Clients package contains:
    • Interfaces package contains payment and redemption client callbacks that you can use for controlling views display, scanning devices and payment status.
    • Clients package also contains PaymentClient, RedemptionClient and WalletClient classes that have functions that call Bluetooth commands for executing payment, wallet operations etc. You will use these clients through use case functions.
  • Commands package contains BluetoothCommands class with specific callback functions for payment, redemption and wallet operations, which payment, redemption and wallet clients use directly.
  • DI package contains Module package and Graph class for dependency injection.
  • WalletSdkApplication class is used for initialising the dependency injection Graph.

Getting started

Current SDK version: 1.0.0
Minimum SDK version for using a library: 21

Permissions:

  • "android.permission.ACCESS_FINE_LOCATION"
  • "android.permission.ACCESS_COARSE_LOCATION"
  • "android.permission.ACCESS_BACKGROUND_LOCATION"
  • "android.permission.BLUETOOTH_CONNECT"
  • "android.permission.INTERNET"
  • "android.permission.ACCESS_NETWORK_STATE"
  • "android.permission.READ_PHONE_STATE"
  • "android.permission.BLUETOOTH"
  • "android.permission.BLUETOOTH_ADMIN"
  • "android.permission.UPDATE_DEVICE_STATSU"
  • "android.permission.ACCESS_NETWORK_STATE"
  • "android.hardware.location.network"

To use Wallet SDK functions you need to instantiate a WalletAppClient class, example:

var appClient: WalletAppClient = WalletAppClient(YourApplication.context)

Use case classes and functions with examples

Registration and reactivation of a consumer

we provide a straigth forward registration process and support the a reactivation of a wallet as well. The consumer receives a registration code per SMS and a link per mail.

This shows how the app could look like:

1119
  • UserRegistrationUseCase.requestUserRegistration(registrationRequest, deviceId)
    Takes first name, last name, email, phone number and device ID and returns applicationToken, walletUserId, serverPublicKey and activationUrl.
    Call example:
userRegistrationUseCase.requestUserRegistration(
            firstName,
            lastName,
            email,
            phoneNumber,
            deviceId
        ).subscribe({
            	if (it.header != null && it.header?.isSuccess()) {
             		 // Insert your success code
              }
            }, {
               // Throwable
            })
  • SendPukRequestUseCase.sendPukRequest(context, email)
    Takes context, email and callback and returns is it request a success or not.
    Call example:
sendPukRequestUseCase.sendPukRequest(context, emailEditText.text.toString()) {
                if (it) {
                    repository.walletClient.state = WalletClientState.REACTIVATION_PUK
                    // Insert code for succesfull request.
                    }
                } else {
                    // Insert code for failed request.
                }
            }
  • ValidatePukUseCase.validatePuk(puk, walletId)
    Takes PUK and wallet ID(this property you need to cache from register wallet response, walletUserId) and returns is it a success.
    Call example:
validatePukUseCase.validatePuk(pukCode, walletId)
            .subscribe({
                if (it.header != null && it.header.isSuccess()) {
                    repository.walletClient.state = WalletClientState.REGISTRATION_CONFIRM_EMAIL
                    // Insert your success code.
                }
            }, {
                //Throwable
            })
  • ReactivateWalletUseCase.reactivateWallet(reactivationToken)
    Takes reactivation token from GetReactivationTokenUseCase and returns applicationToken, walletUserId, serverPublicKey, activationUrl. (See GetReactivationTokenUseCase for example)

  • GetReactivationTokenUseCase.requestReactivationToken(puk, reactivationEmail, deviceId)
    Takes puk, reactivation Email and device ID and returns reactivationToken that you can use for wallet reactivation call(See ReactivateWalletUseCase.reactivateWallet(reactivationToken) for info).
    Call example:

getReactivationTokenUseCase.requestReactivationToken(restorationPukEditText.text.toString())
            .subscribe({ response ->
                if (response.header != null && response.header?.isSuccess()) {                 
                    repository.walletClient.state = WalletClientState.REACTIVATION_WALLET
                }
                if (response.payload != null) {
                    repository.reactivateWallet().subscribe({ response ->
                        stopProgressDialog()
                        if (response.header != null && response.header?.isSuccess()!!) {
                            repository.walletClient.cachedReactivationToken = null
                            HorizonApplication.appToken = response.payload?.applicationToken
                            HorizonApplication.serverPublicKey = response.payload?.serverPublicKey
                            repository.walletClient.state = WalletClientState.ACCOUNT_ACTIVATED
                        }
                        val payload = response.payload
                        if (payload != null) {                        
                            // Insert your succes code
                        }                     
                    }, {                      
                        stopProgressDialog()
                    })               
            }, {
                // Throwable
            })
  • GetWalletActivationUseCase.checkWalletActivation()
    Check if account is activated. If returns 401, account is not activated yet.
    Returns credit info.
    Call example:
getWalletActivationUseCase.checkWalletActivation().subscribe({
            if (it.header != null && it.header?.isSuccess()) {
                // Account activated
                // Insert your code here
            }          
        }, {
            // Throwable
        })

Add Payment Methods

with our SDK the consumer is able to add multiple methods of payment to your app. The following example will focus on adding a credit card.

1107
  • AddPaymentCardUseCase.addPaymentCard(paymentCard) function:
    Takes a payment card info and returns wallet info with all credit cards and bonus programs.
    Return WalletResponse and CardDetailsResponse that handle verification data of credit card(redirectionUrl, md, paReq, termUrl).
    Call example:
val paymentCard = PaymentCard(
                cardNumberEditText.text.toString(),
                cardHolderEditText.text.toString(),
                cardDateExpireEditText.text.toString(),
                cardCvcEditText.text.toString())
addPaymentCardUseCase.addPaymentCard(paymentCard).subscribe({                 
                    if (it.header != null && it.header?.isSuccess()) {
                        it.payload?.walletData?.paymentCards?.lastOrNull()?.let { paymentCard ->
                            it.payload?.paymentCardData?.let { creditCard ->
                                 // Insert your code here
                                )
                            }
                        }
                    }
								}, {
                // Throwable
            })
  • SendVerificationRequestUseCase.sendVerificationRequest(context, redirectionUrl ,md ,paReq ,termUrl)
    Takes context, redirection URL, md, paReq, termUrl from CardDetailsResponse(response from AddPaymentCardUseCase) and returns is it request a success and a data response(See ExecuteAddCardUseCase for more details of the parameters).
    Call example:
cardData: CardDetailsResponse
sendVerificationRequestUseCase.sendVerificationRequest(
  					context, 
            cardData.redirectionUrl,
            cardData.postDataMD,
            cardData.postDataPaReq,
            cardData.postDataTermUrl
					) { success, data ->
                if (success) {
                    // Insert success code.                   
                } else {
                    // Insert fail code.
                }
            }
  • ExecuteAddCardUseCase.executeAddCard(cardId, paymentId, shopId, md, paRes)
    Takes a card ID, payment ID, shop ID, md and paRes and returns paymentCards, dailyToken, credit, participatingBonusPrograms and couponPrograms.
    - The variable paymentId and shopId containing the value from CardDetailsResponse.
    - The variable PaReq containing the value of PaReq received from the 3dscheck call.
    - The variable TermUrl containing the value of a return URL for 3DS handling on your server.
    - The variable MD containing a unique value for the order (like an order ID).
executeAddCardUseCase.executeAddCard(
            cardId,
            paymentId,
            shopId,
            md,
            paRes
        ).subscribe({
            // Check success
        }, {
            // Display error
        })
  • UpdateCardUseCase.updateCard(cardId, cardName)
    Takes card ID and card name and returns wallet data.
    Call example:
updateCardUseCase.updateCard(cardId, cardName).subscribe({
            if (it.payload != null) {
               // Insert your code here
            }
        }, {
            // Throwable
        })
  • RemoveCardUseCase.removeCard(cardId)
    Takes card ID and returns wallet data.
    Call example:
removeCardUseCase.removeCard(cardId).subscribe({
            if (it.payload != null) {
               // Insert your code here
            }
        }, {
            // Throwable
        })

Payment Process

Our SDK allows a simple and intuitive payment process. The consumer can select the payment method of choice and add a tip to the payment. This is what i could look like in the app:

1184
  • CheckPaymentUseCase.checkPayment(sessionId, cardId, deviceId)
    Takes a session ID, card ID and device ID and returns Invoice, encryptedAes, merchantImageUrl, merchantSharingText, requestTimeout.
    Call example:
checkPaymentUseCase.checkPayment(sessionId, cardId, deviceId)?.subscribe({      
            if (it.payload != null) {
               // Insert your code here for success.
            } else {
               // Insert your code here for fail.
            }
         },{
             // Throwable
          })
  • ExecutePaymentUseCase.executePayment(sessionId, tip, invoice, aes)
    Takes session ID, tip, invoice and aes(invoiceString and encryptedAes parameters from CheckPaymentResponse) and returns sessionState, paymentConfirmation, paymentOrder.
    Call example:
executePaymentUseCase.executePayment(sessionId, tip, checkPaymentResponse.invoiceString, checkPaymentResponse.encryptedAes)
            ?.subscribe({ response ->
                if (response.payload != null) {
                    if (payload.paymentSessionState == PaymentSessionState.PAYMENT_EXECUTED) {
                        bluetoothCommands?.paymentCompletedCommand({
                            paymentFinished()
                            callback.invoke(true)
                        }, {
                            paymentFinished()
                            callback.invoke(false)
                        })
           			 }, {
                		 sendPaymentFailed()
               			 callback.invoke(false)
           			 })

Show transactions, merchants, wallet and user data

The following use cases are focusing on:

  1. displaying the transaction list and the details to a payment
  2. showing the available merchants
  3. presenting the wallet home screen
  4. and the user data as well as updating the user data
1237
  • GetTransactionsUseCase.getTransactions()
    Returns transactions list.

  • GetTransactionDetailsUseCase.getTransactionDetails(sessionId)
    Takes session ID and returns invoiceDictionary, invoiceData, invoiceAmendments, merchantImageUrl, transaction.
    Call example:

getTransactionDetailsUseCase.getTransactionDetails(sessionId)
            .subscribe({
               	// Insert your code here
            }, {
                // Throwable
            })
  • GetMerchantsUseCase.getAllMerchants()
    Returns all merchants list.

  • GetWalletUseCase.getWallet()
    Returns paymentCards, dailyToken, credit, participatingBonusPrograms

  • GetUserInfoUseCase.getUser()
    Returns accountData.

  • UpdateUserDataUseCase.updateUserData(accountDataResponse, firstName, lastName, phoneNumber)
    Takes account data response, first name, last name and phone number and returns account data for user.
    Call example:

updateUserDataUseCase.updateUserData(accountDataResponse
            accountFirstNameText.text.toString(),
            accountLastNameText.text.toString(),
            accountPhoneNumberText.text.toString()
        )?.subscribe({
            // Insert your success code.
        }, {
            // Insert your fail code.
        })

Loyalty Program

An additional feature of the SDK is the loyalty program which enables you to integrate bonus points for your consumers.

  • ExecuteRedemptionUseCase.executeRedemption(redemptionId)
    Takes redemption ID and returns redemptionState, bonusProgram.

  • GetBonusProgramUseCase.getBonusPrograms()
    Returns bonus programs list.

  • GetRedemptionStateUseCase.getRedemptionState(redemptionId)
    Takes redemption ID and returns redemptionState, bonusProgram.

  • GiveBonusPointsUseCase.giveBonusPoints(bonusProgramId, points)
    Takes bonus program ID and points and returns bonusProgram info.

  • SetBonusProgramUseCase.setBonusProgramParticipationState(bonusProgramId, state)
    Takes bonus program ID and state and returns bonusPrograms list.
    Call example:

setBonusProgramUseCase.setBonusProgramParticipationState(id, newState).subscribe({
                    val payload = it.payload?.bonusPrograms
                    payload?.forEach { bonusProgram ->
                        if (bonusProgram.id == id) {
                            //Insert code for each bonus program.
                        }
                    }
                }, {
  									// Throwable
                })