Android + PAM integration (English)
This book describes how to successfully integrate and communicate with the PAM from an Android application, in order to provide a mobile wagering application for clerks.
Introduction
Introduction
This document is intended to describe the requirements and flow to integrate the Mete y Gana (MG) web application with the GoPay android app. This document presents the details only regarding a wagering session.
A wagering session is the period where a clerk places wagers on a customer’s behalf with MG. The session ends when the customer has placed all desired wagers.
This document is based on the assumption that the MG site is embedded into the application as a WebView component, and considers the GoPay payment flow including messaging in three steps:
- Balance check: before proceeding with the operation.
- Wager confirmation: After confirming a wager.
- Session ended: customer leaves.
Integration basics
In order to support a wagering session, the MG site relies on bidirectional communication to be in place between the web app and the wrapper app.
Prerequisites
Prerequisites
- WebView JavaScript enabled
- Have access to MG private key in order to generate secure token logins
- Set up user agent in the app to be “android-go-pay”
Implementation Details
Authenticating the admin user without password
In order to authenticate a user into de MG app, a token needs to be generated with a certain payload. This token should follow the JWT RS256 format, in which, the payload would include a structure as follows:
{
sub: // adminUserName,
rol: // roles,
aid: // agentId,
nam: // name,
oth: // email,
tit: // title,
}
* The generated tokens log in an admin user if it existed, or creates one with the provided details if none existed.
Required Field description:
- Sub: The admin users name
- Rol: an array of roles to apply (typically, when creating clerks, the payload should be [*clerk]
- Aid: is the masterAgentId, this should be provided by MG
Other fields:
- Nam: Name of the user
- Oth: Email of the user
- Tit: Job title of the user
* These optional fields are descriptive only.
Creating Retail App URL
Retail app is constructed of a base path, plus two optional parameters.
The base path is https://pwallet.partner-domain.com/admin/pos/retail.
Optional query parameters:
- Token: the value for this query parameter should be generated securely with the private key provided in Prerequisites section #2, plus following the Authenticating the admin user without password
- customerId: if provided, we will initiate the session as the customer in question. If not the session will be started as a retail session.
- customerEmail: if provided the anonymous customer will be created or retrieved using this email
- customerPhone: if provided the customer will be created or retrieved using this phoneNumber
Notes:
- If provided, customerId will take precedence over the other attributes
- customerEmail and customerPhone will perform an OR operation in the database. If there were more than 1 customer associated to the same emails / phone number, there will be an error, which means the clerk wont be able to accomplish its task. We recommend using one or the other, but not both at the same time.
Examples:
- https://pwallet.meteygana.pe/admin/pos/retail?token=<authToken>
To be redirected to the retail mode with a newly created session - https://pwallet.meteygana.pe/admin/pos/retail?token=<authToken>&customerId=12345
To retrieve customer with id 12345 - https://pwallet.meteygana.pe/admin/pos/retail?token=<authToken>&customerEmail=test@domain.com
To retrieve customer with email test@domain.com - https://pwallet.meteygana.pe/admin/pos/retail?token=<authToken>&customerPhone=1234590
To retrieve customer with phon 1234590
Communication App to WebView details
References: https://developer.android.com/guide/webapps/webview
This implementation is used to send data from the Web Application to the wrapper application. In an empirical approach, you need to define a class that will handle the message sent.
/** Instantiate the interface and set the context */
class WebAppInterface(private val mContext: Context) {
/** Handles the JSON stringified object sent by the web application */
@JavascriptInterface
fun messagesHandler(data: String) {
// App logic goes here
}
}
* The `messagesHandler` is an example, not a method that should be implemented.
After this, you should add the Javascript interface with the recently created class from your WebView object.
mWebView.addJavascriptInterface(WebAppInterface(this), "AndroidInterface")
The second argument should always be AndroidInterface, since this is the name that we will be using to communicate from the web view to the wrapper in JavaScript.
The methods defined in the WebAppInterface class will be the ones that we use to interact with your application, so, you will be expected to create specific methods with specific responses. The implementation logic is at your discretion, provided we receive the expected response object format.
Interface methods
Important notice: Prerequisite #3 should be completed for this to work. If the user agent does not contain the ‘android-go-pay’ string, it will not emit any event.
Check Balance
This method sends out a balance request to GoPay that asks for confirmation that the wager amount is valid and may be used by the customer for the current wager session.
@JavascriptInterface
fun checkBalance(amount: Float, currency: String = "PEN") {
// Your logic
}
Before we proceed with wager placement, we must receive balance confirmation. Otherwise the wager will not be placed.
We expect a response message in the following format:
{
‘balance-check’: {
success: Boolean,
error?: Any, // This exists only when success is false, if extra data is needed to be sent.
data?: Any // This exists only when success is true, if extra data is needed to be sent.
}
}
Wager confirmation
This method receives two arguments, a json array of wagerIds (integers) and a totalAmount float value. This total amount will always be less than or equal to the amount previously confirmed in the checkBalance call.
@JavascriptInterface
fun wagersPlaced(wagerIds: IntArray, totalAmount: Float) {
// Your logic here
}
WagerIds represents one or many wagers, the totalAmount is the total amount wagered among all of those wagers.
This method is not expected to send any acknowledgement back to the web app. It’s just meant for conciliation between systems and to provide a mapping of financial transactions to wagers.
Session end
This method is called in the Web App whenever a clerk’s wagering interaction with a customer has completed. This will only occur if the receipt has been sent to the customer via email or text message.
This method, as with wager confirmation, expects no acknowledgement.
Communication WebView to App details
We communicate from the WebView to the Web app by invoking a postMessage call in the window object through JavaScript evaluation in the Android context.
webView.post(Runnable {
webView.evaluateJavascript("(function () { window.postMessage(object-defined-for-each-method); })();", null)
})
Response should be always as defined in each method, other messages will not work.