DocumentationRecipesAPI ReferenceChangelog
Documentation

Payment

Transaction API supports SALE and PRE-AUTH operations. This endpoint is used to initiate a new transaction.

You can integrate in two UI environments:

  1. Traditional Activity / Fragment UI
  2. Modern Jetpack Compose UI

Payment Request

To initiate a Payment ( Sales or Preauth ) request, follow the examples below

Option 1 : Payment in Activity or Fragment

class PaymentActivity : AppCompatActivity() {

    private val transactionLauncher = registerForActivityResult(msaPosApi.transactionContract()) { result ->
        when (result) {
            is PosResponse.Success -> {
              val txn = result.data
							// handle success

            }
            is PosResponse.Failed -> {
              	// handle fail
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_payment)

        // Sample values
        val amount = BigDecimal("25.50")
        val posMessageId = "POS123456789"

        triggerSaleTransaction(amount, posMessageId)
    }
    	
		// for Sales Transaction
    private fun triggerSaleTransaction(amount: BigDecimal, posMessageId: String) {
        val saleRequest = PosRequest.Transaction.Sale(
            amount = amount,
            posMessageId = posMessageId,
            autoDismissResult = true
        )
        transactionLauncher.launch(saleRequest)
    }

    // for Auth Transaction
    private fun triggerAuthTransaction(amount: BigDecimal, posMessageId: String) {
        val authRequest = PosRequest.Transaction.Auth(
            amount = amount,
            posMessageId = posMessageId,
            autoDismissResult = true
        )
        transactionLauncher.launch(authRequest)
    }

    // for QR Transaction
    private fun triggerQRSaleTransaction(amount: BigDecimal, posMessageId: String) {
        val qrSaleRequest = PosRequest.Transaction.Auth(
            amount = amount,
            posMessageId = posMessageId,
          	autoDismissResult = true,
          	preferredInstrument = PreferredInstrument.QR_GUEST_SCAN,
						qrPaymentMethods = null
        )
        transactionLauncher.launch(qrSaleRequest)
    }

}

Option 2 : Payment in Jetpack Compose

@Composable
fun PaymentScreen(msaPosApi: MsaPosApi) {
    val context = LocalContext.current
    val transactionLauncher = rememberLauncherForActivityResult(
        msaPosApi.transactionContract()
    ) { result ->
        when (result) {
            is PosResponse.Success -> {
              val txn = result.data
              // handle success
							// save tran_id from response to use with void if required

            }
            is PosResponse.Failed -> {
                // handle failed
            }
        }
    }

    val amount = BigDecimal("45.00")
    val posMessageId = "POS_QR_GUEST_001"

    Button(onClick = {
        val qrRequest = PosRequest.Transaction.Sale(
            amount = amount,
            posMessageId = posMessageId,
            autoDismissResult = true,
            preferredInstrument = PreferredInstrument.QR_GUEST_SCAN,
            qrPaymentMethods = null
        )

        transactionLauncher.launch(qrRequest)
    }) {
        Text("Pay via QR Guest Scan")
    }
}

Payment Response

{
 "rspCode" : "0",
 "rspMsg": "Success",
 "data" : {
  "tranId": "M9279873298",
  "trace": "M9279873298",
  "rrn": "897323",
  "tranType": "SALE",
  "tranStatus": "Approved",
  "approvalCode": "979384",
  "paymentMethod": "Visa",
  "cardData" : {
    "aid": "",
    "appName": "",
    "tc": "",
    "tsi": "",
    "tvr": ""
  },
  "entryMode" : "NFC",
  "maskedAccount": "**** **** **** 1234",
  "cvmPerformed": "NO_CVM",
  "acqMid": "MID98392",
  "acqTid": "0001",
  "posMessageId": "{merchant unique reference no}",
  "mchAddress": "",
  "mchName": "2C2P Pte Ltd",
  "totalAmount": 60.00,
  "createByName": "",
  "createdAt": "1744687184773",
  "updatedAt": "1744687184773"
 }
}

Response: PosResponse<T>

All responses from the POS Lib return as a sealed class:

sealed class PosResponse<T>(val rspCode: String, val rspMsg: String) : Serializable

Sub Types

TypeDescription
Success<Unit>Response: Completed successfully
Failed<Unit>Response: failed. Use rspCode, rspMsg for debugging

Successful Transaction Response

data class TransactionResponse(
    val tranId: String,
    val tranType: String,           // SALE, VOID, etc.
    val tranStatus: String,         // Approved, Declined, etc.
    val rrn: String,                // Reference number
    val approvalCode: String,
    val paymentMethod: String,      // Visa, MasterCard, etc.
    val maskedAccount: String,
    val totalAmount: BigDecimal,
    val posMessageId: String,
    val acqMid: String,
    val acqTid: String,
    val entryMode: String,
    val trace: String,
    val cardData: CardData,
    val cvmPerformed: String,
    val mchName: String,
    val mchAddress: String,
    val createdAt: String,
    val updatedAt: String
)
Status Reference
FieldDescription
tranTypeSALE / VOID / REFUND / AUTH
tranStatusApproved / Declined / Processing / Voided / Reversed
rrnHost-generated reference number (ARN)
tranIdUnique ID from backend
posMessageIdYour reference ID for tracking
approvalCodeApproval code from issuer
maskedAccountMasked card number

Card Data Object

data class CardData(
  val aid: String,
  val appName: String,
  val tc: String,
  val tsi: String,
  val tvr: String,
)