@cardql/react-native-tap
Version:
CardQL SDK for React Native tap-to-pay for secure in-person payments
380 lines (304 loc) • 8.98 kB
Markdown
# @cardql/react-native-tap
CardQL SDK for React Native tap-to-pay for secure in-person payments.
## Features
- **Payment Terminal Integration**: Built on certified payment infrastructure
- **Multiple Reader Support**: Works with certified card readers
- **Local Mobile Payments**: Tap-to-phone payments using device NFC (where supported)
- **Real-time Processing**: Live payment status and transaction updates
- **TypeScript Support**: Fully typed API with comprehensive type definitions
- **Error Handling**: Detailed error reporting with user-friendly messages
- **Offline Support**: Inherits offline capabilities from @cardql/react-native
- **Receipt Generation**: Automatic receipt creation with transaction details
## Installation
```bash
npm install @cardql/react-native-tap
# or
yarn add @cardql/react-native-tap
```
### Peer Dependencies
This package requires the following peer dependencies:
```bash
npm install @cardql/react-native-tap react react-native
```
## Quick Start
### 1. Setup Payment Terminal Provider
First, wrap your app with the payment terminal provider and implement a token provider:
```tsx
import React from "react";
import { PaymentTerminalProvider } from "@cardql/react-native-tap";
function App() {
const fetchTokenProvider = async () => {
// Fetch connection token from your backend
const response = await fetch(`${API_URL}/connection_token`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
});
const { secret } = await response.json();
return secret;
};
return (
<PaymentTerminalProvider
logLevel="verbose"
tokenProvider={fetchTokenProvider}>
{/* Your app components */}
</PaymentTerminalProvider>
);
}
```
### 2. Use the TapToPayReader Component
```tsx
import React from "react";
import { TapToPayReader } from "@cardql/react-native-tap";
function PaymentScreen() {
const fetchTokenProvider = async () => {
// Your token provider implementation
const response = await fetch(`${API_URL}/connection_token`, {
method: "POST",
});
const { secret } = await response.json();
return secret;
};
const handleSuccess = (result) => {
console.log("Payment successful:", result);
// Handle successful payment
};
const handleError = (error) => {
console.error("Payment failed:", error);
// Handle payment error
};
return (
<TapToPayReader
amount="10.00"
currency="USD"
merchantID="your-merchant-id"
userID="user-123"
tokenProvider={fetchTokenProvider}
onSuccess={handleSuccess}
onError={handleError}
autoInit={true}
autoDiscoverReaders={true}
simulated={__DEV__} // Use simulated readers in development
/>
);
}
```
### 3. Using the Hook Directly
For more control, use the `useTapToPay` hook:
```tsx
import React, { useEffect } from "react";
import { useTapToPay } from "@cardql/react-native-tap";
function CustomPaymentFlow() {
const fetchTokenProvider = async () => {
const response = await fetch(`${API_URL}/connection_token`, {
method: "POST",
});
const { secret } = await response.json();
return secret;
};
const tapToPay = useTapToPay({
config: {
merchantID: "your-merchant-id",
currency: "USD",
paymentConfig: {
tokenProvider: fetchTokenProvider,
logLevel: "info",
simulated: __DEV__,
},
},
readerConfig: {
discoveryMethod: "localMobile",
simulated: __DEV__,
},
events: {
onReaderDiscovered: (readers) => {
console.log("Found readers:", readers.length);
},
onReaderConnected: (reader) => {
console.log("Connected to reader:", reader.id);
},
onPaymentMethodCollected: (paymentMethod) => {
console.log("Payment method collected:", paymentMethod.type);
},
onSuccess: (result) => {
console.log("Payment successful:", result);
},
onError: (error) => {
console.error("Payment error:", error);
},
},
autoInit: true,
autoDiscoverReaders: true,
});
const handlePayment = async () => {
try {
const result = await tapToPay.processPayment({
amount: "25.00",
currency: "USD",
merchantID: "your-merchant-id",
userID: "user-123",
description: "Coffee and pastry",
});
if (result.success) {
console.log("Payment completed:", result.payment);
} else {
console.error("Payment failed:", result.error);
}
} catch (error) {
console.error("Payment processing error:", error);
}
};
return (
<View>
<Text>
Status: {tapToPay.isInitialized ? "Ready" : "Initializing..."}
</Text>
<Text>Readers: {tapToPay.discoveredReaders.length}</Text>
<Text>Connected: {tapToPay.connectedReader?.id || "None"}</Text>
<Button
title="Start Payment"
onPress={handlePayment}
disabled={!tapToPay.connectedReader || tapToPay.isCollectingPayment}
/>
</View>
);
}
```
## Reader Types
### Local Mobile (Tap-to-Phone)
Use your device's built-in NFC for contactless payments:
```tsx
const readerConfig = {
discoveryMethod: "localMobile",
simulated: false,
};
```
### Bluetooth Readers
Connect to certified Bluetooth card readers:
```tsx
const readerConfig = {
discoveryMethod: "bluetoothScan",
simulated: false,
};
```
### Internet Readers
Connect to internet-connected payment terminal readers:
```tsx
const readerConfig = {
discoveryMethod: "internet",
locationId: "your-location-id",
};
```
## Configuration
### TapToPayConfig
```tsx
interface TapToPayConfig {
merchantID: string;
currency?: string;
timeout?: number;
acceptedCardTypes?: CardType[];
paymentConfig: PaymentTerminalConfig;
captureMethod?: "automatic" | "manual";
customBranding?: {
primaryColor?: string;
logo?: string;
merchantName?: string;
};
}
```
### PaymentTerminalConfig
```tsx
interface PaymentTerminalConfig {
tokenProvider: () => Promise<string>;
logLevel?: "verbose" | "info" | "warn" | "error";
simulated?: boolean;
}
```
### CardReaderConfig
```tsx
interface CardReaderConfig {
discoveryMethod: "bluetoothScan" | "localMobile" | "internet";
simulated?: boolean;
locationId?: string;
autoConnect?: boolean;
enableTipping?: boolean;
skipTipping?: boolean;
}
```
## Payment Flow
1. **Initialize**: Terminal SDK initializes with your token provider
2. **Discover**: Find available card readers (automatic or manual)
3. **Connect**: Connect to a specific reader
4. **Create Payment Intent**: Initialize payment with amount and currency
5. **Collect Payment Method**: Reader captures card information
6. **Confirm Payment**: Process the payment through the payment gateway
7. **Complete**: Payment is confirmed and receipt is generated
## Error Handling
The SDK provides detailed error information:
```tsx
interface TapToPayError {
code: TapToPayErrorCode;
message: string;
details?: any;
gatewayError?: any;
userFriendlyMessage?: string;
canRetry?: boolean;
suggestedAction?: string;
}
```
Common error codes:
- `TERMINAL_NOT_SUPPORTED`: Device doesn't support payment terminal
- `READER_CONNECTION_FAILED`: Could not connect to card reader
- `PAYMENT_COLLECTION_FAILED`: Could not collect payment method
- `PAYMENT_CONFIRMATION_FAILED`: Could not confirm payment
- `TRANSACTION_DECLINED`: Payment was declined by issuer
## Events
Listen to payment flow events:
```tsx
const events = {
onReaderDiscovered: (readers: Reader[]) => void;
onReaderConnected: (reader: Reader) => void;
onReaderDisconnected: (reason?: string) => void;
onPaymentMethodCollected: (paymentMethod: PaymentMethod) => void;
onPaymentIntentCreated: (paymentIntent: PaymentIntent) => void;
onDisplayMessage: (message: string) => void;
onError: (error: TapToPayError) => void;
onSuccess: (result: TapPaymentResult) => void;
onCancel: () => void;
};
```
## Testing
### Simulated Mode
Enable simulated mode for testing:
```tsx
<TapToPayReader
simulated={true}
// ... other props
/>
```
### Test Cards
In simulated mode, use these test card numbers:
- Visa: `4242424242424242`
- Mastercard: `5555555555554444`
- American Express: `378282246310005`
## Requirements
### iOS
- iOS 15.1 or later
- NFC-capable device for local mobile payments
- Xcode 13 or later
### Android
- Android API level 26 (Android 8.0) or later
- NFC-capable device for local mobile payments
- compileSdkVersion 35
- targetSdkVersion 35
## Security
- All payment data is handled securely by the payment terminal
- Card data never touches your application
- PCI DSS compliant by design
- End-to-end encryption for all transactions
## Support
For support with payment terminal integration:
- [CardQL Documentation](https://docs.cardql.com)
## License
MIT License - see LICENSE file for details.