Capacitor Stripe Terminal
capacitor-stripe-terminal
Capacitor plugin for Stripe Terminal (unofficial)
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.
Sponsors
Acknowledgements
- Thanks Stripe for creating such an amazing product
- Thanks react-native-stripe-terminal for quite a few borrowed concepts