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.
Files changed (27) hide show
  1. package/dist/emvPaymentProvider/EMVPaymentProvider.js +59 -93
  2. package/dist/emvPaymentProvider/EMVPaymentProvider.js.map +1 -1
  3. package/dist/emvPaymentProvider/types.d.ts +1 -4
  4. package/dist/example/EMVPaymentScreen.d.ts +1 -4
  5. package/dist/example/EMVPaymentScreen.js +8 -33
  6. package/dist/example/EMVPaymentScreen.js.map +1 -1
  7. package/dist/example/EMVSettingsScreen.js +6 -4
  8. package/dist/example/EMVSettingsScreen.js.map +1 -1
  9. package/dist/example/ExternalSystemsScreen.js +3 -46
  10. package/dist/example/ExternalSystemsScreen.js.map +1 -1
  11. package/dist/example/MainScreen.js +1 -1
  12. package/dist/example/MainScreen.js.map +1 -1
  13. package/libs/emvCardReaderLib/src/main/java/com/rohan/emvcardreaderlib/POSTransactionExecutor.kt +2 -5
  14. package/libs/emvCardReaderLib/src/main/java/com/rohan/emvcardreaderlib/builder/DsiEMVRequestBuilder.kt +7 -14
  15. package/libs/emvCardReaderLib/src/main/java/com/rohan/emvcardreaderlib/manager/EMVPaymentManager.kt +13 -19
  16. package/libs/emvNative/src/main/java/com/quivio_transaction_processor/EMVPaymentManagerModule.kt +3 -9
  17. package/package.json +1 -1
  18. package/src/emvPaymentProvider/EMVPaymentProvider.tsx +61 -96
  19. package/src/emvPaymentProvider/types.ts +1 -4
  20. package/src/example/EMVPaymentScreen.tsx +18 -48
  21. package/src/example/EMVSettingsScreen.tsx +5 -3
  22. package/src/example/ExternalSystemsScreen.tsx +27 -84
  23. package/src/example/MainScreen.tsx +1 -1
  24. package/dist/example/helper/deviceStore.d.ts +0 -11
  25. package/dist/example/helper/deviceStore.js +0 -37
  26. package/dist/example/helper/deviceStore.js.map +0 -1
  27. 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, { posConfig: config });
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,IAAC,SAAS,EAAE,MAAM,GAAG,CAAC;KAC/C;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"}
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"}
@@ -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 var merchantID = ""
8
- private var operationMode = "CERT"
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 var secureDevice = ""
11
- private var posPackageID = ""
12
- private var userTrace = ""
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"?>
@@ -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
- requestLog("Operation Cancelled Called")
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
- requestLog("Operation cancellation Failed: ${e.message}")
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
- requestLog("Operation Collision: Process already running detected")
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
- requestLog("Message from IDTECH: $message")
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
- requestLog("Response from IDTECH: $res")
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 == ReaderState.IDLE
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 == ReaderState.IDLE
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
  }
@@ -45,17 +45,11 @@ class EMVPaymentManagerModule(private val reactContext: ReactApplicationContext)
45
45
  override fun getName() = NAME
46
46
 
47
47
  @ReactMethod
48
- fun initializeLib() {
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quivio-transaction-processor",
3
- "version": "1.23.1-beta",
3
+ "version": "1.23.2",
4
4
  "description": "React Native hook for Card payment integration with DataCap",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -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
- const clearDisconnectTimeout = () => {
78
- if (disconnectTimeoutRef.current) {
79
- clearTimeout(disconnectTimeoutRef.current);
80
- disconnectTimeoutRef.current = null;
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
- useEffect(() => {
85
- pushLog('PAYMENT LIBRARY', `SERIAL NUMBER: ${deviceSerialNumber}`);
86
- }, [deviceSerialNumber]);
73
+ // Ref to maintain device connection/disconnection
74
+ const isDeviceConnectedRef = useRef<boolean>(isDeviceConnected);
87
75
 
88
76
  useEffect(() => {
89
- // Stop already running timeout
90
- clearDisconnectTimeout();
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
- useEffect(() => {
109
- if (!isIDTECHConnected) {
110
- setIsConfigured(false);
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
- }, [isIDTECHConnected]);
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
- // Clean up timeout references
127
- useEffect(() => {
128
- return () => {
129
- clearDisconnectTimeout();
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 = !isIDTECHConnected
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
- DsiEMVManagerBridge.setMerchantDetails(config);
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 (!isIDTECHConnected || !isConfigured) return;
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 (!isIDTECHConnected || !isConfigured) return;
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 (!isIDTECHConnected || !isConfigured) return;
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 (!isIDTECHConnected || !isConfigured) return;
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 (!isIDTECHConnected) return;
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: isIDTECHConnected,
282
+ isDeviceConnected,
315
283
  isConfigured,
316
- deviceSerialNumber,
317
284
  isTransactionCurrentlyRunning,
318
285
  isConfigurationInProgress,
319
286
  isCancellationRunning,
320
287
  displayMessage,
321
- setIsConfigured,
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
- setMerchantDetails: (config: EMVConfig) => void,
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, { useEffect, useState } from '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 = ( {posConfig}: {posConfig: EMVConfig}) => {
52
- const [config, setConfig] = useState<EMVConfig | null>(posConfig);
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
- if (!showAlertIfNotConfigured()) creditCardRecurringSale('1.50');
198
- }}
199
- disabled={isTransactionCurrentlyRunning}
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
- if (!showAlertIfNotConfigured()) zeroAuthTransaction();
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
- getDeviceDetails();
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;