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

@woovi/react-native-tap-to-pix

v0.1.0

Published

Woovi's React Native library for BACEN's 'Pix por aproximação para Android' (Tap to Pix). Ships the HCE service, AID registration, Expo config plugin, and native bridge tuned for Woovi's Pix stack. Android only.

Readme

@woovibr/react-native-tap-to-pix

npm version platform BACEN Pix spec Woovi types license

Woovi's React Native library implementing BACEN's "Pix por aproximação para Android" (Tap to Pix) protocol end-to-end, tuned for the Woovi Pix stack. Ships the Android HCE service, the AID registration, the Expo config plugin, and a native bridge for the "Default contactless payment app" Android settings. Android only.

iOS is not supported. Apple does not currently allow third-party HCE services to claim Pix AIDs in Brazil; this library deliberately does not ship speculative iOS fallbacks.

Based on jgcmarins/react-native-tap-to-pix — see Relationship to the upstream library. The BACEN protocol implementation comes from that upstream work; this fork adds Woovi-specific integration guidance and is maintained against Woovi's production Pix APIs.

Why Woovi

Woovi is a Brazilian Pix infrastructure provider. If you are building a Pix-enabled app for the Brazilian market and want Tap to Pix to "just work" against a production-grade Pix stack, this fork is wired for that path:

  • Pix charges & checkout — decode the EMV "Copia e Cola" string tapped from a POS terminal and create / reconcile a Pix charge via the Woovi API.
  • OpenPix GraphQL & REST — the same account works across OpenPix and Woovi, so the EMV-decoding and charge flows documented below apply to either.
  • Webhooks for POS confirmations — after the user authorizes payment, receive near-real-time webhook events for charge lifecycle updates.
  • PSPs supported by Woovi — the library is protocol-level (raw BACEN APDU), so it works with any Woovi-supported bank partner for settlement.

This repo is intentionally UI-free — you bring the checkout / confirmation screens, Woovi brings the Pix rails.

What this library does

  1. Registers your app as an HCE (Host Card Emulation) service under the BACEN Tap to Pix AID A000000940BCB000, category="payment".
  2. Handles the full APDU state machine from a Pix-compatible POS terminal (SELECT AID, chunked UPDATE BINARY, short and extended Lc forms).
  3. Reassembles the NDEF URI record and fires Intent.ACTION_VIEW on the extracted pix://<host>?qr=<URL-encoded EMV> URI.
  4. Exposes a native bridge for CardEmulation.setPreferredService (foreground override), isDefaultServiceForCategory (default-app check), and a deep link to the Android "Default contactless payment app" settings screen.

What it does NOT do

  • Payment UI, PIN, biometrics, confirmation screens.
  • Backend integration with Woovi (or any other Pix provider). The library hands you the EMV string — you call Woovi's API from your app or backend.
  • Deep-link routing — register your own pix scheme intent filter and handle the URI however you want.
  • iOS anything.

The library's contract ends at Intent.ACTION_VIEW: after a successful tap, your app receives a pix://...?qr=<EMV> URL through the intent filter you registered. Everything from there is your code (and, if you use Woovi, a call to the Woovi Pix API).

Install

npm install @woovibr/react-native-tap-to-pix
npx expo prebuild --clean

Requires Expo SDK 52+, React Native 0.76+, and expo-dev-client installed in the host app.

Setup

1. Add the config plugin

In app.json:

{
  "expo": {
    "plugins": [
      ["@woovibr/react-native-tap-to-pix", {
        "serviceName": ".nfc.PixTapToPixService",
        "description": "Tap to Pix",
        "aidGroupDescription": "Pagamentos Pix por aproximacao"
      }]
    ]
  }
}

All options are optional. Defaults shown.

| Option | Default | Notes | | --- | --- | --- | | serviceName | .nfc.PixTapToPixService | Relative class name, starts with a dot. Written into AndroidManifest.xml and resolved against android.package at build time. | | description | Tap to Pix | Short label shown next to your service in the Android Default Contactless Payment App picker. | | aidGroupDescription | Pagamentos Pix por aproximacao | Description shown for the AID group in Android's tap-and-pay settings. |

2. Register the pix scheme in your app

Still in app.json:

{
  "expo": {
    "scheme": ["yourapp", "pix"],
    "android": {
      "package": "com.yourapp",
      "intentFilters": [
        {
          "action": "VIEW",
          "category": ["DEFAULT", "BROWSABLE"],
          "data": [{ "scheme": "pix" }],
          "autoVerify": false
        }
      ]
    }
  }
}

3. Handle the pix:// URI and hand the EMV to Woovi

When the user taps a POS, Android fires Intent.ACTION_VIEW on a URL like pix://cielo.com.br?qr=<URL-encoded EMV>. Your app receives it via the pix scheme intent filter. With expo-router a catch-all route works well:

