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:
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 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 "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
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) { } }); } }
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
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.
// 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. [[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 while testing, power off the reader.
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 }
- (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 }
// 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, 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.
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.