Skip to main content

Recommended integration

IMPORTANTE

Starting with version 2.1.0, changes were made to the integration of the Izipay SDK into an Android application. If you are using a version earlier than 2.1.0, please refer to section Old integration.

This guide provides detailed technical information on integrating the SDK into an Android application. Be sure to follow the steps and considerations below for a successful integration.

Step 1: Download the SDK

  1. Download the SDK file here.

  2. Once on the link, click the download button to get the SDK file in compressed format.

  3. Unzip the downloaded file to a location of your choice on your development machine.

Step 2: Integrating the SDK into your project

First, you need to add the SDK to your Android application project. To do this, create a folder called "libs" inside the corresponding directory and copy the library (AAR) into that folder.

Paso 3: Dependency Management with libs.versions.toml

This project now uses libs.versions.toml for centralized version and dependency management in Gradle. and dependencies in Gradle. Library versions are defined in the gradle/libs.versions.toml file. To add or update dependencies, edit this file instead of doing it directly in build.gradle. directly in build.gradle.kts.

[versions]
agp = "8.1.0"
kotlin = "1.9.24"
navigation-safeargs = "2.5.3"
appcompatVersion = "1.7.0"
balloonVersion = "1.5.2"
constraintVersion = "2.2.0"
espressoCoreVersion = "3.5.1"
gsonVersion = "2.11.0"
hiltVersion = "2.55"
junit = "1.1.5"
junitVersion = "4.13.2"
ktxVersion = "1.15.0"
lifecycleViewmodelKtxVersion = "2.8.7"
materialVersion = "1.12.0"
navigationVersion = "2.8.5"
powerspinnerVersion = "1.2.4"
retrofitVersion = "2.9.0"
kotlin-kapt = "1.9.10"
glballoonide = "1.5.2"
glide = "4.14.2"
[libraries]
androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompatVersion" }
androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "constraintVersion" }
androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "ktxVersion" }
androidx-espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "espressoCoreVersion" }
androidx-junit = { module = "androidx.test.ext:junit", version.ref = "junit" }
androidx-lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtxVersion" }
androidx-navigation-fragment-ktx = { module = "androidx.navigation:navigation-fragment-ktx", version.ref = "navigationVersion" }
androidx-navigation-ui-ktx = { module = "androidx.navigation:navigation-ui-ktx", version.ref = "navigationVersion" }
balloon = { module = "com.github.skydoves:balloon", version.ref = "balloonVersion" }
converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "retrofitVersion" }
converter-scalars = { module = "com.squareup.retrofit2:converter-scalars", version.ref = "retrofitVersion" }
gson = { module = "com.google.code.gson:gson", version.ref = "gsonVersion" }
hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hiltVersion" }
hilt-compiler = { module = "com.google.dagger:hilt-compiler", version.ref = "hiltVersion" }
junit = { module = "junit:junit", version.ref = "junitVersion" }
material = { module = "com.google.android.material:material", version.ref = "materialVersion" }
powerspinner = { module = "com.github.skydoves:powerspinner", version.ref = "powerspinnerVersion" }
retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofitVersion" }
glide = {group = "com.github.bumptech.glide", name = "glide", version.ref = "glide"}
glballoonide = {group = "com.github.skydoves", name = "balloon", version.ref = "glballoonide"}
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
android-library = { id = "com.android.library", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
navigation-safeargs = { id = "androidx.navigation.safeargs", version.ref = "navigation-safeargs" }
dagger-hilt = { id = "com.google.dagger.hilt.android", version.ref = "hiltVersion" }
kotlin-kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin-kapt" }

Paso 4: Modify the build.gradle of the "APP"

We go to build.gradle of the app and put the following lines of code.

plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.kapt)
alias(libs.plugins.dagger.hilt)
alias(libs.plugins.navigation.safeargs)
}

