交易模塊
調用流程
要使用
transactionFlowController
開發應用程序,建議您具備 EMV 交易流程方面的知識或經驗。
設置
創建一個實例,並通過 getControllerInstance()
and connectController()
連接到終端。
如果發生任何錯誤,應通過 onError
通知應用程序。
abstract class ApolloTransactionFlow(private val context: Context) : TransactionFlowDelegate {
private var transactionFlowController: TransactionFlowController? = null
fun connect(): Boolean {
try {
if (transactionFlowController == null) {
// get instance
transactionFlowController = getControllerInstance(context, this)
// enable debug log display in console
SPDeviceController.enableDebugLog(true)
}
// establish the communication channel with secure module
transactionFlowController?.connectController()
} catch (ex: Exception) {
return false
}
return true
}
fun disconnect() {
transactionFlowController?.disconnectController()
transactionFlowController?.releaseControllerInstance()
}
override fun onError(errorType: ControllerError.Error?, message: String?) {
// app handle error here
}
}
EMV 交易流程
開始交易
應用程序應將金額、貨幣、卡檢測模式和交易序列號(退款或取消)放入 Hashtable
中,並調用 startTransactionFlow
啟動 EMV 交易。
fun startTransactionFlow(mode: BaseCardController.CheckCardMode, amount: String, amountCashback: String?, transactionSequenceNumber: String?, currency: Currency) {
val data = Hashtable<String, Any>()
// eg. BaseCardController.CheckCardMode.SWIPE_OR_INSERT_OR_TAP
data["checkCardMode"] = mode
// ISO 4217 currency code eg. 344 for HKD
data["currencyCode"] = currency.numericCode.toString()
// decimal string, eg. 2.00 for $2.00
data["amount"] = amount
data["transactionType"] = TransactionType.GOODS
// indicate the transaction sequence number for refund or void
if (transactionSequenceNumber != null) {
data["transactionNo"] = transactionSequenceNumber
}
transactionFlowController?.startTransactionFlow(data)
}
打開讀卡器,在選擇的 CheckCardMode
中開始檢測任意卡。如果沒有檢測到卡的交互 (拍卡,插卡或者刷卡),應用將接收到 onCardInteractionDetecting
。
override fun onCardInteractionDetecting(p0: BaseCardController.CheckCardMode?) {
// app handle the UI here
}
於卡片檢測階段,您可以發送 abortDetection
來終止交易。 onTransactionStatusReceived
將以交易狀態返回給應用程序。
fun abortDetection() {
transactionFlowController?.abortDetection()
}
override fun onTransactionStatusReceived(p0: TransactionResult?) {
// display transaction result
}
應用程序選擇和讀取應用程序數據
如果該卡有多個支付應用,你的應用程序將收到帶有一系列 AID 的 onSelectAIDRequested
。應用程序應通過 selectAID()
選擇其中一個。
override fun onSelectAIDRequested(p0: ArrayList<String>?) {
p0?.let {
val items = it.toTypedArray()
// display a dialog for user to select AID
MaterialAlertDialogBuilder(context)
.setTitle("Select Application")
.setItems(items) { dialog, item ->
transactionFlowController?.selectAID(item)
dialog.dismiss()
}
.setCancelable(false)
.show()
}
}
選擇 AID 後,終端從卡中讀取必要的數據。
數據驗證和處理限制
然後終端使用該卡進行數據驗證和限制處理。如果任意一個失敗或被拒絕,應用程序將收到 onTransactionStatusReceived
。
override fun onTransactionStatusReceived(p0: TransactionResult?) {
// display transaction result
}
確認
在完成上述步驟後,應用程序將收到 onConfirmationRequested
。應用程序提示用戶進行確認,並將 sendConfirmation(true)
發送回終端。
override fun onConfirmationRequested() {
transactionFlowController?.sendConfirmation(true)
}
持卡人驗證(密碼)
EMV 交易中有不同的持卡人驗證方法(CVM),密碼輸入就是其中之一。
如果交易需要輸入密碼,應用程序將收到 onPinEntryRequested
。
override fun onPinEntryRequested(p0: PinEntrySource?) {
// app display UI to prompt user to enter PIN
}
終端風險管理
持卡人驗證後,交易進入終端風險管理。這一過程發生在終端和卡之間,如果失敗,應用程序將收到 onTransactionStatusReceived
。
終端和卡片行為分析
在此階段,終端應根據前面處理步驟的結果確定下一步操作。
聯機處理和腳本處理
如果該卡通過聯機進行身份驗證,應用程序將收到 onOnlineProcessingRequested
,並以 TLV 格式接收交易數據。應用程序應將數據格式化為收單方 / 收單機構指定的格式,例如 ISO8583、XML 或 JSON,並且發送到收單方/收單機構進行身份驗證,並等待響應。
override fun onOnlineProcessRequested(p0: String?) {
// app handle online processing here and get the online reply TLV data
}
一旦從收單方 / 收單機構獲得響應,應用程序應通過 sendOnlineProcessingData(data)
將響應數據發送回終端。
var replyTlv: String = ""
// app return the online processing data to the terminal
transactionFlowController?.sendOnlineProcessingData(replyTlv)
在正常情況下,應用程序應收到收單方 / 收單機構以下響應。
標籤 | 參數 |
---|---|
8A | 授權響應代碼 |
91 | 發卡行認證數據 |
71 | 發卡行腳本模板 1 |
72 | 發卡行腳本模板 2 |
腳本處理
如果收單方 / 收單機構的響應中有任何標籤 71 或 72,終端從應用程序接收到 sendOnlineProcessingData()
後,將自動執行腳本。
收單機構無回應
如果應用程序因異常情況無法獲得收單方 / 收單機構的任何響應,則應用程序應通過sendOnlineProcessingData("")
發送 null
或者空字符串,以完成 EMV 交易。
有關標籤詳情,參考EMV Book 3 - Application Specification, Annex A: Data Elements Dictionary
完成
在完成上述步驟後,應用程序將接收到 onBatchDataReceived
和 onTransactionStatusReceived
,並獲得該卡的最終交易結果。
應用程序應存儲批次數據,如有需要,後續上傳至收單機構進行結算。
override fun onBatchDataReceived(p0: String?) {
// store the batch data and upload to the processor later for settlement
}
override fun onTransactionStatusReceived(p0: TransactionResult?) {
// App handle UI display
}