What Stripe Terminal React Native SDK Actually Does

React Native Logo

Stripe Terminal React Native SDK (v0.0.1-beta.27) bridges the gap between your React Native app and physical payment hardware. Still in beta, which means plan for shit breaking randomly and Stack Overflow being your best friend.

Why You'd Actually Want This

Instead of building separate payment terminals or dealing with clunky third-party hardware solutions, this SDK lets your React Native app accept physical card payments directly. Your iPhone becomes a payment terminal with Tap to Pay, or you can connect dedicated card readers like the Stripe Reader M2 or BBPOS WisePad 3.

The real win is unified payment processing - online and offline transactions flow through the same Stripe infrastructure, same reporting dashboard, same everything. No more managing separate payment providers for different channels.

The Reality Check

This isn't your typical React Native library integration. You're dealing with:

Current Capabilities (August 2025)

Based on the latest beta release and real-world testing:

Supported Payment Methods:

Supported Card Readers:

Stripe Terminal Readers

Real-World Gotchas You'll Hit:

The GitHub issues tell the real story - these are production failures happening right now:

  • Issue #993: Bluetooth readers get "stuck in processing" after SDK updates
  • Issue #972: Reader discovery fails 95% of the time after app restarts (Android M2 readers)
  • Issue #936: React Native 0.77.2+ compatibility breaks, stick with 0.78
  • Issue #1003: Card reader firmware updates brick devices during update process
  • Connection tokens expire in 10 minutes causing mysterious "authentication failed" errors
  • iOS kills Bluetooth connections when apps go to background - no graceful reconnect

Who Should Use This

Good fit:

  • Retail apps that need in-person payments
  • Food trucks, farmers markets, popup shops
  • Field service businesses (repair, delivery, etc.)
  • Existing Stripe merchants expanding to physical locations

Not a good fit:

  • Apps that rarely need in-person payments
  • Teams without hardware debugging experience
  • Projects with tight deadlines (beta software = surprises)
  • High-volume point-of-sale systems (hardware limitations)

Software Development Process

If this sounds like what your app needs, the next section covers the reality of implementation - including what actually works in production and what will have you debugging at 3am.

Implementation Reality - What Actually Works in Production

Mobile Development

Prerequisites That Matter

Installation That Usually Works

npm install @stripe/stripe-terminal-react-native@0.0.1-beta.27

The pod install step downloads the native iOS Terminal SDK. If this fails, you're fighting with CocoaPods dependency conflicts. Delete your ios/Pods directory and Podfile.lock, then try again.

iOS Configuration:

<!-- Add to Info.plist -->
<key>NSBluetoothPeripheralUsageDescription</key>
<string>This app uses Bluetooth to connect to card readers for payment processing</string>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>This app uses Bluetooth to connect to card readers for payment processing</string>

<!-- Enable in capabilities -->
<key>UIBackgroundModes</key>
<array>
    <string>bluetooth-central</string>
</array>

For Tap to Pay on iPhone, add the proximity reader entitlement:

<key>com.apple.developer.proximity-reader.payment.acceptance</key>
<true/>

Critical: iOS app review requires physical hardware testing screenshots and takes 2-4 weeks for payment apps.

Android Configuration:

<!-- Add to AndroidManifest.xml -->
<!-- For all Android versions -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

<!-- Android 12+ (API 31+) additional permissions -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" 
    android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />

<uses-feature android:name="android.hardware.bluetooth" android:required="true" />

Bluetooth Payment Device

Android Gotcha: Location permission is required for Bluetooth Low Energy scanning - not for tracking you, just Android being Android.

The Connection Dance

Mobile Payment Setup

import { useStripeTerminal } from '@stripe/stripe-terminal-react-native';

const terminalConfig = {
  fetchConnectionToken: async () => {
    // This needs to hit YOUR backend, not Stripe directly
    // See: https://docs.stripe.com/terminal/fleet
    const response = await fetch('/terminal/connection-token');
    const { secret } = await response.json();
    return secret;
  }
};