// app/[...rest].tsx
import { useEffect, useRef } from 'react';
import { useLocalSearchParams, useRouter } from 'expo-router';

export default function CatchAll() {
  const router = useRouter();
  const params = useLocalSearchParams<{ qr?: string | string[] }>();
  const dispatched = useRef(false);

  useEffect(() => {
    if (dispatched.current) return;
    dispatched.current = true;

    const qr =
      typeof params.qr === 'string'
        ? params.qr
        : Array.isArray(params.qr)
        ? params.qr[0]
        : null;

    if (qr) {
      // The library's job is done. Hand off to your Woovi-backed payment flow.
      router.replace({ pathname: '/payment', params: { emv: qr } });
      return;
    }

    router.replace('/');
  }, [params, router]);

  return null;
}

The qr query param is already URL-decoded by expo-router. It is the Pix "Copia e Cola" EMV string — it starts with 000201.

From your /payment screen (or your backend), post it to the Woovi Pix API to decode, validate and pay the charge. See the Woovi API docs for the current endpoint and authentication shape.

4. (Optional) Claim the AID while your screen is focused

setPreferredService is a foreground override — it makes the OS route taps to your HCE service while your Activity is in foreground, even if another app is the device-wide default. The useTapToPixPreferred hook handles the mount/blur lifecycle for you:

import { useTapToPixPreferred } from '@woovibr/react-native-tap-to-pix';

export default function PaymentOptionsScreen() {
  useTapToPixPreferred();
  return <View>...</View>;
}

This is in addition to the user marking your app as the Default Contactless Payment App in Android Settings — not a replacement. The default-app setting is the primary mechanism; this hook is an extra safety net for when your screen is visible.

5. (Optional) Check default-app status and open Android settings

import { isDefault, openTapAndPaySettings } from '@woovibr/react-native-tap-to-pix';

if (!isDefault()) {
  openTapAndPaySettings(); // drops the user on the Android default-payment chooser
}

Setup — bare React Native (no Expo prebuild)

Bare React Native projects can use this library as long as expo-modules-core is installed and configured. Most modern RN projects already have it (directly or as a transitive dep). If yours doesn't:

npm install expo expo-modules-core
npx install-expo-modules

The Expo modules runtime autolinks the native bridge (setPreferred / unsetPreferred / isDefault / openTapAndPaySettings) for you. What the Expo config plugin would have written into your android/ folder on expo prebuild has no equivalent in bare RN — you apply those edits once by hand, then they stay as part of your Android project source.

1. Install

npm install @woovibr/react-native-tap-to-pix

2. Wire the Android project by hand

Replace com.yourapp with your actual Android package (the applicationId in android/app/build.gradle).

a. android/app/src/main/AndroidManifest.xml — inside <manifest>:

<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc" android:required="true" />
<uses-feature android:name="android.hardware.nfc.hce" android:required="true" />

Inside <application>, add the HCE service:

<service
    android:name=".nfc.PixTapToPixService"
    android:exported="true"
    android:permission="android.permission.BIND_NFC_SERVICE">
    <intent-filter>
        <action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
    <meta-data
        android:name="android.nfc.cardemulation.host_apdu_service"
        android:resource="@xml/apduservice" />
</service>

Inside your main Activity's existing <activity> tag, add the pix scheme intent filter:

<intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="pix" />
</intent-filter>

b. android/app/src/main/res/xml/apduservice.xml — copy verbatim from the library:

mkdir -p android/app/src/main/res/xml
cp node_modules/@woovibr/react-native-tap-to-pix/android-native-templates/apduservice.xml \
   android/app/src/main/res/xml/apduservice.xml

c. android/app/src/main/res/values/strings.xml — append two strings:

<string name="tap_to_pix_description" translatable="false">Tap to Pix</string>
<string name="tap_to_pix_aid_group" translatable="false">Pagamentos Pix por aproximacao</string>

Customize tap_to_pix_description — it shows next to your app in the Android "Default contactless payment app" picker.

d. HCE service source — copy the template and replace __PACKAGE__ with your Android package. On macOS / Linux:

