Giter Site home page Giter Site logo

stripe / stripe-terminal-react-native Goto Github PK

View Code? Open in Web Editor NEW
96.0 12.0 47.0 8.39 MB

React Native SDK for Stripe Terminal

Home Page: https://stripe.com/docs/terminal/payments/setup-integration?terminal-sdk-platform=react-native

License: MIT License

Shell 0.41% Kotlin 20.01% JavaScript 3.01% Java 1.10% Swift 16.27% Ruby 1.13% C 0.03% Objective-C 1.32% TypeScript 56.23% Objective-C++ 0.47%
react-native stripe stripe-terminal

stripe-terminal-react-native's Introduction

Stripe Terminal React Native SDK (Beta)

Stripe Terminal enables you to build your own in-person checkout to accept payments in the physical world. Built on Stripe's payments network, Terminal helps you unify your online and offline payment channels. With the Stripe Terminal React Native SDK, you can connect to pre-certified card readers from your React Native app and drive a customized in-store checkout flow.

Getting started

Note: The below docs are not yet available and will be released as we near open beta

Get started with our πŸ“š integration guides and example project, or πŸ“˜ browse the SDK reference.

Updating to a newer version of the SDK? See our release notes.

Requirements

JS

  • The SDK uses TypeScript features available in Babel version 7.9.0 and above. Alternatively use the plugin-transform-typescript plugin in your project.

Android

  • Android API level 26 and above
    • Note that attempting to override minSdkVersion to decrease the minimum supported API level will not work due to internal runtime API level validation. Furthermore, Stripe is updating the Terminal Android SDK to support Google’s recently released Android 14 (SDK 34). Please continue to target SDK 33 in the meantime as there are known issues with mPOS devices and TTP when targeting SDK 34. Please track the following ticket for updates on progress.
  • compileSdkVersion = 33
  • targetSdkVersion = 31

iOS

  • Compatible with apps targeting iOS 13 or above.

Try the example app

The React Native SDK includes an open-source example app, which you can use to familiarize yourself with the SDK and reader before starting your own integration.

To build the example app from source, you'll need to:

  1. Run yarn bootstrap from the root directory to build the SDK.
  2. Navigate to our example backend and click the button to deploy it on Heroku.
  3. Navigate to the example-app folder and run yarn install to install all example app dependencies.
  4. Copy .env.example to .env, and set the URL of the Heroku app you just deployed.
  5. Run either yarn ios or yarn android depending on which platform you would like to build.

Installation

yarn add @stripe/stripe-terminal-react-native

or

npm install @stripe/stripe-terminal-react-native

Example code

Initialization

To initialize Stripe Terminal SDK in your React Native app, use the StripeTerminalProvider component in the root component of your application.

First, create an endpoint on your backend server that creates a new connection token via the Stripe Terminal API.

Next, create a token provider that will fetch connection token from your server and provide it to StripeTerminalProvider as a parameter. Stripe Terminal SDK will fetch it when it's needed.

// Root.tsx
import { StripeTerminalProvider } from '@stripe/stripe-terminal-react-native';

function Root() {
  const fetchTokenProvider = async () => {
    const response = await fetch(`${API_URL}/connection_token`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
    });
    const { secret } = await response.json();
    return secret;
  };

  return (
    <StripeTerminalProvider
      logLevel="verbose"
      tokenProvider={fetchTokenProvider}
    >
      <App />
    </StripeTerminalProvider>
  );
}

As a last step, simply call initialize method from useStripeTerminal hook. Please note that initialize method must be called from a nested component of StripeTerminalProvider.

// App.tsx
function App() {
  const { initialize } = useStripeTerminal();

  useEffect(() => {
    initialize();
  }, [initialize]);

  return <View />;
}

Hooks and events

Stripe Terminal SDK provides dedicated hook which exposes bunch of methods and props to be used within your App. Additionally, you have access to the internal state of SDK that contains information about the current connection, discovered readers and loading state.

// PaymentScreen.tsx

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

