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

@ryftpay/react-native

v1.0.1

Published

Official React Native components for Ryft payment processing, providing seamless integration of payment forms, digital wallets, and checkout flows in native mobile apps.

Downloads

280

Readme

Ryft React Native SDK (@ryftpay/react-native)

⚠️ Beta software. The Ryft React Native SDK is currently in beta. APIs, component props, and native setup requirements may change between releases without following semantic versioning guarantees. We recommend pinning an exact version in your package.json. Please report any issues to Ryft support via the usual channels.

This package provides the Ryft React Native SDK — native iOS and Android components for accepting payments in React Native apps. It includes a card form, a field-collection form, a native PassKit-backed Apple Pay button (iOS), and a native Google Pay button (Android).

Quick start

1) Install

npm install @ryftpay/react-native
# or
pnpm add @ryftpay/react-native
# or
yarn add @ryftpay/react-native
# or
bun add @ryftpay/react-native

react-native-webview is a required peer dependency (the card form and field-collection components iframe-host the web SDK via WebView):

npm install react-native-webview

2) Follow the quick start guide

A quick start guide along with full technical documentation is available in the Ryft React Native SDK docs.


Setup doctor

Apple Pay and native 3DS require native-platform configuration the JS install can't do for you (see the sections below). To catch a misconfiguration before it burns a build cycle, run the bundled doctor from your project root:

npx @ryftpay/react-native doctor

It detects whether your app is bare React Native or Expo-managed and checks the relevant setup: required dependencies and React Native version, the Ravelin Maven repository, core library desugaring and minSdk on Android, the RyftReactNative pod on iOS, and — for Expo apps — the config plugin entry in app.json. Each failed check prints an exact copy-pasteable fix snippet and a link to the matching section of this README.

If your app accepts Apple Pay, add the --apple-pay flag so the Apple Pay entitlement is checked too (the doctor also asks interactively when run in a terminal):

npx @ryftpay/react-native doctor --apple-pay

