
Research
Malicious npm Packages Impersonate Flashbots SDKs, Targeting Ethereum Wallet Credentials
Four npm packages disguised as cryptographic tools steal developer credentials and send them to attacker-controlled Telegram infrastructure.
quivio-transaction-processor
Advanced tools
React Native hook for Card payment integration with DataCap
A comprehensive React Native library for EMV payment integration with DataCap terminals. This package provides a robust, TypeScript-first approach to integrating EMV card reader functionality into React Native Android applications.
npm install quivio-transaction-processor
# or
yarn add quivio-transaction-processor
The package uses React Context for state management, providing:
// Wrap your app or component with PaymentProvider
<PaymentProvider config={emvConfig}>
<YourPaymentComponent />
</PaymentProvider>
// Use the hook in any child component
const { handleCardPayment, isDeviceConnected } = useEMVPayment();
This package includes native Android libraries that require proper configuration. Follow these steps carefully:
First, ensure the dsiEMVAndroid.aar
file is present in your android/app/libs/
folder. This file contains the core EMV functionality.
Important: Create the libs
folder if it doesn't exist in your android/app/
directory.
Add the following lines to your android/settings.gradle
:
include ':emvCardReaderLib'
project(':emvCardReaderLib').projectDir = file('../node_modules/quivio-transaction-processor/libs/emvCardReaderLib')
include ':emvNative'
project(':emvNative').projectDir = file('../node_modules/quivio-transaction-processor/libs/emvNative')
Add the following dependencies to your android/app/build.gradle
:
dependencies {
// ... other dependencies
implementation files("libs/dsiEMVAndroid.aar")
implementation project(":emvCardReaderLib")
implementation project(":emvNative")
}
Critical: The implementation files("libs/dsiEMVAndroid.aar")
line is essential for EMV functionality.
Add the import and package registration to your android/app/src/main/java/com/your-app/MainApplication.kt
:
import com.quivio_transaction_processor.EMVPaymentPackage
class MainApplication : Application(), ReactApplication {
private val mReactNativeHost = object : ReactNativeHost(this) {
override fun getPackages(): List<ReactPackage> {
return PackageList(this).packages.apply {
// Add the EMV payment package
add(EMVPaymentPackage())
}
}
// ... rest of your MainApplication code
}
}
import React from 'react';
import { View, Text, TouchableOpacity, ScrollView } from 'react-native';
import { PaymentProvider, useEMVPayment, EMVConfig } from 'quivio-transaction-processor';
const emvConfig: EMVConfig = {
merchantID: "YOUR_MERCHANT_ID",
onlineMerchantID: "YOUR_ONLINE_MERCHANT_ID",
isSandBox: true, // true for testing, false for production
secureDeviceName: "YOUR_DEVICE_NAME",
operatorID: "YOUR_OPERATOR_ID",
posPackageID: "com.your_app:1.0" // App Bundle ID and version
};
const PaymentScreen = () => {
return (
<PaymentProvider config={emvConfig}>
<PaymentContent />
</PaymentProvider>
);
};
const PaymentContent = () => {
const {
logs,
isDeviceConnected,
loading,
isInitialized,
handleCardPayment,
setupConfig,
EVENTS
} = useEMVPayment();
return (
<View style={{ flex: 1, padding: 16 }}>
<Text style={{ fontSize: 18, fontWeight: 'bold', marginBottom: 10 }}>
Status: {isInitialized ? '✅ Initialized' : '❌ Not Initialized'}
</Text>
<Text style={{ fontSize: 16, marginBottom: 10 }}>
Device: {isDeviceConnected ? '✅ Connected' : '❌ Not Connected'}
</Text>
<TouchableOpacity
style={{
backgroundColor: isDeviceConnected ? '#4CAF50' : '#FF9800',
padding: 12,
borderRadius: 8,
marginBottom: 10
}}
onPress={setupConfig}
disabled={loading}
>
<Text style={{ color: 'white', textAlign: 'center' }}>
{isDeviceConnected ? 'Configuration Ready' : 'Setup Configuration'}
</Text>
</TouchableOpacity>
<TouchableOpacity
style={{
backgroundColor: (loading || !isDeviceConnected) ? '#ccc' : '#2196F3',
padding: 12,
borderRadius: 8,
marginBottom: 10
}}
onPress={() => handleCardPayment('5.00')}
disabled={loading || !isDeviceConnected}
>
<Text style={{ color: 'white', textAlign: 'center' }}>
Process Payment ($5.00)
</Text>
</TouchableOpacity>
{loading && (
<Text style={{ textAlign: 'center', color: '#FF9800', marginBottom: 10 }}>
Processing...
</Text>
)}
<ScrollView style={{ flex: 1 }}>
{logs.map((log, index) => (
<View key={index} style={{
backgroundColor: '#f5f5f5',
padding: 8,
marginBottom: 5,
borderRadius: 4
}}>
<Text style={{ fontWeight: 'bold' }}>{log.type}</Text>
<Text>{JSON.stringify(log.payload, null, 2)}</Text>
</View>
))}
</ScrollView>
</View>
);
};
import React, { useEffect } from 'react';
import { View, Text, TouchableOpacity, ScrollView } from 'react-native';
import { PaymentProvider, useEMVPayment, EMVConfig } from 'quivio-transaction-processor';
const emvConfig: EMVConfig = {
merchantID: "YOUR_MERCHANT_ID",
onlineMerchantID: "YOUR_ONLINE_MERCHANT_ID",
isSandBox: true,
secureDeviceName: "YOUR_DEVICE_NAME",
operatorID: "YOUR_OPERATOR_ID",
posPackageID: "com.your_app:1.0"
};
const AdvancedPaymentScreen = () => {
return (
<PaymentProvider config={emvConfig}>
<AdvancedPaymentContent />
</PaymentProvider>
);
};
const AdvancedPaymentContent = () => {
const {
logs,
isDeviceConnected,
loading,
isInitialized,
handleCardPayment,
handleInHousePayment,
runRecurringTransaction,
replaceCardInRecurring,
setupConfig,
pingConfig,
clearAllTransactions,
cancelOperation,
subscribeToEvent,
unsubscribeFromEvent,
EVENTS
} = useEMVPayment();
useEffect(() => {
// Subscribe to payment events
const saleListener = subscribeToEvent(EVENTS.onSaleTransactionCompleted, (payload) => {
console.log('Sale completed:', payload);
// Handle successful sale transaction
});
const cardReadListener = subscribeToEvent(EVENTS.onCardReadSuccessfully, (payload) => {
console.log('Card read successfully:', payload);
// Handle card read event
});
const errorListener = subscribeToEvent(EVENTS.onError, (payload) => {
console.error('Payment error:', payload);
// Handle error events
});
const configSuccessListener = subscribeToEvent(EVENTS.onConfigCompleted, (payload) => {
console.log('Configuration completed:', payload);
// Handle successful configuration
});
const deviceConnectedListener = subscribeToEvent(EVENTS.onConfigPingSuccess, (payload) => {
console.log('Device connected:', payload);
// Handle device connection success
});
// Cleanup on unmount
return () => {
if (saleListener) unsubscribeFromEvent(EVENTS.onSaleTransactionCompleted, saleListener.listener);
if (cardReadListener) unsubscribeFromEvent(EVENTS.onCardReadSuccessfully, cardReadListener.listener);
if (errorListener) unsubscribeFromEvent(EVENTS.onError, errorListener.listener);
if (configSuccessListener) unsubscribeFromEvent(EVENTS.onConfigCompleted, configSuccessListener.listener);
if (deviceConnectedListener) unsubscribeFromEvent(EVENTS.onConfigPingSuccess, deviceConnectedListener.listener);
};
}, [subscribeToEvent, unsubscribeFromEvent, EVENTS]);
return (
<View style={{ flex: 1, padding: 16 }}>
<Text style={{ fontSize: 18, fontWeight: 'bold', marginBottom: 10 }}>
Status: {isInitialized ? '✅ Initialized' : '❌ Not Initialized'}
</Text>
<Text style={{ fontSize: 16, marginBottom: 10 }}>
Device: {isDeviceConnected ? '✅ Connected' : '❌ Not Connected'}
</Text>
<View style={{ flexDirection: 'row', flexWrap: 'wrap', gap: 10, marginBottom: 10 }}>
<TouchableOpacity
style={{
backgroundColor: '#4CAF50',
padding: 10,
borderRadius: 8,
flex: 1,
minWidth: 120
}}
onPress={setupConfig}
disabled={loading}
>
<Text style={{ color: 'white', textAlign: 'center', fontSize: 12 }}>
Setup Config
</Text>
</TouchableOpacity>
<TouchableOpacity
style={{
backgroundColor: '#2196F3',
padding: 10,
borderRadius: 8,
flex: 1,
minWidth: 120
}}
onPress={pingConfig}
disabled={loading}
>
<Text style={{ color: 'white', textAlign: 'center', fontSize: 12 }}>
Ping Config
</Text>
</TouchableOpacity>
</View>
<View style={{ flexDirection: 'row', flexWrap: 'wrap', gap: 10, marginBottom: 10 }}>
<TouchableOpacity
style={{
backgroundColor: (loading || !isDeviceConnected) ? '#ccc' : '#9C27B0',
padding: 10,
borderRadius: 8,
flex: 1,
minWidth: 120
}}
onPress={() => handleCardPayment('5.00')}
disabled={loading || !isDeviceConnected}
>
<Text style={{ color: 'white', textAlign: 'center', fontSize: 12 }}>
EMV Sale
</Text>
</TouchableOpacity>
<TouchableOpacity
style={{
backgroundColor: (loading || !isDeviceConnected) ? '#ccc' : '#FF5722',
padding: 10,
borderRadius: 8,
flex: 1,
minWidth: 120
}}
onPress={handleInHousePayment}
disabled={loading || !isDeviceConnected}
>
<Text style={{ color: 'white', textAlign: 'center', fontSize: 12 }}>
In-House
</Text>
</TouchableOpacity>
</View>
<View style={{ flexDirection: 'row', flexWrap: 'wrap', gap: 10, marginBottom: 10 }}>
<TouchableOpacity
style={{
backgroundColor: (loading || !isDeviceConnected) ? '#ccc' : '#607D8B',
padding: 10,
borderRadius: 8,
flex: 1,
minWidth: 120
}}
onPress={() => runRecurringTransaction('5.00')}
disabled={loading || !isDeviceConnected}
>
<Text style={{ color: 'white', textAlign: 'center', fontSize: 12 }}>
Recurring
</Text>
</TouchableOpacity>
<TouchableOpacity
style={{
backgroundColor: (loading || !isDeviceConnected) ? '#ccc' : '#795548',
padding: 10,
borderRadius: 8,
flex: 1,
minWidth: 120
}}
onPress={replaceCardInRecurring}
disabled={loading || !isDeviceConnected}
>
<Text style={{ color: 'white', textAlign: 'center', fontSize: 12 }}>
Replace Card
</Text>
</TouchableOpacity>
</View>
<TouchableOpacity
style={{
backgroundColor: '#F44336',
padding: 10,
borderRadius: 8,
marginBottom: 10
}}
onPress={clearAllTransactions}
disabled={loading}
>
<Text style={{ color: 'white', textAlign: 'center' }}>
Clear Logs
</Text>
</TouchableOpacity>
{loading && (
<Text style={{ textAlign: 'center', color: '#FF9800', marginBottom: 10 }}>
Processing...
</Text>
)}
<ScrollView style={{ flex: 1 }}>
{logs.map((log, index) => (
<View key={index} style={{
backgroundColor: '#f5f5f5',
padding: 8,
marginBottom: 5,
borderRadius: 4
}}>
<Text style={{ fontWeight: 'bold' }}>{log.type}</Text>
<Text>{JSON.stringify(log.payload, null, 2)}</Text>
</View>
))}
</ScrollView>
</View>
);
};
The main provider component that manages EMV payment state and initialization.
Prop | Type | Required | Description |
---|---|---|---|
config | EMVConfig | Yes | EMV configuration object |
children | React.ReactNode | Yes | Child components |
interface EMVConfig {
merchantID: string; // Your merchant ID
onlineMerchantID: string; // Your online merchant ID
isSandBox: boolean; // true for testing, false for production
secureDeviceName: string; // Terminal device name
operatorID: string; // Employee/operator ID
posPackageID: string; // App Bundle ID and version
}
The main hook that provides all EMV payment functionality. Must be used within a PaymentProvider
.
None - the hook automatically uses the configuration from the PaymentProvider
.
Property | Type | Description |
---|---|---|
logs | CallbackLog[] | Array of transaction logs for debugging |
isDeviceConnected | boolean | Device connection status |
isInitialized | boolean | EMV initialization status |
loading | boolean | Loading state for operations |
handleCardPayment | (amount: string) => void | Process EMV card payment |
handleInHousePayment | () => void | Process in-house payment |
runRecurringTransaction | (amount: string) => void | Process recurring payment |
replaceCardInRecurring | () => void | Replace card in recurring setup |
setupConfig | () => void | Setup device configuration |
pingConfig | () => void | Ping device configuration |
clearTransactionListener | () => void | Clear transaction listener |
clearAllTransactions | () => void | Clear all transaction logs |
cancelOperation | () => void | Cancel current operation |
initializeEMV | () => void | Manually initialize EMV |
subscribeToEvent | (eventName, callback) => Listener | Subscribe to events |
unsubscribeFromEvent | (eventName, callback) => void | Unsubscribe from events |
EVENTS | Record<EMVEventName, EMVEventName> | Available event names |
The following events are available for subscription:
Event | Description | Payload |
---|---|---|
onError | Payment or device errors | Error message |
onCardReadSuccessfully | Card successfully read | Card data with BIN |
onSaleTransactionCompleted | Sale transaction completed | Transaction details |
onRecurringSaleCompleted | Recurring sale completed | Recurring transaction details |
onShowMessage | Display messages from device | Message content |
onConfigError | Configuration errors | Error details |
onConfigPingFailed | Configuration ping failed | Failure details |
onConfigPingSuccess | Configuration ping successful | Success details |
onConfigCompleted | Configuration setup completed | Configuration details |
interface SaleTransactionResponse {
cmdStatus: string;
textResponse: string;
sequenceNo: string;
userTrace: string;
acctNo: string;
cardType: string;
authCode: string;
captureStatus: string;
refNo: string;
invoiceNo: string;
amount: { purchase: string };
acqRefData: string;
entryMethod: string;
date: string;
time: string;
}
interface RecurringTransactionResponse {
cmdStatus: string;
textResponse: string;
sequenceNo: string;
userTrace: string;
captureStatus: string;
refNo: string;
invoiceNo: string;
amount: { purchase: string };
cardholderName: string;
acctNo: string;
cardType: string;
authCode: string;
entryMethod: string;
recordNo: string;
recurringData: string;
acqRefData: string;
date: string;
time: string;
payAPIId: string;
}
Symptoms: isDeviceConnected
remains false
Solutions:
Symptoms: Transactions fail or timeout Solutions:
Symptoms: No event callbacks received Solutions:
Symptoms: isInitialized
remains false
Solutions:
posPackageID
matches your app's bundle IDThe hook provides detailed logging through the logs
array. Display these logs to debug issues:
{logs.map((log, index) => (
<View key={index} style={styles.logItem}>
<Text style={styles.logType}>{log.type}</Text>
<Text style={styles.logPayload}>
{typeof log.payload === 'object'
? JSON.stringify(log.payload, null, 2)
: String(log.payload)}
</Text>
<Text style={styles.logTime}>
{new Date(log.timestamp).toLocaleTimeString()}
</Text>
</View>
))}
The package includes a complete example implementation that demonstrates:
import React from 'react';
import { EMVPaymentScreenExample, EMVConfig } from 'quivio-transaction-processor';
const App = () => {
const emvConfig: EMVConfig = {
merchantID: "YOUR_MERCHANT_ID",
onlineMerchantID: "YOUR_ONLINE_MERCHANT_ID",
isSandBox: true,
secureDeviceName: "YOUR_DEVICE_NAME",
operatorID: "YOUR_OPERATOR_ID",
posPackageID: "com.your_app:1.0"
};
return <EMVPaymentScreenExample config={emvConfig} />;
};
The example component includes:
We welcome contributions! Please follow these steps:
git checkout -b feature/amazing-feature
)git commit -m 'Add some amazing feature'
)git push origin feature/amazing-feature
)# Clone the repository
git clone https://github.com/RohanAppinventiv/RN-Bridge-App.git
# Install dependencies
npm install
# Build the package
npm run build
# Run tests
npm test
This project is licensed under the MIT License - see the LICENSE file for details.
For support and questions:
FAQs
React Native hook for Card payment integration with DataCap
We found that quivio-transaction-processor demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Four npm packages disguised as cryptographic tools steal developer credentials and send them to attacker-controlled Telegram infrastructure.
Security News
Ruby maintainers from Bundler and rbenv teams are building rv to bring Python uv's speed and unified tooling approach to Ruby development.
Security News
Following last week’s supply chain attack, Nx published findings on the GitHub Actions exploit and moved npm publishing to Trusted Publishers.