Requirements
- Android 5.0 (API level 21) and above
- Android Gradle Plugin 3.5.1
- Gradle 5.4.1+
- AndroidX (as of v11.0.0)
Installation
Add io.elements.pay:core-module
to your build.gradle
dependencies.
Gradle
dependencies {
implementation 'io.elements.pay:core-module:1.0.7'
}
Usage
ElementsApiClient
The ElementsApiClient
handles the low level api communications to Elements server. i.e. Card Tokenization
Initialize the API client.
The api client requires clientToken
fetched from your backend server. Once you have obtained your clientToken
you can initialize the api client in the following way.
// Environment -> The environment that ElementsApiClient runs.
// StripeTestKey -> Optional if you want to take fall back to Stripe tokenization
// if elements tokenization failed
val configuration = ElementsApiClientConfiguration(
Environment.sandbox(clientToken)
)
val elementsApiClient = ElementsApiClient(configuration = configuration)
In order to call the tokenize api, you need to create and pass in ElementsCardParams
object, example:
val cardParams = ElementsCardParams(
cardNumber = "424242424242",
expiryMonth = 4,
expiryYear = 24,
securityCode = "242",
holderName = "Test"
)
Once you have created the ElementsAPIClient
and ElementsCardParams
you can call the following to tokenize a card.
elementsApiClient.tokenizeCard(cardParams, callback = object : ApiResultCallback<VaultToken> {
override fun onSuccess(result: VaultToken) {
Log.d("Your Logger Tag", "Tokenization succeeded $result")
result.elementsToken?.let {
// Now you can pass this token object to your backend server
}
result.fallbackStripToken?.let {
// If Elements tokenization failed, a stripe token will be generated if you have provided the `stripePublishableKey`
// You can pass the stripe key to your backend server as a fall back.
}
}
override fun onError(e: Exception) {
// Check ElementsException for tokenization failure.
Log.d("Your Logger Tag", "Tokenization failed $e")
}
})
ElementsToken
The ElementsToken
model returns the response received from Elements server once tokenization succeeded. It contains the corresponded elements token matching the ElementsCardParams
you passed in the method. It will also contain an ElementsCard
object that has the tokenized card info.
ElementsToken(
id = tok_xxxxxxxxxxxxxxxx
card = ElementsCard(
id = card-9a06775f-d4d7-4413-8fed-379ac610283e,
last4 = 4242,
expiryMonth= 4,
expiryYear = 2024,
brand = VISA,
fingerprint = mhahtPiD6Yns0Nnyn82206DG1l17mxYIedFkWuQ6GUg=
)
)
3DS2 Flow
ElementsAPIClient
also supports tokenize card with 3DS2 auth flow enabled. In order to handle 3DS2 flow correctly you need to pass an activity
param to the tokenization method. This activity will be the host of all 3DS flow activities from Elements.
private fun tokenizeCard(cardParams: ElementsCardParams) {
client.tokenizeCard(cardParams, this, callback = object : ApiResultCallback<VaultToken> {
override fun onSuccess(result: VaultToken) {
result.elementsToken?.let {
Log.d("Tokenization succeeded", parseElementsTokenToDisplayString(it)).show()
}
result.fallbackStripToken?.let {
Log.d("Tokenization succeeded", "Stripe token $it").show()
}
}
override fun onError(e: Exception) {
Log.d("Your Logger Tag", "Tokenization failed $e")
}
})
}
You will also need to listen for 3DS result from onActivityResult
and obtain result from apiClient.
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
client.onTokenizationSetupResult(requestCode, data, object : ApiResultCallback<ElementsToken> {
override fun onSuccess(result: ElementsToken) {
Log.d("Your Logger Tag", "Tokenization succeeded $result")
}
override fun onError(e: Exception) {
Log.d("Your Logger Tag", "Tokenization failed $e")
}
})
}
Now the token you obtained from onActivityResult
will be a token validated through 3DS.
ElementsActionDriver
The ElemenetsActionDriver
handles Elements redirect payment methods, i.e. Paypal/Kakao/Klarna etc...
Initialize the action driver.
The action driver requires clientToken fetched from your backend server. Once you have obtained your client key you can initialize the action driver in the following way.
class YourActivity : AppCompatActivity() {
private val environment = Environment.sandbox(clientToken)
private lateinit var actionDriver: ElementsActionDriver
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//...
actionDriver = ElementsActionDriver(
this@YourActivity,
environment,
WeakReference(this)
)
//...
}
}
Setting up the required components.
Add return URL scheme
- You need to config the redirect URL scheme in your application manifest file.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.elements.sampleApp">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MyApplication">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
// Add this block into your manifest file
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
// This is important!!
<data
android:host="${applicationId}"
android:scheme="elements">
</data>
</intent-filter>
</activity>
</application>
</manifest>
- Handle redirect intent
private fun handleIntent(intent: Intent) {
when (intent.action) {
// Redirect response
Intent.ACTION_VIEW -> {
val data = intent.data
Logger.d("Your Logger Tag", "scheme: ${RedirectUtil.REDIRECT_RESULT_SCHEME}")
if (data != null && data.toString().startsWith(RedirectUtil.REDIRECT_RESULT_SCHEME)) {
actionDriver.handleRedirectResponse(data)
} else {
Logger.e("Your Logger Tag", "Unexpected response from ACTION_VIEW - ${intent.data}")
}
}
else -> {
Logger.e("Your Logger Tag", "Unable to find action")
}
}
}
call handleIntent in your activity
class MainActivity : AppCompatActivity() {
// ...
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
handleIntent(intent)
}
// ...
}
Implement ElementsActionDriver.ActionCompletionListener
// Elements SDK will trigger this function when redirect failed.
override fun elementsActionFailed(error: Exception) {
Logger.d("Your Logger Tag", "Action failed $error")
}
// Elements SDK will trigger this function when redirect succeeded and returns an element token.
override fun elementsActionSucceeded(chargeToken: String?) {
Logger.d("Your Logger Tag", "Action succeeded $chargeToken")
}
Start ElementsActionDriver
actionDriver.requestPaymentSetup("vipps") // Starts Vipps payment method
actionDriver.requestPaymentSetup("paypal") // Start Paypal payment method
Example App
Clone this repo and run the app. The demo app demonstrated how to use ElementsApiClient
.