Android integration guide
- Add the the payment SDK to your application
- Initialize the SDK
- Make a payment
- Check the transaction status
This page provides information on how to:
- View our integration examples
- Customize the SDK
- Cancel a payment in progress
- Enable NFC feature
- Enable the card scanning feature
View our integration examples
You will find many examples of our SDK's integration codes in different languages in the Github repository.
Add the the payment SDK to your application
To add the payment SDK to your application, it is necessary to add the following dependency in your build.gradle
, :
implementation 'com.lyra:sdk:1.6.+'
We recommend to regularly update the payment SDK in order to guarantee optimal security of your payments.
To stay informed about new SDK releases, you can regularly check our GitHub repository .
Optimize the efficiency of our support service
Our SDK can send Sentry messages to our servers when an unusual situation or problem occurs. In this case, no sensitive data is transferred nor any data from your application.
Only if your minSdkVersion is <= 23, it is then necessary to follow the following procedure https://developer.android.com/studio/write/java8-support to allow Android devices <= 6 to benefit from sending sentry messages. When filtering sensitive data, our SDK uses Java8 code.
In summary, here are the changes you need to make to your app's build.gradle
:
// only if your minSdkVersion <= 23 android { compileOptions { // Flag to enable support for the new language APIs coreLibraryDesugaringEnabled = true // Sets Java compatibility to Java 8 sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } } dependencies { // Needed by coreLibraryDesugaringEnabled compileOptions coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.1.5") }
Initialize the SDK
As mentioned in the chapter on how the solution works , it is necessary to perform the SDK initialization when launching your application , typically in the onCreate
method of your main activity.
To do this, simply call the Lyra.initialize
method with the following parameters:
PARAMETER | FORMAT | Description |
---|---|---|
publicKey | String | Your public key (available in the |
options | HashMap | Map allowing you to configure the SDK: NFC, card scan |
Example of a call:
val options = HashMap<String, Any>() options[Lyra.OPTION_API_SERVER_NAME] = "MY_API_SERVER_NAME" Lyra.initialize(applicationContext, PUBLIC_KEY, options)
HashMap options = new HashMap(); options.put(Lyra.OPTION_API_SERVER_NAME, "MY_API_SERVER_NAME"); Lyra.INSTANCE.initialize(getApplicationContext(), PUBLIC_KEY, options);
The possible keys in this dictionary are:
Keys | Value format | Description | required |
---|---|---|---|
apiServerName | String | Name of the REST API server (available in | required |
cardScanningEnabled | Bool | Enables/Disables the camera scan functionality of the map. If not set, the functionality will be disabled. | Optional |
nfcEnabled | Bool | Enables/Disables the NFC card scanning functionality. If not set, the functionality will be disabled. | Optional |
Make a payment
Making a payment is divided into 2 steps: initializing the display of the form and processing the payment itself.
Initialize the display of the payment form
When the user decides to pay, you can initialize the payment form display.
To do this, you need to call your merchant server, to verify the user's purchases, and then generate a form identifier (called formToken
) by calling the Charge/createPayment Web Service (still from your merchant server). In this request, you need to pass a formTokenVersion
parameter that corresponds to the result of the SDK's getFormTokenVersion
method. The response from the Web Service or this form identifier must then be sent back to your mobile application.
Here is a sample code based on the Android code examples and the provided merchant server.
requestQueue.add(JsonObjectRequest(Request.Method.POST, "${SERVER_URL}/createPayment", paymentParams, Response.Listener { response -> //Extract the formToken from the serverResponse val answer = JSONObject(response).getJSONObject("answer") val formToken = answer.getString("formToken") //Now, call Lyra.process() with the formToken }, Response.ErrorListener { error -> //Please manage your error behaviour here Toast.makeText( applicationContext, "Error Creating Payment", Toast.LENGTH_LONG ).show() } ))
requestQueue.add(new JsonObjectRequest(Request.Method.POST, SERVER_URL + "/createPayment", getPaymentParams(), new Response.Listener<JSONObject>() { //Process merchant server response @Override public void onResponse(JSONObject response) { //Extract the formToken from the serverResponse JSONObject answer = new JSONObject(response).getJSONObject("answer"); String formToken = answer.getString("formToken"); //Now, call Lyra.process() with the formToken } }, new Response.ErrorListener() { //Error when calling merchant server @Override public void onErrorResponse(VolleyError error) { //Please manage your error behaviour here Toast.makeText(getApplicationContext(), "Error Creating Payment", Toast.LENGTH_LONG).show(); } }));
- The step of shopping cart validation is crucial. You must also check on your servers that the amount matches the amount in the cart before transferring it to us.
- Calling the Web Service from the mobile application is amounts to making your call keys available to it (and to potential hackers), which is contrary to the security rules.
Displaying the payment screen
Once the formToken
is received in the mobile app, you need to pass it to our Payment SDK by calling the Lyra.process
method with the following parameters:
PARAMETER | FORMAT | Description |
---|---|---|
supportFragmentManager | FragmentManager | Reference to your UI so that the SDK can display the payment form. |
formToken | String | The formToken, extracted from the previously called createPayment response. |
paymentHandler | LyraHandler | Callback to process the payment result. |
The SDK then checks the formToken consistency and displays the available payment methods.
Example of a call:
Lyra.process(supportFragmentManager, formToken, object : LyraHandler { override fun onSuccess(lyraResponse: LyraResponse) { verifyPayment(lyraResponse) } override fun onError(lyraException: LyraException, lyraResponse: LyraResponse?) { Toast.makeText( applicationContext, "Payment fail: ${lyraException.errorMessage}", Toast.LENGTH_LONG ).show() } })
Lyra.INSTANCE.process(getSupportFragmentManager(), formToken, new LyraHandler() { @Override public void onSuccess(LyraResponse lyraResponse) { verifyPayment(lyraResponse); } @Override public void onError(LyraException e, LyraResponse lyraResponse) { Toast.makeText(getApplicationContext(), "Payment fail: " + e.getErrorMessage(), Toast.LENGTH_LONG).show(); } });
The paymentHandler
is an interface that you need to implement and which contains 2 methods:
Description | |
---|---|
onSuccess | Called if the payment was successful. |
onError | This method is called if the payment failed or could not be initiated. This situation can occur if a functional (payment was refused) or technical error occurred during payment. To find out more, see: Error handling. |
Object descriptionLyraResponse
The same LyraResponse
object is returned in both cases: onSuccess
and onError
. It is a JSONObject object. In case of success, its integrity must be checked before displaying the payment result.
In case the transaction was initiated on the server side, it will be possible to simply retrieve the payment details.
Example: .
{ "kr-hash":"80f5188e757c1828e8d4ccab87467eb50c4299e4057fa03b3f3185342f6d509c", "kr-hash-algorithm":"sha256_hmac", "kr-answer-type":"V4\/Payment", "kr-answer": "{ "shopId":"65512466", "orderCycle":"CLOSED", "orderStatus":"PAID", "serverDate":"2019-03-01T10:54:45+00:00", "orderDetails":{ "orderTotalAmount":1100, "orderEffectiveAmount":1100, "orderCurrency":"EUR", "mode":"TEST", "orderId":null, "_type":"V4\/OrderDetails" }, "customer":{ "billingDetails":{ "address":null, "category":null, "cellPhoneNumber":null, ... }, "email":null, "reference":null, "shippingDetails":{ "address":null, "address2":null, "category":null, ... }, "extraDetails":{ "browserAccept":null, "fingerPrintId":null, "ipAddress":"77.136.84.251", "browserUserAgent":"{\"deviceName\":\"Xiaomi Mi MIX 2S\",\"os\":\"Android\",\"osVersion\":\"[9]\",\"sdkVersion\":28,\"isMobile\":true}", "_type":"V4\/Customer\/ExtraDetails" }, "shoppingCart":{ "insuranceAmount":null, "shippingAmount":null, "taxAmount":null, "cartItemInfo":null, "_type":"V4\/Customer\/ShoppingCart" }, "_type":"V4\/Customer\/Customer" }, "transactions":[ { "shopId":"65512466", "uuid":"64d704a9bb664898954c3ef537982f99", "amount":1100, "currency":"EUR", "paymentMethodType":"CARD", "status":"PAID", "detailedStatus":"AUTHORISED", "operationType":"DEBIT", "creationDate":"2019-03-01T10:54:44+00:00", ... } ], "_type":"V4\/Payment" }" }
The response contains the same elements as the ones sent in the IPN:
PARAMETER | Description |
---|---|
kr-hash | Hash of the JSON object stored in kr-answer. It allows to verify the authenticity of the response. |
kr-hash-algorithm | Algorithm used to calculate the hash. |
kr-hash-key | Key used for signing kr-answer. |
kr-answer-type | Type the JSON object stored in kr-answer. |
kr-answer | Object containing complete transaction objects encoded in JSON. |
The kr-answer
object contains the elements described here .
In some cases, it may be that the transaction could not be initiated on the server side. It will be possible to find the error returned by the API in the json (you can find the format here: Error codes ).
Check the transaction status
Once the payment has been finalized, regardless of whether was accepted or rejected, you will be notified in two 2 ways:
- via a call (IPN) to your merchant server, if you have correctly configured the notification rules,
- by the call of
paymentHandler
mobile application side.
It is necessary to check the integrity of the message (see here for more details) and to launch the business processing on the server side (when receiving the IPN).
Our code samples provide an example of message integrity checking through your merchant server. This is the endPoint verifyResult
called in the application's verifyResult
method.
Here is a sample code based on the Android code examples and the provided merchant server.
requestQueue.add(JsonObjectRequest(Request.Method.POST, "${SERVER_URL}/verifyResult", payload, Response.Listener { response -> //Check the response integrity by verifying the hash on your server Toast.makeText( applicationContext, "Payment success", Toast.LENGTH_LONG ).show() }, Response.ErrorListener { error -> //Manage error here, please refer to the documentation for more information Toast.makeText( applicationContext, "Payment verification fail", Toast.LENGTH_LONG ).show() } ))
requestQueue.add(new JsonObjectRequest(Request.Method.POST, SERVER_URL + "/verifyResult", response, new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { //Check the response integrity by verifying the hash on your server Toast.makeText(getApplicationContext(), "Payment Success", Toast.LENGTH_LONG).show(); } }, new Response.ErrorListener() { //Error when verifying payment @Override public void onErrorResponse(VolleyError error) { //Manage error here, please refer to the documentation for more information Toast.makeText(getApplicationContext(), "Payment verification fail", Toast.LENGTH_LONG).show(); } }));
Customize the SDK
Theme
It is possible to customize the SDK so that the views generated via the SDK (payment form) are displayed with the same colors and font as those used in your application.
You can define:
- One main color,
- A secondary color,
- the font to be used for all the texts that appear in the SDK.
The main color allows to modify:
- the header background color,
- The background color of the “Pay” button,
- the color of the word for closing the CVV tooltip pop-up,
- the color of the word for closing the brand selection pop-up,
- the color for highlighting the field and of its label when it is being edited,
- the color of the text in the payment in progress message,
- the color of the spinner in the current payment message.
The secondary color allows to change:
- the color of the arrow image for going back in the SDK header,
- the color of the texts in the SDK header,
- the text color of the “Pay” button.
To customize the colors, simply define them in your colors.xml file:
<color name="payment_sdk_PrimaryColor">#293C7A</color>
<color name="payment_sdk_SecondaryColor">#FFFFFF</color>
To customize the font you just need to override the necessary style in the filestyles.xml :
<style name="PaymentSDK_Theme">
<item name="android:fontFamily"></i>casual</item></style>
Texts
It is also possible to personalize certain texts. To do this, specify the optional "options" parameter when calling the Lyra.process()
.
PAY button
- The text of the PAY button can be customized.
Specify the key Lyra.CUSTOM_PAY_BUTTON_LABEL
.
Header
- If the text is forced and there is no orderId , it will replace the default text which is "Payment" or "Card Registration".
- On the other hand, if a orderId is specified then we will continue to display "Order OrderId ".
Specify the key Lyra.CUSTOM_HEADER_LABEL
.
Payment popup
- The popup text that opens when clicked PAY button can also be customized.
Specify the key Lyra.CUSTOM_POPUP_LABEL
.
Lyra.process(supportFragmentManager, formToken, LyraHandler, hashMapOf(Lyra.CUSTOM_PAY_BUTTON_LABEL to "MyPayButtonLabel", Lyra.CUSTOM_HEADER_LABEL to "MyHeaderLabel", Lyra.CUSTOM_POPUP_LABEL to "MyPopupLabel"))
Cancel a payment in progress
It is possible to cancel a payment in progress using the Lyra.cancelProcess()
method. In general, this method exits the payment form correctly, but there are different scenarios:
- The payment process can be cancelled:
- the payment form closes correctly.
- the
handler onError
who passed toLyra.process()
is called with the errorMOB_009 - Payment cancelled, indicating that the payment process has been canceled.
- The payment process cannot be canceled. If the
Lyra.cancelProcess()
is invoked while the SDK is communicating with the payment platform (the user has just clicked the pay button):
- the payment form remains displayed.
- the
handler onError
who passed toLyra.process()
is called with the errorMOB_013 - Payment cannot be cancelledindicating that the payment process cannot be canceled. - normal SDK behavior continues:
- if the payment completes correctly then the
handler onSuccess
will be called. - if the payment is unsuccessful. Depending on the error, the payment form remains displayed or the
handler onError
will be called.
- if the payment completes correctly then the
- If there is no payment process in progress, calling
Lyra.cancelProcess()
will have no effect.
Enable NFC feature
It is possible, in the SDK, to activate the NFC functionality. This feature allows a user not to enter his card information manually but to use NFC to scan it and automatically fill in the payment form.
To enable this feature, you need to:
- When initializing the SDK, sendtrueas value for key
nfcEnabled
in the configuration options (SeeInitialize the SDK).
options[Lyra.OPTION_NFC_ENABLED] = true
options.put(Lyra.OPTION_NFC_ENABLED, true);
- Add the following permission to the file
AndroidManifest.xml
of your application:
<uses-permission android:name="android.permission.NFC" />
Enable the card scanning feature
It is possible, in the SDK, to enable the card scanning functionality by camera. This feature allows a user to not enter his card information manually but use the camera of his mobile device to scan it and automatically fill in the payment form.
To enable this feature, you need to:
- Integrate the library
CardsCameraRecognizer
in your Android project by adding the following dependency to yourbuild.gradle
:
// Lyra Cards Camera Recognizer SDK
implementation 'com.lyra:cards-camera-recognizer:1.0.+'
- When initializing the SDK, sendtrueas value for key
cardScanningEnabled
in the configuration options (SeeInitialize the SDK).
options[Lyra.OPTION_CARD_SCANNING_ENABLED] = true
options.put(Lyra.OPTION_CARD_SCANNING_ENABLED, true);
Note that the following permissions will be directly added to the AndroidManifest.xml
file when compiling the project:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-feature android:name="android.hardware.CAMERA" android:required="false" />
<uses-feature android:name="android.hardware.camera.AUTOFOCUS" android:required="false" />