A flutter plugin to scan stripe readers and connect to the them and get the payment methods.


This plugin tries to faithfully follow the signature of classes and methods. Most of the classes in dart have the same name as the native classes. There may be some differences between this sdk and the native one to expose an API more simply by supporting streams instead of callbacks for listeners


All features of android and ios sdk are supported (Also the TapToPay feature)

Offline mode is not supported



If you are using this plugin along with Stripe Terminal SDK see this section [Issue #349][]
android {
    // TODO: remove this two directives once stripe_terminal fixes its plugin
    //      these two snippets are excluding a dup dependency that is probably not transitive
    configurations {
        all*.exclude module: 'bcprov-jdk15to18'
    packagingOptions {
        pickFirst 'org/bouncycastle/x509/'
        pickFirst 'org/bouncycastle/x509/'


You need to provide permission request strings to your Info.plist file. A sample content can be

	<string>Location access is required in order to accept payments.</string>
	<string>Bluetooth access is required in order to connect to supported bluetooth card readers.</string>
	<string>This app uses Bluetooth to connect to supported card readers.</string>

You also need to authorize background modes authorization for bluetooth-central. Paste the following to your Info.plist file


Known bugs


You can see the usage example in the example folder


  1. Request the permissions

    import 'package:permission_handler/permission_handler.dart';
    final permissions = [
      if (Platform.isAndroid) ...[
    await permissions.request();
  2. Initialize the SDK

    stripeTerminal = StripeTerminal.getInstance(
      fetchToken: () async {
        // Call your backend to get the connection token and return to this function
        // Example token can be.
        const token = "pst_test_XXXXXXXXXX...."; 
        return token;

    Example backend code to get the connection token written on node.js:

     import Stripe from "stripe";
     import express from "express";
     const stripe = new Stripe("sk_test_XXXXXXXXXXXXXXXXXX", {
         apiVersion: "2020-08-27"
     const app = express();
     app.get("/connectionToken", async (req, res) => {
         const token = await stripe.terminal.connectionTokens.create();
             success: true,
             data: token.secret
     app.listen(8000, () => {
         console.log("Server started")

Discover and Connect Reader

  1. Discover the devices nearby and show it to the user. Stripe Docs
        .discoverReaders(BluetoothProximityDiscoveryConfiguration(isSimulated: true))
        .listen((List<StripeReader> readers) {
            setState(() => _readers = readers);
  2. Connect to a reader
    • Bluetooth reader
      await stripeTerminal.connectBluetoothReader(readers[0].serialNumber, locationId: locationId);
      print("Connected to a device");
    • TapToPay
      await stripeTerminal.connectMobileReader(readers[0].serialNumber, locationId: locationId);
      print("Connected to a device");

Process a Payment

  1. Create a payment intent on backend side
    // Get this from your backend by creating a new payment intent
    final backendPaymentIntent = await backend.createPaymentIntent();
  2. Retrieve payment intent
    final paymentIntent = await stripeTerminal.retrievePaymentIntent(backendPaymentIntent.clientSecret);
  3. Collect payment method
    final processablePaymentIntent = await stripeTerminal.collectPaymentMethod(paymentIntent);
  4. Collect payment method
    final capturablePaymentIntent = await stripeTerminal.confirmPaymentIntent(processablePaymentIntent)
    print("A payment intent has captured a payment method, send this payment intent to you backend to capture the payment");


The code is formatted with a line/page length of 100 characters. Use conventional commits for your commits. Much code in this plugin is auto generated:


Format code with ./gradlew spotlessApply