Integration via App to App call
For app-to-app launch mode, the MineSec SoftPOS App (MSA) accept android Intent
for various requests.
We provide a wrapper library - poslib
that wraps the essential APIs and data classes for the ease of integration.
Prerequisite
Before start integrating with the MSA app, you'll need:
- MSA App (DEMO): Get it from Play Store (opens in a new tab)
- MSA POS Lib
v1.2.4
Gradle setup
In your machine/ environment, set up the credential for downloading the sdk package:
# minesec client registry
MINESEC_REGISTRY_LOGIN=minesec-product-support
MINESEC_REGISTRY_TOKEN={token-value}
Please seek our customer support for the token.
In your project, (usually) the settings.gradle
or settings.gradle.kts
, setup the maven registry like the following:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
// MineSec's maven registry
maven {
val MINESEC_REGISTRY_LOGIN: String? by settings
val MINESEC_REGISTRY_TOKEN: String? by settings
requireNotNull(MINESEC_REGISTRY_LOGIN) {
"""
Please set your MineSec Github credential in `gradle.properties`.
On local machine,
** DO NOT **
** DO NOT **
** DO NOT **
Do not put it in the project's file. (and accidentally commit and push)
** DO **
Do set it in your machine's global (~/.gradle/gradle.properties)
""".trimIndent()
}
requireNotNull(MINESEC_REGISTRY_TOKEN)
name = "MineSecMavenClientRegistry"
url = uri("https://maven.pkg.github.com/theminesec/ms-registry-client")
credentials {
username = MINESEC_REGISTRY_LOGIN
password = MINESEC_REGISTRY_TOKEN
}
}
}
}
dependencies {
// ... other deps
implementation("com.theminesec.app:poslib:1.2.4")
}
PosLib Setups
Create POS API
Passing along your white label app's package name to the MsaPosApi
from the poslib:
private val msaPosApi = MsaPosApi(YOUR_MSA_PACKAGE_NAME)
Check App Install Status
Started from android 11 (API level 30) or higher, you'll need to include the <query>
in the manifest to query package info.
→ More on Android dev doc (opens in a new tab)
<queries>
<!--e.g.-->
<!--<package android:name="com.minesec.msa" />-->
<package android:name="{YOUR_MSA_PACKAGE_NAME}" />
</queries>
Then you can check if the MSA app is installed on the device:
// require context for packageManager
// can pass in activity or compose view localContext
msaPosApi.isSoftPosInstalled(context)
Call gesture
The POS lib currently provides the ActivityResultContract
(opens in a new tab) for the following MSA operations:
- Activation: to activate the app and load configs from the backend
- WarmUp: to warm up the SoftPOS app, perform the runtime checking on device and application
- Transaction: to perform a transaction like sale, void, or refund
- Enquiry: to check the previous transaction status
- Settlement: to settle all the batch under the merchant
Generally you'll want to register for the activity result in either your activity or in compose scope with:
// [Activity] Register with the contract first
val someOperationLauncher = registerForActivityResult(operationContract) { result ->
// handle the activity result here
when (warmUpResult) {
is PosResponse.Failed -> {
/* handle failed */
}
is PosResponse.Success -> {
/* handle success */
}
}
}
// [Compose Scope] Remember the launcher to avoid redundant instantiation during re-composition
val someOperationLauncher =
rememberLauncherForActivityResult(operationContract) { result ->
// handle the activity result here
when (warmUpResult) {
is PosResponse.Failed -> { /* handle failed */
}
is PosResponse.Success -> { /* handle success */
}
}
}
// in call site
fun triggerOperation() {
// optional data required for specific operation like the transaction amount
someOperationLauncher.launch(requiredData)
}
Warm Up
The WarmUp
calls the MSA to perform a series of runtime checking. It takes no argument.
// activity
private val warmUpLauncher = registerForActivityResult(msaPosApi.warmUpContract()) {
// handle the activity result here
}
// compose scope
val warmUpLauncher = rememberLauncherForActivityResult(msaPosApi.warmUpContract()) {
// handle the activity result here
}
// call site
fun triggerWarmUp() {
warmUpLauncher.launch()
}
Activation
The Activation
calls the MSA to activate the app, loads the necessary configs, like store information and EMV configs for later transaction.
Required the activationCode
// activity
private val activationLauncher = registerForActivityResult(msaPosApi.activationContract()) {
// handle the activity result here
}
// compose scope
val activationLauncher = rememberLauncherForActivityResult(msaPosApi.activationContract()) {
// handle the activity result here
}
// call site
fun triggerActivation(code: String) {
activationLauncher.launch(PosRequest.Activation(activationCode = code))
}
Transaction
Initiate a transaction request, including the SALE
, VOID
, or REFUND
.
For new transaction SALE
, requires amount
field.
For void & refund request, requires the orgTranId
.
// activity
private val transactionLauncher = registerForActivityResult(msaPosApi.transactionContract()) {
// handle the activity result here
}
// compose scope
val transactionLauncher = rememberLauncherForActivityResult(msaPosApi.transactionContract()) {
// handle the activity result here
}
// call site
// sale request
fun triggerSaleTransaction(amount: BigDecimal, posMessageId: String) {
transactionLauncher.launch(
PosRequest.Transaction.Sale(
amount = amount,
// posMessageId - a reference from POS system, that will pass to MineSec backend for later query
posMessageId = posMessageId,
// auto dismiss the SoftPOS transaction result screen and return to Business App
autoDismissResult = true
)
)
}
// void request
fun triggerVoidTransaction(originalTransactionId: String, passcode: String, posMessageId: String) {
transactionLauncher.launch(
PosRequest.Transaction.Void(
orgTranId = originalTransactionId,
// posMessageId - a reference from POS system, that will pass to MineSec backend for later query
posMessageId = posMessageId,
// merchant admin passcode for void/ refund
adminPwd = passcode
)
)
}
Enquiry Transaction Status
To enquiry previous transaction by the transaction ID
// activity
private val enquiryTranLauncher = registerForActivityResult(msaPosApi.enquiryTranStatusContract()) {
// handle the activity result here
}
// compose scope
val enquiryTranLauncher = rememberLauncherForActivityResult(msaPosApi.enquiryTranStatusContract()) {
// handle the activity result here
}
// call site
fun triggerEnquiryTranStatus(orignalTranId: String) {
enquiryTranLauncher.launch(PosRequest.EnquiryTranStatus(orgTranId = orignalTranId))
}
Reload configuration
Force to reload EMV configurations and payment keys
// activity
private val reloadConfigurationLauncher = registerForActivityResult(msaPosApi.reloadConfigurationContract()) {
// handle the activity result here
}
// compose scope
val reloadConfigurationLauncher = rememberLauncherForActivityResult(msaPosApi.reloadConfigurationContract()) {
// handle the activity result here
}
// call site
fun reloadConfiguration() {
reloadConfigurationLauncher.launch()
}
Enquiry Bluetooth Connection Status
Obtain the Bluetooth connection status between phone and MPOS D177 device
// activity
private val enquiryBTConnectStatusLauncher = registerForActivityResult(msaPosApi.enquiryBTConnectStatusContract()) {
// handle the activity result here
}
// compose scope
val enquiryBTConnectStatusLauncher = rememberLauncherForActivityResult(msaPosApi.enquiryBTConnectStatusContract()) {
// handle the activity result here
}
// call site
fun enquiryBTConnectStatus() {
enquiryBTConnectStatusLauncher.launch()
}
Settlement
To settle all available batches:
// activity
private val settlementLauncher = registerForActivityResult(msaPosApi.settlementContract()) {
// handle the activity result here
}
// compose scope
val settlementLauncher = rememberLauncherForActivityResult(msaPosApi.settlementContract()) {
// handle the activity result here
}
// call site
fun triggerSettlement(posMessageId: String) {
settlementLauncher.launch(PosRequest.Settlement(posMessageId = posMessageId))
}
Response Code & Data Model
Refer to Response code for more details
Refer to Data Model for more details