PKG=com.yourapp
mkdir -p android/app/src/main/java/${PKG//./\/}/nfc
sed "s/__PACKAGE__/$PKG/g" \
  node_modules/@woovibr/react-native-tap-to-pix/android-native-templates/PixTapToPixService.kt.tmpl \
  > android/app/src/main/java/${PKG//./\/}/nfc/PixTapToPixService.kt

On Windows, copy the .kt.tmpl file by hand to android/app/src/main/java/<your/package/path>/nfc/PixTapToPixService.kt and replace every occurrence of __PACKAGE__ in the file with your package name.

3. Rebuild

cd android && ./gradlew clean && cd ..
npm run android

4. Handle the pix:// URI in JS

No expo-router required — the core React Native Linking API is enough:

import { useEffect } from 'react';
import { Linking } from 'react-native';
import { parsePixUri } from '@woovibr/react-native-tap-to-pix';

export default function App() {
  useEffect(() => {
    const handle = (url: string | null) => {
      if (!url) return;
      const parsed = parsePixUri(url);
      if (parsed?.qr) {
        // Hand parsed.qr (the EMV string) to your Woovi-backed payment flow.
      }
    };
    Linking.getInitialURL().then(handle);
    const sub = Linking.addEventListener('url', ({ url }) => handle(url));
    return () => sub.remove();
  }, []);
  return <YourApp />;
}

Keeping the manual wiring in sync across upgrades

In Expo projects the config plugin re-runs on every expo prebuild --clean, so changes to the template files ship automatically. Bare RN projects have no such hook — when you upgrade @woovibr/react-native-tap-to-pix, check the release notes: if PixTapToPixService.kt.tmpl or apduservice.xml changed, re-apply the copy steps above.

API

All runtime functions are no-ops (return false / null) when the native module isn't available (iOS, web, or the module failed to link).

import {
  setPreferred,
  unsetPreferred,
  isDefault,
  openTapAndPaySettings,
  useTapToPixPreferred,
  parsePixUri,
  BACEN_PIX_AID,
  DEFAULT_SERVICE_NAME,
} from '@woovibr/react-native-tap-to-pix';

| Export | Signature | Purpose | | --- | --- | --- | | setPreferred | (options?: { serviceName?: string }) => boolean | Claim the AID while your Activity is foreground. | | unsetPreferred | () => boolean | Release the foreground claim. | | isDefault | (options?: { serviceName?: string }) => boolean | Whether your HCE service is the device-wide default payment app. | | openTapAndPaySettings | () => boolean | Deep link the user to the Android default-payment chooser. | | useTapToPixPreferred | (options?: { serviceName?: string }) => void | Hook: calls setPreferred on mount and unsetPreferred on blur/unmount, handles AppState transitions. | | parsePixUri | (uri: string) => { host, qr, params } \| null | Pure helper to extract the EMV from a pix://...?qr=... URI. | | BACEN_PIX_AID | 'A000000940BCB000' | The AID this library registers. | | DEFAULT_SERVICE_NAME | '.nfc.PixTapToPixService' | Default HCE service class (relative to host android.package). |

Default Contactless Payment App — a note

Because the BACEN Pix AID shares the category="payment" namespace with Google Wallet, the user must manually set your app as the Default Contactless Payment App in Android Settings. Same UX every bank app uses — this is an Android security policy, not something any app can self-promote around.

Expect to build onboarding UI in your app that:

  1. Checks isDefault().
  2. If false, shows a banner / card instructing the user to enable it.
  3. Calls openTapAndPaySettings() when the user taps the CTA (drops them on the exact Android screen).
  4. Re-checks isDefault() when the user returns (e.g. on AppState.active).

The library stays UI-free so you can design this to match your app.

Verifying HCE registration

After expo prebuild --clean and a local build:

adb shell dumpsys nfc | grep -A 5 "A000000940BCB000"

Must show:

"A000000940BCB000" (category: payment)
    ComponentInfo{com.yourapp/.nfc.PixTapToPixService}

category: payment is non-negotiable — Android refuses to let category="other" services preempt Google Wallet via setPreferredService. If you see other, the APK was built from a stale manifest: adb uninstall com.yourapp then adb install a fresh build.

Relationship to the upstream library

This library is a Woovi-maintained fork of jgcmarins/react-native-tap-to-pix (published on npm as react-native-tap-to-pix). The upstream repo validated the BACEN APDU state machine against a live Cielo POS terminal and remains the reference implementation.

What this fork adds:

  • Woovi-oriented integration examples (EMV → Woovi Pix API handoff) in the README.
  • Published under the @woovibr npm scope so it can be consumed alongside other Woovi SDKs without stepping on the upstream package name.
  • Maintained against Woovi's production Pix stack as the BACEN spec evolves.

What stays the same:

  • The HCE service, AID registration, APDU parser, NDEF reassembly logic, Expo config plugin, and native bridge API are unchanged from upstream and will track it. If you hit a protocol-level bug, please cross-check against the upstream issue tracker — the fix likely belongs there.

If you are not on the Woovi stack, prefer the upstream package directly.

Reference

Status

Protocol plumbing inherited from upstream and validated against a live Cielo POS terminal. Woovi-specific integration guidance will evolve alongside the Woovi Pix API. Track open items on GitHub Issues.

License

MIT © Woovi, based on work © jgcmarins — see LICENSE.