export default function PaymentScreen() {
  const { discoverReaders, connectedReader, discoveredReaders } =
    useStripeTerminal({
      onUpdateDiscoveredReaders: (readers) => {
        // access to discovered readers
      },
      onDidChangeConnectionStatus: (status) => {
        // access to the current connection status
      },
    });

  useEffect(() => {
    const { error } = await discoverReaders({
      discoveryMethod: 'bluetoothScan',
      simulated: true,
    });
  }, [discoverReaders]);

  return <View />;
}

In case your app uses React Class Components you can use dedicated withStripeTerminal Higher-Order-Component. Please note that unlike the hooks approach, you need to use event emitter to listen on specific events that comes from SDK.

Here you can find the list of available events to be used within the event emitter.

Example:

// PaymentScreen.tsx

import {
  withStripeTerminal,
  WithStripeTerminalProps,
  CHANGE_CONNECTION_STATUS,
  Reader,
} from '@stripe/stripe-terminal-react-native';

class PaymentScreen extends React.Component {
  componentDidMount() {
    this.discoverReaders();
    const eventSubscription = props.emitter.addListener(
      CHANGE_CONNECTION_STATUS, // didChangeConnectionStatus
      (status: Reader.ConnectionStatus) => {
        // access to the current connection status
      }
    );
  }
  async discoverReaders() {
    this.props.discoverReaders({
      discoveryMethod: 'bluetoothScan',
      simulated: true,
    });
  }
}

export default withStripeTerminal(PaymentScreen);

Additional docs

Contributing

See the contributor guidelines to learn how to contribute to the repository.

stripe-terminal-react-native's People

Contributors

arekkubaczkowski avatar billfinn-stripe avatar bric-stripe avatar chenzesam avatar chr-stripe avatar davidme-stripe avatar dependabot[bot] avatar dhenry-stripe avatar ericlin-bbpos avatar henryx-stripe avatar ianlin-bbpos avatar jdivock-stripe avatar jil-stripe avatar kevinlam92 avatar lins-stripe avatar martinmroz-stripe avatar maxa-stripe avatar mihaildu avatar mindy-stripe avatar nazli-stripe avatar noahweingand avatar rdupon avatar sudoplz avatar thepianokid avatar therusskiy avatar tomas-stripe avatar ts-candide avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

stripe-terminal-react-native's Issues

Failure to fetch ConnectionToken on app init does not throw or surface error

Steps to repro:

  • turn off backend
  • initialize app

I think we need error handling logic in

const tokenProviderHandler = useCallback(async () => {
const connectionToken = await tokenProvider();
setConnectionToken(connectionToken);
}, [tokenProvider]);

Currently the app will continue to init and calls to discoverReaders() will execute but not update discoveredReaders, more concerning the error payload from discoverReaders does not populate when there's no connectionToken in use.

Also it looks like there's logic in the iOS app about using the correct key that's surpassed so looks like we want to make sure we're surfacing that as well (thanks @jil-stripe #76)

Create a nuclear "clean and re-bootstrap" target

Low hanging fruit, I've found it's pretty easy to get in a bad state and often I have to run

git clean -dfx
yarn bootstrap

So pending any other ideas let's just make this a target in the example app

Halting discover clears all `discoveredReaders`

This seems unexpected, if I halt discovering I should still have a list of readers to connect to in my application state.

Steps to repro:

  • discover readers (BT)
  • invoke cancelDiscover
  • discoveredReaders is now empy

Npm release scripts

I see we've earmarked using release-it and documented it, but it's not yet defined as a dep in the SDK. Just creating this issue to track this work so it doesn't slip by.

Android API level build warnings

> Task :app:dexBuilderDebug
AGPBI: {"kind":"warning","text":"An API level of 31 is not supported by this compiler. Please use an API level of 30 or earlier","sources":[{}],"tool":"D8"}
AGPBI: {"kind":"warning","text":"An API level of 31 is not supported by this compiler. Please use an API level of 30 or earlier","sources":[{}],"tool":"D8"}
AGPBI: {"kind":"warning","text":"An API level of 31 is not supported by this compiler. Please use an API level of 30 or earlier","sources":[{}],"tool":"D8"}
AGPBI: {"kind":"warning","text":"An API level of 31 is not supported by this compiler. Please use an API level of 30 or earlier","sources":[{}],"tool":"D8"}