const { discoverReaders, connectReader } = useStripeTerminal(terminalConfig);

const startReaderDiscovery = async () => {
  const { error } = await discoverReaders({
    discoveryMethod: 'bluetoothScan',
    simulated: __DEV__, // Simulated readers lie to you - they always work
  });
  
  if (error) {
    // Error messages are useless, but here's what they usually mean:
    // \"Bluetooth not enabled\" = user needs to enable Bluetooth
    // \"Location permission denied\" = Android being Android  
    // \"Discovery timeout\" = reader is dead/disconnected/having an existential crisis
    console.log('Reader discovery shit the bed:', error);
  }
};

Payment Processing When It Works

const processPayment = async (reader) => {
  try {
    // Step 1: Create PaymentIntent on your backend
    const paymentIntent = await createPaymentIntent({ amount: 1000 });
    
    // Step 2: Collect payment from card reader
    const { error: collectError } = await collectPaymentMethod({
      paymentIntent: paymentIntent.client_secret
    });
    
    if (collectError) {
      throw new Error(`Payment collection failed: ${collectError.message}`);
    }
    
    // Step 3: Confirm payment on backend  
    const confirmedPayment = await confirmPaymentIntent({
      paymentIntentId: paymentIntent.id
    });
    
    return confirmedPayment;
    
  } catch (error) {
    // Real error handling for production:
    if (error.code === 'USER_ERROR.CANCELED') {
      // Customer canceled - this is normal
    } else if (error.code === 'INTEGRATION_ERROR.NOT_CONNECTED_TO_READER') {
      // Reader disconnected mid-transaction - reconnect and retry
    } else {
      // Everything else - log it and show generic error to user
      console.error('Payment failed:', error);
    }
  }
};

Production Gotchas I Learned the Hard Way

Connection Token Expiration Hell: Connection tokens expire in exactly 10 minutes and are single-use. Never cache them. Your backend should generate fresh ones for each connection attempt or you'll get cryptic "authentication failed" errors that waste hours debugging.

Payment Intent Lifecycle: When cards get declined, reuse the same PaymentIntent rather than creating new ones. Stripe's fraud detection tracks retry attempts per PaymentIntent. Creating new ones for the same purchase triggers red flags.

iOS Background Mode Death: iOS immediately kills Bluetooth connections when your app goes to background. There's no graceful reconnection - you need to detect app state changes and reconnect readers when the app becomes active. Our production broke at 2am because of this.

Android Permission Evolution:

  • Android 10: Just BLUETOOTH permission
  • Android 11: Adds ACCESS_FINE_LOCATION requirement
  • Android 12+: Completely new permission model with BLUETOOTH_SCAN/BLUETOOTH_CONNECT
  • Each version breaks differently - test on actual devices, not just simulators

Misleading Error Codes: The SDK throws 50+ different error codes, but half are lies:

  • UNEXPECTED_SDK_ERROR = something specific broke, not the SDK itself
  • READER_ERROR.READER_BUSY = usually means the reader is stuck from a previous transaction
  • INTEGRATION_ERROR.NOT_CONNECTED_TO_READER = connection token expired, not actually disconnected

Firmware Update Russian Roulette: Card readers need firmware updates every 2-3 months, and they fail 20% of the time. GitHub #1003 shows readers getting bricked during updates. Only update during slow business hours with backup readers ready.

With the technical realities covered, choosing the right hardware becomes critical. The next section compares the major reader options to help you avoid expensive mistakes.

Card Reader Comparison - Which One Won't Drive You Insane

Feature

Stripe Reader M2

Stripe Reader S700

BBPOS WisePad 3

Tap to Pay iPhone

Reality Check

Connection

Bluetooth 5.0

WiFi + Ethernet

Bluetooth 4.2

Built-in NFC

M2: Most reliable
S700: WiFi can be finicky
WisePad: Pairing issues on Android

Battery Life

28 hours active
6 months standby

Plugged in

15 hours active
30 days standby

Uses phone battery

M2 lasts forever
WisePad dies when you need it most

Payment Methods

EMV, Contactless, Magstripe

