capacitor-stripe-terminal
Capacitor plugin for Stripe Terminal (unofficial)
Maintainer | GitHub | Social |
---|---|---|
Noah Prail | nprail | @NoahPrail |
Using npm:
npm install capacitor-stripe-terminal
Using yarn:
yarn add capacitor-stripe-terminal
Sync native files:
npx cap sync
Follow all Stripe instructions under "Configure your app".
Add the plugin to your MainActivity.java
:
// import it at the top
import io.event1.capacitorstripeterminal.StripeTerminal;
this.init(savedInstanceState, new ArrayList<Class<? extends Plugin>>() {{
// Additional plugins you've installed go here
// Ex: add(TotallyAwesomePlugin.class);
add(StripeTerminal.class);
}});
Add the ACCESS_FINE_LOCATION
, BLUETOOTH
, and BLUETOOTH_ADMIN
permissions 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" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
</manifest>
On Android, you must also make sure that Location permission has been granted by the user:
const response = await StripeTerminalPlugin.getPermissions()
if (!response.granted) {
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.granted
will always be false
. You will have to ask the user to go into the app's settings to allow Location permission.
import {
StripeTerminalPlugin,
DeviceType,
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,
deviceType: DeviceType.Chipper2X,
discoveryMethod: DiscoveryMethod.BluetoothProximity
})
.subscribe(readers => {
if (readers.length) {
terminal
.connectReader({ serialNumber: readers[0].serialNumber })
.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
.readerDisplayMessage()
.subscribe(displayMessage => {
console.log('displayMessage', displayMessage)
})
const inputSubscription = terminal.readerInput().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()
See the full API docs here.
- Thanks Stripe for creating such an amazing product
- Thanks react-native-stripe-terminal for quite a few borrowed concepts