Android builds frequently OOM


Execution failed for task ':app:packageDebug'.
> A failure occurred while executing com.android.build.gradle.tasks.PackageAndroidArtifact$IncrementalSplitterRunnable
   > java.lang.OutOfMemoryError (no error message)

We should see if we can resolve on our side, if nothing can be done we should provide guidance to add the following to the manifest:

      android:largeHeap="true"

Even with this I still get the occasional OOM which doesn't feel terrfic

Add docs on using with expo

Alright, looks like the SDK works with expo out of the box, we should just have steps in our readme and other docs calling out the need to eject.

Related: we need to have the Info.plist changes surfaced higher in our docs, without adding them to the manifest the user's app will immediately crash out with no trace which is a pretty frustrating experience.

Can we use `.rbenv` or a `gemfile` to lock in the cocoapods version?

Hey @arekkubaczkowski when I bootstrap locally I always wind up with the following diff that I don't want to check in

diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock
index b49b55b..58f72c1 100644
--- a/example/ios/Podfile.lock
+++ b/example/ios/Podfile.lock
@@ -450,11 +450,11 @@ EXTERNAL SOURCES:

 SPEC CHECKSUMS:
   boost: a7c83b31436843459a1961bfd74b96033dc77234
-  DoubleConversion: cde416483dac037923206447da6e1454df403714
+  DoubleConversion: 831926d9b8bf8166fd87886c4abab286c2422662
   FBLazyVector: de148e8310b8b878db304ceea2fec13f2c02e3a0
   FBReactNativeSpec: 6192956c9e346013d5f1809ba049af720b11c6a4
   fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
-  glog: 40a13f7840415b9a77023fbcae0f1e6f43192af3
+  glog: 5337263514dd6f09803962437687240c5dc39aa4
   RCT-Folly: a21c126816d8025b547704b777a2ba552f3d9fa9
   RCTRequired: 59d2b744d8c2bf2d9bc7032a9f654809adcf7d50
   RCTTypeSafety: d0aaf7ccae5c70a4aaa3a5c3e9e0db97efae760e
@@ -490,6 +490,6 @@ SPEC CHECKSUMS:
   StripeTerminal: da566fa62a4e7bbf0510dd27614f3087293cd79e
   Yoga: 32a18c0e845e185f4a2a66ec76e1fd1f958f22fa

-PODFILE CHECKSUM: 4f0873ca93c8515b2736ed78b61a035f42aa658c
+PODFILE CHECKSUM: 84b73709c1edcf5ac7a2639adb1bd9760a58aef7

-COCOAPODS: 1.10.1
+COCOAPODS: 1.11.2

Can we leverage rbenv or a gemfile to pin this? Thanks!

Get CI Green and require CI to pass on future merges

Currently on main we have the following failures, after we've resolve them we should make CI blocking on merge to prevent future regressions.

iOS:
https://app.circleci.com/pipelines/github/stripe/stripe-terminal-react-native/136/workflows/372de0d8-68f6-4687-ba77-fe71190c7b8c/jobs/603

FAIL  e2e/app.e2e.js (278.253 s)
  Payments
    βœ“ Connect and disconnect (16599 ms)
    βœ“ Install required update and connect (28667 ms)
    βœ“ Change discovery method to bluetooth proximity (12046 ms)
    βœ“ Change discovery method to Internet (12192 ms)
    βœ“ Collect card payment (38420 ms)
    βœ• Store card via readReusableCard (37932 ms)
    βœ• Store card via SetupIntent (34321 ms)
    βœ• In-Person Refund failed due to unsupported country (50061 ms)
    β—‹ skipped Required update impossible due to low battery

Android:
https://app.circleci.com/pipelines/github/stripe/stripe-terminal-react-native/136/workflows/372de0d8-68f6-4687-ba77-fe71190c7b8c/jobs/602