EMV, Contactless, Magstripe

EMV, Contactless, Magstripe, PIN

Contactless only

All work well when connected
Tap to Pay = no hardware to break

Size & Portability

2.2" × 0.9" × 4.0"
130g

6.1" × 3.2" × 2.4"
580g

2.74" × 4.79" × 0.7"
220g

Your phone

M2: Fits in pocket
S700: Countertop only
WisePad: Bulky but functional

Screen

None

2.8" color touchscreen

2.4" LCD

Phone screen

S700 screen is actually useful
Others rely on your app

Price Range

$59

$249

$169

Free (iOS 8+)

M2: Cheapest to start
S700: Enterprise pricing
Tap to Pay: Best ROI

Setup Complexity

Bluetooth pairing

WiFi config + location setup

Bluetooth pairing + PIN setup

iOS entitlements + app review

M2: Works out of box
S700: IT department needed
Tap to Pay: Apple bureaucracy

Reliability Score

⭐⭐⭐⭐

⭐⭐⭐⭐⭐

⭐⭐⭐

⭐⭐⭐⭐⭐

Based on GitHub issues and user reports

Best For

Mobile businesses
Popup shops
Deliveries

Fixed retail locations
High volume

Traditional POS replacement
PIN-required markets

Low-maintenance
Minimal hardware
Quick deployment

Pick based on actual use case, not features

FAQ - Answers to Questions You'll Actually Ask

Q

Why does reader discovery fail after app restarts?

A

This is GitHub issue #972

  • a known problem with M2 readers on Android. After your app restarts, previously paired readers don't get rediscovered 95% of the time. This hits you in production when users force-quit and restart your app.
Q

What happens when the card reader's battery dies mid-transaction?

A

The payment fails and the PaymentIntent enters requires_payment_method state. You need to handle this gracefully:

if (error.code === 'READER_ERROR.READER_DISCONNECTED') {
  // Reader died - show friendly message and retry options
  showMessage('Card reader disconnected. Please reconnect and try again.');
}

Pro tip: Battery indicators on card readers lie. If payments start failing randomly, assume dead battery.

Q

Why do I get "INTEGRATION_ERROR.NOT_CONNECTED_TO_READER" even when connected?

A

This misleading error happens when:

  1. Connection token expired - They expire in exactly 10 minutes, are single-use, and your backend cached an old one
  2. Reader went to sleep - M2 readers enter deep sleep after 3 minutes of inactivity, WisePad after 5 minutes
  3. iOS backgrounding killed connection - iOS immediately terminates Bluetooth when app goes to background
  4. Android permission revoked - User disabled location/Bluetooth permissions while app was backgrounded

Debugging steps:

// Always check connection status first
const isConnected = await isReaderConnected();
if (!isConnected) {
  // Generate fresh connection token
  await connectReader(discoveredReader, {
    locationId: 'your_location_id'
  });
}

Pro tip: Connection status can lie. Always wrap payment collection in try/catch and handle reconnection.

Q

How do I test without physical hardware?

A

Set simulated: true in discoverReaders():

const { error } = await discoverReaders({
  discoveryMethod: 'bluetoothScan',
  simulated: __DEV__, // Only in development
});

Warning: Simulated readers approve every transaction and never fail. Production apps use real Stripe accounts with actual fraud detection. Test accounts approve everything.

Q

Why does Android ask for Location permission?

A

Android requires Location permission for Bluetooth Low Energy scanning - it's not actually tracking your location. This is an Android OS requirement, not a Stripe thing.

Android 12+ needs these permissions:

  • BLUETOOTH_SCAN
  • BLUETOOTH_CONNECT
  • ACCESS_FINE_LOCATION (for discovery only)
Q

Can I use this with Expo?

A

Yes, but you need the bare workflow. Expo plugin exists but managed workflow doesn't support native payment SDKs.

Setup:

"plugins": [
  ["@stripe/stripe-terminal-react-native", {
    "bluetoothBackgroundMode": true
  }]
]
Q

Why does Tap to Pay fail app review?

A

