Create account
Sign in
Home
Payments
Business operations
Financial services
Developer tools
Security
All products
Home
Payments
Business operations
Home
Payments
Business operations
Financial services
Developer tools
Support
Overview
Overview
Sample integration
Example applications
Designing an integration
Getting started
JavaScript
iOS
Android
Readers
Reader setup
Connecting to a reader
BBPOS Chipper 2X BT
Verifone P400
Fleet management
Placing orders
Transactions
Collecting payments
Connect platforms
Saving cards
Refunds
Checkout experience
Cart display
Receipts
Global
Canada
Beta
Beta migration guide
Testing
Checklist
Testing
terminal
·
HomePaymentsIn-person paymentsConnecting to a reader

Connecting to the BBPOS Chipper 2X BT

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

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:

  • Discovering readers
  • Connecting to a reader

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

Do not use mobile device settings to pair with your reader. Pairing the BBPOS Chipper 2X BT through device settings makes the reader unavailable to connect to your app.

Discovering readers

SDK Reference

  • discoverReaders (iOS)
  • discoverReaders (Android)

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

iOS Android
Swift Objective-C
ReaderDiscoveryViewController.swift
Download
import UIKit import StripeTerminal class ReaderDiscoveryViewController: UIViewController, DiscoveryDelegate { var discoverCancelable: Cancelable? // ... // Action for a "Discover Readers" button func discoverReadersAction() { let config = DiscoveryConfiguration( discoveryMethod: .bluetoothProximity, simulated: false ) self.discoverCancelable = Terminal.shared.discoverReaders(config, delegate: self) { 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 UIKit import StripeTerminal class ReaderDiscoveryViewController: UIViewController, DiscoveryDelegate { var discoverCancelable: Cancelable? // ... // Action for a "Discover Readers" button func discoverReadersAction() { let config = DiscoveryConfiguration( discoveryMethod: .bluetoothProximity, simulated: false ) self.discoverCancelable = Terminal.shared.discoverReaders(config, delegate: self) { 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. } }
APPReaderDiscoveryViewController.m
Download
#import "APPReaderDiscoveryViewController.h" #import <StripeTerminal/StripeTerminal.h> @interface APPReaderDiscoveryViewController () <SCPDiscoveryDelegate> @property (nonatomic, nullable, strong) SCPCancelable *discoverCancelable; // ... @end @implementation APPReaderDiscoveryViewController // Action for a "Discover Readers" button - (void)discoverReadersAction { SCPDiscoveryConfiguration *config = [[SCPDiscoveryConfiguration alloc] initWithDiscoveryMethod:SCPDiscoveryMethodBluetoothScan simulated:NO]; 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
#import "APPReaderDiscoveryViewController.h" #import <StripeTerminal/StripeTerminal.h> @interface APPReaderDiscoveryViewController () <SCPDiscoveryDelegate> @property (nonatomic, nullable, strong) SCPCancelable *discoverCancelable; // ... @end @implementation APPReaderDiscoveryViewController // Action for a "Discover Readers" button - (void)discoverReadersAction { SCPDiscoveryConfiguration *config = [[SCPDiscoveryConfiguration alloc] initWithDiscoveryMethod:SCPDiscoveryMethodBluetoothScan simulated:NO]; 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
Java Kotlin
ReaderActivity.java
private Cancelable discoveryCancelable; public void onDiscoverReaders() { DiscoveryConfiguration config = new DiscoveryConfiguration(0, DeviceType.CHIPPER_2X, false); // Save this cancelable to an instance variable discoveryCancelable = 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(); } } } @Override public void onStop() { // If you're leaving the activity or fragment without selecting a reader, // make sure you cancel the discovery process or the SDK will be stuck in // a discover readers phase if (discoveryCancelable != null) { discoveryCancelable.cancel(new Callback() { @Override public void onSuccess() { } @Override public void onFailure(TerminalException e) { } }); } }
private Cancelable discoveryCancelable; public void onDiscoverReaders() { DiscoveryConfiguration config = new DiscoveryConfiguration(0, DeviceType.CHIPPER_2X, false); // Save this cancelable to an instance variable discoveryCancelable = 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(); } } } @Override public void onStop() { // If you're leaving the activity or fragment without selecting a reader, // make sure you cancel the discovery process or the SDK will be stuck in // a discover readers phase if (discoveryCancelable != null) { discoveryCancelable.cancel(new Callback() { @Override public void onSuccess() { } @Override public void onFailure(TerminalException e) { } }); } }
ReaderActivity.kt
var discoveryCancelable: Cancelable? = null fun onDiscoverReaders() { var config = DiscoveryConfiguration(0, DeviceType.CHIPPER_2X, false) // Save this cancelable to an instance variable discoveryCancelable = 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() } }) } override fun onStop() { // If you're leaving the activity or fragment without selecting a reader, // make sure you cancel the discovery process or the SDK will be stuck in // a discover readers phase discoveryCancelable?.cancel(object : Callback { override fun onSuccess() { } override fun onFailure(e: TerminalException) { } }) }
var discoveryCancelable: Cancelable? = null fun onDiscoverReaders() { var config = DiscoveryConfiguration(0, DeviceType.CHIPPER_2X, false) // Save this cancelable to an instance variable discoveryCancelable = 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() } }) } override fun onStop() { // If you're leaving the activity or fragment without selecting a reader, // make sure you cancel the discovery process or the SDK will be stuck in // a discover readers phase discoveryCancelable?.cancel(object : Callback { override fun onSuccess() { } override fun onFailure(e: TerminalException) { } }) }

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 to invoke the DiscoveryDelegate.didUpdateDiscoveredReaders method 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. This is useful for managing battery life or triggering an error message if no devices are found.

In your mobile application, 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

SDK Reference

  • connectReader (iOS)
  • connectReader (Android)

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.

iOS Android
Swift Objective-C
ReaderDiscoveryViewController.swift
// Call `connectReader` with the selected reader. Terminal.shared.connectReader(selectedReader) { reader, error in if let reader = reader { print("Successfully connected to reader: \(reader)") } else if let error = error { print("connectReader failed: \(error)") } }
// Call `connectReader` with the selected reader. Terminal.shared.connectReader(selectedReader) { reader, error in if let reader = reader { print("Successfully connected to reader: \(reader)") } else if let error = error { print("connectReader failed: \(error)") } }
APPReaderDiscoveryViewController.m
// 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); } }];
// 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); } }];
Java Kotlin
ReaderActivity.java
// 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, new ReaderCallback() { @Override public void onSuccess(Reader r) { System.out.println("Connected to reader"); } @Override public void onFailure(@Nonnull TerminalException e) { e.printStackTrace(); } });
ReaderActivity.kt
// 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() } })
// 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

SDK Reference

  • TerminalDelegate (iOS)
  • TerminalListener (Android)

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 while testing, power off the reader.

iOS Android
Swift Objective-C
ReaderViewController.swift
override func viewDidLoad() { super.viewDidLoad() Terminal.shared.delegate = self } // ... // MARK: TerminalDelegate func terminal(_ terminal: Terminal, didReportUnexpectedReaderDisconnect reader: Reader) { // You might want to display UI to notify the user and start re-discovering readers }
override func viewDidLoad() { super.viewDidLoad() Terminal.shared.delegate = self } // ... // MARK: TerminalDelegate func terminal(_ terminal: Terminal, didReportUnexpectedReaderDisconnect reader: Reader) { // You might want to display UI to notify the user and start re-discovering readers }
APPReaderViewController.m
- (void)viewDidLoad { [super viewDidLoad]; [SCPTerminal shared].delegate = self; } // ... #pragma mark – SCPTerminalDelegate - (void)terminal:(SCPTerminal *)terminal didReportUnexpectedReaderDisconnect:(SCPReader *)reader { // You might want to display UI to notify the user and start re-discovering readers }
- (void)viewDidLoad { [super viewDidLoad]; [SCPTerminal shared].delegate = self; } // ... #pragma mark – SCPTerminalDelegate - (void)terminal:(SCPTerminal *)terminal didReportUnexpectedReaderDisconnect:(SCPReader *)reader { // You might want to display UI to notify the user and start re-discovering readers }
Java Kotlin
MainActivity.java
// 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) { // You might want to display UI to notify the user and start re-discovering readers } })
// 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) { // You might want to display UI to notify the user and start re-discovering readers } })
MainActivity.kt
// Note: TokenProvider is a class defined by your app implementing the ConnectionTokenProvider interface Terminal.initTerminal(applicationContext, LogLevel.VERBOSE, TokenProvider(), object: TerminalListener { override fun onUnexpectedReaderDisconnect(reader: Reader) { // You might want to display UI to notify the user and start re-discovering readers } })
// Note: TokenProvider is a class defined by your app implementing the ConnectionTokenProvider interface Terminal.initTerminal(applicationContext, LogLevel.VERBOSE, TokenProvider(), object: TerminalListener { override fun onUnexpectedReaderDisconnect(reader: Reader) { // You might want to display UI to notify the user and start re-discovering readers } })

Next steps

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

  • Collecting Payments
  • Using Terminal with Connect

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.

Was this page helpful?
Questions? Contact us.
Developer tutorials on YouTube.
You can unsubscribe at any time. Read our privacy policy.
On this page
Discovering readers
Connecting to a reader
Handling disconnects
Next steps