FAIL  e2e/app.e2e.js (811.605 s)
  Payments
    βœ• Connect and disconnect (216594 ms)
    βœ• Install required update and connect (216015 ms)
    βœ“ Change discovery method to bluetooth proximity (22016 ms)
    βœ“ Change discovery method to Internet (22621 ms)
    βœ“ Collect card payment (64384 ms)
    βœ• Store card via readReusableCard (65149 ms)
    βœ• Store card via SetupIntent (64599 ms)
    βœ“ In-Person Refund failed due to unsupported country (51630 ms)
    β—‹ skipped Required update impossible due to low battery

Example app no longer loads, fails with `RCTBridge required dispatch_sync to load RCTDevLoadingView. This may lead to deadlocks`

When loading the sample app the following warning appears, after it's dismissed the sample app displays as completely blank.

Screen Shot 2022-01-27 at 11 02 44 AM

Unsure if this was a regression or is somehow related to my work laptop being upgraded to OSX Monterey, my own dogfood app in another repo is still running correctly on [email protected]

Steps to repro:

  • checked out main
  • removed all non repo files with git clean -dfx
  • yarn bootstrap, cd example, yarn start, yarn ios
  • complied and deployed to simulator via the .xcworkspace file, no change

Looks like S/O solved it, but this seems gross and it's unclear why the issue just started manifesting. https://amanhimself.dev/blog/rctbridge-required-dispatch-sync-to-load-warning/

CI intermittently flaking on android test suite

Related to #60

#60 (comment)

Hrm, might still be flaking, going to re-open and keep and eye on it

detox[11347] ERROR: [Client.js/ERROR] Detox can't seem to connect to the test app(s)!

HINT: 

Have you forgotten to call 'device.launchApp()' in the beginning of your test?
Refer to our troubleshooting guide, for full details: https://wix.github.io/Detox/docs/troubleshooting/running-tests#tests-execution-hangs

---
The following package could not be delivered:

{
  type: 'invoke',
  params: [Object],
  messageId: 103
}

https://app.circleci.com/pipelines/github/stripe/stripe-terminal-react-native/175/workflows/a8b4e90b-c653-4106-997a-1c01459e450b/jobs/798

#60 (comment)

https://app.circleci.com/pipelines/github/stripe/stripe-terminal-react-native/177/workflows/29d5f1a1-a0b8-41c5-8103-9274288f0848/jobs/809

Clean up collect payment screen

We can make this a bit more intuitive, currently the inputs are blank while there's a displayed value, perhaps we should just have populated values in the form drive what's collected?
collect

Unit tests

Currently there are none

stripe-terminal-react-native git/jdivock/env-backend  109s
❯ yarn test
yarn run v1.22.11
$ jest
No tests found, exiting with code 1
Run with `--passWithNoTests` to exit with code 0
In /Users/jdivock/stripe/stripe-terminal-react-native
  96 files checked.
  testMatch: **/__tests__/**/*.[jt]s?(x), **/?(*.)+(spec|test).[tj]s?(x) - 0 matches
  testPathIgnorePatterns: /node_modules/ - 96 matches
  testRegex:  - 0 matches
Pattern:  - 0 matches
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
  • Android Unit Tests #204
  • iOS Unit Tests
  • JS/TS Unit Tests

RN Version Update to 0.66.3

automatic code scanning found that the version of RN being used in the stripe-terminal-react-native repo has a vulnerability and needs to be updated.
Package: react-native
Repository: stripe/stripe-terminal-react-native
Manifest File: yarn.lock and example/yarn.lock
Vulnerable Version Range: >= 0.63.0, < 0.64.1
Fixed In Version: 0.64.1 ( We will go to 0.66.3 as this is currently the latest version)

CI takes ~25m to complete

We're currently clocking in at roughly ~20m which is a little rough, let's see if we can improve things by:

  • caching any build artifacts
  • parallelize tasks, currently we just have 1 thread
  • detox is the bulk of this, we have an 8m config target and an 8m build target
    • config
    • android build: #147
    • iOS build
    • can we combine or streamline these, or rely on cache somehow?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.