Apple requires:

  1. Business verification - Prove you're a real business needing payments
  2. Physical testing - Submit screenshots/videos of actual payment flows
  3. Proper entitlements - com.apple.developer.proximity-reader.payment.acceptance
  4. Geographic restrictions - Tap to Pay isn't available in all countries

Timeline: Apple review for payment apps takes 2-4 weeks, not the usual few days.

Q

What's the deal with React Native 0.77+ support?

A

GitHub issue #936 shows breaking changes in RN 0.77.2+. Stick with 0.78 for now

  • that's what Stripe officially tests against.
Q

How do I handle "stuck in processing" payments?

A

This is GitHub issue #993. When payments get stuck:

  1. Don't create new PaymentIntents - Reuse the existing one
  2. Cancel the current payment if possible with cancelCollectPaymentMethod()
  3. Disconnect and reconnect the reader as last resort
  4. Never charge the same PaymentIntent twice
Q

Why do firmware updates fail constantly?

A

Card reader firmware updates fail when:

  • Internet connection drops during update
  • Reader battery is low (needs >50% charge)
  • Multiple devices trying to update same reader
  • Update servers are overloaded

Prevention: Only update readers during slow business hours with strong internet and fully charged batteries.

Q

Can I build a full POS system with this?

A

Technically yes, practically no. This SDK handles payment collection, but you still need:

  • Inventory management
  • Receipt printing (separate SDK)
  • Employee management
  • Tax calculations
  • Tip handling
  • Offline mode for when internet dies

Consider established POS platforms unless payments are your core business.

Q

What are the most common production failures?

A

Based on 18 months of production experience:

  1. Reader discovery timeouts (40% of failures) - Android Bluetooth cache issues after app restarts
  2. Connection token expiration (25% of failures) - Backend caches expired tokens, causes "authentication failed"
  3. Payment stuck in processing (20% of failures) - Reader doesn't complete transaction, requires restart
  4. iOS background disconnections (10% of failures) - App backgrounded during payment, connection lost
  5. Reader firmware update failures (5% of failures) - Updates fail, brick readers during business hours

Mitigation strategies that actually work:

  • Implement connection health checks every 30 seconds during active use
  • Never cache connection tokens - generate fresh ones each time
  • Keep backup readers charged and ready for firmware update failures
  • Show clear error messages when readers need power cycling
  • Log everything - Stripe support needs detailed error traces to help

Armed with these troubleshooting insights, you'll want quick access to documentation, tools, and community resources when problems arise. The resources section provides links to everything you'll need.

Production monitoring alerts:

  • Reader discovery taking >30 seconds
  • Connection token generation failures
  • Payment collection timeout >60 seconds
  • Multiple retry attempts on same PaymentIntent

Related Tools & Recommendations

integration
Similar content

Stripe Terminal iOS Integration: Go Native for Reliable POS

Skip the Cross-Platform Nightmare - Go Native

Stripe Terminal
/integration/stripe-terminal-pos/ios-native-integration
100%
tool
Similar content

Stripe Terminal: Unified In-Person Payments Platform

Integrate in-person payments with your existing Stripe infrastructure using pre-certified card readers, SDKs, and Tap to Pay technology

Stripe Terminal
/tool/stripe-terminal/overview
96%
integration
Similar content

Stripe React Native Firebase: Complete Auth & Payment Flow Guide

Stripe + React Native + Firebase: A Guide to Not Losing Your Mind

Stripe
/integration/stripe-react-native-firebase/complete-authentication-payment-flow
86%
integration
Similar content

Stripe Terminal React Native: Production Deployment Guide

Don't Let Beta Software Ruin Your Weekend: A Reality Check for Card Reader Integration

Stripe Terminal
/integration/stripe-terminal-react-native/production-deployment-guide
76%
compare
Similar content

Flutter vs React Native vs Kotlin Multiplatform: Choose Your Framework

The Real Question: Which Framework Actually Ships Apps Without Breaking?

Flutter
/compare/flutter-react-native-kotlin-multiplatform/cross-platform-framework-comparison
47%
tool
Similar content

