npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@cardql/react-native-tap

v1.0.1

Published

CardQL SDK for React Native tap-to-pay for secure in-person payments

Readme

@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

npm install @cardql/react-native-tap
# or
yarn add @cardql/react-native-tap

Peer Dependencies

This package requires the following peer dependencies:

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:

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

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:

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:

const readerConfig = {
  discoveryMethod: "localMobile",
  simulated: false,
};

Bluetooth Readers

Connect to certified Bluetooth card readers:

const readerConfig = {
  discoveryMethod: "bluetoothScan",
  simulated: false,
};

Internet Readers

Connect to internet-connected payment terminal readers:

const readerConfig = {
  discoveryMethod: "internet",
  locationId: "your-location-id",
};

Configuration

TapToPayConfig

interface TapToPayConfig {
  merchantID: string;
  currency?: string;
  timeout?: number;
  acceptedCardTypes?: CardType[];
  paymentConfig: PaymentTerminalConfig;
  captureMethod?: "automatic" | "manual";
  customBranding?: {
    primaryColor?: string;
    logo?: string;
    merchantName?: string;
  };
}

PaymentTerminalConfig

interface PaymentTerminalConfig {
  tokenProvider: () => Promise<string>;
  logLevel?: "verbose" | "info" | "warn" | "error";
  simulated?: boolean;
}

CardReaderConfig

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:

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:

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:

<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:

License

MIT License - see LICENSE file for details.