Skip to content
master
Switch branches/tags
Code


Capacitor Stripe Terminal

capacitor-stripe-terminal

Capacitor plugin for Stripe Terminal (unofficial)


Current project status

WARNING

These instructions are for v2 which is currently in beta. See the v1-support branch for v1 instructions.

Maintainers

Maintainer GitHub Social
Noah Prail nprail @NoahPrail

Installation

Using npm:

npm install capacitor-stripe-terminal

Using yarn:

yarn add capacitor-stripe-terminal

Sync native files:

npx cap sync

Configuration

iOS

Follow all Stripe instructions under "Configure your app".

Android

Add the ACCESS_FINE_LOCATION permission to your app's manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.stripe.example.app">

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>

On Android, you must also make sure that Location permission has been granted by the user:

if (Capacitor.getPlatform() === 'android') {
  // check if permission is required
  let response = await StripeTerminalPlugin.checkPermissions();

  if (response.location === 'prompt') {
    // if it is required, request it
    response = await StripeTerminalPlugin.requestPermissions();

    if (response.location !== 'granted') {
      // if the request fails, show a message to the user
      throw new Error('Location permission is required.')
    }
  }
}

const terminal = await StripeTerminalPlugin.create({ ... })

If the user does not grant permission, StripeTerminalPlugin will throw an error when you try to initialize it so you will have to handle that.

Hint: If the user denies Location permission the first time you ask for it, Android will not display a prompt to the user on subsequent requests for permission and response will always be denied. You will have to ask the user to go into the app's settings to allow Location permission.

Usage

import {
  StripeTerminalPlugin,
  DiscoveryMethod
} from 'capacitor-stripe-terminal'

// First, initialize the SDK
const terminal = await StripeTerminalPlugin.create({
  fetchConnectionToken: async () => {
    const resp = await fetch('https://your-backend.dev/token', {
      method: 'POST'
    })
    const data = await resp.json()

    return data.secret
  },
  onUnexpectedReaderDisconnect: () => {
    // handle reader disconnect
  }
})

// Start scanning for readers
// capacitor-stripe-terminal uses Observables for any data streams
// To stop scanning, unsubscribe from the Observable.
// You must connect to a reader while scanning
terminal
  .discoverReaders({
    simulated: false,
    discoveryMethod: DiscoveryMethod.BluetoothProximity
  })
  .subscribe(readers => {
    if (readers.length) {
      const selectedReader = readers[0]
      const connectionConfig = {
        locationId: '{{LOCATION_ID}}'
      }
      terminal
        .connectBluetoothReader(selectedReader, connectionConfig)
        .then(connectedReader => {
          // the reader is now connected and usable
        })
    }
  })

// Once the reader is connected, collect a payment intent!

// subscribe to user instructions - these should be displayed to the user
const displaySubscription = terminal
  .didRequestReaderDisplayMessage()
  .subscribe(displayMessage => {
    console.log('displayMessage', displayMessage)
  })
const inputSubscription = terminal
  .didRequestReaderInput()
  .subscribe(inputOptions => {
    console.log('inputOptions', inputOptions)
  })

// retrieve the payment intent
await terminal.retrievePaymentIntent('your client secret created server side')

// collect the payment method
await terminal.collectPaymentMethod()

// and finally, process the payment
await terminal.processPayment()

// once you are done, make sure to unsubscribe (e.g. in ngOnDestroy)
displaySubscription.unsubscribe()
inputSubscription.unsubscribe()

API Reference

See the full API docs here.

Acknowledgements