dependencies {
implementation files('../libs/izipay-pw-sdk-scroll.aar')
implementation files('../libs/sonic-sdk-release-1.4.0.aar')
implementation files('../libs/visa-sensory-branding-2.1.aar')
implementation files('../libs/TMXBehavioralBiometrics-RL-6.3-77.aar')
implementation files('../libs/TMXDeviceSecurityHealth-RL-6.3-77.aar')
implementation files('../libs/TMXProfilingConnections-RL-6.3-77.aar')
implementation files('../libs/TMXProfiling-RL-6.3-77.aar')
implementation libs.androidx.core.ktx
implementation libs.androidx.appcompat
implementation libs.material
implementation libs.androidx.constraintlayout
implementation libs.androidx.navigation.fragment.ktx
implementation libs.androidx.navigation.ui.ktx
implementation libs.hilt.android
kapt libs.hilt.compiler
implementation libs.powerspinner
implementation libs.balloon
implementation libs.glide
implementation libs.glballoonide
implementation libs.gson
implementation libs.retrofit
implementation libs.converter.gson
implementation libs.converter.scalars
implementation libs.androidx.lifecycle.viewmodel.ktx
testImplementation libs.junit
androidTestImplementation libs.androidx.junit
androidTestImplementation libs.androidx.espresso.core
}

Paso 5: Modify the build.gradle of the "Project"

If you have already configured the Dagger Hilt, Navegation SafeArgs and Kapt libraries in your project, you can skip this step. project, you can skip this step. Otherwise we go to the build.gradle of the Project and put the following lines of code:

plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.android.library) apply false
alias(libs.plugins.kotlin.android) apply false
alias(libs.plugins.navigation.safeargs) apply false
alias(libs.plugins.dagger.hilt) apply false
alias(libs.plugins.kotlin.kapt) apply false
}

then click on the Sync Now button at the top right of the Android Studio.

(*) The highlighted button in the image is the Sync Now button.

Paso 6: Add @HiltAndroidApp file

If you have already added the @HiltAndroidApp annotation in your application, there is no need to repeat it. If it has not been added yet, in your App file you should add in the header the following line of code @HiltAndroidApp (If you don't have the file: App you should create one).

@HiltAndroidApp
class NombreDeTuArchivo: Application{
}
Tip

FileName is the name of your file and can look like this: SDKExampleApp

Send a CONFIGREQUEST object with these corresponding parameters

CONFIGREQUEST = {
data class ConfigRequest(
var environment: String?,
var action: String?,
var publicKey: String?,
var transactionId: String?,
var merchantCode: String?,
var facilitatorCode: String?,
var order: OrderPaymentIzipay?,
var token: TokenPaymentIzipay?,
var billing: BillingPaymentIzipay?,
var shipping: ShippingPaymentIzipay?,
var appearance: AppearencePaymentIzipay?,
var urlIPN: String?,
): Serializable

data class OrderPaymentIzipay(
var orderNumber: String?,
var currency: String?,
var amount: String?,
var payMethod: String?,
var channel: String?,
var processType: String?,
var merchantBuyerId: String?,
var dateTimeTransaction: String?
): Serializable

data class BillingPaymentIzipay(
var firstName: String?,
var lastName: String?,
var email: String?,
var phoneNumber: String?,
var street: String?,
var city: String?,
var state: String?,
var country: String?,
var postalCode: String?,
var documentType: String?,
var document: String?
): Serializable

data class ShippingPaymentIzipay(
var firstName: String?,
var lastName: String?,
var email: String?,
var phoneNumber: String?,
var street: String?,
var city: String?,
var state: String?,
var country: String?,
var postalCode: String?,
var documentType: String?,
var document: String?
): Serializable

data class AppearencePaymentIzipay(
var language: String? = "",
var formControls: AppearenceControlsPaymentIzipay?,
var visualSettings: AppearenceVisualSettingsPaymentIzipay?,
var theme: String? = "",
var customTheme: CustomThemePaymentIzipay?,
var logo: String? = "",
): Serializable

data class AppearenceVisualSettingsPaymentIzipay(
showMessageResult: Boolean? = false
)


data class AppearenceControlsPaymentIzipay(
var isAmountLabelVisible: Boolean? = false,
var isLangControlVisible: Boolean? = false,
): Serializable

data class CustomThemePaymentIzipay(
var payButtonBackgroundColor: String? = "",
var textInputBorderColor: String? = "",
var textInputPlaceholderTextColor: String? = ""
): Serializable

data class TokenPaymentIzipay(
var cardToken : String? = "",
): Serializable

}

You can send the request in the following way:

val intent = Intent(activity, ContainerActivity::class.java)
intent.putExtra(ContainerActivity.REQUEST, request) // request is an instance of CONFIGREQUEST
responseLauncher.launch(intent)
Important

Currently the SDK has two display modes: FullScreen Mode and Embedded Mode. Below you will see how both modes respond and also the steps to follow to implement the Embbedded mode.

6.1 FullScreen Screen Mode

To receive and implement, in fullscreen mode, the response of the "RESPONSE" object, the following lines of code must be added in the source code of the application. It is important to note that the response is a string in JSON format. To perform a correct reading of the response data, it is recommended to review the JSON examples provided in the use-cases chapter. These examples will serve as a reference to understand the structure of the data and to facilitate their manipulation in the implementation of the code

private val responseLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()){ result ->
val dataSignature = result.data?.getStringExtra(ContainerActivity.RESPONSESIGNTURE).orEmpty()
val dataPayLoad:PaymentResponse = Gson().fromJson(result.data?.getStringExtra(ContainerActivity.RESPONSEPAYLOAD).orEmpty(), object: TypeToken<PaymentResponse>(){}.type)

if(result.resultCode == AppCompatActivity.RESULT_OK){
val response = "$timeStamp :: $dataPayLoad->$dataSignature"
binding.etResponse.setText(response)
}else{
val response = "$timeStamp :: $dataPayLoad->$dataSignature"
binding.etResponse.setText(response)
}
}