The doctor reads only package.json, app.json, and your android/ and ios/ files — it makes no network calls and sends no telemetry. It exits 0 when everything passes and 1 if any check fails, so you can wire it into CI. Warnings (e.g. a minSdk set via a Gradle variable it can't resolve) don't affect the exit code.


Apple Pay (iOS) setup

Apple Pay requires extra iOS-platform setup that the JS install can't do for you.

Prerequisites

  1. Apple Developer Program membership (paid). Apple Pay capability is not available in the free "Personal Team" tier.
  2. An Apple Pay merchant identifier registered in your Apple Developer account and associated with your app's bundle ID. This is a string in reverse-domain format, e.g. merchant.com.acme.store.
  3. A valid Apple Pay Payment Processing Certificate uploaded via the Ryft Merchant Portal.
  4. The amexPayments sub-account capability if you want to accept Amex via Apple Pay (see Amex availability below).

iOS app configuration

For bare React Native apps

  1. Add the Apple Pay capability in Xcode: select your target → Signing & Capabilities+ CapabilityApple Pay → tick your merchant ID.
  2. Run pod install from your ios/ directory. The RyftReactNative pod is autolinked from the package.

For Expo-managed apps

Add @ryftpay/react-native to the plugins array in your app.json and pass your merchant ID. The bundled config plugin adds the Apple Pay entitlement (com.apple.developer.in-app-payments) on every prebuild, so it persists across expo prebuild --clean:

{
  "expo": {
    "plugins": [
      [
        "@ryftpay/react-native",
        { "applePay": { "merchantId": "merchant.com.acme.store" } }
      ]
    ]
  }
}

Then regenerate the native projects and open the workspace:

  1. Run npx expo prebuild --clean — the entitlement is injected and the RyftReactNative pod is autolinked.
  2. Open the generated ios/ workspace in Xcode and select your team under Signing & Capabilities if it isn't set.

The entitlement only declares the merchant ID — you still need a valid Apple Pay Payment Processing Certificate uploaded by Ryft (see Prerequisites above). Omit the applePay option to skip Apple Pay setup entirely. The same plugin entry also configures Android 3DS — see Native 3DS (Android) setup.

Component usage

import { RyftProvider, ApplePay } from '@ryftpay/react-native';

export function Checkout() {
  return (
    <RyftProvider publicKey="pk_..." clientSecret="ps_..._secret_...">
      <ApplePay
        merchantIdentifier="merchant.com.acme.store"
        merchantName="Acme Store"
        merchantCountryCode="GB"
        onPaymentSessionResult={(event) => {
          if (event.result.type === 'final') {
            // Navigate to confirmation, show receipt, etc.
          }
        }}
        onError={(event) => console.error(event.message)}
      />
    </RyftProvider>
  );
}

merchantIdentifier is required on iOS — the component throws a RyftError at render time if it's missing. It's ignored on Android.

Testing on a real device

  • Simulator: the Apple Pay sheet renders from iOS 13.4, but you cannot authorise real payments (the simulator has no Wallet).
  • Real device: add sandbox test cards from developer.apple.com/apple-pay/sandbox-testing to Wallet via Settings → Wallet & Apple Pay → Add Card → manual entry. The device routes sandbox FPANs through Apple's sandbox network automatically.
  • Sandbox tester account: create one in App Store Connect → Users and Access → Sandbox → Test Accounts, then sign in via Settings → App Store → Sandbox Account on the device.

Android behaviour

<ApplePay /> renders null on Android and is safe to import without crashes — no native methods are invoked. There's no Android counterpart for Apple Pay; the no-op exists so cross-platform code compiles without conditional rendering.


Native 3DS (Android) setup

The native 3DS Identify / Challenge flow uses the Ravelin Android 3DS SDK. It powers any Android payment that triggers 3D Secure — both <CardForm /> and Google Pay route through it. Two one-time setup steps are required in any consumer app that depends on @ryftpay/react-native: a Maven repository declaration and core library desugaring. Both are constraints set by Ravelin's AAR rather than choices we've made.

Step 1 — Add Ravelin's Maven repository

The Ravelin SDK is not published to Maven Central or Google's Maven repository, so consumer apps must declare Ravelin's own Maven repo explicitly. Without it, builds fail with:

> Could not find com.ravelin.threeds2service:threeds2service-sdk:2.0.2.
  Searched in the following locations:
    - https://dl.google.com/dl/android/maven2/…
    - https://repo.maven.apache.org/maven2/…
    …

For bare React Native apps

Add the Ravelin Maven repo to your project's root android/build.gradle inside allprojects { repositories { } }:

allprojects {
  repositories {
    google()
    mavenCentral()
    // Ravelin 3DS SDK — required by @ryftpay/react-native
    maven { url 'https://maven.ravelin.com/public/repositories/threeds2service/' }
  }
}

For Expo-managed apps

Add @ryftpay/react-native to the plugins array in your app.json. The bundled config plugin injects the Ravelin Maven repo and enables core library desugaring (Step 2) on every prebuild, so both survive expo prebuild --clean — no manual android/ edits to make or re-apply:

{
  "expo": {
    "plugins": ["@ryftpay/react-native"]
  }
}

Then regenerate the native projects:

npx expo prebuild --clean

If you also use Apple Pay, pass your merchant ID in the same plugin entry (see Apple Pay (iOS) setup):

{
  "expo": {
    "plugins": [
      [
        "@ryftpay/react-native",
        { "applePay": { "merchantId": "merchant.com.acme.store" } }
      ]
    ]
  }
}

Expo-managed apps using the plugin can skip Step 2 below — it is applied automatically.

Step 2 — Enable core library desugaring

Ravelin's AAR sets metadata declaring it needs core library desugaring in the consumer — a Gradle feature that backports java.time, streams, and other Java 8+ APIs to older Android runtimes. Without it, builds fail with:

Dependency 'com.ravelin.threeds2service:threeds2service-sdk:2.0.2' requires
core library desugaring to be enabled for :app.

Add to your app module's android/app/build.gradle:

android {
  // …

  compileOptions {
    coreLibraryDesugaringEnabled true
    sourceCompatibility JavaVersion.VERSION_17
    targetCompatibility JavaVersion.VERSION_17
  }
}

dependencies {
  // …

  // Required by @ryftpay/react-native (Ravelin 3DS).
  coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5'
}

The sourceCompatibility / targetCompatibility levels can be anything ≥ Java 8 — VERSION_17 matches the rest of the React Native + Expo ecosystem. The desugar_jdk_libs version is pinned to match ryft-android; bump only when ryft-android does.

Why we can't auto-inject this

Gradle resolves transitive dependencies — and runs AAR-metadata checks — against the consumer app's configuration, not the library's. A repositories { } block or a compileOptions { coreLibraryDesugaringEnabled = true } block in our library's build.gradle only affects our library's own classpath — neither propagates to your app. React Native's autolinking system has no hook for Maven repository injection or AGP compile-option injection. Stripe's, Adyen's, and Braintree's React Native SDKs all require an equivalent one-time setup; this is the industry pattern.

We're tracking whether we can bundle the Ravelin SDK locally as part of @ryftpay/react-native (which would remove Step 1 but not Step 2 — desugaring is still required by Ravelin's bytecode) — that work is gated on Ravelin's redistribution license terms.


Native 3DS (iOS) setup

The native 3DS Identify / Challenge flow on iOS uses the Ravelin iOS 3DS SDK (Ravelin3DS ~> 2.0.1). It powers any iOS payment that triggers 3D Secure inside <CardForm />. Unlike Android, no app-level Gradle or repository configuration is required — CocoaPods resolves Ravelin3DS through the standard pod-spec chain.

Prerequisites

  • iOS 13.4 deployment target or higher. This matches the React Native + Apple Pay floor and is set on @ryftpay/react-native's podspec.
  • CocoaPods 1.10+ for the consumer app.

Step 1 — Run pod install

After npm install @ryftpay/react-native, run pod install from your ios/ directory:

cd ios && pod install

The RyftReactNative pod is autolinked from the package, and it pulls in Ravelin3DS transitively. Re-run pod install whenever you upgrade @ryftpay/react-native.

Step 2 — Rebuild the iOS app

