Omise is a payment service provider currently operating in Thailand. Omise provides a set of clean APIs that help merchants of any size accept credit cards online.
Omise Android SDK provides Android bindings for the Omise Token and Source API as well as components for entering credit card information.
Hop into our forum (click the badge above) or email our support team if you have any questions regarding this SDK and the functionality it provides.
- Public key. Register for an Omise account to obtain your API keys.
- Android 4.1+ (API 16) target or higher.
- Android Studio and Gradle build system.
Card data should never transit through your server. We recommend that you follow our guide on how to safely collect credit information.
To be authorized to create tokens server-side you must have a currently valid PCI-DSS Attestation of Compliance (AoC) delivered by a certified QSA Auditor.
This SDK provides means to tokenize card data on end-user mobile phone without the data having to go through your server.
Add the following line to your project's build.gradle file inside the dependencies
block:
implementation 'co.omise:omise-android:3.0.0'
The simplest way to use this SDK is to integrate the provided CreditCardActivity
directly into your application. This activity contains a pre-made credit form and will
automatically tokenize credit card
information for you.
To use it, first declare the availability of the activity in your AndroidManifest.xml
file as follows:
<activity
android:name="co.omise.android.ui.CreditCardActivity"
android:theme="@style/OmiseTheme" />
Then in your activity, declare the method that will start this activity as follows:
private val OMISE_PKEY: String = "pkey_test_123"
private val REQUEST_CC: Int = 100
private fun showCreditCardForm() {
val intent = Intent(this, CreditCardActivity::class.java)
intent.putExtra(CreditCardActivity.EXTRA_PKEY, OMISE_PKEY)
startActivityForResult(intent, REQUEST_CC)
}
Replace the string pkey_test_123
with the public key obtained from your Omise dashboard.
After the end-user completes entering credit card information, the activity result callback will be called, handle it like so:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_CANCELED) {
// handle the cancellation
return
}
if (requestCode == REQUEST_CC) {
val token = data?.getParcelableExtra<Token>(EXTRA_TOKEN_OBJECT)
// process your token here
}
}
A number of results are returned from the activity. You can obtain them from the
resulting Intent
with the following code:
data.getStringExtra(OmiseActivity.EXTRA_TOKEN)
- The string ID of the token. Use this if you only needs the ID and not the card data.data.getParcelableExtra(OmiseActivity.EXTRA_TOKEN_OBJECT)
- The fullToken
object returned from the Omise API.data.getParcelableExtra(OmiseActivity.EXTRA_CARD_OBJECT)
- TheCard
object which is part of theToken
object returned from the Omise API.
If you need to build your own credit card form, components inside CreditCardActivity
can be used on their own. For example, the CreditCardEditText
can be used in XML in this way:
<co.omise.android.ui.CreditCardEditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
This component provides automatic spacing into groups of 4 digits as the user inputs their credit card number. Additionally the following utility classes are available from the SDK:
co.omise.android.ui.CreditCardEditText
- TheCreditCardEditText
class provides utility methods for validating and formatting credit card numbers.co.omise.android.ui.CardNameEditText
- TheCardNameEditText
class handles formatting and input type for card holder name.co.omise.android.ui.ExpiryDateEditText
- TheExpiryDateEditText
class handles formatting and date range limitation.co.omise.android.ui.SecurityCodeEditText
- TheSecurityCodeEditText
class handles formatting and input type for security code.
If you have built your own credit card form, you can use the SDK to manually tokenize the
card. First build the Client
and supply your public key this way:
private val client = Client("pkey_test_123")
Then construct the token request with values from your custom form:
val cardParam = CardParam(
name = "JOHN Doe",
number = "4242424242424242",
expirationMonth = 10,
expirationYear = 2020,
securityCode = "123")
val request = Token.CreateTokenRequestBuilder(cardParam).build()
And then send the request using the client
you have constructed earlier:
client.send(request, object : RequestListener<Token>{
override fun onRequestSucceed(model: Token) {
// you've got a Token!
}
override fun onRequestFailed(throwable: Throwable) {
// something bad happened
}
})
The Client
class will automatically dispatch the network call on an internal background
thread and will call listener methods on the thread that initially calls the send
method.
Another way to use the Omise Android SDK is to integrate the PaymentCreatorActivity
in order to allow users to create a payment source from the list of
sources available for the implementer.
To use it, first declare the availability of the activity in your AndroidManifest.xml file as follows:
<activity
android:name="co.omise.android.ui.PaymentCreatorActivity"
android:theme="@style/OmiseTheme" />
Then in your activity, declare the method that will start this activity as follows:
private val OMISE_PKEY: String = "pkey_test_123"
private val REQUEST_CC: Int = 100
private fun showPaymentCreatorActivity() {
val intent = Intent(this@CheckoutActivity, PaymentCreatorActivity::class.java)
intent.putExtra(OmiseActivity.EXTRA_PKEY, OMISE_PKEY)
intent.putExtra(OmiseActivity.EXTRA_AMOUNT, 150000L)
intent.putExtra(OmiseActivity.EXTRA_CURRENCY, "thb")
// you can retrieve your account's capabilities through the SDK (will be explained in a different section)
intent.putExtra(OmiseActivity.EXTRA_CAPABILITY, capability)
startActivityForResult(intent, REQUEST_CC)
}
Replace the string pkey_test_123
with the public key obtained from your Omise dashboard.
After the end user selects and creates a payment source, the activity result callback will be called; handle it as follows:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_CANCELED) {
// handle the cancellation
return
}
if (requestCode == REQUEST_CC) {
if (data.hasExtra(OmiseActivity.EXTRA_SOURCE_OBJECT)) {
val source = data?.getParcelableExtra<Source>(OmiseActivity.EXTRA_SOURCE_OBJECT)
// process the source here
} else if (data.hasExtra(OmiseActivity.EXTRA_TOKEN)) {
val token = data?.getParcelableExtra<Token>(OmiseActivity.EXTRA_TOKEN_OBJECT)
// process the token here
}
}
}
Two different results that could be returned are:
data.hasExtra(OmiseActivity.EXTRA_SOURCE_OBJECT)
- TheSource
object created by the payment creator.data.hasExtra(OmiseActivity.EXTRA_TOKEN)
- TheToken
object created in case the payment source created was a credit card.
If you need to create a payment source on your own and use it outside of the provided SDK context, you can do follow these steps. First build the Client and supply your public key in this manner:
private val client = Client("pkey_test_123")
Then construct the Source request:
val request = Source.CreateSourceRequestBuilder(25000L, "thb", SourceType.Installment.Bay)
.description("Item")
.email("[email protected]")
.storeId("id-123")
.storeName("Store")
.phoneNumber("06207658854")
.installmentTerm(3)
.build()
And then send the request using the client
you have constructed earlier and you will get a Source
object in response:
client.send(request, object : RequestListener<Source>{
override fun onRequestSucceed(model: Source) {
// you've got a Source!
}
override fun onRequestFailed(throwable: Throwable) {
// something bad happened
}
})
The Client
class will automatically dispatch the network call on an internal background thread and will call listener methods on the thread that initially calls the send method.
You can retrieve all of your capabilities and available payment sources through the SDK in the following manner.
First build the Client and supply your public key this way:
private val client = Client("pkey_test_123")
Then construct the Capability request:
val request = Capability.GetCapabilitiesRequestBuilder().build()
And then send the request using the client we constructed earlier:
client.send(request, object : RequestListener<Capability> {
override fun onRequestSucceed(model: Capability) {
// you have capabilities!
}
override fun onRequestFailed(throwable: Throwable) {
// something bad happened
}
})
The Client
class will automatically dispatch the network call on an internal background thread and will call listener methods on the thread that initially calls the send method.
If you wish to customize the elements on the CreditCardActivity
in order to
match your application's branding, you can do so by overriding the following styles
as shown in the snippet below:
AndroidManifest.xml
<activity
android:name="co.omise.android.ui.CreditCardActivity"
android:theme="@style/SampleTheme" />
style.xml
<style name="SampleTheme" parent="Theme.MaterialComponents">
<item name="android:editTextStyle">@style/SampleEditText</item>
<item name="materialButtonStyle">@style/SampleButton</item>
<item name="editTextLabelStyle">@style/SampleEditTextLabel</item>
<item name="editTextErrorStyle">@style/SampleEditTextError</item>
</style>
<style name="SampleEditText" parent="Widget.AppCompat.EditText">
<item name="android:textColor">#FFFFFFFF</item>
<item name="android:textColorHint">#B3FFFFFF</item>
<item name="android:textSize">12sp</item>
<item name="backgroundTint">#FFFFFFFF</item>
</style>
<style name="SampleEditTextLabel">
<item name="android:textColor">#B3FFFFFF</item>
<item name="android:textAppearance">@style/TextAppearance.AppCompat.Body1</item>
</style>
<style name="SampleEditTextError">
<item name="android:textColor">#FFFF0000</item>
</style>
<style name="SampleButton" parent="Widget.MaterialComponents.Button">
<item name="backgroundTint">#FFFFFFFF</item>
<item name="android:textColor">#FF000000</item>
</style>
And if you choose to customize the item text sizes for the lists in PaymentCreatorActivity
, you
can do so by overriding the following style.
AndroidManifest.xml
<activity
android:name="co.omise.android.ui.PaymentCreatorActivity"
android:theme="@style/SampleTheme" />
style.xml
<style name="SampleTheme" parent="Theme.MaterialComponents">
...
<item name="android:itemTextAppearance">@style/SampleItemTextAppearance</item>
</style>
<style name="SampleItemTextAppearance" parent="TextAppearance.AppCompat.Body1">
<item name="android:textSize">16sp</item>
<item name="android:textColor">#FFFFFF</item>
</style>
Some payment methods require the customer to authorize the payment via an authorization URL. This includes the 3-D Secure verification, Internet Banking payment, Alipay, etc. Omise Android SDK provides a built in class to handle the authorization.
To use it, first declare the availability of the activity in your AndroidManifest.xml
file as follows:
<activity
android:name="co.omise.android.ui.AuthorizingPaymentActivity"
android:theme="@style/OmiseTheme" />
Then in your activity, declare the method that will start this activity this way:
private fun showAuthorizingPaymentForm() {
val intent = Intent(this, AuthorizingPaymentActivity::class.java)
intent.putExtra(AuthorizingPaymentURLVerifier.EXTRA_AUTHORIZED_URLSTRING, AUTHORIZED_URL)
intent.putExtra(AuthorizingPaymentURLVerifier.EXTRA_EXPECTED_RETURN_URLSTRING_PATTERNS, EXPECTED_URL_PATTERNS)
startActivityForResult(intent, AUTHORIZING_PAYMENT_REQUEST_CODE)
}
Replace the string AUTHORIZED_URL
with the authorized URL that comes with the created charge and the array of string EXPECTED_URL_PATTERNS
with the expected pattern of redirected URLs array.
After the end-user completes the authorizing payment process, the activity result callback will be called, handle it in this manner:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == AUTHORIZING_PAYMENT_REQUEST_CODE && resultCode == RESULT_OK) {
val url = data?.getStringExtra(AuthorizingPaymentURLVerifier.EXTRA_RETURNED_URLSTRING)
// Use the redirected URL here
}
}
Some request methods allow the user to authorize the payment with an external app, for example Alipay. When a user would like to authorize the payment with an external app, AuthorizingPaymentActivity
will automatically open an external app. However merchant developers must handle the Intent
callback by themselves.
If you enable ProGuard, then add this rules in your ProGuard file.
-dontwarn okio.**
-dontwarn com.google.common.**
-dontwarn org.joda.time.**
-dontwarn javax.annotation.**
-dontwarn com.squareup.**
PCI-DSS standard requires the service to communicate in TLS 1.2 or higher using strong encryption suites. This means that every client must connect to Omise service with those valid suites. However TLS 1.2 support in Android depends on the Android OS version. Please follow the following instructions to add support for TLS 1.2 in your app.
You can use our SDK without any changes. The SDK already fully supports communication with the Omise Service using TLS 1.2 with the correct encryption suite.
These versions of the Android API do not support the required encryption suites out of the box. However Google Play Services
has the ProviderInstaller
API to add the required support. You may already use Google Play Services in your app; Google Play Services includes many common libraries used in Android apps including GCM, Analytics and more. You can add support for the proper encryption suite with Google Play Services by carrying out the following steps.
- Add Google Play Service Analytics to your app grade setting:
implementation 'com.google.android.gms:play-services-analytics:17.0.0'
- Ask the ProviderInstaller to install the encryption suites with the following code:
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
try {
ProviderInstaller.installIfNeeded(this)
} catch (e: GooglePlayServicesRepairableException) {
e.printStackTrace()
} catch (e: GooglePlayServicesNotAvailableException) {
e.printStackTrace()
}
}
Note: Google Play Services may not available on every brand or model. Please be mindful about Google Play Services compatibility.
These versions of the Android API do not support the required encryption suites which means that Android devices running those OS versions will not be able to securely connect to our services. We recommend that you drop support for those API versions.
Pull requests and bug fixes are welcome. For larger scope of work, please pop on to our forum to discuss first.