quivio-transaction-processor 1.23.1-beta → 1.23.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/emvPaymentProvider/EMVPaymentProvider.js +59 -93
- package/dist/emvPaymentProvider/EMVPaymentProvider.js.map +1 -1
- package/dist/emvPaymentProvider/types.d.ts +1 -4
- package/dist/example/EMVPaymentScreen.d.ts +1 -4
- package/dist/example/EMVPaymentScreen.js +8 -33
- package/dist/example/EMVPaymentScreen.js.map +1 -1
- package/dist/example/EMVSettingsScreen.js +6 -4
- package/dist/example/EMVSettingsScreen.js.map +1 -1
- package/dist/example/ExternalSystemsScreen.js +3 -46
- package/dist/example/ExternalSystemsScreen.js.map +1 -1
- package/dist/example/MainScreen.js +1 -1
- package/dist/example/MainScreen.js.map +1 -1
- package/libs/emvCardReaderLib/src/main/java/com/rohan/emvcardreaderlib/POSTransactionExecutor.kt +2 -5
- package/libs/emvCardReaderLib/src/main/java/com/rohan/emvcardreaderlib/builder/DsiEMVRequestBuilder.kt +7 -14
- package/libs/emvCardReaderLib/src/main/java/com/rohan/emvcardreaderlib/manager/EMVPaymentManager.kt +13 -19
- package/libs/emvNative/src/main/java/com/quivio_transaction_processor/EMVPaymentManagerModule.kt +3 -9
- package/package.json +1 -1
- package/src/emvPaymentProvider/EMVPaymentProvider.tsx +61 -96
- package/src/emvPaymentProvider/types.ts +1 -4
- package/src/example/EMVPaymentScreen.tsx +18 -48
- package/src/example/EMVSettingsScreen.tsx +5 -3
- package/src/example/ExternalSystemsScreen.tsx +27 -84
- package/src/example/MainScreen.tsx +1 -1
- package/dist/example/helper/deviceStore.d.ts +0 -11
- package/dist/example/helper/deviceStore.js +0 -37
- package/dist/example/helper/deviceStore.js.map +0 -1
- package/src/example/helper/deviceStore.ts +0 -41
|
@@ -33,7 +33,7 @@ var MainScreen = function (_a) {
|
|
|
33
33
|
var config = _a.config;
|
|
34
34
|
var _b = (0, react_1.useState)(false), showEMV = _b[0], setShowEMV = _b[1];
|
|
35
35
|
if (showEMV) {
|
|
36
|
-
return react_1.default.createElement(EMVPaymentScreen_1.default,
|
|
36
|
+
return react_1.default.createElement(EMVPaymentScreen_1.default, null);
|
|
37
37
|
}
|
|
38
38
|
return (react_1.default.createElement(react_native_1.View, { style: styles.container },
|
|
39
39
|
react_1.default.createElement(react_native_1.Text, { style: styles.title }, "Welcome to Quivio Payment Processor"),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MainScreen.js","sourceRoot":"","sources":["../../src/example/MainScreen.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,6CAAwC;AACxC,6CAA8D;AAC9D,wEAAkD;AAGlD,IAAM,UAAU,GAAoC,UAAC,EAAU;QAAR,MAAM,YAAA;IACrD,IAAA,KAAwB,IAAA,gBAAQ,EAAC,KAAK,CAAC,EAAtC,OAAO,QAAA,EAAE,UAAU,QAAmB,CAAC;IAE9C,IAAI,OAAO,EAAE;QACX,OAAO,8BAAC,0BAAgB,
|
|
1
|
+
{"version":3,"file":"MainScreen.js","sourceRoot":"","sources":["../../src/example/MainScreen.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,6CAAwC;AACxC,6CAA8D;AAC9D,wEAAkD;AAGlD,IAAM,UAAU,GAAoC,UAAC,EAAU;QAAR,MAAM,YAAA;IACrD,IAAA,KAAwB,IAAA,gBAAQ,EAAC,KAAK,CAAC,EAAtC,OAAO,QAAA,EAAE,UAAU,QAAmB,CAAC;IAE9C,IAAI,OAAO,EAAE;QACX,OAAO,8BAAC,0BAAgB,OAAG,CAAC;KAC7B;IAED,OAAO,CACL,8BAAC,mBAAI,IAAC,KAAK,EAAE,MAAM,CAAC,SAAS;QAC3B,8BAAC,mBAAI,IAAC,KAAK,EAAE,MAAM,CAAC,KAAK,0CAA4C;QACrE,8BAAC,mBAAI,IAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,uCAAyC;QACrE,8BAAC,mBAAI,IAAC,KAAK,EAAE,MAAM,CAAC,eAAe;YACjC,8BAAC,qBAAM,IACL,KAAK,EAAC,YAAY,EAClB,OAAO,EAAE,cAAM,OAAA,UAAU,CAAC,IAAI,CAAC,EAAhB,CAAgB,GAC/B,CACG,CACF,CACR,CAAC;AACJ,CAAC,CAAC;AAEF,IAAM,MAAM,GAAG,yBAAU,CAAC,MAAM,CAAC;IAC/B,SAAS,EAAE;QACT,IAAI,EAAE,CAAC;QACP,cAAc,EAAE,QAAQ;QACxB,UAAU,EAAE,QAAQ;QACpB,eAAe,EAAE,SAAS;QAC1B,OAAO,EAAE,EAAE;KACZ;IACD,KAAK,EAAE;QACL,QAAQ,EAAE,EAAE;QACZ,UAAU,EAAE,MAAM;QAClB,YAAY,EAAE,EAAE;QAChB,KAAK,EAAE,MAAM;QACb,SAAS,EAAE,QAAQ;KACpB;IACD,QAAQ,EAAE;QACR,QAAQ,EAAE,EAAE;QACZ,KAAK,EAAE,MAAM;QACb,YAAY,EAAE,EAAE;QAChB,SAAS,EAAE,QAAQ;KACpB;IACD,eAAe,EAAE;QACf,KAAK,EAAE,MAAM;QACb,QAAQ,EAAE,GAAG;KACd;CACF,CAAC,CAAC;AAEH,kBAAe,UAAU,CAAC"}
|
package/libs/emvCardReaderLib/src/main/java/com/rohan/emvcardreaderlib/POSTransactionExecutor.kt
CHANGED
|
@@ -10,18 +10,15 @@ import kotlinx.coroutines.Dispatchers
|
|
|
10
10
|
import kotlinx.coroutines.withContext
|
|
11
11
|
import javax.security.auth.callback.Callback
|
|
12
12
|
|
|
13
|
-
class POSTransactionExecutor(context: Context) {
|
|
13
|
+
class POSTransactionExecutor(context: Context, posConfig: ConfigFactory) {
|
|
14
14
|
|
|
15
15
|
private val dsiEMVAndroidLib by lazy {
|
|
16
16
|
DsiEMVInstanceBuilder.getInstance(context)
|
|
17
17
|
}
|
|
18
18
|
private val requestBuilder by lazy {
|
|
19
|
-
DsiEMVRequestBuilder()
|
|
19
|
+
DsiEMVRequestBuilder(posConfig)
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
fun setPaymentConfig(posConfig: ConfigFactory){
|
|
23
|
-
requestBuilder.setPaymentConfig(posConfig)
|
|
24
|
-
}
|
|
25
22
|
suspend fun doSale(amount: String) {
|
|
26
23
|
withContext(Dispatchers.IO){
|
|
27
24
|
val request = requestBuilder.buildEMVSaleRequest(amount)
|
|
@@ -3,26 +3,19 @@ package com.rohan.emvcardreaderlib.builder
|
|
|
3
3
|
import com.rohan.emvcardreaderlib.ConfigFactory
|
|
4
4
|
import com.rohan.emvcardreaderlib.TransType
|
|
5
5
|
|
|
6
|
-
class DsiEMVRequestBuilder() {
|
|
7
|
-
private
|
|
8
|
-
private
|
|
6
|
+
class DsiEMVRequestBuilder(val config: ConfigFactory) {
|
|
7
|
+
private val merchantID = config.merchantID
|
|
8
|
+
private val operationMode = if (config.isSandBox) "CERT" else "PROD"
|
|
9
9
|
private val comPort = 1
|
|
10
|
-
private
|
|
11
|
-
private
|
|
12
|
-
|
|
10
|
+
private val secureDevice = config.secureDeviceName
|
|
11
|
+
private val posPackageID = config.posPackageID
|
|
12
|
+
|
|
13
|
+
private val userTrace = config.operatorID
|
|
13
14
|
|
|
14
15
|
private var sequenceNo = "0010010010"
|
|
15
16
|
|
|
16
17
|
private fun createUniqueInvoiceNo() = "${userTrace}-${System.currentTimeMillis()}"
|
|
17
18
|
|
|
18
|
-
fun setPaymentConfig(config: ConfigFactory) {
|
|
19
|
-
this.merchantID = config.merchantID
|
|
20
|
-
this.operationMode = if(config.isSandBox) "CERT" else "PROD"
|
|
21
|
-
this.secureDevice = config.secureDeviceName
|
|
22
|
-
this.posPackageID = config.posPackageID
|
|
23
|
-
this.userTrace = config.operatorID
|
|
24
|
-
}
|
|
25
|
-
|
|
26
19
|
fun buildPinPadResetRequest(): String {
|
|
27
20
|
return """
|
|
28
21
|
<?xml version="1.0"?>
|
package/libs/emvCardReaderLib/src/main/java/com/rohan/emvcardreaderlib/manager/EMVPaymentManager.kt
CHANGED
|
@@ -5,14 +5,15 @@ import android.util.Log
|
|
|
5
5
|
import com.datacap.android.DisplayMessageListener
|
|
6
6
|
import com.datacap.android.ProcessTransactionResponseListener
|
|
7
7
|
import com.rohan.emvcardreaderlib.ConfigFactory
|
|
8
|
+
import com.rohan.emvcardreaderlib.communicator.ConfigurationCommunicator
|
|
9
|
+
import com.rohan.emvcardreaderlib.communicator.EMVTransactionCommunicator
|
|
8
10
|
import com.rohan.emvcardreaderlib.POSTransactionExecutor
|
|
9
11
|
import com.rohan.emvcardreaderlib.PRINT_TAG
|
|
10
12
|
import com.rohan.emvcardreaderlib.ReaderState
|
|
11
13
|
import com.rohan.emvcardreaderlib.XMLResponseExtractor
|
|
12
|
-
import com.rohan.emvcardreaderlib.communicator.ConfigurationCommunicator
|
|
13
|
-
import com.rohan.emvcardreaderlib.communicator.EMVTransactionCommunicator
|
|
14
14
|
import kotlinx.coroutines.CoroutineScope
|
|
15
15
|
import kotlinx.coroutines.Dispatchers
|
|
16
|
+
import kotlinx.coroutines.delay
|
|
16
17
|
import kotlinx.coroutines.launch
|
|
17
18
|
import kotlinx.coroutines.withContext
|
|
18
19
|
|
|
@@ -21,7 +22,8 @@ import kotlinx.coroutines.withContext
|
|
|
21
22
|
* 1. Handle case when raised a transaction again and response says In-Progress
|
|
22
23
|
* */
|
|
23
24
|
class EMVPaymentManager(
|
|
24
|
-
val context: Context
|
|
25
|
+
val context: Context,
|
|
26
|
+
posConfig: ConfigFactory
|
|
25
27
|
) {
|
|
26
28
|
private val cancellationTimeout: Long = 2000
|
|
27
29
|
private var currentPosState: ReaderState = ReaderState.IDLE
|
|
@@ -29,17 +31,13 @@ class EMVPaymentManager(
|
|
|
29
31
|
private var configCommunicator: ConfigurationCommunicator? = null
|
|
30
32
|
|
|
31
33
|
private val posTransactionExecutor by lazy {
|
|
32
|
-
POSTransactionExecutor(context)
|
|
34
|
+
POSTransactionExecutor(context, posConfig)
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
private val posXMLResponseExtractor by lazy {
|
|
36
38
|
XMLResponseExtractor()
|
|
37
39
|
}
|
|
38
40
|
|
|
39
|
-
fun setPaymentParams(posConfig: ConfigFactory){
|
|
40
|
-
posTransactionExecutor.setPaymentConfig(posConfig)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
41
|
private suspend fun resetPinPad() {
|
|
44
42
|
currentPosState = ReaderState.Reset
|
|
45
43
|
posTransactionExecutor.resetPinPad()
|
|
@@ -52,11 +50,11 @@ class EMVPaymentManager(
|
|
|
52
50
|
|
|
53
51
|
suspend fun cancelTransaction(){
|
|
54
52
|
try {
|
|
55
|
-
|
|
53
|
+
Log.d(PRINT_TAG, "Class: ${this::class.java.simpleName} \n Operation Cancelled Called")
|
|
56
54
|
currentPosState = ReaderState.CancelTransaction
|
|
57
55
|
posTransactionExecutor.cancelTransaction()
|
|
58
56
|
} catch (e: Exception){
|
|
59
|
-
|
|
57
|
+
Log.d(PRINT_TAG, "Class: ${this::class.java.simpleName} \n Operation cancellation Failed: ${e.message}")
|
|
60
58
|
e.printStackTrace()
|
|
61
59
|
}
|
|
62
60
|
}
|
|
@@ -87,7 +85,7 @@ class EMVPaymentManager(
|
|
|
87
85
|
}
|
|
88
86
|
private suspend fun ignoreResponseIfProcessAlreadyRunning(res: String): Boolean {
|
|
89
87
|
if (posXMLResponseExtractor.isProcessAlreadyRunning(res)) {
|
|
90
|
-
|
|
88
|
+
Log.d(PRINT_TAG, "Class: ${this::class.java.simpleName} \n Process already running detected. Auto-cancelling transaction...")
|
|
91
89
|
communicator?.processAlreadyRunning()
|
|
92
90
|
return true
|
|
93
91
|
} else {
|
|
@@ -97,13 +95,12 @@ class EMVPaymentManager(
|
|
|
97
95
|
}
|
|
98
96
|
|
|
99
97
|
private val displayMessageCallback = DisplayMessageListener { message ->
|
|
100
|
-
|
|
98
|
+
Log.d(PRINT_TAG, "Class: ${this::class.java.simpleName} \n Display Message: $message")
|
|
101
99
|
communicator?.onShowDisplayMessage(message)
|
|
102
100
|
}
|
|
103
101
|
|
|
104
|
-
|
|
105
102
|
private val processListener = ProcessTransactionResponseListener { res ->
|
|
106
|
-
|
|
103
|
+
Log.d(PRINT_TAG, "Class: ${this::class.java.simpleName} \n Device Response: $res")
|
|
107
104
|
|
|
108
105
|
CoroutineScope(Dispatchers.IO).launch {
|
|
109
106
|
|
|
@@ -150,7 +147,7 @@ class EMVPaymentManager(
|
|
|
150
147
|
}
|
|
151
148
|
ReaderState.DownloadingConfig -> {
|
|
152
149
|
configCommunicator?.onConfigCompleted()
|
|
153
|
-
currentPosState
|
|
150
|
+
currentPosState != ReaderState.IDLE
|
|
154
151
|
}
|
|
155
152
|
ReaderState.CancelTransaction -> {
|
|
156
153
|
communicator?.transactionCancelled(null)
|
|
@@ -161,7 +158,7 @@ class EMVPaymentManager(
|
|
|
161
158
|
clientVersionDetails?.let {
|
|
162
159
|
communicator?.onDeviceDetailsRetrieved(it)
|
|
163
160
|
}
|
|
164
|
-
currentPosState
|
|
161
|
+
currentPosState != ReaderState.IDLE
|
|
165
162
|
}
|
|
166
163
|
ReaderState.PrePaidCardDataCollect -> {
|
|
167
164
|
val cardData = posXMLResponseExtractor.extractCardResponse(xml)
|
|
@@ -213,7 +210,4 @@ class EMVPaymentManager(
|
|
|
213
210
|
posTransactionExecutor.clearAllListeners()
|
|
214
211
|
}
|
|
215
212
|
|
|
216
|
-
private fun requestLog(log: String){
|
|
217
|
-
Log.d(PRINT_TAG, "Class: ${this::class.java.simpleName} \n Message: $log")
|
|
218
|
-
}
|
|
219
213
|
}
|
package/libs/emvNative/src/main/java/com/quivio_transaction_processor/EMVPaymentManagerModule.kt
CHANGED
|
@@ -45,17 +45,11 @@ class EMVPaymentManagerModule(private val reactContext: ReactApplicationContext)
|
|
|
45
45
|
override fun getName() = NAME
|
|
46
46
|
|
|
47
47
|
@ReactMethod
|
|
48
|
-
fun
|
|
48
|
+
fun initialize(map: ReadableMap) {
|
|
49
|
+
val config = ConfigConverterFactory.processMap(map)
|
|
49
50
|
val context = currentActivity ?: reactContext
|
|
50
|
-
dsiEMVManager = EMVPaymentManager(context)
|
|
51
|
+
dsiEMVManager = EMVPaymentManager(context, config)
|
|
51
52
|
dsiEMVManager?.registerListener(this, this)
|
|
52
|
-
log("Payment Library Initialised!")
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
@ReactMethod
|
|
56
|
-
fun setMerchantDetails(map: ReadableMap){
|
|
57
|
-
val config = ConfigConverterFactory.processMap(map)
|
|
58
|
-
dsiEMVManager?.setPaymentParams(config)
|
|
59
53
|
log("Configurational parameters sent to library: $map")
|
|
60
54
|
}
|
|
61
55
|
|
package/package.json
CHANGED
|
@@ -34,21 +34,9 @@ const EMVPaymentProvider: React.FC<{ children: React.ReactNode }> = ({
|
|
|
34
34
|
'onTransactionCancelled',
|
|
35
35
|
];
|
|
36
36
|
|
|
37
|
-
// Initialization Flag
|
|
38
|
-
const [isLibraryInitialized, setIsInitialzed] = useState(false);
|
|
39
|
-
|
|
40
37
|
// Device Connected State
|
|
41
38
|
const { isDeviceConnected } = useUSBDevice();
|
|
42
39
|
|
|
43
|
-
const [deviceSerialNumber, setDeviceSerialNumber] = useState('');
|
|
44
|
-
|
|
45
|
-
// Buffered Device Connection Flag
|
|
46
|
-
const [isIDTECHConnected, setIDTECHConnected] = useState(isDeviceConnected);
|
|
47
|
-
|
|
48
|
-
const disconnectTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(
|
|
49
|
-
null,
|
|
50
|
-
);
|
|
51
|
-
|
|
52
40
|
// Show Display Message Cache
|
|
53
41
|
const [displayMessage, setDisplayMessage] = useState('');
|
|
54
42
|
|
|
@@ -74,61 +62,55 @@ const EMVPaymentProvider: React.FC<{ children: React.ReactNode }> = ({
|
|
|
74
62
|
Map<EMVEventName, Set<(payload: any) => void>>
|
|
75
63
|
>(new Map());
|
|
76
64
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
65
|
+
// Ref to maintain timeout during configuration
|
|
66
|
+
// Because after a successfull EMVParamDownload
|
|
67
|
+
// Device reboots which leads to USB disconnection
|
|
68
|
+
// and connection
|
|
69
|
+
const unconfigureTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(
|
|
70
|
+
null,
|
|
71
|
+
);
|
|
83
72
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}, [deviceSerialNumber]);
|
|
73
|
+
// Ref to maintain device connection/disconnection
|
|
74
|
+
const isDeviceConnectedRef = useRef<boolean>(isDeviceConnected);
|
|
87
75
|
|
|
88
76
|
useEffect(() => {
|
|
89
|
-
//
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
// If device connects -> update immediately
|
|
93
|
-
if (isDeviceConnected) {
|
|
94
|
-
setIDTECHConnected(true);
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// If device disconnects -> delay 1500ms
|
|
99
|
-
disconnectTimeoutRef.current = setTimeout(() => {
|
|
100
|
-
setIDTECHConnected(false);
|
|
101
|
-
}, 2000);
|
|
102
|
-
|
|
103
|
-
return () => {
|
|
104
|
-
clearDisconnectTimeout();
|
|
105
|
-
};
|
|
106
|
-
}, [isDeviceConnected]);
|
|
77
|
+
// Always sync ref first
|
|
78
|
+
isDeviceConnectedRef.current = isDeviceConnected;
|
|
107
79
|
|
|
108
|
-
|
|
109
|
-
if (!
|
|
110
|
-
|
|
80
|
+
// Handle disconnect logic
|
|
81
|
+
if (!isDeviceConnected) {
|
|
82
|
+
unconfigureDevice(false);
|
|
111
83
|
setConfigurationInProgress(false);
|
|
112
84
|
setTransactionCurrentlyRunning(false);
|
|
113
85
|
setCancellationRunning(false);
|
|
114
|
-
setDeviceSerialNumber('');
|
|
115
|
-
setDisplayMessage('');
|
|
116
|
-
} else {
|
|
117
|
-
getDeviceDetails();
|
|
118
86
|
}
|
|
119
|
-
}, [
|
|
87
|
+
}, [isDeviceConnected]);
|
|
120
88
|
|
|
121
89
|
// Logging helper
|
|
122
90
|
const pushLog = (type: string, payload: any) => {
|
|
123
91
|
setLogs(prev => [...prev, { type, payload, timestamp: Date.now() }]);
|
|
124
92
|
};
|
|
125
93
|
|
|
126
|
-
//
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
94
|
+
// Exposed Method to unconfigure Device
|
|
95
|
+
const unconfigureDevice = (immediate: boolean = false) => {
|
|
96
|
+
// Cancel any pending delayed unconfigure
|
|
97
|
+
if (unconfigureTimeoutRef.current) {
|
|
98
|
+
clearTimeout(unconfigureTimeoutRef.current);
|
|
99
|
+
unconfigureTimeoutRef.current = null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (immediate) {
|
|
103
|
+
setIsConfigured(false);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Delayed unconfigure (handles IDTECH reboot)
|
|
108
|
+
unconfigureTimeoutRef.current = setTimeout(() => {
|
|
109
|
+
if (!isDeviceConnectedRef.current) {
|
|
110
|
+
setIsConfigured(false);
|
|
111
|
+
}
|
|
112
|
+
}, 2000);
|
|
113
|
+
};
|
|
132
114
|
|
|
133
115
|
// Native to Provider EMV event listening
|
|
134
116
|
useEffect(() => {
|
|
@@ -140,10 +122,6 @@ const EMVPaymentProvider: React.FC<{ children: React.ReactNode }> = ({
|
|
|
140
122
|
setDisplayMessage(payload);
|
|
141
123
|
}
|
|
142
124
|
|
|
143
|
-
if (eventName === 'onDeviceDetailsRetrieved') {
|
|
144
|
-
setDeviceSerialNumber(payload?.serialNumber ?? '');
|
|
145
|
-
}
|
|
146
|
-
|
|
147
125
|
if (eventName === 'onConfigCompleted') {
|
|
148
126
|
setConfigurationInProgress(false);
|
|
149
127
|
setCancellationRunning(false);
|
|
@@ -164,7 +142,7 @@ const EMVPaymentProvider: React.FC<{ children: React.ReactNode }> = ({
|
|
|
164
142
|
if (TRANSACTION_RESPONSE_EVENTS.includes(eventName)) {
|
|
165
143
|
setTransactionCurrentlyRunning(false);
|
|
166
144
|
setCancellationRunning(false);
|
|
167
|
-
setDisplayMessage(
|
|
145
|
+
setDisplayMessage("")
|
|
168
146
|
}
|
|
169
147
|
|
|
170
148
|
const callbacks = subscriptionsRef.current.get(eventName);
|
|
@@ -181,7 +159,7 @@ const EMVPaymentProvider: React.FC<{ children: React.ReactNode }> = ({
|
|
|
181
159
|
// Exposed method to run EMV configuration
|
|
182
160
|
const runConfiguration = (config: EMVConfig) => {
|
|
183
161
|
const title = 'CONFIGURATION DENIED';
|
|
184
|
-
const message = !
|
|
162
|
+
const message = !isDeviceConnected
|
|
185
163
|
? 'IDTECH device is not connected via USB'
|
|
186
164
|
: config.merchantID == ''
|
|
187
165
|
? 'Merchant ID not found'
|
|
@@ -189,8 +167,6 @@ const EMVPaymentProvider: React.FC<{ children: React.ReactNode }> = ({
|
|
|
189
167
|
? 'Operator ID not Found'
|
|
190
168
|
: config.secureDeviceName == '' || config.posPackageID == ''
|
|
191
169
|
? 'Some configuration parameters are missing'
|
|
192
|
-
: !isLibraryInitialized
|
|
193
|
-
? 'Payment Library not initialized. Call initializePaymentLib() first'
|
|
194
170
|
: '';
|
|
195
171
|
|
|
196
172
|
if (message != '') {
|
|
@@ -199,69 +175,53 @@ const EMVPaymentProvider: React.FC<{ children: React.ReactNode }> = ({
|
|
|
199
175
|
}
|
|
200
176
|
|
|
201
177
|
setConfigurationInProgress(true);
|
|
202
|
-
|
|
178
|
+
console.log(
|
|
179
|
+
'Initialising::: ConfugurationProgress:',
|
|
180
|
+
isConfigurationInProgress,
|
|
181
|
+
'isDeviceConnected: ',
|
|
182
|
+
isDeviceConnected,
|
|
183
|
+
);
|
|
184
|
+
DsiEMVManagerBridge.clearTransactionListener();
|
|
185
|
+
DsiEMVManagerBridge.initialize(config);
|
|
203
186
|
DsiEMVManagerBridge.configureDevice();
|
|
204
187
|
};
|
|
205
188
|
|
|
206
|
-
const setMerchantDetails = (config: EMVConfig) => {
|
|
207
|
-
DsiEMVManagerBridge.setMerchantDetails(config);
|
|
208
|
-
if(!deviceSerialNumber?.trim())
|
|
209
|
-
getDeviceDetails()
|
|
210
|
-
};
|
|
211
|
-
// Initialize payment library
|
|
212
|
-
const initializePaymentLib = () => {
|
|
213
|
-
if (!isLibraryInitialized) {
|
|
214
|
-
DsiEMVManagerBridge.initializeLib();
|
|
215
|
-
setIsInitialzed(true);
|
|
216
|
-
pushLog('PAYMENT LIBRARY', 'Payment library has been initialised!');
|
|
217
|
-
} else {
|
|
218
|
-
pushLog('PAYMENT LIBRARY', 'Already initialized!');
|
|
219
|
-
}
|
|
220
|
-
};
|
|
221
189
|
// Exposed method to run EMV CC Sale
|
|
222
190
|
const creditCardSale = (amount: string) => {
|
|
223
|
-
if (!
|
|
191
|
+
if (!isDeviceConnected || !isConfigured) return;
|
|
224
192
|
|
|
225
193
|
setTransactionCurrentlyRunning(true);
|
|
226
194
|
DsiEMVManagerBridge.runSaleTransaction(amount);
|
|
227
|
-
pushLog('EMV TRANSACTION', 'Credit card sale transaction initiated');
|
|
228
195
|
};
|
|
229
196
|
|
|
230
197
|
// Exposed method to run In House/ Prepaid Card Read
|
|
231
198
|
const prepaidCardRead = () => {
|
|
232
|
-
if (!
|
|
199
|
+
if (!isDeviceConnected || !isConfigured) return;
|
|
233
200
|
|
|
234
201
|
setTransactionCurrentlyRunning(true);
|
|
235
202
|
DsiEMVManagerBridge.collectCardDetails();
|
|
236
|
-
pushLog('PREPAID TRANSACTION', 'Prepaid card read initiated');
|
|
237
203
|
};
|
|
238
204
|
|
|
239
205
|
// Exposed method to run EMV CC Sale for Sale
|
|
240
206
|
const creditCardRecurringSale = (amount: string) => {
|
|
241
|
-
if (!
|
|
207
|
+
if (!isDeviceConnected || !isConfigured) return;
|
|
242
208
|
|
|
243
209
|
setTransactionCurrentlyRunning(true);
|
|
244
210
|
DsiEMVManagerBridge.runRecurringTransaction(amount);
|
|
245
|
-
pushLog(
|
|
246
|
-
'EMV TRANSACTION',
|
|
247
|
-
'Credit card sale transaction for recurring initiated',
|
|
248
|
-
);
|
|
249
211
|
};
|
|
250
212
|
|
|
251
213
|
// Exposed method to run EMV CC Zero Auth
|
|
252
214
|
const zeroAuthTransaction = () => {
|
|
253
|
-
if (!
|
|
215
|
+
if (!isDeviceConnected || !isConfigured) return;
|
|
254
216
|
|
|
255
217
|
setTransactionCurrentlyRunning(true);
|
|
256
218
|
DsiEMVManagerBridge.replaceCardInRecurring();
|
|
257
|
-
pushLog('EMV TRANSACTION', 'Zero auth transaction has been initiated');
|
|
258
219
|
};
|
|
259
220
|
|
|
260
221
|
// Exposed method to fetch device details
|
|
261
222
|
const getDeviceDetails = () => {
|
|
262
|
-
if (!
|
|
223
|
+
if (!isDeviceConnected) return;
|
|
263
224
|
DsiEMVManagerBridge.getDeviceDetails();
|
|
264
|
-
pushLog('PAYMENT LIBRARY', 'Retrieving IDTECH device details');
|
|
265
225
|
};
|
|
266
226
|
|
|
267
227
|
// Exposed method to cancel transaction
|
|
@@ -270,7 +230,6 @@ const EMVPaymentProvider: React.FC<{ children: React.ReactNode }> = ({
|
|
|
270
230
|
setConfigurationInProgress(false);
|
|
271
231
|
setCancellationRunning(true);
|
|
272
232
|
DsiEMVManagerBridge.cancelTransaction();
|
|
273
|
-
pushLog('PAYMENT LIBRARY', 'Current Transaction cancelled by User');
|
|
274
233
|
};
|
|
275
234
|
|
|
276
235
|
// Exposed method to remove all attached listener
|
|
@@ -308,19 +267,25 @@ const EMVPaymentProvider: React.FC<{ children: React.ReactNode }> = ({
|
|
|
308
267
|
[],
|
|
309
268
|
);
|
|
310
269
|
|
|
270
|
+
// Cleanup on unmount
|
|
271
|
+
useEffect(() => {
|
|
272
|
+
return () => {
|
|
273
|
+
if (unconfigureTimeoutRef.current) {
|
|
274
|
+
clearTimeout(unconfigureTimeoutRef.current);
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
}, []);
|
|
278
|
+
|
|
311
279
|
// Context value builder
|
|
312
280
|
const value: EMVPaymentContextType = {
|
|
313
281
|
logs,
|
|
314
|
-
isDeviceConnected
|
|
282
|
+
isDeviceConnected,
|
|
315
283
|
isConfigured,
|
|
316
|
-
deviceSerialNumber,
|
|
317
284
|
isTransactionCurrentlyRunning,
|
|
318
285
|
isConfigurationInProgress,
|
|
319
286
|
isCancellationRunning,
|
|
320
287
|
displayMessage,
|
|
321
|
-
|
|
322
|
-
setMerchantDetails,
|
|
323
|
-
initializePaymentLib,
|
|
288
|
+
unconfigureDevice,
|
|
324
289
|
creditCardSale,
|
|
325
290
|
prepaidCardRead,
|
|
326
291
|
creditCardRecurringSale,
|
|
@@ -24,15 +24,12 @@ export interface CallbackLog {
|
|
|
24
24
|
export interface EMVPaymentHook {
|
|
25
25
|
logs: CallbackLog[];
|
|
26
26
|
isDeviceConnected: boolean;
|
|
27
|
-
deviceSerialNumber: string,
|
|
28
27
|
isConfigured: boolean;
|
|
29
28
|
isTransactionCurrentlyRunning: boolean,
|
|
30
29
|
isConfigurationInProgress: boolean,
|
|
31
30
|
isCancellationRunning: boolean,
|
|
32
31
|
displayMessage: string,
|
|
33
|
-
|
|
34
|
-
setIsConfigured: (isConfigured: boolean) => void,
|
|
35
|
-
initializePaymentLib: () => void,
|
|
32
|
+
unconfigureDevice: (immediate: boolean) => void,
|
|
36
33
|
creditCardSale: (amount: string) => void;
|
|
37
34
|
prepaidCardRead: () => void;
|
|
38
35
|
creditCardRecurringSale: (amount: string) => void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
View,
|
|
4
4
|
Text,
|
|
@@ -16,14 +16,12 @@ import { USBDeviceProvider } from '../usb/USBDeviceContext';
|
|
|
16
16
|
import { EMVPaymentProvider } from '../emvPaymentProvider/EMVPaymentProvider';
|
|
17
17
|
import { useEMVPayment } from '../emvPaymentProvider/useEMVPayment';
|
|
18
18
|
import { EMVConfig } from '../emvPaymentProvider/types';
|
|
19
|
-
import { getDeviceBySerial } from './helper/deviceStore';
|
|
20
19
|
|
|
21
20
|
type IconCallback = {
|
|
22
21
|
onPress: () => void;
|
|
23
22
|
};
|
|
24
23
|
|
|
25
24
|
type PaymentScreenIconsCallback = {
|
|
26
|
-
config: EMVConfig | null;
|
|
27
25
|
onPressExternalSystem: () => void;
|
|
28
26
|
onPressSettings: () => void;
|
|
29
27
|
};
|
|
@@ -48,8 +46,8 @@ const CrossIcon = () => (
|
|
|
48
46
|
<Text style={{ color: 'red', fontSize: 18, marginRight: 6 }}>❌</Text>
|
|
49
47
|
);
|
|
50
48
|
|
|
51
|
-
const EMVPaymentScreenExample = (
|
|
52
|
-
const [config, setConfig] = useState<EMVConfig | null>(
|
|
49
|
+
const EMVPaymentScreenExample = () => {
|
|
50
|
+
const [config, setConfig] = useState<EMVConfig | null>(null);
|
|
53
51
|
const [showSettingsScreen, setShowSettingsScreen] = useState(false);
|
|
54
52
|
const [showExternalSystemScreen, setShowExternalSystemScreen] =
|
|
55
53
|
useState(false);
|
|
@@ -83,7 +81,6 @@ const EMVPaymentScreenExample = ( {posConfig}: {posConfig: EMVConfig}) => {
|
|
|
83
81
|
|
|
84
82
|
return (
|
|
85
83
|
<ExampleContent
|
|
86
|
-
config={config}
|
|
87
84
|
onPressSettings={toggleSettingsScreen}
|
|
88
85
|
onPressExternalSystem={toggleExternalSystemScreen}
|
|
89
86
|
/>
|
|
@@ -98,50 +95,22 @@ const EMVPaymentScreenExample = ( {posConfig}: {posConfig: EMVConfig}) => {
|
|
|
98
95
|
};
|
|
99
96
|
|
|
100
97
|
const ExampleContent = ({
|
|
101
|
-
config,
|
|
102
98
|
onPressExternalSystem,
|
|
103
99
|
onPressSettings,
|
|
104
100
|
}: PaymentScreenIconsCallback) => {
|
|
105
101
|
const [infoVisible, setInfoVisible] = useState(false);
|
|
106
102
|
const {
|
|
107
103
|
logs,
|
|
108
|
-
deviceSerialNumber,
|
|
109
|
-
initializePaymentLib,
|
|
110
|
-
setMerchantDetails,
|
|
111
104
|
isConfigured,
|
|
112
105
|
creditCardSale,
|
|
113
106
|
prepaidCardRead,
|
|
114
107
|
creditCardRecurringSale,
|
|
115
108
|
zeroAuthTransaction,
|
|
116
109
|
cancelOperation,
|
|
117
|
-
setIsConfigured,
|
|
118
110
|
getDeviceDetails,
|
|
119
111
|
isTransactionCurrentlyRunning,
|
|
120
|
-
displayMessage
|
|
112
|
+
displayMessage
|
|
121
113
|
} = useEMVPayment();
|
|
122
|
-
//Device Connected -> Serial Received -> Lookup Local Config -> Auto Configure -> Enable Transactions
|
|
123
|
-
useEffect(() => {
|
|
124
|
-
if (deviceSerialNumber) {
|
|
125
|
-
const matchedDevice = getDeviceBySerial(deviceSerialNumber);
|
|
126
|
-
|
|
127
|
-
if (matchedDevice?.isConfigured) {
|
|
128
|
-
setIsConfigured(true);
|
|
129
|
-
} else {
|
|
130
|
-
setIsConfigured(false);
|
|
131
|
-
}
|
|
132
|
-
} else {
|
|
133
|
-
setIsConfigured(false);
|
|
134
|
-
}
|
|
135
|
-
}, [deviceSerialNumber]);
|
|
136
|
-
|
|
137
|
-
const initialiseLib = () => {
|
|
138
|
-
initializePaymentLib();
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
useEffect(() => {
|
|
142
|
-
initialiseLib();
|
|
143
|
-
if (config != null) setMerchantDetails(config);
|
|
144
|
-
}, []);
|
|
145
114
|
|
|
146
115
|
const showAlertIfNotConfigured = () => {
|
|
147
116
|
if (isConfigured) return false;
|
|
@@ -171,6 +140,7 @@ const ExampleContent = ({
|
|
|
171
140
|
|
|
172
141
|
{/** Button Row 1 */}
|
|
173
142
|
<View style={styles.buttonRow}>
|
|
143
|
+
|
|
174
144
|
<TouchableOpacity
|
|
175
145
|
style={[
|
|
176
146
|
styles.ctaButton,
|
|
@@ -194,9 +164,10 @@ const ExampleContent = ({
|
|
|
194
164
|
: styles.ctaButtonEnabled,
|
|
195
165
|
]}
|
|
196
166
|
onPress={() => {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
167
|
+
if(!showAlertIfNotConfigured())
|
|
168
|
+
creditCardRecurringSale('1.50')
|
|
169
|
+
}}
|
|
170
|
+
disabled={isTransactionCurrentlyRunning }
|
|
200
171
|
>
|
|
201
172
|
<Text style={styles.ctaButtonText}>CC Sale (Recurring)</Text>
|
|
202
173
|
</TouchableOpacity>
|
|
@@ -211,7 +182,7 @@ const ExampleContent = ({
|
|
|
211
182
|
onPress={() => {
|
|
212
183
|
if (!showAlertIfNotConfigured()) prepaidCardRead();
|
|
213
184
|
}}
|
|
214
|
-
disabled={isTransactionCurrentlyRunning}
|
|
185
|
+
disabled={isTransactionCurrentlyRunning }
|
|
215
186
|
>
|
|
216
187
|
<Text style={styles.ctaButtonText}>Read Prepaid Card</Text>
|
|
217
188
|
</TouchableOpacity>
|
|
@@ -226,10 +197,11 @@ const ExampleContent = ({
|
|
|
226
197
|
? styles.ctaButtonDisabled
|
|
227
198
|
: styles.ctaButtonEnabled,
|
|
228
199
|
]}
|
|
229
|
-
onPress={()
|
|
230
|
-
|
|
200
|
+
onPress={()=> {
|
|
201
|
+
if(!showAlertIfNotConfigured())
|
|
202
|
+
zeroAuthTransaction()
|
|
231
203
|
}}
|
|
232
|
-
disabled={isTransactionCurrentlyRunning}
|
|
204
|
+
disabled={isTransactionCurrentlyRunning }
|
|
233
205
|
>
|
|
234
206
|
<Text style={styles.ctaButtonText}>CC $0 Auth</Text>
|
|
235
207
|
</TouchableOpacity>
|
|
@@ -241,8 +213,8 @@ const ExampleContent = ({
|
|
|
241
213
|
? styles.ctaButtonDisabled
|
|
242
214
|
: styles.ctaButtonEnabled,
|
|
243
215
|
]}
|
|
244
|
-
onPress={()
|
|
245
|
-
|
|
216
|
+
onPress={()=> {
|
|
217
|
+
getDeviceDetails()
|
|
246
218
|
}}
|
|
247
219
|
disabled={isTransactionCurrentlyRunning}
|
|
248
220
|
>
|
|
@@ -260,9 +232,7 @@ const ExampleContent = ({
|
|
|
260
232
|
<View style={styles.modalOverlay}>
|
|
261
233
|
<View style={styles.modalContent}>
|
|
262
234
|
<ActivityIndicator size="large" color="#007AFF" />
|
|
263
|
-
<Text style={styles.modalText}>
|
|
264
|
-
Processing...\n{displayMessage}
|
|
265
|
-
</Text>
|
|
235
|
+
<Text style={styles.modalText}>Processing...\n{displayMessage}</Text>
|
|
266
236
|
<TouchableOpacity
|
|
267
237
|
style={styles.cancelButton}
|
|
268
238
|
onPress={cancelOperation}
|
|
@@ -481,7 +451,7 @@ const styles = StyleSheet.create({
|
|
|
481
451
|
paddingVertical: 8,
|
|
482
452
|
paddingHorizontal: 14,
|
|
483
453
|
borderRadius: 6,
|
|
484
|
-
}
|
|
454
|
+
}
|
|
485
455
|
});
|
|
486
456
|
|
|
487
457
|
export default EMVPaymentScreenExample;
|