Native module changes require a fresh iOS build. After pod install completes, do a clean rebuild from Xcode or via the React Native CLI:

npx react-native run-ios

A stale build cache is the most common cause of a runtime Native 3DS module is not available error on iOS — the JS layer sees NativeModules.RyftThreeDs as undefined because the autolinking manifest from the previous build is still in place.

Step 3 — (Optional) Universal Link domain for OOB authentication

The native 3DS flow opportunistically supports OOB (out-of-band) authentication — the customer is redirected to their banking app, authorises there, and is returned to your app automatically. iOS routes the return via Universal Links, which require a configured https:// domain you own with an apple-app-site-association (AASA) file served from /.well-known/.

If you've configured a Universal Link domain, pass it via the oobReturnUrl prop on <RyftProvider>:

<RyftProvider
  publicKey="pk_test_…"
  oobReturnUrl="https://your-merchant-domain.com/oob-return"
>
  …
</RyftProvider>

When oobReturnUrl is omitted, OOB flows still work — the customer just has to manually swipe back to your app after their banking app finishes (today's default behaviour).

Custom URL schemes (e.g. myapp://oob-return) do NOT work on iOS. The Ravelin iOS SDK uses UIApplication.shared.open(..., universalLinksOnly: true) for OOB return, which silently drops non-https schemes. For cross-platform parity with Android, use the same https:// Universal Link on both platforms.

No Info.plist entries, AppDelegate hooks, or entitlements are required by the SDK itself. (Merchants who want welcome-back UX or inbound-URL analytics can wire React Native's Linking API in their own app code, independent of the SDK — Ravelin's status callback drives protocol completion regardless of whether the merchant app handles the inbound URL.)


Behaviour notes

Async walletButtonClickHandler

The walletButtonClickHandler prop may be synchronous or async — returning a Promise is supported and the SDK awaits it before opening the Apple Pay sheet. You can do network work inside the handler (e.g. refreshing the cart or fetching a payment session) and then return { type: 'approve' } (optionally with a paymentSession override) or { type: 'reject' }. The customer sees the standard tap latency until the promise resolves.

This is a deliberate divergence from the web SDK, where Safari ties new ApplePaySession(...) to the synchronous user-gesture window and so requires the handler to return synchronously. PassKit on iOS has no such constraint, so React Native lifts it.

Amex availability

The SDK advertises Amex in supportedNetworks to PassKit. Acceptance depends on your Ryft sub-account having the amexPayments capability — without it, Amex attempts fail with lastError: 'payment_method_option_amex_not_available'. If you don't process Amex, customers may still see Amex cards in the wallet picker but the payment will fail. Contact Ryft support to request the capability before relying on Amex Apple Pay.

Billing-address collection

Billing-address collection is opt-in via requiredBillingContactFields. By default no billing information is collected — set:

<ApplePay
  requiredBillingContactFields={['postalAddress']}
  // …
/>

if you require it.

Identifier header

The RN SDK sends an identifier header on every API call so Ryft can attribute traffic:

  • Ryft-Client: ryft-react-native-sdk/<version>

The web SDK sends the equivalent header with its own client name (Ryft-Client: ryft-web-sdk/<version>). Expect this header when inspecting outbound traffic from RN apps.

3DS device channel

RN-iOS Apple Pay attempts include threeDsRequestDetails.deviceChannel: 'Application', signalling to Ryft that any 3DS challenge must be frictionless (the native PassKit sheet cannot render a browser-channel challenge UI). This is set automatically by the SDK; no merchant configuration required.

Styling the Apple Pay button

PassKit renders the Apple Pay button itself — Apple's Human Interface Guidelines lock the colour to one of three preset variants, so the RN component cannot honour an arbitrary applePayButtonColor value. Use applePayButtonStyle from the theme to pick the variant:

  • 'black' (default) — PKPaymentButtonStyle.black
  • 'white'PKPaymentButtonStyle.white
  • 'white-outline'PKPaymentButtonStyle.whiteOutline

applePayButtonColor is accepted on RN only for API symmetry with the web SDK and has no effect on the rendered button. Width, height, and corner radius are honoured (defaults: 100% width, 44pt height, 4px corner radius — override via applePayButtonWidth / applePayButtonHeight / applePayButtonBorderRadius).

The buttonType enum surfaces every value the web SDK accepts, but PassKit's PKPaymentButtonType enum doesn't include a literal .pay case. When buttonType: 'pay' is supplied on RN, the button renders as "Buy with Apple Pay" (PKPaymentButtonType.buy) — the closest transactional semantic. Set buttonType: 'buy' explicitly for full clarity on RN.

Similarly, PassKit displays its own OS-controlled validation strings on the sheet, so text.invalidFieldCollectionData (and any other future entries on RyftApplePayConfig.text) are accepted but have no effect on RN.


Supported platforms

  • iOS 13.4+ (the host app's React Native version may impose a higher floor — RN 0.76+ requires iOS 15.1+)
  • Android 7.0+ (minSdk 24) — <CardForm />, <FieldCollectionForm />, and <GooglePay />; <ApplePay /> renders null
  • React Native 0.73+
  • React 18 or 19