diff --git a/Hardware/Hardware.xcodeproj/project.pbxproj b/Hardware/Hardware.xcodeproj/project.pbxproj index d29e2586506..cc5ec57b976 100644 --- a/Hardware/Hardware.xcodeproj/project.pbxproj +++ b/Hardware/Hardware.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 019A77CA2D88645100ABBB71 /* PaymentMethodType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 019A77C92D88645100ABBB71 /* PaymentMethodType.swift */; }; 028C39E028255CFE0007BA25 /* Models+Copiable.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 028C39DF28255CFE0007BA25 /* Models+Copiable.generated.swift */; }; 02B5147A28254ED300750B71 /* Codegen in Frameworks */ = {isa = PBXBuildFile; productRef = 02B5147928254ED300750B71 /* Codegen */; }; 02FDAB102CEEF11F00B6C8AA /* PaymentChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02FDAB0F2CEEF11D00B6C8AA /* PaymentChannel.swift */; }; @@ -159,6 +160,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 019A77C92D88645100ABBB71 /* PaymentMethodType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaymentMethodType.swift; sourceTree = ""; }; 02351FF56149ADCD11338B19 /* Pods-SampleReceiptPrinter.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SampleReceiptPrinter.release.xcconfig"; path = "Target Support Files/Pods-SampleReceiptPrinter/Pods-SampleReceiptPrinter.release.xcconfig"; sourceTree = ""; }; 028C39DF28255CFE0007BA25 /* Models+Copiable.generated.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Models+Copiable.generated.swift"; sourceTree = ""; }; 02FDAB0F2CEEF11D00B6C8AA /* PaymentChannel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaymentChannel.swift; sourceTree = ""; }; @@ -476,6 +478,7 @@ 02FDAB0F2CEEF11D00B6C8AA /* PaymentChannel.swift */, D89B8F0125DDC7500001C726 /* PaymentIntentStatus.swift */, D88FDB2325DD21B000CB0DBD /* PaymentIntentParameters.swift */, + 019A77C92D88645100ABBB71 /* PaymentMethodType.swift */, 03CF78D627DF9BE500523706 /* RefundParameters.swift */, D88FDB2025DD21AF00CB0DBD /* PaymentStatus.swift */, D845BDBB262D980C00A3E40F /* CardPresentTransactionDetails.swift */, @@ -843,6 +846,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 019A77CA2D88645100ABBB71 /* PaymentMethodType.swift in Sources */, B9C4AB2327FDE133007008B8 /* Email.swift in Sources */, D845BE59262ED84000A3E40F /* AirPrintReceiptPrinterService.swift in Sources */, 317975C2274EBC1F004357B1 /* DeclineReason+Stripe.swift in Sources */, diff --git a/Hardware/Hardware/CardReader/PaymentIntentParameters.swift b/Hardware/Hardware/CardReader/PaymentIntentParameters.swift index 365be400a4d..bf2b34d7a13 100644 --- a/Hardware/Hardware/CardReader/PaymentIntentParameters.swift +++ b/Hardware/Hardware/CardReader/PaymentIntentParameters.swift @@ -45,7 +45,7 @@ public struct PaymentIntentParameters { /// /// Can be `card_present`, `interac_present`. /// - public let paymentMethodTypes: [String] + public let paymentMethodTypes: [PaymentMethodType] public init(amount: Decimal, currency: String, @@ -54,7 +54,7 @@ public struct PaymentIntentParameters { receiptDescription: String? = nil, statementDescription: String? = nil, receiptEmail: String? = nil, - paymentMethodTypes: [String] = [], + paymentMethodTypes: [PaymentMethodType] = [], metadata: [String: String]? = nil) { self.amount = amount self.currency = currency diff --git a/Hardware/Hardware/CardReader/PaymentMethodType.swift b/Hardware/Hardware/CardReader/PaymentMethodType.swift new file mode 100644 index 00000000000..6ee556410be --- /dev/null +++ b/Hardware/Hardware/CardReader/PaymentMethodType.swift @@ -0,0 +1,7 @@ +/// PaymentMethodType defines supported hardware payment types. +/// Mirrors supported types from StripeTerminal.PaymentMethodType https://stripe.dev/stripe-terminal-ios/docs/Enums/SCPPaymentMethodType.html +/// +public enum PaymentMethodType { + case cardPresent + case interacPresent +} diff --git a/Hardware/Hardware/CardReader/StripeCardReader/CardReaderDiscoveryMethod+Stripe.swift b/Hardware/Hardware/CardReader/StripeCardReader/CardReaderDiscoveryMethod+Stripe.swift index 0b9d785728e..e7f356fdb6c 100644 --- a/Hardware/Hardware/CardReader/StripeCardReader/CardReaderDiscoveryMethod+Stripe.swift +++ b/Hardware/Hardware/CardReader/StripeCardReader/CardReaderDiscoveryMethod+Stripe.swift @@ -5,7 +5,7 @@ public extension CardReaderDiscoveryMethod { func toStripe() -> DiscoveryMethod { switch self { case .localMobile: - return .localMobile + return .tapToPay case .bluetoothScan: return .bluetoothScan } diff --git a/Hardware/Hardware/CardReader/StripeCardReader/CardReaderType+Stripe.swift b/Hardware/Hardware/CardReader/StripeCardReader/CardReaderType+Stripe.swift index dc264833a64..c6913fa0032 100644 --- a/Hardware/Hardware/CardReader/StripeCardReader/CardReaderType+Stripe.swift +++ b/Hardware/Hardware/CardReader/StripeCardReader/CardReaderType+Stripe.swift @@ -13,7 +13,7 @@ extension CardReaderType { return .stripeM2 case .wisePad3: return .wisepad3 - case .appleBuiltIn: + case .tapToPay: return appleBuiltIn default: return .other @@ -29,7 +29,7 @@ extension CardReaderType { case .wisepad3: return .wisePad3 case .appleBuiltIn: - return .appleBuiltIn + return .tapToPay case .other: return nil } diff --git a/Hardware/Hardware/CardReader/StripeCardReader/PaymentIntentParameters+Stripe.swift b/Hardware/Hardware/CardReader/StripeCardReader/PaymentIntentParameters+Stripe.swift index 232b96c7629..e1b00602d51 100644 --- a/Hardware/Hardware/CardReader/StripeCardReader/PaymentIntentParameters+Stripe.swift +++ b/Hardware/Hardware/CardReader/StripeCardReader/PaymentIntentParameters+Stripe.swift @@ -34,32 +34,32 @@ private extension Hardware.PaymentIntentParameters { func build(_ builder: PaymentIntentParametersBuilder, with cardReaderMetadata: CardReaderMetadata? = nil) throws -> StripeTerminal.PaymentIntentParameters? { - builder.setPaymentMethodTypes(paymentMethodTypes) - builder.setStripeDescription(receiptDescription) + _ = builder.setPaymentMethodTypes(paymentMethodTypes.map(\.stripeTerminalPaymentMethodType)) + builder.setStripeDescription(receiptDescription) - /// Stripe allows the credit card statement descriptor to be nil, but not an empty string - /// https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPPaymentIntentParameters.html#/c:objc(cs)SCPPaymentIntentParameters(py)statementDescriptor - builder.setStatementDescriptor(nil) + /// Stripe allows the credit card statement descriptor to be nil, but not an empty string + /// https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPPaymentIntentParameters.html#/c:objc(cs)SCPPaymentIntentParameters(py)statementDescriptor + builder.setStatementDescriptor(nil) - let descriptor = statementDescription ?? "" - if !descriptor.isEmpty { - builder.setStatementDescriptor(descriptor) - } + let descriptor = statementDescription ?? "" + if !descriptor.isEmpty { + builder.setStatementDescriptor(descriptor) + } - if let applicationFee = applicationFee { - /// Stripe requires that "The amount must be provided as a boxed UInt in the currency's smallest unit." - /// Smallest-unit and UInt conversion is done in the same way as for the total amount, but that does not need to be boxed. - let applicationFeeForStripe = NSNumber(value: prepareAmountForStripe(applicationFee)) - builder.setApplicationFeeAmount(applicationFeeForStripe) - } + if let applicationFee = applicationFee { + /// Stripe requires that "The amount must be provided as a boxed UInt in the currency's smallest unit." + /// Smallest-unit and UInt conversion is done in the same way as for the total amount, but that does not need to be boxed. + let applicationFeeForStripe = NSNumber(value: prepareAmountForStripe(applicationFee)) + builder.setApplicationFeeAmount(applicationFeeForStripe) + } - builder.setReceiptEmail(receiptEmail) + builder.setReceiptEmail(receiptEmail) - let updatedMetadata = prepareMetadataForStripe(with: cardReaderMetadata) - builder.setMetadata(updatedMetadata) + let updatedMetadata = prepareMetadataForStripe(with: cardReaderMetadata) + builder.setMetadata(updatedMetadata) - // Return payment intent built configuration: - return try builder.build() + // Return payment intent built configuration: + return try builder.build() } /// Updates the existing PaymentIntentParameters metadata with our CardReader metadata, if any. @@ -80,4 +80,16 @@ private extension Hardware.PaymentIntentParameters { return updatedMetadata } } + +private extension PaymentMethodType { + var stripeTerminalPaymentMethodType: StripeTerminal.PaymentMethodType { + switch self { + case .cardPresent: + return .cardPresent + case .interacPresent: + return .interacPresent + } + } +} + #endif diff --git a/Hardware/Hardware/CardReader/StripeCardReader/StripeCardReaderService.swift b/Hardware/Hardware/CardReader/StripeCardReader/StripeCardReaderService.swift index f2fc9ccc118..df9aca9f64a 100644 --- a/Hardware/Hardware/CardReader/StripeCardReader/StripeCardReaderService.swift +++ b/Hardware/Hardware/CardReader/StripeCardReader/StripeCardReaderService.swift @@ -142,11 +142,11 @@ extension StripeCardReaderService: CardReaderService { throw error } case .localMobile: - let localMobileConfig = LocalMobileDiscoveryConfigurationBuilder() + let tapToPayConfig = TapToPayDiscoveryConfigurationBuilder() do { - config = try localMobileConfig.setSimulated(shouldUseSimulatedCardReader).build() + config = try tapToPayConfig.setSimulated(shouldUseSimulatedCardReader).build() } catch let error as UnderlyingError { - DDLogError("Failed to start LocalMobileDiscovery. Error:\(String(describing: error.failureReason))") + DDLogError("Failed to start TapToPayDiscovery. Error:\(String(describing: error.failureReason))") throw error } catch { DDLogError("\(error)") @@ -159,8 +159,6 @@ extension StripeCardReaderService: CardReaderService { throw CardReaderServiceError.bluetoothDenied } - Terminal.shared.delegate = self - // We're now ready to start discovery, but first we'll check that we're not starting or canceling // another discovery process. // If we can't grab a lock quickly, let's fail rather than wait indefinitely @@ -198,7 +196,7 @@ extension StripeCardReaderService: CardReaderService { // as the simulator won't have Bluetooth available. // If we're using Tap to Pay on iPhone, bluetooth is not required. private func shouldSkipBluetoothCheck(discoveryConfiguration: DiscoveryConfiguration) -> Bool { - shouldUseSimulatedCardReader || discoveryConfiguration.discoveryMethod == .localMobile + shouldUseSimulatedCardReader || discoveryConfiguration.discoveryMethod == .tapToPay } public func cancelDiscovery() -> Future { @@ -273,7 +271,7 @@ extension StripeCardReaderService: CardReaderService { /// https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPTerminal.html#/c:objc(cs)SCPTerminal(im)disconnectReader: /// The completion block for disconnect, apparently, is called when the SDK has not really transitioned to an idle state. /// Clients might need to dispatch operations that rely on this completion block to start a second operation on the card reader. - /// (for example, starting a `localMobile` connection after a BlueTooth reader has been disconnected) + /// (for example, starting a `tapToPay` connection after a BlueTooth reader has been disconnected) Terminal.shared.disconnectReader { error in DispatchQueue.main.asyncAfter(deadline: .now() + 1) { if let error = error { @@ -453,7 +451,7 @@ extension StripeCardReaderService: CardReaderService { connectionAttemptInvalidated = false switch stripeReader.deviceType { - case .appleBuiltIn: + case .tapToPay: return getLocalMobileConfiguration(stripeReader, options: options).flatMap { configuration in self.connect(stripeReader, configuration: configuration) } @@ -480,7 +478,7 @@ extension StripeCardReaderService: CardReaderService { self.readerLocationProvider?.fetchDefaultLocationID { result in switch result { case .success(let locationId): - let buildConfig = BluetoothConnectionConfigurationBuilder(locationId: locationId) + let buildConfig = BluetoothConnectionConfigurationBuilder(delegate: self, locationId: locationId) do { let config = try buildConfig.build() return promise(.success(config)) @@ -497,7 +495,7 @@ extension StripeCardReaderService: CardReaderService { } private func getLocalMobileConfiguration(_ reader: StripeTerminal.Reader, - options: CardReaderConnectionOptions?) -> Future { + options: CardReaderConnectionOptions?) -> Future { return Future() { [weak self] promise in guard let self = self else { promise(.failure(CardReaderServiceError.connection())) @@ -509,7 +507,7 @@ extension StripeCardReaderService: CardReaderService { self.readerLocationProvider?.fetchDefaultLocationID { result in switch result { case .success(let locationId): - let localMobileConfig = LocalMobileConnectionConfigurationBuilder(locationId: locationId) + let localMobileConfig = TapToPayConnectionConfigurationBuilder(delegate: self, locationId: locationId) localMobileConfig.setMerchantDisplayName(nil) localMobileConfig.setOnBehalfOf(nil) localMobileConfig.setTosAcceptancePermitted(options?.builtInOptions?.termsOfServiceAcceptancePermitted ?? true) @@ -540,7 +538,7 @@ extension StripeCardReaderService: CardReaderService { return } - Terminal.shared.connectBluetoothReader(reader, delegate: self, connectionConfig: configuration) { [weak self] (reader, error) in + Terminal.shared.connectReader(reader, connectionConfig: configuration) { [weak self] (reader, error) in guard let self = self else { promise(.failure(CardReaderServiceError.connection())) return @@ -573,14 +571,14 @@ extension StripeCardReaderService: CardReaderService { } } - public func connect(_ reader: StripeTerminal.Reader, configuration: LocalMobileConnectionConfiguration) -> Future { + public func connect(_ reader: StripeTerminal.Reader, configuration: TapToPayConnectionConfiguration) -> Future { return Future { [weak self] promise in guard let self = self else { promise(.failure(CardReaderServiceError.connection())) return } - Terminal.shared.connectLocalMobileReader(reader, delegate: self, connectionConfig: configuration) { [weak self] (reader, error) in + Terminal.shared.connectReader(reader, connectionConfig: configuration) { [weak self] (reader, error) in guard let self = self else { promise(.failure(CardReaderServiceError.connection())) return @@ -873,7 +871,7 @@ extension StripeCardReaderService: DiscoveryDelegate { // MARK: - ReaderDisplayDelegate. -extension StripeCardReaderService: BluetoothReaderDelegate { +extension StripeCardReaderService: MobileReaderDelegate { public func reader(_ reader: Reader, didReportAvailableUpdate update: ReaderSoftwareUpdate) { softwareUpdateSubject.send(.available) } @@ -960,29 +958,33 @@ extension StripeCardReaderService: BluetoothReaderDelegate { connectedReadersSubject.send([connectedReaderWithUpdatedBatteryLevel]) } + + public func reader(_ reader: Reader, didDisconnect reason: DisconnectReason) { + connectedReadersSubject.send([]) + } } -extension StripeCardReaderService: LocalMobileReaderDelegate { - public func localMobileReader(_ reader: Reader, didRequestReaderInput inputOptions: ReaderInputOptions = []) { +extension StripeCardReaderService: TapToPayReaderDelegate { + public func tapToPayReader(_ reader: Reader, didRequestReaderInput inputOptions: ReaderInputOptions = []) { sendReaderEvent(CardReaderEvent.make(stripeReaderInputOptions: inputOptions)) } - public func localMobileReader(_ reader: Reader, didRequestReaderDisplayMessage displayMessage: ReaderDisplayMessage) { + public func tapToPayReader(_ reader: Reader, didRequestReaderDisplayMessage displayMessage: ReaderDisplayMessage) { sendReaderEvent(CardReaderEvent.make(displayMessage: displayMessage)) } // TODO: use a specific `deviceSetup` in these three functions instead of reusing the softwareUpdateSubject // https://github.com/woocommerce/woocommerce-ios/issues/8088 - public func localMobileReader(_ reader: Reader, didStartInstallingUpdate update: ReaderSoftwareUpdate, cancelable: Cancelable?) { + public func tapToPayReader(_ reader: Reader, didStartInstallingUpdate update: ReaderSoftwareUpdate, cancelable: Cancelable?) { softwareUpdateSubject.send(.started(cancelable: cancelable.map(StripeCancelable.init(cancelable:)))) } - public func localMobileReader(_ reader: Reader, didReportReaderSoftwareUpdateProgress progress: Float) { + public func tapToPayReader(_ reader: Reader, didReportReaderSoftwareUpdateProgress progress: Float) { softwareUpdateSubject.send(.installing(progress: progress)) } - public func localMobileReader(_ reader: Reader, didFinishInstallingUpdate update: ReaderSoftwareUpdate?, error: Error?) { + public func tapToPayReader(_ reader: Reader, didFinishInstallingUpdate update: ReaderSoftwareUpdate?, error: Error?) { if let error = error { let underlyingError = Self.logAndDecodeError(error) softwareUpdateSubject.send(.failed( @@ -1002,18 +1004,11 @@ extension StripeCardReaderService: LocalMobileReaderDelegate { } } - public func localMobileReaderDidAcceptTermsOfService(_ reader: Reader) { + public func tapToPayReaderDidAcceptTermsOfService(_ reader: Reader) { builtInCardReaderAcceptToSSubject.send(()) } } -// MARK: - Terminal delegate -extension StripeCardReaderService: TerminalDelegate { - public func terminal(_ terminal: Terminal, didReportUnexpectedReaderDisconnect reader: Reader) { - connectedReadersSubject.send([]) - } -} - // MARK: - Reader events private extension StripeCardReaderService { func sendReaderEvent(_ event: CardReaderEvent) { diff --git a/Hardware/Hardware/CardReader/StripeCardReader/UnderlyingError+Stripe.swift b/Hardware/Hardware/CardReader/StripeCardReader/UnderlyingError+Stripe.swift index f7d6d959447..610ad9d72d7 100644 --- a/Hardware/Hardware/CardReader/StripeCardReader/UnderlyingError+Stripe.swift +++ b/Hardware/Hardware/CardReader/StripeCardReader/UnderlyingError+Stripe.swift @@ -92,23 +92,23 @@ extension UnderlyingError { self = .processorAPIError case .passcodeNotEnabled: self = .passcodeNotEnabled - case .appleBuiltInReaderTOSAcceptanceRequiresiCloudSignIn: + case .tapToPayReaderTOSAcceptanceRequiresiCloudSignIn: self = .appleBuiltInReaderTOSAcceptanceRequiresiCloudSignIn case .nfcDisabled: self = .nfcDisabled - case .appleBuiltInReaderFailedToPrepare: + case .tapToPayReaderFailedToPrepare: self = .appleBuiltInReaderFailedToPrepare - case .appleBuiltInReaderTOSAcceptanceCanceled: + case .tapToPayReaderTOSAcceptanceCanceled: self = .appleBuiltInReaderTOSAcceptanceCanceled - case .appleBuiltInReaderTOSNotYetAccepted: + case .tapToPayReaderTOSNotYetAccepted: self = .appleBuiltInReaderTOSNotYetAccepted - case .appleBuiltInReaderTOSAcceptanceFailed: + case .tapToPayReaderTOSAcceptanceFailed: self = .appleBuiltInReaderTOSAcceptanceFailed - case .appleBuiltInReaderMerchantBlocked: + case .tapToPayReaderMerchantBlocked: self = .appleBuiltInReaderMerchantBlocked - case .appleBuiltInReaderInvalidMerchant: + case .tapToPayReaderInvalidMerchant: self = .appleBuiltInReaderInvalidMerchant - case .appleBuiltInReaderDeviceBanned: + case .tapToPayReaderDeviceBanned: self = .appleBuiltInReaderDeviceBanned case .unsupportedMobileDeviceConfiguration: self = .unsupportedMobileDeviceConfiguration @@ -170,7 +170,7 @@ extension UnderlyingError { self = .internetConnectTimeOut case .bluetoothReconnectStarted: self = .bluetoothReconnectStarted - case .appleBuiltInReaderAccountDeactivated: + case .tapToPayReaderAccountDeactivated: self = .appleBuiltInReaderAccountDeactivated case .readerMissingEncryptionKeys: self = .readerMissingEncryptionKeys diff --git a/Hardware/HardwareTests/PaymentIntentParametersTests.swift b/Hardware/HardwareTests/PaymentIntentParametersTests.swift index f2196da2f3c..b5a2dee8e3d 100644 --- a/Hardware/HardwareTests/PaymentIntentParametersTests.swift +++ b/Hardware/HardwareTests/PaymentIntentParametersTests.swift @@ -7,7 +7,7 @@ final class PaymentIntentParametersTests: XCTestCase { currency: "usd", stripeSmallestCurrencyUnitMultiplier: 100, receiptEmail: "validemail@validdomain.us", - paymentMethodTypes: ["card_present"]) + paymentMethodTypes: [.cardPresent]) XCTAssertNotNil(params.receiptEmail) } @@ -17,7 +17,7 @@ final class PaymentIntentParametersTests: XCTestCase { currency: "usd", stripeSmallestCurrencyUnitMultiplier: 100, receiptEmail: "woocommerce", - paymentMethodTypes: ["card_present"]) + paymentMethodTypes: [.cardPresent]) XCTAssertNil(params.receiptEmail) } @@ -26,7 +26,7 @@ final class PaymentIntentParametersTests: XCTestCase { let params = PaymentIntentParameters(amount: 100, currency: "USD", stripeSmallestCurrencyUnitMultiplier: 100, - paymentMethodTypes: ["card_present"]) + paymentMethodTypes: [.cardPresent]) XCTAssertEqual(params.currency, "usd") } @@ -35,7 +35,7 @@ final class PaymentIntentParametersTests: XCTestCase { let params = PaymentIntentParameters(amount: 100, currency: "cesar", stripeSmallestCurrencyUnitMultiplier: 100, - paymentMethodTypes: ["card_present"]) + paymentMethodTypes: [.cardPresent]) XCTAssertNil(params.toStripe()) } @@ -44,7 +44,7 @@ final class PaymentIntentParametersTests: XCTestCase { let params = PaymentIntentParameters(amount: 100, currency: "", stripeSmallestCurrencyUnitMultiplier: 100, - paymentMethodTypes: ["card_present"]) + paymentMethodTypes: [.cardPresent]) XCTAssertNil(params.toStripe()) } @@ -67,7 +67,7 @@ final class PaymentIntentParametersTests: XCTestCase { let params = PaymentIntentParameters(amount: amount, currency: "usd", stripeSmallestCurrencyUnitMultiplier: stripeSmallestCurrencyUnitMultiplier, - paymentMethodTypes: ["card_present"]) + paymentMethodTypes: [.cardPresent]) let stripeParams = try XCTUnwrap(params.toStripe()) XCTAssertEqual(expectation, stripeParams.amount) @@ -79,7 +79,7 @@ final class PaymentIntentParametersTests: XCTestCase { currency: "usd", stripeSmallestCurrencyUnitMultiplier: 100, statementDescription: "A < DESCRIPTION' longer THAN 22 Characters", - paymentMethodTypes: ["card_present"] + paymentMethodTypes: [.cardPresent] ) let statementDescription = try XCTUnwrap(params.statementDescription) @@ -93,7 +93,7 @@ final class PaymentIntentParametersTests: XCTestCase { currency: "usd", stripeSmallestCurrencyUnitMultiplier: 100, statementDescription: "A DESCRIPTION", - paymentMethodTypes: ["card_present"]) + paymentMethodTypes: [.cardPresent]) let statementDescription = try XCTUnwrap(params.statementDescription) @@ -106,7 +106,7 @@ final class PaymentIntentParametersTests: XCTestCase { currency: "usd", stripeSmallestCurrencyUnitMultiplier: 100, statementDescription: "A DESCRIPTION LONGER THAN 22 CHARACTERS", - paymentMethodTypes: ["card_present"] + paymentMethodTypes: [.cardPresent] ) let statementDescription = try XCTUnwrap(params.statementDescription) @@ -119,7 +119,7 @@ final class PaymentIntentParametersTests: XCTestCase { currency: "usd", stripeSmallestCurrencyUnitMultiplier: 100, statementDescription: "", - paymentMethodTypes: ["card_present"]) + paymentMethodTypes: [.cardPresent]) let stripeParameters = params.toStripe() @@ -131,7 +131,7 @@ final class PaymentIntentParametersTests: XCTestCase { currency: "usd", stripeSmallestCurrencyUnitMultiplier: 100, statementDescription: nil, - paymentMethodTypes: ["card_present"]) + paymentMethodTypes: [.cardPresent]) let stripeParameters = params.toStripe() @@ -178,7 +178,7 @@ private extension PaymentIntentParametersTests { PaymentIntentParameters(amount: 100, currency: "usd", stripeSmallestCurrencyUnitMultiplier: 100, - paymentMethodTypes: ["card_present"], + paymentMethodTypes: [.cardPresent], metadata: withMetaKeys) } } diff --git a/Podfile b/Podfile index 60d04a5e1e0..7f6f9a19a6e 100644 --- a/Podfile +++ b/Podfile @@ -57,7 +57,7 @@ def cocoa_lumberjack end def stripe_terminal - pod 'StripeTerminal', '~> 3.9.1' + pod 'StripeTerminal', '~> 4.2.0' end def networking_pods diff --git a/Podfile.lock b/Podfile.lock index d91b01b69d2..987da18b654 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -36,7 +36,7 @@ PODS: - Sourcery/CLI-Only (= 2.2.6) - Sourcery/CLI-Only (2.2.6) - Specta (1.0.7) - - StripeTerminal (3.9.1) + - StripeTerminal (4.2.0) - SVProgressHUD (2.2.5) - SwiftLint (0.54.0) - UIDeviceIdentifier (2.3.0) @@ -77,7 +77,7 @@ DEPENDENCIES: - Sentry (~> 8.43.0) - Sourcery (~> 2.2.6) - Specta (= 1.0.7) - - StripeTerminal (~> 3.9.1) + - StripeTerminal (~> 4.2.0) - SVProgressHUD (= 2.2.5) - SwiftLint (= 0.54.0) - UIDeviceIdentifier (~> 2.0) @@ -139,7 +139,7 @@ SPEC CHECKSUMS: Sodium: 23d11554ecd556196d313cf6130d406dfe7ac6da Sourcery: 4427fd22f0c12bd1ef75dd9045d50e01c17a43e1 Specta: 3e1bd89c3517421982dc4d1c992503e48bd5fe66 - StripeTerminal: f7f5e176979224ed76edb3724f41138fbb28053c + StripeTerminal: 58a08668f6731666fc1ab878ac4a510ecfb403c9 SVProgressHUD: 1428aafac632c1f86f62aa4243ec12008d7a51d6 SwiftLint: c1de071d9d08c8aba837545f6254315bc900e211 UIDeviceIdentifier: 442b65b4ff1832d4ca9c2a157815cb29ad981b17 @@ -158,6 +158,6 @@ SPEC CHECKSUMS: ZendeskSupportProvidersSDK: 281acf2bb731d2a67f913cfe653ed0da9f5b2f42 ZendeskSupportSDK: b512cfc74b6bf8490e589f02cf52e27ed4f2bebe -PODFILE CHECKSUM: 51e4e2fe15da596ac38202135c4b2b7ab42c49b8 +PODFILE CHECKSUM: f1435b14e58d62d2787b5a70da8047b4e4b93f56 COCOAPODS: 1.16.2 diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 85510a28ffd..d886bd37fe3 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -15,6 +15,7 @@ - [*] Added an entry point to Troubleshoot Connection from the Settings screen. [https://github.com/woocommerce/woocommerce-ios/pull/15391] - [**] Filters in Orders and Products lists are now persisted. [https://github.com/woocommerce/woocommerce-ios/issues/14791] - [internal] Add site related properties to crowdsignal surveys. [https://github.com/woocommerce/woocommerce-ios/pull/15353] +- [internal] Update Stripe Terminal SDK to 4.2.0 [https://github.com/woocommerce/woocommerce-ios/pull/15377] - [**] Notification settings are now available for configuring notifications for each store. [https://github.com/woocommerce/woocommerce-ios/pull/15386] 21.9 diff --git a/WooCommerce/Classes/POS/Card Present Payments/CardPresentPaymentInvalidatablePaymentOrchestrator.swift b/WooCommerce/Classes/POS/Card Present Payments/CardPresentPaymentInvalidatablePaymentOrchestrator.swift index 55f474b3733..fff883da6f7 100644 --- a/WooCommerce/Classes/POS/Card Present Payments/CardPresentPaymentInvalidatablePaymentOrchestrator.swift +++ b/WooCommerce/Classes/POS/Card Present Payments/CardPresentPaymentInvalidatablePaymentOrchestrator.swift @@ -12,7 +12,7 @@ final class CardPresentPaymentInvalidatablePaymentOrchestrator: PaymentCaptureOr func collectPayment(for order: Order, orderTotal: NSDecimalNumber, paymentGatewayAccount: PaymentGatewayAccount, - paymentMethodTypes: [String], + paymentMethodTypes: [PaymentMethodType], stripeSmallestCurrencyUnitMultiplier: Decimal, channel: PaymentChannel, onPreparingReader: @escaping () -> Void, diff --git a/WooCommerce/Classes/ViewModels/CardPresentPayments/PaymentCaptureOrchestrator.swift b/WooCommerce/Classes/ViewModels/CardPresentPayments/PaymentCaptureOrchestrator.swift index 14b2cba0d7b..5c7a4fff97b 100644 --- a/WooCommerce/Classes/ViewModels/CardPresentPayments/PaymentCaptureOrchestrator.swift +++ b/WooCommerce/Classes/ViewModels/CardPresentPayments/PaymentCaptureOrchestrator.swift @@ -15,7 +15,7 @@ protocol PaymentCaptureOrchestrating { func collectPayment(for order: Order, orderTotal: NSDecimalNumber, paymentGatewayAccount: PaymentGatewayAccount, - paymentMethodTypes: [String], + paymentMethodTypes: [PaymentMethodType], stripeSmallestCurrencyUnitMultiplier: Decimal, channel: PaymentChannel, onPreparingReader: @escaping () -> Void, @@ -69,7 +69,7 @@ final class PaymentCaptureOrchestrator: PaymentCaptureOrchestrating { func collectPayment(for order: Order, orderTotal: NSDecimalNumber, paymentGatewayAccount: PaymentGatewayAccount, - paymentMethodTypes: [String], + paymentMethodTypes: [PaymentMethodType], stripeSmallestCurrencyUnitMultiplier: Decimal, channel: PaymentChannel, onPreparingReader: @escaping () -> Void, @@ -281,7 +281,7 @@ private extension PaymentCaptureOrchestrator { orderTotal: NSDecimalNumber, country: String, statementDescriptor: String?, - paymentMethodTypes: [String], + paymentMethodTypes: [PaymentMethodType], stripeSmallestCurrencyUnitMultiplier: Decimal, channel: PaymentChannel) -> PaymentParameters { let metadata = PaymentIntent.initMetadata( diff --git a/WooCommerce/Classes/ViewRelated/Orders/Collect Payments/CollectOrderPaymentUseCase.swift b/WooCommerce/Classes/ViewRelated/Orders/Collect Payments/CollectOrderPaymentUseCase.swift index 076a9bf9c37..2b77467167c 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/Collect Payments/CollectOrderPaymentUseCase.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/Collect Payments/CollectOrderPaymentUseCase.swift @@ -312,7 +312,7 @@ private extension CollectOrderPaymentUseCase { for: self.order, orderTotal: orderTotal, paymentGatewayAccount: paymentGatewayAccount, - paymentMethodTypes: self.configuration.paymentMethods.map(\.rawValue), + paymentMethodTypes: self.configuration.paymentMethods, stripeSmallestCurrencyUnitMultiplier: self.configuration.stripeSmallestCurrencyUnitMultiplier, channel: channel, onPreparingReader: { [weak self] in diff --git a/WooCommerce/WooCommerceTests/Mocks/MockPaymentCaptureOrchestrator.swift b/WooCommerce/WooCommerceTests/Mocks/MockPaymentCaptureOrchestrator.swift index 6e80e8e0ef0..3db9f1ec901 100644 --- a/WooCommerce/WooCommerceTests/Mocks/MockPaymentCaptureOrchestrator.swift +++ b/WooCommerce/WooCommerceTests/Mocks/MockPaymentCaptureOrchestrator.swift @@ -13,13 +13,13 @@ final class MockPaymentCaptureOrchestrator: PaymentCaptureOrchestrating { var spyDidCallCollectPayment = false var spyCollectPaymentOrder: Order? = nil var spyCollectPaymentGatewayAccount: PaymentGatewayAccount? = nil - var spyCollectPaymentMethodTypes: [String]? = nil + var spyCollectPaymentMethodTypes: [PaymentMethodType]? = nil var spyCollectPaymentStripeSmallestCurrencyUnitMultiplier: Decimal? = nil var spyChannel: PaymentChannel? = nil func collectPayment(for order: Order, orderTotal: NSDecimalNumber, paymentGatewayAccount: PaymentGatewayAccount, - paymentMethodTypes: [String], + paymentMethodTypes: [PaymentMethodType], stripeSmallestCurrencyUnitMultiplier: Decimal, channel: PaymentChannel, onPreparingReader: () -> Void, diff --git a/WooCommerce/WooCommerceTests/ViewModels/CardPresentPayments/PaymentCaptureOrchestratorTests.swift b/WooCommerce/WooCommerceTests/ViewModels/CardPresentPayments/PaymentCaptureOrchestratorTests.swift index a292cd54c42..325f7e2c132 100644 --- a/WooCommerce/WooCommerceTests/ViewModels/CardPresentPayments/PaymentCaptureOrchestratorTests.swift +++ b/WooCommerce/WooCommerceTests/ViewModels/CardPresentPayments/PaymentCaptureOrchestratorTests.swift @@ -43,7 +43,7 @@ final class PaymentCaptureOrchestratorTests: XCTestCase { for: order, orderTotal: orderTotal, paymentGatewayAccount: PaymentGatewayAccount.fake(), - paymentMethodTypes: ["card_present"], + paymentMethodTypes: [.cardPresent], stripeSmallestCurrencyUnitMultiplier: 100, channel: .storeManagement, onPreparingReader: {}, @@ -75,7 +75,7 @@ final class PaymentCaptureOrchestratorTests: XCTestCase { for: order, orderTotal: orderTotal, paymentGatewayAccount: PaymentGatewayAccount.fake(), - paymentMethodTypes: ["card_present"], + paymentMethodTypes: [.cardPresent], stripeSmallestCurrencyUnitMultiplier: 100, channel: .storeManagement, onPreparingReader: {}, @@ -115,7 +115,7 @@ final class PaymentCaptureOrchestratorTests: XCTestCase { for: order, orderTotal: orderTotal, paymentGatewayAccount: PaymentGatewayAccount.fake(), - paymentMethodTypes: ["card_present"], + paymentMethodTypes: [.cardPresent], stripeSmallestCurrencyUnitMultiplier: 100, channel: .storeManagement, onPreparingReader: {}, @@ -135,7 +135,7 @@ final class PaymentCaptureOrchestratorTests: XCTestCase { receiptDescription: "In-Person Payment for Order #482 for AwesomeStore blog_id \(sampleSiteID)", statementDescription: "", receiptEmail: "bob.smith@example.com", - paymentMethodTypes: ["card_present"], + paymentMethodTypes: [.cardPresent], metadata: PaymentIntent.initMetadata( store: "AwesomeStore", customerName: "Bob Smith", @@ -169,7 +169,7 @@ final class PaymentCaptureOrchestratorTests: XCTestCase { for: order, orderTotal: orderTotal, paymentGatewayAccount: account, - paymentMethodTypes: ["card_present"], + paymentMethodTypes: [.cardPresent], stripeSmallestCurrencyUnitMultiplier: 100, channel: .storeManagement, onPreparingReader: {}, @@ -206,7 +206,7 @@ final class PaymentCaptureOrchestratorTests: XCTestCase { for: order, orderTotal: orderTotal, paymentGatewayAccount: account, - paymentMethodTypes: ["card_present"], + paymentMethodTypes: [.cardPresent], stripeSmallestCurrencyUnitMultiplier: 100, channel: .storeManagement, onPreparingReader: {}, diff --git a/Yosemite/Yosemite/Model/Model.swift b/Yosemite/Yosemite/Model/Model.swift index 91b2e439f76..2a958d6be9d 100644 --- a/Yosemite/Yosemite/Model/Model.swift +++ b/Yosemite/Yosemite/Model/Model.swift @@ -220,6 +220,7 @@ public typealias CardReaderConfigError = Hardware.CardReaderConfigError public typealias PaymentChannel = Hardware.PaymentChannel public typealias PaymentMethod = Hardware.PaymentMethod public typealias PaymentParameters = Hardware.PaymentIntentParameters +public typealias PaymentMethodType = Hardware.PaymentMethodType public typealias RefundParameters = Hardware.RefundParameters public typealias PaymentIntent = Hardware.PaymentIntent public typealias PrintingResult = Hardware.PrintingResult diff --git a/Yosemite/Yosemite/Model/Payments/CardPresentPaymentsConfiguration.swift b/Yosemite/Yosemite/Model/Payments/CardPresentPaymentsConfiguration.swift index 44d5862a4cc..1ca080e5638 100644 --- a/Yosemite/Yosemite/Model/Payments/CardPresentPaymentsConfiguration.swift +++ b/Yosemite/Yosemite/Model/Payments/CardPresentPaymentsConfiguration.swift @@ -3,7 +3,7 @@ import WooFoundation public struct CardPresentPaymentsConfiguration: Equatable { public let countryCode: CountryCode - public let paymentMethods: [WCPayPaymentMethodType] + public let paymentMethods: [PaymentMethodType] public let currencies: [CurrencyCode] public let paymentGateways: [String] public let supportedReaders: [CardReaderType] @@ -22,7 +22,7 @@ public struct CardPresentPaymentsConfiguration: Equatable { public let minimumOperatingSystemVersionForTapToPay: OperatingSystemVersion init(countryCode: CountryCode, - paymentMethods: [WCPayPaymentMethodType], + paymentMethods: [PaymentMethodType], currencies: [CurrencyCode], paymentGateways: [String], supportedReaders: [CardReaderType],