Connecting to the BBPOS Chipper 2X BT

    To connect your point of sale application to a BBPOS Chipper 2X BT reader, use Bluetooth and the Stripe Terminal SDK.

    The BBPOS Chipper 2X BT is a Bluetooth LE device. It collects payment details, but relies on a paired mobile device for communication with Stripe. Connecting your app to a Bluetooth reader requires two steps:

    Use this guide to connect your application to the reader using the discoverReaders and connectReader methods.

    Discovering readers

    First, make sure the reader is turned on. Then, from your app, search for nearby Bluetooth readers using the discoverReaders method.

    import UIKit
    import StripeTerminal
    
    class ReaderViewController: UIViewController, DiscoveryDelegate, TerminalDelegate {
    
        var discoverCancelable: Cancelable?
    
        // ...
    
        // Action for a "Connect Reader" button
        func connectReaderAction() {
            let config = DiscoveryConfiguration(deviceType: .chipper2X,
                                                discoveryMethod: .bluetoothProximity,
                                                simulated: false)
            self.discoverCancelable = Terminal.shared.discoverReaders(config, delegate: self, completion: { error in
                if let error = error {
                    print("discoverReaders failed: \(error)")
                }
                else {
                    print("discoverReaders succeeded")
                }
            })
        }
    
        // ...
    
        // MARK: DiscoveryDelegate
    
        func terminal(_ terminal: Terminal, didUpdateDiscoveredReaders readers: [Reader]) {
            // In your app, display the discovered reader(s) to the user.
            // Call `connectReader` after the user selects a reader to connect to.
        }
    }
    
    #import "APPReaderViewController.h"
    #import <StripeTerminal/StripeTerminal.h>
    
    @interface APPReaderViewController () <SCPDiscoveryDelegate, SCPTerminalDelegate>
    
    @property (nonatomic, nullable, strong) SCPCancelable *discoverCancelable;
    
    // ...
    
    @end
    
    @implementation APPReaderViewController
    
    // Action for a "Connect Reader" button
    - (void)connectReaderAction {
        SCPDiscoveryConfiguration *config = [[SCPDiscoveryConfiguration alloc] initWithDeviceType:SCPDeviceTypeChipper2X
                                                                                  discoveryMethod:SCPDiscoveryMethodBluetoothProximity
                                                                                        simulated:YES];
        self.discoverCancelable = [[SCPTerminal shared] discoverReaders:config delegate:self completion:^(NSError *error) {
            if (error != nil) {
                NSLog(@"discoverReaders failed: %@", error);
            }
            else {
                NSLog(@"discoverReaders succeeded");
            }
        }];
    }
    
    // ...
    
    #pragma mark - SCPDiscoveryDelegate
    
    - (void)terminal:(SCPTerminal *)terminal didUpdateDiscoveredReaders:(NSArray<SCPReader *> *)readers {
        // In your app, display the discovered reader(s) to the user.
        // Call `connectReader` after the user selects a reader to connect to.
    }
    
    @end
    
    public void onDiscoverReaders() {
      DiscoveryConfiguration config = new DiscoveryConfiguration(0, DeviceType.CHIPPER_2X, false);
      Terminal.getInstance().discoverReaders(config, readers -> {
        // Display the discovered readers to the user
      }, new Callback() {
        @Override
        public void onSuccess() {
          System.out.println("Finished discovering readers");
        }
    
        @Override
        public void onFailure(TerminalException e) {
          e.printStackTrace();
        }
      }
    }
    fun onDiscoverReaders() {
      var config = DiscoveryConfiguration(0, DeviceType.CHIPPER_2X, false)
      Terminal.getInstance().discoverReaders(config, { readers: List<Reader> ->
          // Display the discovered readers to the user
      }, object : Callback {
        override fun onSuccess() {
          System.out.println("Finished discovering readers")
        }
    
        override fun onFailure(e: TerminalException) {
          e.printStackTrace()
        }
      })
    }

    Depending on your SDK, you can use either the bluetoothProximity or bluetoothScan discovery method to search for readers.

    Discovery method Supported SDKs
    Bluetooth Proximity iOS
    Bluetooth Scan iOS, Android

    Bluetooth Proximity

    Bluetooth Proximity filters search results to return the closest reader. When discovered, the reader flashes multicolored lights, making it easy for your user to identify the discovered reader among many other readers. After a reader has been discovered, the SDK won’t switch to a closer reader unless you turn off the discovered reader.

    Note that when using Bluetooth Proximity, the SDK returns the reader to your app’s callback twice. The first time, your app receives a Reader object populated with only the reader’s serial number. After a short delay, your app receives the same Reader object populated with new information, such as the reader’s battery level.

    We recommend displaying the discovered reader in your app’s UI, letting the user either confirm connection to the reader or cancel if they don’t want to connect to this reader.

    Bluetooth Scan

    Bluetooth Scan searches for all nearby readers and returns a list of discovered readers to your app. As the discovery process continues, the SDK continues updating your app’s callback with the latest list of nearby readers. With the Bluetooth Scan discovery method, you can set a timeout to scan for a set period of time.

    In your mobile app, we recommend displaying an auto-updating list of discovered readers, with serial numbers or labels to help users identify their reader.

    Connecting to a reader

    To connect to a discovered reader, call the connectReader method from your app. As soon as the reader is connected, its status light shines steady blue.

    // In your app, display the discovered reader(s) to the user.
    // Call `connectReader` with the selected reader.
    Terminal.shared.connectReader(selectedReader, completion: { reader, error in
        if let reader = reader {
            print("Successfully connected to reader: \(reader)")
        }
        else if let error = error {
            print("connectReader failed: \(error)")
        }
    })
    
    // In your app, display the discovered reader(s) to the user.
    // Call `connectReader` with the selected reader.
    [[SCPTerminal shared] connectReader:selectedReader completion:^(SCPReader *reader, NSError *error) {
        if (reader != nil) {
            NSLog(@"Successfully connected to reader: %@", reader);
        }
        else {
            NSLog(@"connectReader failed: %@", error);
        }
    }];
    
    // after selecting a reader to connect to
    Terminal.getInstance().connectReader(firstReader, new ReaderCallback() {
      @Override
      public void onSuccess(Reader r) {
        System.out.println("Connected to reader");
      }
    
      @Override
      public void onFailure(@Nonnull TerminalException e) {
        e.printStackTrace();
      }
    });
    // after selecting a reader to connect to
    Terminal.getInstance().connectReader(firstReader, object : ReaderCallback {
        override fun onSuccess(r: Reader?) {
            System.out.println("Connected to reader")
        }
    
        override fun onFailure(e: TerminalException) {
            e.printStackTrace()
        }
    })

    On iOS, for your app to run in the background and remain connected to the reader, configure your app to include the required background mode.

    Do not program your app to call disconnectReader to conserve power. The reader efficiently handles power management using its standby mode.

    Handling disconnects

    Your app must implement the UnexpectedReaderDisconnect callback to handle when a reader is disconnected.

    In your implementation of this callback, display a UI to notify the user that the reader disconnected. You may also want to call discoverReaders to begin scanning for readers and reconnect. Your app can attempt to automatically reconnect to the reader that was disconnected, or display a UI for your user to reconnect to another reader.

    The BBPOS Chipper 2X BT can disconnect from your app if it goes out of range or runs out of battery. To simulate an unexpected disconnect, power off the reader.

    override func viewDidLoad() {
        super.viewDidLoad()
        Terminal.shared.delegate = self
    }
    
    // ...
    
    // MARK: TerminalDelegate
    
    func terminal(_ terminal: Terminal, didReportUnexpectedReaderDisconnect reader: Reader) {
        print("Disconnected from reader: \(reader)")
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        [SCPTerminal shared].delegate = self;
    }
    
    // ...
    
    #pragma mark – SCPTerminalDelegate
    
    - (void)terminal:(SCPTerminal *)terminal didReportUnexpectedReaderDisconnect:(SCPReader *)reader {
        NSLog(@"Disconnected from reader: %@", reader);
    }
    
    // Note: TokenProvider is a class defined by your app implementing the ConnectionTokenProvider interface
    Terminal.initTerminal(applicationContext, LogLevel.VERBOSE, new TokenProvider(), new TerminalListener() {
      @Override
      public void onUnexpectedReaderDisconnect(Reader reader) {
        System.out.println("Disconnected from reader");
      }
    })
    // Note: TokenProvider is a class defined by your app implementing the ConnectionTokenProvider interface
    Terminal.initTerminal(appliactionContext, LogLevel.VERBOSE, TokenProvider(), object: TerminalListener {
      override fun onUnexpectedReaderDisconnect(reader: Reader) {
        System.out.println("Disconnected from reader")
      }
    })

    Next steps

    Congratulations! You've connected your app to the reader. Next, collect your first Stripe Terminal payment.

    The BBPOS and Chipper™ name and logo are trademarks or registered trademarks of BBPOS Limited in the United States and/or other countries. The Verifone® name and logo are either trademarks or registered trademarks of Verifone in the United States and/or other countries. Use of the trademarks does not imply any endorsement by BBPOS or Verifone.

    Questions?

    We're always happy to help with code or other questions you might have. Search our documentation, contact support, or connect with our sales team. You can also chat live with other developers in #stripe on freenode.

    Was this page helpful? Yes No

    Send

    Thank you for helping improve Stripe's documentation. If you need help or have any questions, please consider contacting support.

    On this page