quivio-transaction-processor 1.0.5 → 1.0.7
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/README.md +337 -90
- package/dist/PaymentProvider.d.ts +9 -0
- package/dist/PaymentProvider.js +348 -0
- package/dist/PaymentProvider.js.map +1 -0
- package/dist/example/EMVPaymentScreen.js +7 -3
- package/dist/example/EMVPaymentScreen.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/useEMVPayment.d.ts +2 -2
- package/dist/useEMVPayment.js +8 -316
- package/dist/useEMVPayment.js.map +1 -1
- package/libs/emvCardReaderLib/src/main/java/com/rohan/emvcardreaderlib/builder/DsiEMVRequestBuilder.kt +1 -0
- package/package.json +1 -1
- package/src/PaymentProvider.tsx +408 -0
- package/src/example/EMVPaymentScreen.tsx +14 -8
- package/src/index.ts +9 -4
- package/src/types.ts +2 -0
- package/src/useEMVPayment.tsx +11 -394
- package/dist/utils/config.d.ts +0 -2
- package/dist/utils/config.js +0 -12
- package/dist/utils/config.js.map +0 -1
- package/src/utils/config.ts +0 -10
package/README.md
CHANGED
|
@@ -4,15 +4,16 @@ A comprehensive React Native library for EMV payment integration with DataCap te
|
|
|
4
4
|
|
|
5
5
|
## 🚀 Features
|
|
6
6
|
|
|
7
|
-
- **🔌 Easy Integration**: Simple
|
|
7
|
+
- **🔌 Easy Integration**: Simple provider-based API for React Native
|
|
8
8
|
- **💳 Full EMV Support**: Complete EMV card reading and processing capabilities
|
|
9
9
|
- **🤖 Android Native**: Optimized native Android implementation with EMV libraries
|
|
10
10
|
- **🔄 Real-time Events**: Comprehensive event system for payment status updates
|
|
11
11
|
- **📊 Built-in Logging**: Detailed transaction logging for debugging and monitoring
|
|
12
12
|
- **⚡ TypeScript Support**: Full TypeScript definitions and type safety
|
|
13
13
|
- **🔄 Recurring Payments**: Support for recurring payment transactions
|
|
14
|
-
- **🎯 Multiple Payment Types**: Support for sale, in-house, and
|
|
14
|
+
- **🎯 Multiple Payment Types**: Support for sale, in-house, recurring, and card replacement transactions
|
|
15
15
|
- **🛡️ Error Handling**: Robust error handling and recovery mechanisms
|
|
16
|
+
- **🎯 Context-Based State Management**: Centralized state management with React Context
|
|
16
17
|
|
|
17
18
|
## 📦 Installation
|
|
18
19
|
|
|
@@ -22,6 +23,26 @@ npm install quivio-transaction-processor
|
|
|
22
23
|
yarn add quivio-transaction-processor
|
|
23
24
|
```
|
|
24
25
|
|
|
26
|
+
## 🏗️ Architecture Overview
|
|
27
|
+
|
|
28
|
+
### Context-Based State Management
|
|
29
|
+
The package uses React Context for state management, providing:
|
|
30
|
+
- **Centralized State**: All payment state managed in one place
|
|
31
|
+
- **Automatic Initialization**: EMV manager initialized on provider mount
|
|
32
|
+
- **Event Management**: Built-in event subscription and cleanup
|
|
33
|
+
- **Type Safety**: Full TypeScript support with proper typing
|
|
34
|
+
|
|
35
|
+
### Provider Pattern
|
|
36
|
+
```tsx
|
|
37
|
+
// Wrap your app or component with PaymentProvider
|
|
38
|
+
<PaymentProvider config={emvConfig}>
|
|
39
|
+
<YourPaymentComponent />
|
|
40
|
+
</PaymentProvider>
|
|
41
|
+
|
|
42
|
+
// Use the hook in any child component
|
|
43
|
+
const { handleCardPayment, isDeviceConnected } = useEMVPayment();
|
|
44
|
+
```
|
|
45
|
+
|
|
25
46
|
## 🔧 Android Setup
|
|
26
47
|
|
|
27
48
|
This package includes native Android libraries that require proper configuration. Follow these steps carefully:
|
|
@@ -81,50 +102,99 @@ class MainApplication : Application(), ReactApplication {
|
|
|
81
102
|
|
|
82
103
|
## 🎯 Quick Start
|
|
83
104
|
|
|
84
|
-
### Basic Implementation
|
|
105
|
+
### Basic Implementation with PaymentProvider
|
|
85
106
|
|
|
86
107
|
```tsx
|
|
87
108
|
import React from 'react';
|
|
88
|
-
import { View, Text,
|
|
89
|
-
import { useEMVPayment } from 'quivio-transaction-processor';
|
|
109
|
+
import { View, Text, TouchableOpacity, ScrollView } from 'react-native';
|
|
110
|
+
import { PaymentProvider, useEMVPayment, EMVConfig } from 'quivio-transaction-processor';
|
|
111
|
+
|
|
112
|
+
const emvConfig: EMVConfig = {
|
|
113
|
+
merchantID: "YOUR_MERCHANT_ID",
|
|
114
|
+
onlineMerchantID: "YOUR_ONLINE_MERCHANT_ID",
|
|
115
|
+
isSandBox: true, // true for testing, false for production
|
|
116
|
+
secureDeviceName: "YOUR_DEVICE_NAME",
|
|
117
|
+
operatorID: "YOUR_OPERATOR_ID",
|
|
118
|
+
posPackageID: "com.your_app:1.0" // App Bundle ID and version
|
|
119
|
+
};
|
|
90
120
|
|
|
91
121
|
const PaymentScreen = () => {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
posPackageID: "YOUR_POS_PACKAGE_ID" // App Bundle ID
|
|
99
|
-
};
|
|
122
|
+
return (
|
|
123
|
+
<PaymentProvider config={emvConfig}>
|
|
124
|
+
<PaymentContent />
|
|
125
|
+
</PaymentProvider>
|
|
126
|
+
);
|
|
127
|
+
};
|
|
100
128
|
|
|
129
|
+
const PaymentContent = () => {
|
|
101
130
|
const {
|
|
131
|
+
logs,
|
|
102
132
|
isDeviceConnected,
|
|
103
|
-
isInitialized,
|
|
104
133
|
loading,
|
|
134
|
+
isInitialized,
|
|
105
135
|
handleCardPayment,
|
|
106
136
|
setupConfig,
|
|
107
|
-
|
|
108
|
-
} = useEMVPayment(
|
|
137
|
+
EVENTS
|
|
138
|
+
} = useEMVPayment();
|
|
109
139
|
|
|
110
140
|
return (
|
|
111
|
-
<View>
|
|
112
|
-
<Text
|
|
113
|
-
|
|
141
|
+
<View style={{ flex: 1, padding: 16 }}>
|
|
142
|
+
<Text style={{ fontSize: 18, fontWeight: 'bold', marginBottom: 10 }}>
|
|
143
|
+
Status: {isInitialized ? '✅ Initialized' : '❌ Not Initialized'}
|
|
144
|
+
</Text>
|
|
145
|
+
<Text style={{ fontSize: 16, marginBottom: 10 }}>
|
|
146
|
+
Device: {isDeviceConnected ? '✅ Connected' : '❌ Not Connected'}
|
|
147
|
+
</Text>
|
|
114
148
|
|
|
115
|
-
<
|
|
116
|
-
|
|
149
|
+
<TouchableOpacity
|
|
150
|
+
style={{
|
|
151
|
+
backgroundColor: isDeviceConnected ? '#4CAF50' : '#FF9800',
|
|
152
|
+
padding: 12,
|
|
153
|
+
borderRadius: 8,
|
|
154
|
+
marginBottom: 10
|
|
155
|
+
}}
|
|
117
156
|
onPress={setupConfig}
|
|
118
157
|
disabled={loading}
|
|
119
|
-
|
|
158
|
+
>
|
|
159
|
+
<Text style={{ color: 'white', textAlign: 'center' }}>
|
|
160
|
+
{isDeviceConnected ? 'Configuration Ready' : 'Setup Configuration'}
|
|
161
|
+
</Text>
|
|
162
|
+
</TouchableOpacity>
|
|
120
163
|
|
|
121
|
-
<
|
|
122
|
-
|
|
164
|
+
<TouchableOpacity
|
|
165
|
+
style={{
|
|
166
|
+
backgroundColor: (loading || !isDeviceConnected) ? '#ccc' : '#2196F3',
|
|
167
|
+
padding: 12,
|
|
168
|
+
borderRadius: 8,
|
|
169
|
+
marginBottom: 10
|
|
170
|
+
}}
|
|
123
171
|
onPress={() => handleCardPayment('5.00')}
|
|
124
172
|
disabled={loading || !isDeviceConnected}
|
|
125
|
-
|
|
173
|
+
>
|
|
174
|
+
<Text style={{ color: 'white', textAlign: 'center' }}>
|
|
175
|
+
Process Payment ($5.00)
|
|
176
|
+
</Text>
|
|
177
|
+
</TouchableOpacity>
|
|
126
178
|
|
|
127
|
-
{loading &&
|
|
179
|
+
{loading && (
|
|
180
|
+
<Text style={{ textAlign: 'center', color: '#FF9800', marginBottom: 10 }}>
|
|
181
|
+
Processing...
|
|
182
|
+
</Text>
|
|
183
|
+
)}
|
|
184
|
+
|
|
185
|
+
<ScrollView style={{ flex: 1 }}>
|
|
186
|
+
{logs.map((log, index) => (
|
|
187
|
+
<View key={index} style={{
|
|
188
|
+
backgroundColor: '#f5f5f5',
|
|
189
|
+
padding: 8,
|
|
190
|
+
marginBottom: 5,
|
|
191
|
+
borderRadius: 4
|
|
192
|
+
}}>
|
|
193
|
+
<Text style={{ fontWeight: 'bold' }}>{log.type}</Text>
|
|
194
|
+
<Text>{JSON.stringify(log.payload, null, 2)}</Text>
|
|
195
|
+
</View>
|
|
196
|
+
))}
|
|
197
|
+
</ScrollView>
|
|
128
198
|
</View>
|
|
129
199
|
);
|
|
130
200
|
};
|
|
@@ -134,79 +204,227 @@ const PaymentScreen = () => {
|
|
|
134
204
|
|
|
135
205
|
```tsx
|
|
136
206
|
import React, { useEffect } from 'react';
|
|
137
|
-
import { View, Text,
|
|
138
|
-
import { useEMVPayment } from 'quivio-transaction-processor';
|
|
207
|
+
import { View, Text, TouchableOpacity, ScrollView } from 'react-native';
|
|
208
|
+
import { PaymentProvider, useEMVPayment, EMVConfig } from 'quivio-transaction-processor';
|
|
209
|
+
|
|
210
|
+
const emvConfig: EMVConfig = {
|
|
211
|
+
merchantID: "YOUR_MERCHANT_ID",
|
|
212
|
+
onlineMerchantID: "YOUR_ONLINE_MERCHANT_ID",
|
|
213
|
+
isSandBox: true,
|
|
214
|
+
secureDeviceName: "YOUR_DEVICE_NAME",
|
|
215
|
+
operatorID: "YOUR_OPERATOR_ID",
|
|
216
|
+
posPackageID: "com.your_app:1.0"
|
|
217
|
+
};
|
|
139
218
|
|
|
140
219
|
const AdvancedPaymentScreen = () => {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
posPackageID: "YOUR_POS_PACKAGE_ID"
|
|
148
|
-
};
|
|
220
|
+
return (
|
|
221
|
+
<PaymentProvider config={emvConfig}>
|
|
222
|
+
<AdvancedPaymentContent />
|
|
223
|
+
</PaymentProvider>
|
|
224
|
+
);
|
|
225
|
+
};
|
|
149
226
|
|
|
227
|
+
const AdvancedPaymentContent = () => {
|
|
150
228
|
const {
|
|
229
|
+
logs,
|
|
151
230
|
isDeviceConnected,
|
|
152
|
-
isInitialized,
|
|
153
231
|
loading,
|
|
232
|
+
isInitialized,
|
|
154
233
|
handleCardPayment,
|
|
155
234
|
handleInHousePayment,
|
|
156
235
|
runRecurringTransaction,
|
|
236
|
+
replaceCardInRecurring,
|
|
157
237
|
setupConfig,
|
|
158
238
|
pingConfig,
|
|
159
239
|
clearAllTransactions,
|
|
160
240
|
cancelOperation,
|
|
161
241
|
subscribeToEvent,
|
|
162
242
|
unsubscribeFromEvent,
|
|
163
|
-
EVENTS
|
|
164
|
-
|
|
165
|
-
} = useEMVPayment(emvConfig);
|
|
243
|
+
EVENTS
|
|
244
|
+
} = useEMVPayment();
|
|
166
245
|
|
|
167
246
|
useEffect(() => {
|
|
168
247
|
// Subscribe to payment events
|
|
169
|
-
const
|
|
248
|
+
const saleListener = subscribeToEvent(EVENTS.onSaleTransactionCompleted, (payload) => {
|
|
170
249
|
console.log('Sale completed:', payload);
|
|
171
250
|
// Handle successful sale transaction
|
|
172
|
-
};
|
|
251
|
+
});
|
|
173
252
|
|
|
174
|
-
const
|
|
253
|
+
const cardReadListener = subscribeToEvent(EVENTS.onCardReadSuccessfully, (payload) => {
|
|
175
254
|
console.log('Card read successfully:', payload);
|
|
176
255
|
// Handle card read event
|
|
177
|
-
};
|
|
256
|
+
});
|
|
178
257
|
|
|
179
|
-
const
|
|
258
|
+
const errorListener = subscribeToEvent(EVENTS.onError, (payload) => {
|
|
180
259
|
console.error('Payment error:', payload);
|
|
181
260
|
// Handle error events
|
|
182
|
-
};
|
|
261
|
+
});
|
|
183
262
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
263
|
+
const configSuccessListener = subscribeToEvent(EVENTS.onConfigCompleted, (payload) => {
|
|
264
|
+
console.log('Configuration completed:', payload);
|
|
265
|
+
// Handle successful configuration
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
const deviceConnectedListener = subscribeToEvent(EVENTS.onConfigPingSuccess, (payload) => {
|
|
269
|
+
console.log('Device connected:', payload);
|
|
270
|
+
// Handle device connection success
|
|
271
|
+
});
|
|
188
272
|
|
|
189
273
|
// Cleanup on unmount
|
|
190
274
|
return () => {
|
|
191
|
-
unsubscribeFromEvent(EVENTS.onSaleTransactionCompleted,
|
|
192
|
-
unsubscribeFromEvent(EVENTS.onCardReadSuccessfully,
|
|
193
|
-
unsubscribeFromEvent(EVENTS.onError,
|
|
275
|
+
if (saleListener) unsubscribeFromEvent(EVENTS.onSaleTransactionCompleted, saleListener.listener);
|
|
276
|
+
if (cardReadListener) unsubscribeFromEvent(EVENTS.onCardReadSuccessfully, cardReadListener.listener);
|
|
277
|
+
if (errorListener) unsubscribeFromEvent(EVENTS.onError, errorListener.listener);
|
|
278
|
+
if (configSuccessListener) unsubscribeFromEvent(EVENTS.onConfigCompleted, configSuccessListener.listener);
|
|
279
|
+
if (deviceConnectedListener) unsubscribeFromEvent(EVENTS.onConfigPingSuccess, deviceConnectedListener.listener);
|
|
194
280
|
};
|
|
195
|
-
}, []);
|
|
281
|
+
}, [subscribeToEvent, unsubscribeFromEvent, EVENTS]);
|
|
196
282
|
|
|
197
283
|
return (
|
|
198
|
-
<View>
|
|
199
|
-
<Text
|
|
200
|
-
|
|
284
|
+
<View style={{ flex: 1, padding: 16 }}>
|
|
285
|
+
<Text style={{ fontSize: 18, fontWeight: 'bold', marginBottom: 10 }}>
|
|
286
|
+
Status: {isInitialized ? '✅ Initialized' : '❌ Not Initialized'}
|
|
287
|
+
</Text>
|
|
288
|
+
<Text style={{ fontSize: 16, marginBottom: 10 }}>
|
|
289
|
+
Device: {isDeviceConnected ? '✅ Connected' : '❌ Not Connected'}
|
|
290
|
+
</Text>
|
|
291
|
+
|
|
292
|
+
<View style={{ flexDirection: 'row', flexWrap: 'wrap', gap: 10, marginBottom: 10 }}>
|
|
293
|
+
<TouchableOpacity
|
|
294
|
+
style={{
|
|
295
|
+
backgroundColor: '#4CAF50',
|
|
296
|
+
padding: 10,
|
|
297
|
+
borderRadius: 8,
|
|
298
|
+
flex: 1,
|
|
299
|
+
minWidth: 120
|
|
300
|
+
}}
|
|
301
|
+
onPress={setupConfig}
|
|
302
|
+
disabled={loading}
|
|
303
|
+
>
|
|
304
|
+
<Text style={{ color: 'white', textAlign: 'center', fontSize: 12 }}>
|
|
305
|
+
Setup Config
|
|
306
|
+
</Text>
|
|
307
|
+
</TouchableOpacity>
|
|
308
|
+
|
|
309
|
+
<TouchableOpacity
|
|
310
|
+
style={{
|
|
311
|
+
backgroundColor: '#2196F3',
|
|
312
|
+
padding: 10,
|
|
313
|
+
borderRadius: 8,
|
|
314
|
+
flex: 1,
|
|
315
|
+
minWidth: 120
|
|
316
|
+
}}
|
|
317
|
+
onPress={pingConfig}
|
|
318
|
+
disabled={loading}
|
|
319
|
+
>
|
|
320
|
+
<Text style={{ color: 'white', textAlign: 'center', fontSize: 12 }}>
|
|
321
|
+
Ping Config
|
|
322
|
+
</Text>
|
|
323
|
+
</TouchableOpacity>
|
|
324
|
+
</View>
|
|
201
325
|
|
|
202
|
-
<
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
326
|
+
<View style={{ flexDirection: 'row', flexWrap: 'wrap', gap: 10, marginBottom: 10 }}>
|
|
327
|
+
<TouchableOpacity
|
|
328
|
+
style={{
|
|
329
|
+
backgroundColor: (loading || !isDeviceConnected) ? '#ccc' : '#9C27B0',
|
|
330
|
+
padding: 10,
|
|
331
|
+
borderRadius: 8,
|
|
332
|
+
flex: 1,
|
|
333
|
+
minWidth: 120
|
|
334
|
+
}}
|
|
335
|
+
onPress={() => handleCardPayment('5.00')}
|
|
336
|
+
disabled={loading || !isDeviceConnected}
|
|
337
|
+
>
|
|
338
|
+
<Text style={{ color: 'white', textAlign: 'center', fontSize: 12 }}>
|
|
339
|
+
EMV Sale
|
|
340
|
+
</Text>
|
|
341
|
+
</TouchableOpacity>
|
|
342
|
+
|
|
343
|
+
<TouchableOpacity
|
|
344
|
+
style={{
|
|
345
|
+
backgroundColor: (loading || !isDeviceConnected) ? '#ccc' : '#FF5722',
|
|
346
|
+
padding: 10,
|
|
347
|
+
borderRadius: 8,
|
|
348
|
+
flex: 1,
|
|
349
|
+
minWidth: 120
|
|
350
|
+
}}
|
|
351
|
+
onPress={handleInHousePayment}
|
|
352
|
+
disabled={loading || !isDeviceConnected}
|
|
353
|
+
>
|
|
354
|
+
<Text style={{ color: 'white', textAlign: 'center', fontSize: 12 }}>
|
|
355
|
+
In-House
|
|
356
|
+
</Text>
|
|
357
|
+
</TouchableOpacity>
|
|
358
|
+
</View>
|
|
208
359
|
|
|
209
|
-
{
|
|
360
|
+
<View style={{ flexDirection: 'row', flexWrap: 'wrap', gap: 10, marginBottom: 10 }}>
|
|
361
|
+
<TouchableOpacity
|
|
362
|
+
style={{
|
|
363
|
+
backgroundColor: (loading || !isDeviceConnected) ? '#ccc' : '#607D8B',
|
|
364
|
+
padding: 10,
|
|
365
|
+
borderRadius: 8,
|
|
366
|
+
flex: 1,
|
|
367
|
+
minWidth: 120
|
|
368
|
+
}}
|
|
369
|
+
onPress={() => runRecurringTransaction('5.00')}
|
|
370
|
+
disabled={loading || !isDeviceConnected}
|
|
371
|
+
>
|
|
372
|
+
<Text style={{ color: 'white', textAlign: 'center', fontSize: 12 }}>
|
|
373
|
+
Recurring
|
|
374
|
+
</Text>
|
|
375
|
+
</TouchableOpacity>
|
|
376
|
+
|
|
377
|
+
<TouchableOpacity
|
|
378
|
+
style={{
|
|
379
|
+
backgroundColor: (loading || !isDeviceConnected) ? '#ccc' : '#795548',
|
|
380
|
+
padding: 10,
|
|
381
|
+
borderRadius: 8,
|
|
382
|
+
flex: 1,
|
|
383
|
+
minWidth: 120
|
|
384
|
+
}}
|
|
385
|
+
onPress={replaceCardInRecurring}
|
|
386
|
+
disabled={loading || !isDeviceConnected}
|
|
387
|
+
>
|
|
388
|
+
<Text style={{ color: 'white', textAlign: 'center', fontSize: 12 }}>
|
|
389
|
+
Replace Card
|
|
390
|
+
</Text>
|
|
391
|
+
</TouchableOpacity>
|
|
392
|
+
</View>
|
|
393
|
+
|
|
394
|
+
<TouchableOpacity
|
|
395
|
+
style={{
|
|
396
|
+
backgroundColor: '#F44336',
|
|
397
|
+
padding: 10,
|
|
398
|
+
borderRadius: 8,
|
|
399
|
+
marginBottom: 10
|
|
400
|
+
}}
|
|
401
|
+
onPress={clearAllTransactions}
|
|
402
|
+
disabled={loading}
|
|
403
|
+
>
|
|
404
|
+
<Text style={{ color: 'white', textAlign: 'center' }}>
|
|
405
|
+
Clear Logs
|
|
406
|
+
</Text>
|
|
407
|
+
</TouchableOpacity>
|
|
408
|
+
|
|
409
|
+
{loading && (
|
|
410
|
+
<Text style={{ textAlign: 'center', color: '#FF9800', marginBottom: 10 }}>
|
|
411
|
+
Processing...
|
|
412
|
+
</Text>
|
|
413
|
+
)}
|
|
414
|
+
|
|
415
|
+
<ScrollView style={{ flex: 1 }}>
|
|
416
|
+
{logs.map((log, index) => (
|
|
417
|
+
<View key={index} style={{
|
|
418
|
+
backgroundColor: '#f5f5f5',
|
|
419
|
+
padding: 8,
|
|
420
|
+
marginBottom: 5,
|
|
421
|
+
borderRadius: 4
|
|
422
|
+
}}>
|
|
423
|
+
<Text style={{ fontWeight: 'bold' }}>{log.type}</Text>
|
|
424
|
+
<Text>{JSON.stringify(log.payload, null, 2)}</Text>
|
|
425
|
+
</View>
|
|
426
|
+
))}
|
|
427
|
+
</ScrollView>
|
|
210
428
|
</View>
|
|
211
429
|
);
|
|
212
430
|
};
|
|
@@ -214,15 +432,16 @@ const AdvancedPaymentScreen = () => {
|
|
|
214
432
|
|
|
215
433
|
## 📚 API Reference
|
|
216
434
|
|
|
217
|
-
###
|
|
435
|
+
### PaymentProvider Component
|
|
218
436
|
|
|
219
|
-
The main
|
|
437
|
+
The main provider component that manages EMV payment state and initialization.
|
|
220
438
|
|
|
221
|
-
####
|
|
439
|
+
#### Props
|
|
222
440
|
|
|
223
|
-
|
|
|
224
|
-
|
|
441
|
+
| Prop | Type | Required | Description |
|
|
442
|
+
|------|------|----------|-------------|
|
|
225
443
|
| `config` | `EMVConfig` | Yes | EMV configuration object |
|
|
444
|
+
| `children` | `React.ReactNode` | Yes | Child components |
|
|
226
445
|
|
|
227
446
|
#### Configuration Object
|
|
228
447
|
|
|
@@ -233,10 +452,18 @@ interface EMVConfig {
|
|
|
233
452
|
isSandBox: boolean; // true for testing, false for production
|
|
234
453
|
secureDeviceName: string; // Terminal device name
|
|
235
454
|
operatorID: string; // Employee/operator ID
|
|
236
|
-
posPackageID: string; // App Bundle ID
|
|
455
|
+
posPackageID: string; // App Bundle ID and version
|
|
237
456
|
}
|
|
238
457
|
```
|
|
239
458
|
|
|
459
|
+
### useEMVPayment Hook
|
|
460
|
+
|
|
461
|
+
The main hook that provides all EMV payment functionality. Must be used within a `PaymentProvider`.
|
|
462
|
+
|
|
463
|
+
#### Parameters
|
|
464
|
+
|
|
465
|
+
None - the hook automatically uses the configuration from the `PaymentProvider`.
|
|
466
|
+
|
|
240
467
|
#### Returns
|
|
241
468
|
|
|
242
469
|
| Property | Type | Description |
|
|
@@ -248,12 +475,14 @@ interface EMVConfig {
|
|
|
248
475
|
| `handleCardPayment` | `(amount: string) => void` | Process EMV card payment |
|
|
249
476
|
| `handleInHousePayment` | `() => void` | Process in-house payment |
|
|
250
477
|
| `runRecurringTransaction` | `(amount: string) => void` | Process recurring payment |
|
|
478
|
+
| `replaceCardInRecurring` | `() => void` | Replace card in recurring setup |
|
|
251
479
|
| `setupConfig` | `() => void` | Setup device configuration |
|
|
252
480
|
| `pingConfig` | `() => void` | Ping device configuration |
|
|
481
|
+
| `clearTransactionListener` | `() => void` | Clear transaction listener |
|
|
253
482
|
| `clearAllTransactions` | `() => void` | Clear all transaction logs |
|
|
254
483
|
| `cancelOperation` | `() => void` | Cancel current operation |
|
|
255
484
|
| `initializeEMV` | `() => void` | Manually initialize EMV |
|
|
256
|
-
| `subscribeToEvent` | `(eventName, callback) =>
|
|
485
|
+
| `subscribeToEvent` | `(eventName, callback) => Listener` | Subscribe to events |
|
|
257
486
|
| `unsubscribeFromEvent` | `(eventName, callback) => void` | Unsubscribe from events |
|
|
258
487
|
| `EVENTS` | `Record<EMVEventName, EMVEventName>` | Available event names |
|
|
259
488
|
|
|
@@ -387,33 +616,51 @@ The hook provides detailed logging through the `logs` array. Display these logs
|
|
|
387
616
|
|
|
388
617
|
## 📱 Example Implementation
|
|
389
618
|
|
|
390
|
-
The package includes a complete example implementation
|
|
619
|
+
The package includes a complete example implementation that demonstrates:
|
|
391
620
|
|
|
392
|
-
- Complete UI implementation
|
|
393
|
-
- Event handling
|
|
394
|
-
- Error management
|
|
395
|
-
- Loading states
|
|
396
|
-
- Transaction logging
|
|
397
|
-
- Multiple payment types
|
|
621
|
+
- Complete UI implementation with modern styling
|
|
622
|
+
- Event handling with proper cleanup
|
|
623
|
+
- Error management and user feedback
|
|
624
|
+
- Loading states and disabled buttons
|
|
625
|
+
- Transaction logging with formatted display
|
|
626
|
+
- Multiple payment types (sale, in-house, recurring, card replacement)
|
|
398
627
|
|
|
399
|
-
|
|
628
|
+
### Using the Complete Example Component
|
|
400
629
|
|
|
401
630
|
```tsx
|
|
402
|
-
import
|
|
631
|
+
import React from 'react';
|
|
632
|
+
import { EMVPaymentScreenExample, EMVConfig } from 'quivio-transaction-processor';
|
|
403
633
|
|
|
404
|
-
const
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
634
|
+
const App = () => {
|
|
635
|
+
const emvConfig: EMVConfig = {
|
|
636
|
+
merchantID: "YOUR_MERCHANT_ID",
|
|
637
|
+
onlineMerchantID: "YOUR_ONLINE_MERCHANT_ID",
|
|
638
|
+
isSandBox: true,
|
|
639
|
+
secureDeviceName: "YOUR_DEVICE_NAME",
|
|
640
|
+
operatorID: "YOUR_OPERATOR_ID",
|
|
641
|
+
posPackageID: "com.your_app:1.0"
|
|
642
|
+
};
|
|
412
643
|
|
|
413
|
-
|
|
414
|
-
|
|
644
|
+
return <EMVPaymentScreenExample config={emvConfig} />;
|
|
645
|
+
};
|
|
415
646
|
```
|
|
416
647
|
|
|
648
|
+
### Example Features
|
|
649
|
+
|
|
650
|
+
The example component includes:
|
|
651
|
+
|
|
652
|
+
- **Device Status Display**: Real-time connection status with visual indicators
|
|
653
|
+
- **Configuration Management**: Setup and ping device configuration
|
|
654
|
+
- **Payment Operations**:
|
|
655
|
+
- Credit card payments
|
|
656
|
+
- In-house payment collection
|
|
657
|
+
- Recurring payment setup
|
|
658
|
+
- Card replacement in recurring setups
|
|
659
|
+
- **Transaction Logging**: Detailed logs with timestamps and formatted display
|
|
660
|
+
- **Error Handling**: Comprehensive error management with user feedback
|
|
661
|
+
- **Loading States**: Visual feedback during operations
|
|
662
|
+
- **Modern UI**: Styled buttons and responsive layout
|
|
663
|
+
|
|
417
664
|
## 🤝 Contributing
|
|
418
665
|
|
|
419
666
|
We welcome contributions! Please follow these steps:
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { EMVConfig, PaymentContextType } from "./types";
|
|
3
|
+
declare const PaymentContext: React.Context<PaymentContextType | undefined>;
|
|
4
|
+
declare function PaymentProvider({ children, config }: {
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
config: EMVConfig;
|
|
7
|
+
}): React.JSX.Element;
|
|
8
|
+
export { PaymentProvider };
|
|
9
|
+
export { PaymentContext };
|