From f94b4b082bd6825631688fe4f55c697509be1e25 Mon Sep 17 00:00:00 2001 From: Ian Lin Date: Mon, 6 May 2024 11:41:08 +0800 Subject: [PATCH 1/2] add method of supportsReadersOfType --- .../com/stripeterminalreactnative/Mappers.kt | 26 +++++++++++++ .../StripeTerminalReactNativeModule.kt | 39 +++++++++++++++++++ ios/Mappers.swift | 18 +++++++++ ios/StripeTerminalReactNative.m | 5 +++ ios/StripeTerminalReactNative.swift | 33 ++++++++++++++++ src/StripeTerminalSdk.tsx | 3 ++ .../__snapshots__/functions.test.ts.snap | 1 + src/functions.ts | 17 ++++++++ .../useStripeTerminal.test.tsx.snap | 1 + src/hooks/useStripeTerminal.tsx | 19 +++++++++ src/types/Reader.ts | 11 ++++++ 11 files changed, 173 insertions(+) diff --git a/android/src/main/java/com/stripeterminalreactnative/Mappers.kt b/android/src/main/java/com/stripeterminalreactnative/Mappers.kt index 9d976cd3..ee72c170 100644 --- a/android/src/main/java/com/stripeterminalreactnative/Mappers.kt +++ b/android/src/main/java/com/stripeterminalreactnative/Mappers.kt @@ -40,6 +40,7 @@ import com.stripe.stripeterminal.external.models.ReaderInputOptions import com.stripe.stripeterminal.external.models.ReaderInputOptions.ReaderInputOption import com.stripe.stripeterminal.external.models.ReaderSettings import com.stripe.stripeterminal.external.models.ReaderSoftwareUpdate +import com.stripe.stripeterminal.external.models.ReaderSupportResult import com.stripe.stripeterminal.external.models.ReaderTextToSpeechStatus import com.stripe.stripeterminal.external.models.ReceiptDetails import com.stripe.stripeterminal.external.models.Refund @@ -148,6 +149,25 @@ internal fun mapFromDeviceType(type: DeviceType): String { } } +internal fun mapToDeviceType(type: String): DeviceType? { + return when (type) { + "chipper1X" -> DeviceType.CHIPPER_1X + "chipper2X" -> DeviceType.CHIPPER_2X + "cotsDevice" -> DeviceType.COTS_DEVICE + "etna" -> DeviceType.ETNA + "stripeM2" -> DeviceType.STRIPE_M2 + "stripeS700" -> DeviceType.STRIPE_S700 + "stripeS700Devkit" -> DeviceType.STRIPE_S700_DEVKIT + "verifoneP400" -> DeviceType.VERIFONE_P400 + "wiseCube" -> DeviceType.WISECUBE + "wisePad3" -> DeviceType.WISEPAD_3 + "wisePad3s" -> DeviceType.WISEPAD_3S + "wisePosE" -> DeviceType.WISEPOS_E + "wisePosEDevkit" -> DeviceType.WISEPOS_E_DEVKIT + else -> null + } +} + internal fun mapFromLocationStatus(status: LocationStatus): String { return when (status) { LocationStatus.NOT_SET -> "notSet" @@ -730,3 +750,9 @@ fun mapFromCollectInputsResults(results: List): ReadableArr } } } + +fun mapFromReaderSupportResult(readerSupportResult: ReaderSupportResult): ReadableMap { + return nativeMapOf { + putBoolean("readerSupportResult", readerSupportResult.isSupported) + } +} diff --git a/android/src/main/java/com/stripeterminalreactnative/StripeTerminalReactNativeModule.kt b/android/src/main/java/com/stripeterminalreactnative/StripeTerminalReactNativeModule.kt index 804b1c1e..dfb6e7f6 100644 --- a/android/src/main/java/com/stripeterminalreactnative/StripeTerminalReactNativeModule.kt +++ b/android/src/main/java/com/stripeterminalreactnative/StripeTerminalReactNativeModule.kt @@ -922,6 +922,45 @@ class StripeTerminalReactNativeModule(reactContext: ReactApplicationContext) : cancelOperation(promise, collectInputsCancelable, "collectInputs") } + @ReactMethod + @Suppress("unused") + fun supportsReadersOfType(params: ReadableMap, promise: Promise) { + val deviceTypeParams = requireParam(params.getString("deviceType")) { + "You must provide a deviceType" + } + val deviceType = requireParam(mapToDeviceType(deviceTypeParams)) { + "Unknown readerType: $deviceTypeParams" + } + val discoveryMethodParam = requireParam(params.getString("discoveryMethod")) { + "You must provide a discoveryMethod" + } + val discoveryMethod = requireParam(mapToDiscoveryMethod(discoveryMethodParam)) { + "Unknown discoveryMethod: $discoveryMethodParam" + } + + val readerSupportResult = terminal.supportsReadersOfType( + deviceType, + when (discoveryMethod) { + DiscoveryMethod.BLUETOOTH_SCAN -> DiscoveryConfiguration.BluetoothDiscoveryConfiguration( + getInt(params, "timeout") ?: 0, + getBoolean(params, "simulated") + ) + DiscoveryMethod.INTERNET -> DiscoveryConfiguration.InternetDiscoveryConfiguration( + isSimulated = getBoolean(params, "simulated") + ) + DiscoveryMethod.USB -> DiscoveryConfiguration.UsbDiscoveryConfiguration( + getInt(params, "timeout") ?: 0, + getBoolean(params, "simulated") + ) + DiscoveryMethod.HANDOFF -> DiscoveryConfiguration.HandoffDiscoveryConfiguration() + DiscoveryMethod.LOCAL_MOBILE -> DiscoveryConfiguration.LocalMobileDiscoveryConfiguration( + getBoolean(params, "simulated") + ) } + ) + + promise.resolve(mapFromReaderSupportResult(readerSupportResult)) + } + @ReactMethod fun addListener(eventName: String?) { // Set up any upstream listeners or background tasks as necessary diff --git a/ios/Mappers.swift b/ios/Mappers.swift index 58d7ac5e..c520d074 100644 --- a/ios/Mappers.swift +++ b/ios/Mappers.swift @@ -77,6 +77,24 @@ class Mappers { default: return "unknown" } } + + class func mapToDeviceType(_ type: String) -> DeviceType? { + switch type { + case "appleBuiltIn": return DeviceType.appleBuiltIn + case "chipper1X": return DeviceType.chipper1X + case "chipper2X": return DeviceType.chipper2X + case "etna": return DeviceType.etna + case "stripeM2": return DeviceType.stripeM2 + case "stripeS700": return DeviceType.stripeS700 + case "stripeS700Devkit": return DeviceType.stripeS700DevKit + case "verifoneP400": return DeviceType.verifoneP400 + case "wiseCube": return DeviceType.wiseCube + case "wisePad3": return DeviceType.wisePad3 + case "wisePosE": return DeviceType.wisePosE + case "wisePosEDevkit": return DeviceType.wisePosEDevKit + default: return nil + } + } class func mapToCartLineItem(_ cartLineItem: NSDictionary) -> CartLineItem? { guard let displayName = cartLineItem["displayName"] as? String else { return nil } diff --git a/ios/StripeTerminalReactNative.m b/ios/StripeTerminalReactNative.m index 01f83ce8..5d990a01 100644 --- a/ios/StripeTerminalReactNative.m +++ b/ios/StripeTerminalReactNative.m @@ -216,4 +216,9 @@ @interface RCT_EXTERN_MODULE(StripeTerminalReactNative, RCTEventEmitter) rejecter: (RCTPromiseRejectBlock)reject ) +RCT_EXTERN_METHOD( + supportsReadersOfType:(NSDictionary *)params + resolver: (RCTPromiseResolveBlock)resolve + rejecter: (RCTPromiseRejectBlock)reject + ) @end diff --git a/ios/StripeTerminalReactNative.swift b/ios/StripeTerminalReactNative.swift index 08151953..41932f59 100644 --- a/ios/StripeTerminalReactNative.swift +++ b/ios/StripeTerminalReactNative.swift @@ -1139,6 +1139,39 @@ class StripeTerminalReactNative: RCTEventEmitter, DiscoveryDelegate, BluetoothRe } } } + + @objc(supportsReadersOfType:resolver:rejecter:) + func supportsReadersOfType(params: NSDictionary, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) { + let invalidParams = Errors.validateRequiredParameters(params: params, requiredParams: ["deviceType", "discoveryMethod"]) + + guard invalidParams == nil else { + resolve(Errors.createError(code: CommonErrorType.InvalidRequiredParameter, message: "You must provide \(invalidParams!) parameters.")) + return + } + + let deviceTypeParam = params["deviceType"] as? String ?? "" + let simulated = params["simulated"] as? Bool ?? false + let discoveryMethod = params["discoveryMethod"] as? String + let deviceType = Mappers.mapToDeviceType(deviceTypeParam) + guard deviceType != nil else { + resolve(Errors.createError(code: CommonErrorType.InvalidRequiredParameter, message: "You must provide correct deviceType parameter.")) + return + } + print("supportsReadersOfType") + let result = Terminal.shared.supportsReaders(of: deviceType!, discoveryMethod: Mappers.mapToDiscoveryMethod(discoveryMethod), simulated: simulated) + print("result = %s", result) + switch result { + case .success(_): + print("success") + resolve(["readerSupportResult": true]) + break + case .failure(let error): + print("failure") + resolve(["readerSupportResult": false]) + break + } + print("hhhh") + } func reader(_ reader: Reader, didReportAvailableUpdate update: ReaderSoftwareUpdate) { sendEvent(withName: ReactNativeConstants.REPORT_AVAILABLE_UPDATE.rawValue, body: ["result": Mappers.mapFromReaderSoftwareUpdate(update) ?? [:]]) diff --git a/src/StripeTerminalSdk.tsx b/src/StripeTerminalSdk.tsx index 03542c8c..ea5be2c6 100644 --- a/src/StripeTerminalSdk.tsx +++ b/src/StripeTerminalSdk.tsx @@ -153,6 +153,9 @@ export interface StripeTerminalSdkType { cancelCollectInputs(): Promise<{ error?: StripeError; }>; + supportsReadersOfType( + params: Reader.ReaderSupportParams + ): Promise; } export default StripeTerminalReactNative as StripeTerminalSdkType; diff --git a/src/__tests__/__snapshots__/functions.test.ts.snap b/src/__tests__/__snapshots__/functions.test.ts.snap index 047aa2e0..4bfa0842 100644 --- a/src/__tests__/__snapshots__/functions.test.ts.snap +++ b/src/__tests__/__snapshots__/functions.test.ts.snap @@ -41,5 +41,6 @@ Object { "setReaderSettings": [Function], "setSimulatedCard": [Function], "simulateReaderUpdate": [Function], + "supportsReadersOfType": [Function], } `; diff --git a/src/functions.ts b/src/functions.ts index a6dfe16d..921e38c2 100644 --- a/src/functions.ts +++ b/src/functions.ts @@ -831,3 +831,20 @@ export async function cancelCollectInputs(): Promise<{ } }, 'cancelCollectInputs')(); } + +export async function supportsReadersOfType( + params: Reader.ReaderSupportParams +): Promise { + return Logger.traceSdkMethod(async () => { + try { + const supportReaderResult = await StripeTerminalSdk.supportsReadersOfType( + params + ); + return supportReaderResult; + } catch (error) { + return { + error: error as any, + }; + } + }, 'supportsReadersOfType')(); +} diff --git a/src/hooks/__tests__/__snapshots__/useStripeTerminal.test.tsx.snap b/src/hooks/__tests__/__snapshots__/useStripeTerminal.test.tsx.snap index 137f33aa..26613c82 100644 --- a/src/hooks/__tests__/__snapshots__/useStripeTerminal.test.tsx.snap +++ b/src/hooks/__tests__/__snapshots__/useStripeTerminal.test.tsx.snap @@ -46,6 +46,7 @@ Object { "setReaderSettings": [Function], "setSimulatedCard": [Function], "simulateReaderUpdate": [Function], + "supportsReadersOfType": [Function], }, } `; diff --git a/src/hooks/useStripeTerminal.tsx b/src/hooks/useStripeTerminal.tsx index 6440393f..014d940b 100644 --- a/src/hooks/useStripeTerminal.tsx +++ b/src/hooks/useStripeTerminal.tsx @@ -61,6 +61,7 @@ import { setReaderSettings, collectInputs, cancelCollectInputs, + supportsReadersOfType, } from '../functions'; import { StripeTerminalContext } from '../components/StripeTerminalContext'; import { useListener } from './useListener'; @@ -929,6 +930,23 @@ export function useStripeTerminal(props?: Props) { return response; }, [_isInitialized, setLoading]); + const _supportsReadersOfType = useCallback( + async (params: Reader.ReaderSupportParams) => { + if (!_isInitialized()) { + console.error(NOT_INITIALIZED_ERROR_MESSAGE); + throw Error(NOT_INITIALIZED_ERROR_MESSAGE); + } + setLoading(true); + + const response = await supportsReadersOfType(params); + + setLoading(false); + + return response; + }, + [_isInitialized, setLoading] + ); + return { initialize: _initialize, discoverReaders: _discoverReaders, @@ -968,6 +986,7 @@ export function useStripeTerminal(props?: Props) { setReaderSettings: _setReaderSettings, collectInputs: _collectInputs, cancelCollectInputs: _cancelCollectInputs, + supportsReadersOfType: _supportsReadersOfType, emitter: emitter, discoveredReaders, connectedReader, diff --git a/src/types/Reader.ts b/src/types/Reader.ts index 71bca3ea..4c8422a2 100644 --- a/src/types/Reader.ts +++ b/src/types/Reader.ts @@ -140,4 +140,15 @@ export namespace Reader { export type ReaderSettingsParameters = { textToSpeechViaSpeakers: boolean; }; + + export type ReaderSupportParams = { + deviceType: DeviceType; + simulated?: boolean; + discoveryMethod: Reader.DiscoveryMethod; + }; + + export type ReaderSupportResult = { + error?: StripeError; + readerSupportResult: boolean; + }; } From 29fcd25d0101b2664fd38a085313887171df6cc4 Mon Sep 17 00:00:00 2001 From: Ian Lin Date: Tue, 14 May 2024 16:04:54 +0800 Subject: [PATCH 2/2] optimize. --- .../java/com/stripeterminalreactnative/Mappers.kt | 2 +- ios/StripeTerminalReactNative.swift | 13 ++++--------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/android/src/main/java/com/stripeterminalreactnative/Mappers.kt b/android/src/main/java/com/stripeterminalreactnative/Mappers.kt index ee72c170..b83130fd 100644 --- a/android/src/main/java/com/stripeterminalreactnative/Mappers.kt +++ b/android/src/main/java/com/stripeterminalreactnative/Mappers.kt @@ -141,7 +141,7 @@ internal fun mapFromDeviceType(type: DeviceType): String { DeviceType.STRIPE_S700_DEVKIT -> "stripeS700Devkit" DeviceType.UNKNOWN -> "unknown" DeviceType.VERIFONE_P400 -> "verifoneP400" - DeviceType.WISECUBE -> "wisecube" + DeviceType.WISECUBE -> "wiseCube" DeviceType.WISEPAD_3 -> "wisePad3" DeviceType.WISEPAD_3S -> "wisePad3s" DeviceType.WISEPOS_E -> "wisePosE" diff --git a/ios/StripeTerminalReactNative.swift b/ios/StripeTerminalReactNative.swift index 41932f59..599801d7 100644 --- a/ios/StripeTerminalReactNative.swift +++ b/ios/StripeTerminalReactNative.swift @@ -1144,8 +1144,8 @@ class StripeTerminalReactNative: RCTEventEmitter, DiscoveryDelegate, BluetoothRe func supportsReadersOfType(params: NSDictionary, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) { let invalidParams = Errors.validateRequiredParameters(params: params, requiredParams: ["deviceType", "discoveryMethod"]) - guard invalidParams == nil else { - resolve(Errors.createError(code: CommonErrorType.InvalidRequiredParameter, message: "You must provide \(invalidParams!) parameters.")) + if let invalidParams { + resolve(Errors.createError(code: CommonErrorType.InvalidRequiredParameter, message: "You must provide \(invalidParams) parameters.")) return } @@ -1153,24 +1153,19 @@ class StripeTerminalReactNative: RCTEventEmitter, DiscoveryDelegate, BluetoothRe let simulated = params["simulated"] as? Bool ?? false let discoveryMethod = params["discoveryMethod"] as? String let deviceType = Mappers.mapToDeviceType(deviceTypeParam) - guard deviceType != nil else { + guard let deviceType else { resolve(Errors.createError(code: CommonErrorType.InvalidRequiredParameter, message: "You must provide correct deviceType parameter.")) return } - print("supportsReadersOfType") - let result = Terminal.shared.supportsReaders(of: deviceType!, discoveryMethod: Mappers.mapToDiscoveryMethod(discoveryMethod), simulated: simulated) - print("result = %s", result) + let result = Terminal.shared.supportsReaders(of: deviceType, discoveryMethod: Mappers.mapToDiscoveryMethod(discoveryMethod), simulated: simulated) switch result { case .success(_): - print("success") resolve(["readerSupportResult": true]) break case .failure(let error): - print("failure") resolve(["readerSupportResult": false]) break } - print("hhhh") } func reader(_ reader: Reader, didReportAvailableUpdate update: ReaderSoftwareUpdate) {