MetaMask Web3 Integration: Mobile & Production Fixes

Stop fighting MetaMask Web3 integration issues on mobile and in production. Get working code examples and solutions for common connection problems and random di

MetaMask SDK
/tool/metamask-sdk/web3-integration-overview
43%
tool
Similar content

Alpaca-py SDK: Python Stock Trading & API Integration Guide

Explore Alpaca-py, the official Python SDK for Alpaca's trading APIs. Learn installation, API key setup, and how to build powerful stock trading strategies with

Alpaca-py SDK
/tool/alpaca-py/overview
40%
compare
Recommended

Stripe vs Plaid vs Dwolla vs Yodlee - Which One Doesn't Screw You Over

Comparing: Stripe | Plaid | Dwolla | Yodlee

Stripe
/compare/stripe/plaid/dwolla/yodlee/payment-ecosystem-showdown
37%
tool
Recommended

Stripe - The Payment API That Doesn't Suck

Finally, a payment platform that won't make you want to throw your laptop out the window when debugging webhooks at 3am

Stripe
/tool/stripe/overview
37%
news
Popular choice

Anthropic Raises $13B at $183B Valuation: AI Bubble Peak or Actual Revenue?

Another AI funding round that makes no sense - $183 billion for a chatbot company that burns through investor money faster than AWS bills in a misconfigured k8s

/news/2025-09-02/anthropic-funding-surge
34%
news
Popular choice

Morgan Stanley Open Sources Calm: Because Drawing Architecture Diagrams 47 Times Gets Old

Wall Street Bank Finally Releases Tool That Actually Solves Real Developer Problems

GitHub Copilot
/news/2025-08-22/meta-ai-hiring-freeze
33%
tool
Popular choice

Python 3.13 - You Can Finally Disable the GIL (But Probably Shouldn't)

After 20 years of asking, we got GIL removal. Your code will run slower unless you're doing very specific parallel math.

Python 3.13
/tool/python-3.13/overview
31%
compare
Recommended

Payment Processors Are Lying About AI - Here's What Actually Works in Production

After 3 Years of Payment Processor Hell, Here's What AI Features Don't Suck

Stripe
/compare/stripe/adyen/square/paypal/checkout-com/braintree/ai-automation-features-2025
31%
tool
Recommended

Braintree - PayPal's Payment Processing That Doesn't Suck

The payment processor for businesses that actually need to scale (not another Stripe clone)

Braintree
/tool/braintree/overview
31%
news
Popular choice

Anthropic Somehow Convinces VCs Claude is Worth $183 Billion

AI bubble or genius play? Anthropic raises $13B, now valued more than most countries' GDP - September 2, 2025

/news/2025-09-02/anthropic-183b-valuation
28%
news
Popular choice

Apple's Annual "Revolutionary" iPhone Show Starts Monday

September 9 keynote will reveal marginally thinner phones Apple calls "groundbreaking" - September 3, 2025

/news/2025-09-03/iphone-17-launch-countdown
27%
tool
Similar content

Binance Chain JavaScript SDK: Why It's Obsolete & What's Next

This SDK is basically dead. BNB Beacon Chain is being sunset and this thing hasn't been updated in 2 years. Use it for legacy apps, avoid it for new projects

Binance Chain JavaScript SDK
/tool/binance-smart-chain-sdk/performance-optimization
26%
tool
Recommended

React Native - Cross-Platform Mobile Development Framework

built on react-native

react-native
/tool/react-native/overview
26%
news
Recommended

Android 16 Public Beta Launches with Live Updates and Dark Mode Force

depends on General Technology News

General Technology News
/news/2025-08-24/android-16-public-beta
26%
tool
Recommended

Android Studio - Google's Official Android IDE

Current version: Narwhal Feature Drop 2025.1.2 Patch 1 (August 2025) - The only IDE you need for Android development, despite the RAM addiction and occasional s

Android Studio
/tool/android-studio/overview
26%

Recommendations combine user behavior, content similarity, research intelligence, and SEO optimization