6.2 Embedded Mode

Follow the steps below for the implementation of the Embedded mode:

  1. To employ the embedded mode, you start by adding the PayCallback class to the fragment that functions as the SDK container. Then, a libraryManager variable of type PayManager is created.
@AndroidEntryPoint
class HomeFragment : Fragment(), PayCallback {
private lateinit var libraryManager: PayManager
  1. Next, an instance of the PayManager class is created and assigned to the libraryManager variable. Then, the setCallback method is applied to the current context, since this context will be received by our PaymentsFragment (which is part of the SDK).
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {

binding = FragmentHomeBinding.inflate(inflater, container, false)

libraryManager = PayManager()
libraryManager.setCallback(this)
}
  1. Inside the intentActivity() method of your fragment that serves as the SDK container, create a Bundle object in which you include the request of type ConfigRequest. Then, invoke the PaymentsFragment as follows:
private fun intentActivity() {

val bundle = Bundle().apply {
putSerializable("data", request) //donde request es una instancia de ConfigRequest que ya esta llena de valores para el pago
}

val transaction = parentFragmentManager.beginTransaction()
var fragment = PaymentsObject.paymentsObject() as PaymentsFragment
fragment.arguments = bundle
fragment.payManager = libraryManager
transaction
.addToBackStack("HomeFragment")
.add(R.id.navContainer, fragment)
.commit()
}
  1. Implement the PayCallback interface in the fragment that acts as the SDK container, and overwrite the onDataFromPayments method as follows:
override fun onDataFromPayments(success: Boolean, pdata: PaymentResponse?, psignature:String?) {
if(success){
val response = "Success: True \n\nTra.ID: $timeStamp \n\nData: $pdata \n\nSignature: $psignature"
binding.etResponse.setText(response)
}else{
val response = "Success: False \n\nTra.ID: $timeStamp \n\nData: $pdata \n\nSignature: $psignature"
binding.etResponse.setText(response)
}

if (parentFragmentManager.backStackEntryCount > 0)
parentFragmentManager.popBackStack()
}

Note that the pdata, pdataSignature, and pdataPayload values are equivalent to those returned in fullscreen mode and are used in the same way.

Paso 7: Integration with sensory branding libraries

Copy the sensory branding libraries into the libs folder (together with the Izipay SDK).

Insert the following lines in the gradle file located at application level, as shown below:

dependencies {
implementation files('../libs/izipay-sdk-1.2.2.aar')

implementation files('../libs/sonic-sdk-release-1.4.0.aar')

implementation files('../libs/visa-sensory-branding-2.1.aar')

//Other dependencies

}
Important

Integration with sensory branding libraries is a mandatory step required by brands.