diff --git a/android/src/main/java/com/stripeterminalreactnative/StripeTerminalReactNativeModule.kt b/android/src/main/java/com/stripeterminalreactnative/StripeTerminalReactNativeModule.kt
index ef81e545..363d0c0f 100644
--- a/android/src/main/java/com/stripeterminalreactnative/StripeTerminalReactNativeModule.kt
+++ b/android/src/main/java/com/stripeterminalreactnative/StripeTerminalReactNativeModule.kt
@@ -300,6 +300,13 @@ class StripeTerminalReactNativeModule(reactContext: ReactApplicationContext) :
terminal.disconnectReader(NoOpCallback(promise))
}
+ @ReactMethod
+ @Suppress("unused")
+ fun rebootReader(promise: Promise) {
+ paymentIntents.clear()
+ terminal.rebootReader(NoOpCallback(promise))
+ }
+
@ReactMethod
@Suppress("unused")
fun cancelReaderReconnection(promise: Promise) {
diff --git a/dev-app/src/components/ListItem.tsx b/dev-app/src/components/ListItem.tsx
index 0f6186c6..907b9c8a 100644
--- a/dev-app/src/components/ListItem.tsx
+++ b/dev-app/src/components/ListItem.tsx
@@ -16,6 +16,7 @@ type Props = {
onPress?(): void;
color?: string;
testID?: string;
+ visible?: boolean;
};
export default function ListItem({
@@ -26,8 +27,9 @@ export default function ListItem({
onPress,
testID,
disabled,
+ visible = true,
}: Props) {
- return (
+ return visible ? (
{rightElement && rightElement}
- );
+ ) : null;
}
const styles = StyleSheet.create({
diff --git a/dev-app/src/screens/HomeScreen.tsx b/dev-app/src/screens/HomeScreen.tsx
index a82cbfa8..6ca6a64d 100644
--- a/dev-app/src/screens/HomeScreen.tsx
+++ b/dev-app/src/screens/HomeScreen.tsx
@@ -31,48 +31,53 @@ export default function HomeScreen() {
const [online, setOnline] = useState(true);
const [discoveryMethod, setDiscoveryMethod] =
useState('bluetoothScan');
- const { disconnectReader, connectedReader } = useStripeTerminal({
- onDidChangeOfflineStatus(status: OfflineStatus) {
- console.log(status);
- setOnline(status.sdk.networkStatus === 'online' ? true : false);
- },
- onDidForwardingFailure(error) {
- console.log('onDidForwardingFailure ' + error?.message);
- let toast = Toast.show(error?.message ? error.message : 'unknown error', {
- duration: Toast.durations.LONG,
- position: Toast.positions.BOTTOM,
- shadow: true,
- animation: true,
- hideOnPress: true,
- delay: 0,
- });
+ const { disconnectReader, connectedReader, rebootReader } = useStripeTerminal(
+ {
+ onDidChangeOfflineStatus(status: OfflineStatus) {
+ console.log(status);
+ setOnline(status.sdk.networkStatus === 'online' ? true : false);
+ },
+ onDidForwardingFailure(error) {
+ console.log('onDidForwardingFailure ' + error?.message);
+ let toast = Toast.show(
+ error?.message ? error.message : 'unknown error',
+ {
+ duration: Toast.durations.LONG,
+ position: Toast.positions.BOTTOM,
+ shadow: true,
+ animation: true,
+ hideOnPress: true,
+ delay: 0,
+ }
+ );
- setTimeout(function () {
- Toast.hide(toast);
- }, 3000);
- },
- onDidForwardPaymentIntent(paymentIntent, error) {
- let toastMsg =
- 'Payment Intent ' +
- paymentIntent.id +
- ' forwarded. ErrorCode' +
- error?.code +
- '. ErrorMsg = ' +
- error?.message;
- let toast = Toast.show(toastMsg, {
- duration: Toast.durations.LONG,
- position: Toast.positions.BOTTOM,
- shadow: true,
- animation: true,
- hideOnPress: true,
- delay: 0,
- });
+ setTimeout(function () {
+ Toast.hide(toast);
+ }, 3000);
+ },
+ onDidForwardPaymentIntent(paymentIntent, error) {
+ let toastMsg =
+ 'Payment Intent ' +
+ paymentIntent.id +
+ ' forwarded. ErrorCode' +
+ error?.code +
+ '. ErrorMsg = ' +
+ error?.message;
+ let toast = Toast.show(toastMsg, {
+ duration: Toast.durations.LONG,
+ position: Toast.positions.BOTTOM,
+ shadow: true,
+ animation: true,
+ hideOnPress: true,
+ delay: 0,
+ });
- setTimeout(function () {
- Toast.hide(toast);
- }, 3000);
- },
- });
+ setTimeout(function () {
+ Toast.hide(toast);
+ }, 3000);
+ },
+ }
+ );
const batteryPercentage =
(connectedReader?.batteryLevel ? connectedReader?.batteryLevel : 0) * 100;
const batteryStatus = batteryPercentage
@@ -106,6 +111,19 @@ export default function HomeScreen() {
await disconnectReader();
}}
/>
+ {
+ await rebootReader();
+ }}
+ visible={
+ discoveryMethod === 'bluetoothScan' ||
+ discoveryMethod === 'bluetoothProximity' ||
+ discoveryMethod === 'usb'
+ }
+ />
diff --git a/ios/StripeTerminalReactNative.m b/ios/StripeTerminalReactNative.m
index 335a7fb9..516f8c38 100644
--- a/ios/StripeTerminalReactNative.m
+++ b/ios/StripeTerminalReactNative.m
@@ -43,6 +43,11 @@ @interface RCT_EXTERN_MODULE(StripeTerminalReactNative, RCTEventEmitter)
rejecter: (RCTPromiseRejectBlock)reject
)
+RCT_EXTERN_METHOD(
+ rebootReader:(RCTPromiseResolveBlock)resolve
+ rejecter: (RCTPromiseRejectBlock)reject
+ )
+
RCT_EXTERN_METHOD(
createPaymentIntent:(NSDictionary *)params
resolver: (RCTPromiseResolveBlock)resolve
diff --git a/ios/StripeTerminalReactNative.swift b/ios/StripeTerminalReactNative.swift
index bcf03349..3af483dd 100644
--- a/ios/StripeTerminalReactNative.swift
+++ b/ios/StripeTerminalReactNative.swift
@@ -347,6 +347,18 @@ class StripeTerminalReactNative: RCTEventEmitter, DiscoveryDelegate, BluetoothRe
}
}
+ @objc(rebootReader:rejecter:)
+ func rebootReader(resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
+ Terminal.shared.rebootReader() { error in
+ if let error = error as NSError? {
+ resolve(Errors.createError(nsError: error))
+ } else {
+ self.paymentIntents = [:]
+ resolve([:])
+ }
+ }
+ }
+
func terminal(_ terminal: Terminal, didReportUnexpectedReaderDisconnect reader: Reader) {
let error = Errors.createError(code: ErrorCode.unexpectedSdkError, message: "Reader has been disconnected unexpectedly")
sendEvent(withName: ReactNativeConstants.REPORT_UNEXPECTED_READER_DISCONNECT.rawValue, body: error)
diff --git a/src/StripeTerminalSdk.tsx b/src/StripeTerminalSdk.tsx
index e0d98c77..52790a2f 100644
--- a/src/StripeTerminalSdk.tsx
+++ b/src/StripeTerminalSdk.tsx
@@ -7,6 +7,7 @@ import type {
CancelDiscoveringResultType,
ConnectBluetoothReaderParams,
DisconnectReaderResultType,
+ RebootReaderResultType,
Reader,
ConnectInternetReaderParams,
ConnectUsbReaderParams,
@@ -72,6 +73,8 @@ export interface StripeTerminalSdkType {
): Promise;
// Disconnect reader
disconnectReader(): Promise;
+ // Reboot reader
+ rebootReader(): Promise;
// Create a payment intent
createPaymentIntent(
params: CreatePaymentIntentParams
diff --git a/src/__tests__/__snapshots__/functions.test.ts.snap b/src/__tests__/__snapshots__/functions.test.ts.snap
index 5301dc68..7c2de426 100644
--- a/src/__tests__/__snapshots__/functions.test.ts.snap
+++ b/src/__tests__/__snapshots__/functions.test.ts.snap
@@ -30,6 +30,7 @@ Object {
"getOfflineStatus": [Function],
"initialize": [Function],
"installAvailableUpdate": [Function],
+ "rebootReader": [Function],
"retrievePaymentIntent": [Function],
"retrieveSetupIntent": [Function],
"setConnectionToken": [Function],
diff --git a/src/__tests__/functions.test.ts b/src/__tests__/functions.test.ts
index daf9ee76..a50e8b70 100644
--- a/src/__tests__/functions.test.ts
+++ b/src/__tests__/functions.test.ts
@@ -59,6 +59,7 @@ describe('functions.test.ts', () => {
setConnectionToken: jest.fn(),
simulateReaderUpdate: jest.fn(),
disconnectReader: jest.fn(),
+ rebootReader: jest.fn(),
clearCachedCredentials: jest.fn(),
discoverReaders: jest.fn().mockImplementation(() => ({})),
@@ -389,6 +390,7 @@ describe('functions.test.ts', () => {
disconnectReader: jest
.fn()
.mockImplementation(() => ({ error: '_error' })),
+ rebootReader: jest.fn().mockImplementation(() => ({ error: '_error' })),
connectInternetReader: jest
.fn()
.mockImplementation(() => ({ error: '_error' })),
diff --git a/src/functions.ts b/src/functions.ts
index 2062adcc..6aa0c18e 100644
--- a/src/functions.ts
+++ b/src/functions.ts
@@ -9,6 +9,7 @@ import type {
ConnectBluetoothReaderParams,
CancelDiscoveringResultType,
DisconnectReaderResultType,
+ RebootReaderResultType,
ConnectInternetReaderParams,
ConnectUsbReaderParams,
CreatePaymentIntentParams,
@@ -255,6 +256,22 @@ export async function disconnectReader(): Promise {
}, 'disconnectReader')();
}
+export async function rebootReader(): Promise {
+ return Logger.traceSdkMethod(async () => {
+ try {
+ const { error } = await StripeTerminalSdk.rebootReader();
+
+ return {
+ error: error,
+ };
+ } catch (error) {
+ return {
+ error: error as any,
+ };
+ }
+ }, 'rebootReader')();
+}
+
export async function createPaymentIntent(
params: CreatePaymentIntentParams
): Promise {
diff --git a/src/hooks/__tests__/__snapshots__/useStripeTerminal.test.tsx.snap b/src/hooks/__tests__/__snapshots__/useStripeTerminal.test.tsx.snap
index 3e839356..f8742f75 100644
--- a/src/hooks/__tests__/__snapshots__/useStripeTerminal.test.tsx.snap
+++ b/src/hooks/__tests__/__snapshots__/useStripeTerminal.test.tsx.snap
@@ -36,6 +36,7 @@ Object {
"installAvailableUpdate": [Function],
"isInitialized": false,
"loading": false,
+ "rebootReader": [Function],
"retrievePaymentIntent": [Function],
"retrieveSetupIntent": [Function],
"setReaderDisplay": [Function],
diff --git a/src/hooks/__tests__/useStripeTerminal.test.tsx b/src/hooks/__tests__/useStripeTerminal.test.tsx
index 51791815..25310028 100644
--- a/src/hooks/__tests__/useStripeTerminal.test.tsx
+++ b/src/hooks/__tests__/useStripeTerminal.test.tsx
@@ -70,7 +70,9 @@ function spyAllFunctions({ returnWith = null }: { returnWith?: any } = {}) {
.spyOn(functions, 'disconnectReader')
.mockImplementation(disconnectReader);
//
-
+ const rebootReader = jest.fn(() => returnWith);
+ jest.spyOn(functions, 'rebootReader').mockImplementation(rebootReader);
+ //
const installAvailableUpdate = jest.fn(() => returnWith);
jest
.spyOn(functions, 'installAvailableUpdate')
@@ -173,6 +175,7 @@ function spyAllFunctions({ returnWith = null }: { returnWith?: any } = {}) {
cancelDiscovering,
connectBluetoothReader,
disconnectReader,
+ rebootReader,
connectInternetReader,
connectUsbReader,
createPaymentIntent,
@@ -320,6 +323,7 @@ describe('useStripeTerminal.test.tsx', () => {
result.current.createPaymentIntent({} as any);
result.current.createSetupIntent({} as any);
result.current.disconnectReader();
+ result.current.rebootReader();
result.current.retrievePaymentIntent('');
result.current.getLocations({} as any);
result.current.confirmPaymentIntent({} as any);
@@ -371,6 +375,7 @@ describe('useStripeTerminal.test.tsx', () => {
await result.current.createPaymentIntent({} as any);
await result.current.createSetupIntent({} as any);
await result.current.disconnectReader();
+ await result.current.rebootReader();
await result.current.retrievePaymentIntent('');
await result.current.getLocations({} as any);
await result.current.confirmPaymentIntent({} as any);
@@ -467,6 +472,7 @@ describe('useStripeTerminal.test.tsx', () => {
await expect(result.current.disconnectReader()).resolves.toEqual(
'_value'
);
+ await expect(result.current.rebootReader()).resolves.toEqual('_value');
await expect(
result.current.retrievePaymentIntent({} as any)
).resolves.toEqual('_value');
diff --git a/src/hooks/useStripeTerminal.tsx b/src/hooks/useStripeTerminal.tsx
index 8043fa92..6292ca08 100644
--- a/src/hooks/useStripeTerminal.tsx
+++ b/src/hooks/useStripeTerminal.tsx
@@ -27,6 +27,7 @@ import {
cancelDiscovering,
connectBluetoothReader,
disconnectReader,
+ rebootReader,
connectInternetReader,
connectUsbReader,
createPaymentIntent,
@@ -474,6 +475,20 @@ export function useStripeTerminal(props?: Props) {
return response;
}, [setLoading, setConnectedReader, setDiscoveredReaders, _isInitialized]);
+ const _rebootReader = useCallback(async () => {
+ if (!_isInitialized()) {
+ console.error(NOT_INITIALIZED_ERROR_MESSAGE);
+ return;
+ }
+ setLoading(true);
+
+ const response = await rebootReader();
+
+ setLoading(false);
+
+ return response;
+ }, [setLoading, _isInitialized]);
+
const _createPaymentIntent = useCallback(
async (params: CreatePaymentIntentParams) => {
if (!_isInitialized()) {
@@ -850,6 +865,7 @@ export function useStripeTerminal(props?: Props) {
cancelDiscovering: _cancelDiscovering,
connectBluetoothReader: _connectBluetoothReader,
disconnectReader: _disconnectReader,
+ rebootReader: _rebootReader,
connectInternetReader: _connectInternetReader,
connectUsbReader: _connectUsbReader,
createPaymentIntent: _createPaymentIntent,
diff --git a/src/types/index.ts b/src/types/index.ts
index a1b9e5db..95aeec80 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -114,6 +114,10 @@ export type DisconnectReaderResultType = {
error: StripeError;
};
+export type RebootReaderResultType = {
+ error: StripeError;
+};
+
export type UpdateSoftwareResultType = {
update?: Reader.SoftwareUpdate;
error?: StripeError;