From f12ff59a8f63d143989dc36732596c335037fd81 Mon Sep 17 00:00:00 2001 From: Nick Porter Date: Tue, 1 Oct 2024 10:45:46 -0600 Subject: [PATCH 1/7] Introduce IntegrationConfigurable --- .../project.pbxproj | 4 ++ .../PaymentSheetAnalyticsHelper.swift | 37 ++++++++++- .../STPAPIClient+PaymentSheet.swift | 6 +- ...stomerAddPaymentMethodViewController.swift | 2 +- .../CustomerSheetDataSource.swift | 2 +- .../Embedded/EmbeddedPaymentElement.swift | 51 ++------------- .../IntegrationConfigurable.swift | 63 +++++++++++++++++++ .../PaymentSheet/PaymentMethodType.swift | 14 ++--- ...ymentSheet+PaymentMethodAvailability.swift | 17 +---- .../PaymentSheetConfiguration.swift | 12 +--- .../PaymentSheet/PaymentSheetLoader.swift | 12 ++-- 11 files changed, 128 insertions(+), 92 deletions(-) create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/IntegrationConfigurable.swift diff --git a/StripePaymentSheet/StripePaymentSheet.xcodeproj/project.pbxproj b/StripePaymentSheet/StripePaymentSheet.xcodeproj/project.pbxproj index 02dc34e1f40..56c0d916194 100644 --- a/StripePaymentSheet/StripePaymentSheet.xcodeproj/project.pbxproj +++ b/StripePaymentSheet/StripePaymentSheet.xcodeproj/project.pbxproj @@ -119,6 +119,7 @@ 61C0D3B8C63EB4558AB74A7E /* StripePayments.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A1C7CFA5C9C1A8A73CFA1C0 /* StripePayments.framework */; }; 61CB0BD02BED985100E24A4C /* VerticalSavedPaymentMethodsViewControllerSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61CBE6672BED97EE005F7FEB /* VerticalSavedPaymentMethodsViewControllerSnapshotTests.swift */; }; 61CBE6662BED9749005F7FEB /* VerticalSavedPaymentMethodsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61CBE6652BED9749005F7FEB /* VerticalSavedPaymentMethodsViewController.swift */; }; + 61D842442CAC50C5009D2D51 /* IntegrationConfigurable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61D842432CAC50C5009D2D51 /* IntegrationConfigurable.swift */; }; 61D8688E2C06553E001FAD84 /* RightAccessoryButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61D8688D2C06553E001FAD84 /* RightAccessoryButton.swift */; }; 61FB6BCD2C8901B200F8E074 /* EmbeddedPaymentMethodsViewSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61FB6BCC2C8901B200F8E074 /* EmbeddedPaymentMethodsViewSnapshotTests.swift */; }; 623C2D9F87929D6DA9C09E23 /* STPCameraView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D39B31D0B890A4F8E4819B15 /* STPCameraView.swift */; }; @@ -471,6 +472,7 @@ 619AF0882BF56F9100D1C981 /* VerticalSavedPaymentMethodsViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VerticalSavedPaymentMethodsViewControllerTests.swift; sourceTree = ""; }; 61CBE6652BED9749005F7FEB /* VerticalSavedPaymentMethodsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VerticalSavedPaymentMethodsViewController.swift; sourceTree = ""; }; 61CBE6672BED97EE005F7FEB /* VerticalSavedPaymentMethodsViewControllerSnapshotTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VerticalSavedPaymentMethodsViewControllerSnapshotTests.swift; sourceTree = ""; }; + 61D842432CAC50C5009D2D51 /* IntegrationConfigurable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegrationConfigurable.swift; sourceTree = ""; }; 61D8688D2C06553E001FAD84 /* RightAccessoryButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RightAccessoryButton.swift; sourceTree = ""; }; 61FB6BCC2C8901B200F8E074 /* EmbeddedPaymentMethodsViewSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmbeddedPaymentMethodsViewSnapshotTests.swift; sourceTree = ""; }; 62CE362B80042827F47ABC3F /* AffirmCopyLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AffirmCopyLabel.swift; sourceTree = ""; }; @@ -838,6 +840,7 @@ B9A9FDAE66ADA08D85D74E19 /* PaymentSheet+SwiftUI.swift */, B61FFE76D0960C7F1E34B405 /* PaymentSheetAppearance.swift */, C46CB5AB992F8EEFE4E5460A /* PaymentSheetConfiguration.swift */, + 61D842432CAC50C5009D2D51 /* IntegrationConfigurable.swift */, 0DF4D51EEAB1092637BE144E /* PaymentSheetDeferredValidator.swift */, E6DDBBAAC2892467CED23402 /* PaymentSheetError.swift */, 58A85D630BDEA7408391EB8B /* PaymentSheetFlowController.swift */, @@ -1793,6 +1796,7 @@ B8A7575878C5124CF5482097 /* VerificationSession.swift in Sources */, 9326393E775D29F8C661624B /* STPAPIClient+PaymentSheet.swift in Sources */, AA3A96D74B1659CB5725E95F /* CardExpiryDate.swift in Sources */, + 61D842442CAC50C5009D2D51 /* IntegrationConfigurable.swift in Sources */, 64DE5688E4FBE92E1F49810C /* ExternalPaymentMethod.swift in Sources */, 229A4A578609A3711F02682E /* STPCardBrandChoice.swift in Sources */, 3EDFACA133567159875143C5 /* STPElementsSession.swift in Sources */, diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Analytics/PaymentSheetAnalyticsHelper.swift b/StripePaymentSheet/StripePaymentSheet/Source/Analytics/PaymentSheetAnalyticsHelper.swift index 9f27c3311b4..e56525c7e32 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/Analytics/PaymentSheetAnalyticsHelper.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/Analytics/PaymentSheetAnalyticsHelper.swift @@ -12,7 +12,7 @@ import Foundation final class PaymentSheetAnalyticsHelper { let analyticsClient: STPAnalyticsClient let isCustom: Bool - let configuration: PaymentSheet.Configuration + let configuration: IntegrationConfigurable // Vars set later as PaymentSheet successfully loads, etc. var intent: Intent? @@ -22,7 +22,7 @@ final class PaymentSheetAnalyticsHelper { init( isCustom: Bool, - configuration: PaymentSheet.Configuration, + configuration: IntegrationConfigurable, analyticsClient: STPAnalyticsClient = .sharedClient ) { self.isCustom = isCustom @@ -354,3 +354,36 @@ extension PaymentSheet.Configuration { return payload } } + +extension EmbeddedPaymentElement.Configuration { + /// Serializes the configuration into a safe dictionary containing no PII for analytics logging + var analyticPayload: [String: Any] { + var payload = [String: Any]() + payload["allows_delayed_payment_methods"] = allowsDelayedPaymentMethods + payload["apple_pay_config"] = applePay != nil + payload["style"] = style.rawValue + payload["customer"] = customer != nil + payload["customer_access_provider"] = customer?.customerAccessProvider.analyticValue + payload["return_url"] = returnURL != nil + payload["default_billing_details"] = defaultBillingDetails != PaymentSheet.BillingDetails() + payload["save_payment_method_opt_in_behavior"] = savePaymentMethodOptInBehavior.description + payload["appearance"] = appearance.analyticPayload + payload["billing_details_collection_configuration"] = billingDetailsCollectionConfiguration.analyticPayload + payload["preferred_networks"] = preferredNetworks?.map({ STPCardBrandUtilities.apiValue(from: $0) }).joined(separator: ", ") + payload["form_sheet_action"] = formSheetAction.analyticValue + payload["hide_mandate_text"] = hidesMandateText + + return payload + } +} + +extension EmbeddedPaymentElement.Configuration.FormSheetAction { + var analyticValue: String { + switch self { + case .confirm: + return "confirm" + case .continue: + return "continue" + } + } +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/STPAPIClient+PaymentSheet.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/STPAPIClient+PaymentSheet.swift index 384da8cf614..e33c8b5d524 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/STPAPIClient+PaymentSheet.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/STPAPIClient+PaymentSheet.swift @@ -67,7 +67,7 @@ extension STPAPIClient { func retrieveElementsSession( paymentIntentClientSecret: String, clientDefaultPaymentMethod: String?, - configuration: PaymentSheet.Configuration + configuration: IntegrationConfigurable ) async throws -> (STPPaymentIntent, STPElementsSession) { let elementsSession = try await APIRequest.getWith( self, @@ -90,7 +90,7 @@ extension STPAPIClient { func retrieveElementsSession( setupIntentClientSecret: String, clientDefaultPaymentMethod: String?, - configuration: PaymentSheet.Configuration + configuration: IntegrationConfigurable ) async throws -> (STPSetupIntent, STPElementsSession) { let elementsSession = try await APIRequest.getWith( self, @@ -113,7 +113,7 @@ extension STPAPIClient { func retrieveDeferredElementsSession( withIntentConfig intentConfig: PaymentSheet.IntentConfiguration, clientDefaultPaymentMethod: String?, - configuration: PaymentSheet.Configuration + configuration: IntegrationConfigurable ) async throws -> STPElementsSession { let parameters = makeElementsSessionsParams(mode: .deferredIntent(intentConfig), epmConfiguration: configuration.externalPaymentMethodConfiguration, diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/CustomerSheet/CustomerAddPaymentMethodViewController.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/CustomerSheet/CustomerAddPaymentMethodViewController.swift index ce4242a527a..1f54be6ec8f 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/CustomerSheet/CustomerAddPaymentMethodViewController.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/CustomerSheet/CustomerAddPaymentMethodViewController.swift @@ -244,7 +244,7 @@ class CustomerAddPaymentMethodViewController: UIViewController { isSettingUp: true, countryCode: nil, savePaymentMethodConsentBehavior: savePaymentMethodConsentBehavior, - analyticsHelper: .init(isCustom: false, configuration: .init()) // Just use a dummy analytics helper; we don't look at these analytics. + analyticsHelper: .init(isCustom: false, configuration: PaymentSheet.Configuration.init()) // Just use a dummy analytics helper; we don't look at these analytics. ).make() formElement.delegate = self return formElement diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/CustomerSheet/CustomerSheetDataSource.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/CustomerSheet/CustomerSheetDataSource.swift index 8a1ccfc2758..0e57ff701ee 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/CustomerSheet/CustomerSheetDataSource.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/CustomerSheet/CustomerSheetDataSource.swift @@ -141,7 +141,7 @@ extension CustomerSheetDataSource { case .customerAdapter: return try await configuration.apiClient.retrieveElementsSession(setupIntentClientSecret: setupIntentClientSecret, clientDefaultPaymentMethod: nil, - configuration: .init()) + configuration: PaymentSheet.Configuration.init()) case .customerSession(let customerSessionAdapter): return try await customerSessionAdapter.elementsSession(setupIntentClientSecret: setupIntentClientSecret) } diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElement.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElement.swift index a466b0577bf..d5976bf0340 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElement.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElement.swift @@ -55,24 +55,21 @@ public class EmbeddedPaymentElement { intentConfiguration: IntentConfiguration, configuration: Configuration ) async throws -> EmbeddedPaymentElement { - // TODO(porter) MOBILESDK-2533 Make a protocol for our configurations - let paymentSheetConfiguration = configuration.makePaymentSheetConfiguration() - // TODO(porter) When we do analytics decide how to handle `isCustom` - let analyticsHelper = PaymentSheetAnalyticsHelper(isCustom: true, configuration: paymentSheetConfiguration) + let analyticsHelper = PaymentSheetAnalyticsHelper(isCustom: true, configuration: configuration) AnalyticsHelper.shared.generateSessionID() let loadResult = try await PaymentSheetLoader.load(mode: .deferredIntent(intentConfiguration), - configuration: paymentSheetConfiguration, + configuration: configuration, analyticsHelper: analyticsHelper, integrationShape: .embedded) let paymentMethodTypes = PaymentSheet.PaymentMethodType.filteredPaymentMethodTypes(from: .deferredIntent(intentConfig: intentConfiguration), elementsSession: loadResult.elementsSession, - configuration: paymentSheetConfiguration, + configuration: configuration, logAvailability: true) - let shouldShowApplePay = PaymentSheet.isApplePayEnabled(elementsSession: loadResult.elementsSession, configuration: paymentSheetConfiguration) - let shouldShowLink = PaymentSheet.isLinkEnabled(elementsSession: loadResult.elementsSession, configuration: paymentSheetConfiguration) + let shouldShowApplePay = PaymentSheet.isApplePayEnabled(elementsSession: loadResult.elementsSession, configuration: configuration) + let shouldShowLink = PaymentSheet.isLinkEnabled(elementsSession: loadResult.elementsSession, configuration: configuration) let savedPaymentMethodAccessoryType = await RowButton.RightAccessoryButton.getAccessoryButtonType( savedPaymentMethodsCount: loadResult.savedPaymentMethods.count, isFirstCardCoBranded: loadResult.savedPaymentMethods.first?.isCoBrandedCard ?? false, @@ -221,41 +218,3 @@ extension EmbeddedPaymentElement { public typealias BillingDetailsCollectionConfiguration = PaymentSheet.BillingDetailsCollectionConfiguration public typealias ExternalPaymentMethodConfiguration = PaymentSheet.ExternalPaymentMethodConfiguration } - -// TODO(porter) MOBILESDK-2533 Create a protocol for the commonalities between PaymentSheet.Configuration <> EmbeddedPaymentElement.Configuration -extension EmbeddedPaymentElement.Configuration { - func makePaymentSheetConfiguration() -> PaymentSheet.Configuration { - var paymentConfig = PaymentSheet.Configuration() - - paymentConfig.allowsDelayedPaymentMethods = allowsDelayedPaymentMethods - paymentConfig.allowsPaymentMethodsRequiringShippingAddress = allowsPaymentMethodsRequiringShippingAddress - paymentConfig.apiClient = apiClient - paymentConfig.applePay = applePay - paymentConfig.primaryButtonColor = primaryButtonColor - paymentConfig.primaryButtonLabel = primaryButtonLabel - paymentConfig.style = style - paymentConfig.customer = customer - paymentConfig.merchantDisplayName = merchantDisplayName - paymentConfig.returnURL = returnURL - paymentConfig.defaultBillingDetails = defaultBillingDetails - paymentConfig.savePaymentMethodOptInBehavior = savePaymentMethodOptInBehavior - paymentConfig.appearance = appearance - paymentConfig.shippingDetails = shippingDetails - paymentConfig.preferredNetworks = preferredNetworks - paymentConfig.userOverrideCountry = userOverrideCountry - paymentConfig.billingDetailsCollectionConfiguration = billingDetailsCollectionConfiguration - paymentConfig.removeSavedPaymentMethodMessage = removeSavedPaymentMethodMessage - paymentConfig.externalPaymentMethodConfiguration = externalPaymentMethodConfiguration - paymentConfig.paymentMethodOrder = paymentMethodOrder - paymentConfig.allowsRemovalOfLastSavedPaymentMethod = allowsRemovalOfLastSavedPaymentMethod - - /* Note: - There are 3 properties that differ today: - hidesMandateText - formSheetAction - paymentMethodLayout - */ - - return paymentConfig - } -} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/IntegrationConfigurable.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/IntegrationConfigurable.swift new file mode 100644 index 00000000000..cd32f7bee99 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/IntegrationConfigurable.swift @@ -0,0 +1,63 @@ +// +// IntegrationConfigurable.swift +// StripePaymentSheet +// +// Created by Nick Porter on 10/1/24. +// + +import Foundation +import UIKit +@_spi(STP) import StripePayments + +/// Represents shared configuration properties shared between integration surfaces in mobile payment element. +/// - Note: See the concrete implementations of `IntegrationConfigurable` for detailed doc comments. +/// - Note: Not currently used by CustomerSheet. +protocol IntegrationConfigurable: PaymentMethodRequirementProvider { + var allowsDelayedPaymentMethods: Bool { get set } + var allowsPaymentMethodsRequiringShippingAddress: Bool { get set } + var apiClient: STPAPIClient { get set } + var applePay: PaymentSheet.ApplePayConfiguration? { get set } + var primaryButtonColor: UIColor? { get set } + var primaryButtonLabel: String? { get set } + var style: PaymentSheet.UserInterfaceStyle { get set } + var customer: PaymentSheet.CustomerConfiguration? { get set } + var merchantDisplayName: String { get set } + var returnURL: String? { get set } + var defaultBillingDetails: PaymentSheet.BillingDetails { get set } + var savePaymentMethodOptInBehavior: PaymentSheet.SavePaymentMethodOptInBehavior { get set } + var appearance: PaymentSheet.Appearance { get set } + var shippingDetails: () -> AddressViewController.AddressDetails? { get set } + var preferredNetworks: [STPCardBrand]? { get set } + var userOverrideCountry: String? { get set } + var billingDetailsCollectionConfiguration: PaymentSheet.BillingDetailsCollectionConfiguration { get set } + var removeSavedPaymentMethodMessage: String? { get set } + var externalPaymentMethodConfiguration: PaymentSheet.ExternalPaymentMethodConfiguration? { get set } + var paymentMethodOrder: [String]? { get set } + var allowsRemovalOfLastSavedPaymentMethod: Bool { get set } + var analyticPayload: [String: Any] { get } +} + +extension IntegrationConfigurable { + + /// Returns `true` if the merchant requires the collection of _any_ billing detail fields - name, phone, email, address. + func requiresBillingDetailCollection() -> Bool { + return billingDetailsCollectionConfiguration.name == .always + || billingDetailsCollectionConfiguration.phone == .always + || billingDetailsCollectionConfiguration.email == .always + || billingDetailsCollectionConfiguration.address == .full + } + + var fulfilledRequirements: [PaymentMethodTypeRequirement] { + var reqs = [PaymentMethodTypeRequirement]() + if returnURL != nil { reqs.append(.returnURL) } + if allowsDelayedPaymentMethods { reqs.append(.userSupportsDelayedPaymentMethods) } + if allowsPaymentMethodsRequiringShippingAddress { reqs.append(.shippingAddress) } + if FinancialConnectionsSDKAvailability.isFinancialConnectionsSDKAvailable { + reqs.append(.financialConnectionsSDK) + } + return reqs + } +} + +extension PaymentSheet.Configuration: IntegrationConfigurable {} +extension EmbeddedPaymentElement.Configuration: IntegrationConfigurable {} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentMethodType.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentMethodType.swift index 51a3a354576..90c04b54a6a 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentMethodType.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentMethodType.swift @@ -129,7 +129,7 @@ extension PaymentSheet { /// - Parameters: /// - intent: An `intent` to extract `PaymentMethodType`s from. /// - configuration: A `PaymentSheet` configuration. - static func filteredPaymentMethodTypes(from intent: Intent, elementsSession: STPElementsSession, configuration: Configuration, logAvailability: Bool = false) -> [PaymentMethodType] + static func filteredPaymentMethodTypes(from intent: Intent, elementsSession: STPElementsSession, configuration: IntegrationConfigurable, logAvailability: Bool = false) -> [PaymentMethodType] { var recommendedStripePaymentMethodTypes = elementsSession.orderedPaymentMethodTypes recommendedStripePaymentMethodTypes = recommendedStripePaymentMethodTypes.filter { paymentMethodType in @@ -245,7 +245,7 @@ extension PaymentSheet { /// - Returns: a `PaymentMethodAvailabilityStatus` detailing why or why not this payment method can be added static func supportsAdding( paymentMethod: STPPaymentMethodType, - configuration: PaymentSheet.Configuration, + configuration: IntegrationConfigurable, intent: Intent, elementsSession: STPElementsSession, supportedPaymentMethods: [STPPaymentMethodType] = PaymentSheet.supportedPaymentMethods @@ -332,9 +332,9 @@ extension PaymentSheet { } } - /// Returns true if the passed configuration satsifies the passed in `requirements` + /// Returns true if the passed configuration satisfies the passed in `requirements` /// This function is to be used with dynamic payment method types that do not have bindings support and cannot be represented as a `STPPaymentMethodType`. - /// It's required for the client to specfiy dynamic payment method type requirements (rather than being server driven) because dynamically delivering new LPMS to clients that don't know about them is no longer/currently a priority. + /// It's required for the client to specify dynamic payment method type requirements (rather than being server driven) because dynamically delivering new LPMS to clients that don't know about them is no longer/currently a priority. /// - Note: Use this function over `configurationSupports` when the payment method does not have bindings support e.g. cannot be represented as /// a `STPPaymentMethodType`. /// - Parameters: @@ -344,7 +344,7 @@ extension PaymentSheet { /// - Returns: a `PaymentMethodAvailabilityStatus` detailing why or why not this payment method can be added static func configurationSatisfiesRequirements( requirements: [PaymentMethodTypeRequirement], - configuration: PaymentSheet.Configuration, + configuration: IntegrationConfigurable, intent: Intent ) -> PaymentMethodAvailabilityStatus { let fulfilledRequirements = [configuration, intent].reduce([]) { @@ -373,7 +373,7 @@ extension PaymentSheet { static func configurationSupports( paymentMethod: STPPaymentMethodType, requirements: [PaymentMethodTypeRequirement], - configuration: PaymentSheet.Configuration, + configuration: IntegrationConfigurable, intent: Intent, elementsSession: STPElementsSession, supportedPaymentMethods: [STPPaymentMethodType] @@ -414,7 +414,7 @@ extension STPPaymentMethod { /// Returns whether or not saved PaymentMethods of this type should be displayed as an option to customers /// This should only return true if saved PMs of this type can be successfully used to `/confirm` the given `intent` /// - Warning: This doesn't quite work as advertised. We've hardcoded `PaymentSheet+API.swift` to only fetch saved cards and us bank accounts. - func supportsSavedPaymentMethod(configuration: PaymentSheet.Configuration, intent: Intent, elementsSession: STPElementsSession) -> Bool { + func supportsSavedPaymentMethod(configuration: IntegrationConfigurable, intent: Intent, elementsSession: STPElementsSession) -> Bool { let requirements: [PaymentMethodTypeRequirement] = { switch type { case .card: diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheet+PaymentMethodAvailability.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheet+PaymentMethodAvailability.swift index 7e1bc8ff83f..c8cd207f73f 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheet+PaymentMethodAvailability.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheet+PaymentMethodAvailability.swift @@ -42,14 +42,14 @@ extension PaymentSheet { ] /// Canonical source of truth for whether Apple Pay is enabled - static func isApplePayEnabled(elementsSession: STPElementsSession, configuration: Configuration) -> Bool { + static func isApplePayEnabled(elementsSession: STPElementsSession, configuration: IntegrationConfigurable) -> Bool { return StripeAPI.deviceSupportsApplePay() && configuration.applePay != nil && elementsSession.isApplePayEnabled } /// Canonical source of truth for whether Link is enabled - static func isLinkEnabled(elementsSession: STPElementsSession, configuration: Configuration) -> Bool { + static func isLinkEnabled(elementsSession: STPElementsSession, configuration: IntegrationConfigurable) -> Bool { guard elementsSession.supportsLink else { return false } @@ -66,19 +66,6 @@ protocol PaymentMethodRequirementProvider { var fulfilledRequirements: [PaymentMethodTypeRequirement] { get } } -extension PaymentSheet.Configuration: PaymentMethodRequirementProvider { - var fulfilledRequirements: [PaymentMethodTypeRequirement] { - var reqs = [PaymentMethodTypeRequirement]() - if returnURL != nil { reqs.append(.returnURL) } - if allowsDelayedPaymentMethods { reqs.append(.userSupportsDelayedPaymentMethods) } - if allowsPaymentMethodsRequiringShippingAddress { reqs.append(.shippingAddress) } - if FinancialConnectionsSDKAvailability.isFinancialConnectionsSDKAvailable { - reqs.append(.financialConnectionsSDK) - } - return reqs - } -} - extension Intent: PaymentMethodRequirementProvider { var fulfilledRequirements: [PaymentMethodTypeRequirement] { switch self { diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetConfiguration.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetConfiguration.swift index 4977017a161..05e44e5513b 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetConfiguration.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetConfiguration.swift @@ -204,7 +204,7 @@ extension PaymentSheet { /// Payment methods are arranged vertically. Users can scroll up or down to navigate through different payment methods. case vertical - + /// Stripe automatically chooses between `horizontal` and `vertical`. case automatic } @@ -495,16 +495,6 @@ extension PaymentSheet { } } -extension PaymentSheet.Configuration { - /// Returns `true` if the merchant requires the collection of _any_ billing detail fields - name, phone, email, address. - func requiresBillingDetailCollection() -> Bool { - return billingDetailsCollectionConfiguration.name == .always - || billingDetailsCollectionConfiguration.phone == .always - || billingDetailsCollectionConfiguration.email == .always - || billingDetailsCollectionConfiguration.address == .full - } -} - extension STPPaymentMethodBillingDetails { func toPaymentSheetBillingDetails() -> PaymentSheet.BillingDetails { let address = PaymentSheet.Address(city: self.address?.city, diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetLoader.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetLoader.swift index 96cf6a4e5b6..44dd92644f1 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetLoader.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetLoader.swift @@ -45,7 +45,7 @@ final class PaymentSheetLoader { /// Fetches the PaymentIntent or SetupIntent and Customer's saved PaymentMethods static func load( mode: PaymentSheet.InitializationMode, - configuration: PaymentSheet.Configuration, + configuration: IntegrationConfigurable, analyticsHelper: PaymentSheetAnalyticsHelper, integrationShape: IntegrationShape, completion: @escaping (Result) -> Void @@ -143,7 +143,7 @@ final class PaymentSheetLoader { public static func load( mode: PaymentSheet.InitializationMode, - configuration: PaymentSheet.Configuration, + configuration: IntegrationConfigurable, analyticsHelper: PaymentSheetAnalyticsHelper, integrationShape: IntegrationShape ) async throws -> LoadResult { @@ -183,7 +183,7 @@ final class PaymentSheetLoader { } } - static func lookupLinkAccount(elementsSession: STPElementsSession, configuration: PaymentSheet.Configuration) async throws -> PaymentSheetLinkAccount? { + static func lookupLinkAccount(elementsSession: STPElementsSession, configuration: IntegrationConfigurable) async throws -> PaymentSheetLinkAccount? { // Only lookup the consumer account if Link is supported guard PaymentSheet.isLinkEnabled(elementsSession: elementsSession, configuration: configuration) else { return nil @@ -217,7 +217,7 @@ final class PaymentSheetLoader { } typealias ElementSessionAndIntent = (elementsSession: STPElementsSession, intent: Intent) - static func fetchElementsSessionAndIntent(mode: PaymentSheet.InitializationMode, configuration: PaymentSheet.Configuration, analyticsHelper: PaymentSheetAnalyticsHelper) async throws -> ElementSessionAndIntent { + static func fetchElementsSessionAndIntent(mode: PaymentSheet.InitializationMode, configuration: IntegrationConfigurable, analyticsHelper: PaymentSheetAnalyticsHelper) async throws -> ElementSessionAndIntent { let intent: Intent let elementsSession: STPElementsSession let clientDefaultPaymentMethod = defaultStripePaymentMethodId(forCustomerID: configuration.customer?.id) @@ -298,7 +298,7 @@ final class PaymentSheetLoader { } static let savedPaymentMethodTypes: [STPPaymentMethodType] = [.card, .USBankAccount, .SEPADebit] - static func fetchSavedPaymentMethods(elementsSession: STPElementsSession, configuration: PaymentSheet.Configuration) async throws -> [STPPaymentMethod] { + static func fetchSavedPaymentMethods(elementsSession: STPElementsSession, configuration: IntegrationConfigurable) async throws -> [STPPaymentMethod] { // Retrieve the payment methods from ElementsSession or by making direct API calls var savedPaymentMethods: [STPPaymentMethod] if let elementsSessionPaymentMethods = elementsSession.customer?.paymentMethods { @@ -321,7 +321,7 @@ final class PaymentSheetLoader { return savedPaymentMethods } - static func fetchSavedPaymentMethodsUsingApiClient(configuration: PaymentSheet.Configuration) async throws -> [STPPaymentMethod] { + static func fetchSavedPaymentMethodsUsingApiClient(configuration: IntegrationConfigurable) async throws -> [STPPaymentMethod] { guard let customerID = configuration.customer?.id, let ephemeralKey = configuration.customer?.ephemeralKeySecret, !ephemeralKey.isEmpty else { From 8d7f39a285380e023e1322d8b72dfa9c049f653e Mon Sep 17 00:00:00 2001 From: Nick Porter Date: Tue, 1 Oct 2024 10:50:20 -0600 Subject: [PATCH 2/7] update doc comment --- .../Source/PaymentSheet/IntegrationConfigurable.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/IntegrationConfigurable.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/IntegrationConfigurable.swift index cd32f7bee99..7b39f83f04b 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/IntegrationConfigurable.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/IntegrationConfigurable.swift @@ -9,7 +9,7 @@ import Foundation import UIKit @_spi(STP) import StripePayments -/// Represents shared configuration properties shared between integration surfaces in mobile payment element. +/// Represents shared configuration properties between integration surfaces in mobile payment element. /// - Note: See the concrete implementations of `IntegrationConfigurable` for detailed doc comments. /// - Note: Not currently used by CustomerSheet. protocol IntegrationConfigurable: PaymentMethodRequirementProvider { From a4ba6b6b9208a6872104b53698b0ee1e367921cc Mon Sep 17 00:00:00 2001 From: Nick Porter Date: Tue, 1 Oct 2024 11:21:08 -0600 Subject: [PATCH 3/7] Fix tests --- .../LinkSignupViewModelTests.swift | 2 +- .../Webview/ConnectWebViewTests.swift | 2 +- .../Internal/Webview/ScriptWebTestBase.swift | 2 +- .../PaymentSheetAnalyticsHelperTest.swift | 28 +++++++++---------- .../PaymentSheetLoaderStubbedTest.swift | 4 +-- ...etVerticalViewControllerSnapshotTest.swift | 2 +- .../STPFixtures+PaymentSheet.swift | 2 +- 7 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Stripe/StripeiOSTests/LinkSignupViewModelTests.swift b/Stripe/StripeiOSTests/LinkSignupViewModelTests.swift index 23759abe2eb..a5d2441e12d 100644 --- a/Stripe/StripeiOSTests/LinkSignupViewModelTests.swift +++ b/Stripe/StripeiOSTests/LinkSignupViewModelTests.swift @@ -205,7 +205,7 @@ extension LinkInlineSignupViewModelTests { : nil return LinkInlineSignupViewModel( - configuration: .init(), + configuration: PaymentSheet.Configuration(), showCheckbox: showCheckbox, accountService: MockAccountService(shouldFailLookup: shouldFailLookup), linkAccount: linkAccount, diff --git a/StripeConnect/StripeConnectTests/Internal/Webview/ConnectWebViewTests.swift b/StripeConnect/StripeConnectTests/Internal/Webview/ConnectWebViewTests.swift index 9ca63f52969..a25162cb96e 100644 --- a/StripeConnect/StripeConnectTests/Internal/Webview/ConnectWebViewTests.swift +++ b/StripeConnect/StripeConnectTests/Internal/Webview/ConnectWebViewTests.swift @@ -21,7 +21,7 @@ class ConnectWebViewTests: XCTestCase { override func setUp() { mockURLOpener = .init() webView = ConnectWebView(frame: .zero, - configuration: .init(), + PaymentSheet.Configuration(), urlOpener: mockURLOpener, sdkVersion: "1.2.3") } diff --git a/StripeConnect/StripeConnectTests/Internal/Webview/ScriptWebTestBase.swift b/StripeConnect/StripeConnectTests/Internal/Webview/ScriptWebTestBase.swift index 05a74263d99..7c83617a0a2 100644 --- a/StripeConnect/StripeConnectTests/Internal/Webview/ScriptWebTestBase.swift +++ b/StripeConnect/StripeConnectTests/Internal/Webview/ScriptWebTestBase.swift @@ -15,7 +15,7 @@ class ScriptWebTestBase: XCTestCase { override func setUp() { super.setUp() - webView = WKWebView(frame: .zero, configuration: .init()) + webView = WKWebView(frame: .zero, PaymentSheet.Configuration()) } override func tearDown() { diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/PaymentSheetAnalyticsHelperTest.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/PaymentSheetAnalyticsHelperTest.swift index 232329cda73..238ae36b466 100644 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/PaymentSheetAnalyticsHelperTest.swift +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/PaymentSheetAnalyticsHelperTest.swift @@ -27,7 +27,7 @@ final class PaymentSheetAnalyticsHelperTest: XCTestCase { intent: .paymentIntent(STPFixtures.paymentIntent()), elementsSession: .makeBackupElementsSession(with: STPFixtures.paymentIntent()), savedPaymentMethods: [] - ), analyticsHelper: .init(isCustom: true, configuration: .init()) + ), analyticsHelper: .init(isCustom: true, configuration: PaymentSheet.Configuration()) ) XCTAssertTrue(STPAnalyticsClient.sharedClient.productUsage.contains("PaymentSheet.FlowController")) } @@ -86,7 +86,7 @@ final class PaymentSheetAnalyticsHelperTest: XCTestCase { } func testLogLoadFailed() { - let sut = PaymentSheetAnalyticsHelper(isCustom: false, configuration: .init(), analyticsClient: analyticsClient) + let sut = PaymentSheetAnalyticsHelper(isCustom: false, configuration: PaymentSheet.Configuration(), analyticsClient: analyticsClient) // Load started -> failed sut.logLoadStarted() sut.logLoadFailed(error: NSError(domain: "domain", code: 1)) @@ -96,7 +96,7 @@ final class PaymentSheetAnalyticsHelperTest: XCTestCase { } func testLogLoadSucceeded() { - let sut = PaymentSheetAnalyticsHelper(isCustom: false, configuration: .init(), analyticsClient: analyticsClient) + let sut = PaymentSheetAnalyticsHelper(isCustom: false, configuration: PaymentSheet.Configuration(), analyticsClient: analyticsClient) // Load started -> succeeded sut.logLoadStarted() sut.logLoadSucceeded( @@ -116,13 +116,13 @@ final class PaymentSheetAnalyticsHelperTest: XCTestCase { } func testLogShow() { - let paymentSheetHelper = PaymentSheetAnalyticsHelper(isCustom: false, configuration: .init(), analyticsClient: analyticsClient) + let paymentSheetHelper = PaymentSheetAnalyticsHelper(isCustom: false, configuration: PaymentSheet.Configuration(), analyticsClient: analyticsClient) paymentSheetHelper.logShow(showingSavedPMList: true) XCTAssertEqual(analyticsClient._testLogHistory.last!["event"] as? String, "mc_complete_sheet_savedpm_show") paymentSheetHelper.logShow(showingSavedPMList: false) XCTAssertEqual(analyticsClient._testLogHistory.last!["event"] as? String, "mc_complete_sheet_newpm_show") - let flowControllerSUT = PaymentSheetAnalyticsHelper(isCustom: true, configuration: .init(), analyticsClient: analyticsClient) + let flowControllerSUT = PaymentSheetAnalyticsHelper(isCustom: true, configuration: PaymentSheet.Configuration(), analyticsClient: analyticsClient) flowControllerSUT.logShow(showingSavedPMList: true) XCTAssertEqual(analyticsClient._testLogHistory.last!["event"] as? String, "mc_custom_sheet_savedpm_show") flowControllerSUT.logShow(showingSavedPMList: false) @@ -131,7 +131,7 @@ final class PaymentSheetAnalyticsHelperTest: XCTestCase { func testLogSavedPMScreenOptionSelected() { func _createHelper(isCustom: Bool) -> PaymentSheetAnalyticsHelper { - let sut = PaymentSheetAnalyticsHelper(isCustom: isCustom, configuration: .init(), analyticsClient: analyticsClient) + let sut = PaymentSheetAnalyticsHelper(isCustom: isCustom, configuration: PaymentSheet.Configuration(), analyticsClient: analyticsClient) return sut } let testcases: [(isCustom: Bool, option: SavedPaymentOptionsViewController.Selection, expectedEvent: String, expectedSelectedLPM: String?)] = [ @@ -154,25 +154,25 @@ final class PaymentSheetAnalyticsHelperTest: XCTestCase { } } func testLogPaymentMethodRemoved_complete() { - let sut = PaymentSheetAnalyticsHelper(isCustom: false, configuration: .init(), analyticsClient: analyticsClient) + let sut = PaymentSheetAnalyticsHelper(isCustom: false, configuration: PaymentSheet.Configuration(), analyticsClient: analyticsClient) sut.logSavedPaymentMethodRemoved(paymentMethod: ._testCard()) XCTAssertEqual(analyticsClient._testLogHistory.last!["event"] as? String, "mc_complete_paymentoption_removed") XCTAssertEqual(analyticsClient._testLogHistory.last!["selected_lpm"] as? String, "card") } func testLogPaymentMethodRemoved_custom() { - let sut = PaymentSheetAnalyticsHelper(isCustom: true, configuration: .init(), analyticsClient: analyticsClient) + let sut = PaymentSheetAnalyticsHelper(isCustom: true, configuration: PaymentSheet.Configuration(), analyticsClient: analyticsClient) sut.logSavedPaymentMethodRemoved(paymentMethod: ._testCard()) XCTAssertEqual(analyticsClient._testLogHistory.last!["event"] as? String, "mc_custom_paymentoption_removed") XCTAssertEqual(analyticsClient._testLogHistory.last!["selected_lpm"] as? String, "card") } func testLogNewPaymentMethodSelected() { - let sut = PaymentSheetAnalyticsHelper(isCustom: true, configuration: .init(), analyticsClient: analyticsClient) + let sut = PaymentSheetAnalyticsHelper(isCustom: true, configuration: PaymentSheet.Configuration(), analyticsClient: analyticsClient) sut.logNewPaymentMethodSelected(paymentMethodTypeIdentifier: "card") XCTAssertEqual(analyticsClient._testLogHistory.last!["event"] as? String, "mc_carousel_payment_method_tapped") XCTAssertEqual(analyticsClient._testLogHistory.last!["selected_lpm"] as? String, "card") } func testLogFormCompleted() { - let sut = PaymentSheetAnalyticsHelper(isCustom: true, configuration: .init(), analyticsClient: analyticsClient) + let sut = PaymentSheetAnalyticsHelper(isCustom: true, configuration: PaymentSheet.Configuration(), analyticsClient: analyticsClient) sut.logFormShown(paymentMethodTypeIdentifier: "card") sut.logFormCompleted(paymentMethodTypeIdentifier: "card") XCTAssertEqual(analyticsClient._testLogHistory.last!["event"] as? String, "mc_form_completed") @@ -180,7 +180,7 @@ final class PaymentSheetAnalyticsHelperTest: XCTestCase { } func testLogFormShownAndInteracted() { - let sut = PaymentSheetAnalyticsHelper(isCustom: false, configuration: .init(), analyticsClient: analyticsClient) + let sut = PaymentSheetAnalyticsHelper(isCustom: false, configuration: PaymentSheet.Configuration(), analyticsClient: analyticsClient) sut.logFormShown(paymentMethodTypeIdentifier: "card") XCTAssertEqual(analyticsClient._testLogHistory.last!["event"] as? String, "mc_form_shown") XCTAssertEqual(analyticsClient._testLogHistory.last!["selected_lpm"] as? String, "card") @@ -221,7 +221,7 @@ final class PaymentSheetAnalyticsHelperTest: XCTestCase { for (isCustom, paymentOption, result, expected) in testcases { let sut = PaymentSheetAnalyticsHelper( isCustom: isCustom, - configuration: .init(), + configuration: PaymentSheet.Configuration(), analyticsClient: analyticsClient ) sut.intent = ._testValue() @@ -245,7 +245,7 @@ final class PaymentSheetAnalyticsHelperTest: XCTestCase { // Check deferred_intent_confirmation_type gets sent let sut = PaymentSheetAnalyticsHelper( isCustom: false, - configuration: .init(), + configuration: PaymentSheet.Configuration(), analyticsClient: analyticsClient ) sut.logLoadStarted() @@ -264,7 +264,7 @@ final class PaymentSheetAnalyticsHelperTest: XCTestCase { } func testLogConfirmButtonTapped() { - let sut = PaymentSheetAnalyticsHelper(isCustom: false, configuration: .init(), analyticsClient: analyticsClient) + let sut = PaymentSheetAnalyticsHelper(isCustom: false, configuration: PaymentSheet.Configuration(), analyticsClient: analyticsClient) sut.logFormShown(paymentMethodTypeIdentifier: "card") sut.logConfirmButtonTapped(paymentOption: .applePay) diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/PaymentSheetLoaderStubbedTest.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/PaymentSheetLoaderStubbedTest.swift index 1fae3c1755d..e86727e2341 100644 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/PaymentSheetLoaderStubbedTest.swift +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/PaymentSheetLoaderStubbedTest.swift @@ -407,8 +407,8 @@ class PaymentSheetLoaderStubbedTest: APIStubbedTestCase { let intentConfig = PaymentSheet.IntentConfiguration.init(mode: .payment(amount: 100, currency: "USD"), confirmHandler: confirmHandler) PaymentSheetLoader.load( mode: .deferredIntent(intentConfig), - configuration: ._testValue_MostPermissive(), - analyticsHelper: .init(isCustom: false, configuration: ._testValue_MostPermissive(), analyticsClient: analyticsClient), + configuration: PaymentSheet.Configuration._testValue_MostPermissive(), + analyticsHelper: .init(isCustom: false, configuration: PaymentSheet.Configuration._testValue_MostPermissive(), analyticsClient: analyticsClient), integrationShape: .complete ) { result in loadExpectation.fulfill() diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/PaymentSheetVerticalViewControllerSnapshotTest.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/PaymentSheetVerticalViewControllerSnapshotTest.swift index 5427459ac89..da9a74399a4 100644 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/PaymentSheetVerticalViewControllerSnapshotTest.swift +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/PaymentSheetVerticalViewControllerSnapshotTest.swift @@ -144,7 +144,7 @@ final class PaymentSheetVerticalViewControllerSnapshotTest: STPSnapshotTestCase ) // ...and previous customer input is card... let previousPaymentOption = PaymentOption.new(confirmParams: IntentConfirmParams(params: ._testValidCardValue(), type: .stripe(.card))) - let sut = PaymentSheetVerticalViewController(configuration: .init(), loadResult: loadResult, isFlowController: true, analyticsHelper: ._testValue(), previousPaymentOption: previousPaymentOption) + let sut = PaymentSheetVerticalViewController(configuration: PaymentSheet.Configuration(), loadResult: loadResult, isFlowController: true, analyticsHelper: ._testValue(), previousPaymentOption: previousPaymentOption) // ...should display card form w/ fields filled out & *no back button* verify(sut) } diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/STPFixtures+PaymentSheet.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/STPFixtures+PaymentSheet.swift index b8e3bc81930..eaebe638632 100644 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/STPFixtures+PaymentSheet.swift +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/STPFixtures+PaymentSheet.swift @@ -264,7 +264,7 @@ extension PaymentSheetLoader.LoadResult { extension PaymentSheetAnalyticsHelper { static func _testValue(analyticsClient: STPAnalyticsClient = .sharedClient) -> Self { - return .init(isCustom: false, configuration: .init(), analyticsClient: analyticsClient) + return .init(isCustom: false, configuration: PaymentSheet.Configuration(), analyticsClient: analyticsClient) } } From d119ee2970eac0b1f344a89adf53fc3f5a3ffe4f Mon Sep 17 00:00:00 2001 From: Nick Porter Date: Tue, 1 Oct 2024 11:44:18 -0600 Subject: [PATCH 4/7] Don't touch StripeConnect --- .../StripeConnectTests/Internal/Webview/ScriptWebTestBase.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/StripeConnect/StripeConnectTests/Internal/Webview/ScriptWebTestBase.swift b/StripeConnect/StripeConnectTests/Internal/Webview/ScriptWebTestBase.swift index 7c83617a0a2..05a74263d99 100644 --- a/StripeConnect/StripeConnectTests/Internal/Webview/ScriptWebTestBase.swift +++ b/StripeConnect/StripeConnectTests/Internal/Webview/ScriptWebTestBase.swift @@ -15,7 +15,7 @@ class ScriptWebTestBase: XCTestCase { override func setUp() { super.setUp() - webView = WKWebView(frame: .zero, PaymentSheet.Configuration()) + webView = WKWebView(frame: .zero, configuration: .init()) } override func tearDown() { From bae9e15b0df93419e1443bac95e9879ceac6d89d Mon Sep 17 00:00:00 2001 From: Nick Porter Date: Tue, 1 Oct 2024 12:01:06 -0600 Subject: [PATCH 5/7] One more StripeConnect failure --- .../Internal/Webview/ConnectWebViewTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/StripeConnect/StripeConnectTests/Internal/Webview/ConnectWebViewTests.swift b/StripeConnect/StripeConnectTests/Internal/Webview/ConnectWebViewTests.swift index a25162cb96e..9ca63f52969 100644 --- a/StripeConnect/StripeConnectTests/Internal/Webview/ConnectWebViewTests.swift +++ b/StripeConnect/StripeConnectTests/Internal/Webview/ConnectWebViewTests.swift @@ -21,7 +21,7 @@ class ConnectWebViewTests: XCTestCase { override func setUp() { mockURLOpener = .init() webView = ConnectWebView(frame: .zero, - PaymentSheet.Configuration(), + configuration: .init(), urlOpener: mockURLOpener, sdkVersion: "1.2.3") } From d2e1d58cc37db45a11eee3d545789466d248300e Mon Sep 17 00:00:00 2001 From: Nick Porter Date: Wed, 2 Oct 2024 15:05:28 -0600 Subject: [PATCH 6/7] PR feedback --- .../project.pbxproj | 8 ++-- .../PaymentSheetAnalyticsHelper.swift | 37 +------------------ .../STPAPIClient+PaymentSheet.swift | 6 +-- ...stomerAddPaymentMethodViewController.swift | 2 +- .../Embedded/EmbeddedPaymentElement.swift | 4 +- ...wift => PaymentElementConfiguration.swift} | 13 +++---- .../PaymentSheet/PaymentMethodType.swift | 10 ++--- ...ymentSheet+PaymentMethodAvailability.swift | 4 +- .../PaymentSheet/PaymentSheetLoader.swift | 12 +++--- 9 files changed, 31 insertions(+), 65 deletions(-) rename StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/{IntegrationConfigurable.swift => PaymentElementConfiguration.swift} (85%) diff --git a/StripePaymentSheet/StripePaymentSheet.xcodeproj/project.pbxproj b/StripePaymentSheet/StripePaymentSheet.xcodeproj/project.pbxproj index 56c0d916194..6c8d38920ca 100644 --- a/StripePaymentSheet/StripePaymentSheet.xcodeproj/project.pbxproj +++ b/StripePaymentSheet/StripePaymentSheet.xcodeproj/project.pbxproj @@ -119,7 +119,7 @@ 61C0D3B8C63EB4558AB74A7E /* StripePayments.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A1C7CFA5C9C1A8A73CFA1C0 /* StripePayments.framework */; }; 61CB0BD02BED985100E24A4C /* VerticalSavedPaymentMethodsViewControllerSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61CBE6672BED97EE005F7FEB /* VerticalSavedPaymentMethodsViewControllerSnapshotTests.swift */; }; 61CBE6662BED9749005F7FEB /* VerticalSavedPaymentMethodsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61CBE6652BED9749005F7FEB /* VerticalSavedPaymentMethodsViewController.swift */; }; - 61D842442CAC50C5009D2D51 /* IntegrationConfigurable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61D842432CAC50C5009D2D51 /* IntegrationConfigurable.swift */; }; + 61D842892CADE4B9009D2D51 /* PaymentElementConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61D842882CADE4B9009D2D51 /* PaymentElementConfiguration.swift */; }; 61D8688E2C06553E001FAD84 /* RightAccessoryButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61D8688D2C06553E001FAD84 /* RightAccessoryButton.swift */; }; 61FB6BCD2C8901B200F8E074 /* EmbeddedPaymentMethodsViewSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61FB6BCC2C8901B200F8E074 /* EmbeddedPaymentMethodsViewSnapshotTests.swift */; }; 623C2D9F87929D6DA9C09E23 /* STPCameraView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D39B31D0B890A4F8E4819B15 /* STPCameraView.swift */; }; @@ -472,7 +472,7 @@ 619AF0882BF56F9100D1C981 /* VerticalSavedPaymentMethodsViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VerticalSavedPaymentMethodsViewControllerTests.swift; sourceTree = ""; }; 61CBE6652BED9749005F7FEB /* VerticalSavedPaymentMethodsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VerticalSavedPaymentMethodsViewController.swift; sourceTree = ""; }; 61CBE6672BED97EE005F7FEB /* VerticalSavedPaymentMethodsViewControllerSnapshotTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VerticalSavedPaymentMethodsViewControllerSnapshotTests.swift; sourceTree = ""; }; - 61D842432CAC50C5009D2D51 /* IntegrationConfigurable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegrationConfigurable.swift; sourceTree = ""; }; + 61D842882CADE4B9009D2D51 /* PaymentElementConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PaymentElementConfiguration.swift; sourceTree = ""; }; 61D8688D2C06553E001FAD84 /* RightAccessoryButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RightAccessoryButton.swift; sourceTree = ""; }; 61FB6BCC2C8901B200F8E074 /* EmbeddedPaymentMethodsViewSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmbeddedPaymentMethodsViewSnapshotTests.swift; sourceTree = ""; }; 62CE362B80042827F47ABC3F /* AffirmCopyLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AffirmCopyLabel.swift; sourceTree = ""; }; @@ -840,7 +840,6 @@ B9A9FDAE66ADA08D85D74E19 /* PaymentSheet+SwiftUI.swift */, B61FFE76D0960C7F1E34B405 /* PaymentSheetAppearance.swift */, C46CB5AB992F8EEFE4E5460A /* PaymentSheetConfiguration.swift */, - 61D842432CAC50C5009D2D51 /* IntegrationConfigurable.swift */, 0DF4D51EEAB1092637BE144E /* PaymentSheetDeferredValidator.swift */, E6DDBBAAC2892467CED23402 /* PaymentSheetError.swift */, 58A85D630BDEA7408391EB8B /* PaymentSheetFlowController.swift */, @@ -849,6 +848,7 @@ 966339C092711FED8EFE98FB /* STPAnalyticsClient+PaymentSheet.swift */, 446E3BBF316178C04343B193 /* STPApplePayContext+PaymentSheet.swift */, 2C59FD8C17CA1D740BCAFA4D /* STPPaymentIntentShippingDetailsParams+PaymentSheet.swift */, + 61D842882CADE4B9009D2D51 /* PaymentElementConfiguration.swift */, ); path = PaymentSheet; sourceTree = ""; @@ -1763,6 +1763,7 @@ 4E5A3324BBD882A780925E2B /* STPAnalyticsClient+Address.swift in Sources */, 0FB52E5B87B1854B28362BF3 /* STPAnalyticsClient+CustomerSheet.swift in Sources */, 6A529F76ECB33C9154314C1F /* STPAnalyticsClient+LUXE.swift in Sources */, + 61D842892CADE4B9009D2D51 /* PaymentElementConfiguration.swift in Sources */, 06976DDC67A61176FC54AA76 /* Data+SHA256.swift in Sources */, 6180A5CB2C8249D2009D1536 /* UIStackView+Separator.swift in Sources */, B63B2CF52BFBEEAD003810F3 /* PaymentMethodFormViewController.swift in Sources */, @@ -1796,7 +1797,6 @@ B8A7575878C5124CF5482097 /* VerificationSession.swift in Sources */, 9326393E775D29F8C661624B /* STPAPIClient+PaymentSheet.swift in Sources */, AA3A96D74B1659CB5725E95F /* CardExpiryDate.swift in Sources */, - 61D842442CAC50C5009D2D51 /* IntegrationConfigurable.swift in Sources */, 64DE5688E4FBE92E1F49810C /* ExternalPaymentMethod.swift in Sources */, 229A4A578609A3711F02682E /* STPCardBrandChoice.swift in Sources */, 3EDFACA133567159875143C5 /* STPElementsSession.swift in Sources */, diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Analytics/PaymentSheetAnalyticsHelper.swift b/StripePaymentSheet/StripePaymentSheet/Source/Analytics/PaymentSheetAnalyticsHelper.swift index e56525c7e32..9f27c3311b4 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/Analytics/PaymentSheetAnalyticsHelper.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/Analytics/PaymentSheetAnalyticsHelper.swift @@ -12,7 +12,7 @@ import Foundation final class PaymentSheetAnalyticsHelper { let analyticsClient: STPAnalyticsClient let isCustom: Bool - let configuration: IntegrationConfigurable + let configuration: PaymentSheet.Configuration // Vars set later as PaymentSheet successfully loads, etc. var intent: Intent? @@ -22,7 +22,7 @@ final class PaymentSheetAnalyticsHelper { init( isCustom: Bool, - configuration: IntegrationConfigurable, + configuration: PaymentSheet.Configuration, analyticsClient: STPAnalyticsClient = .sharedClient ) { self.isCustom = isCustom @@ -354,36 +354,3 @@ extension PaymentSheet.Configuration { return payload } } - -extension EmbeddedPaymentElement.Configuration { - /// Serializes the configuration into a safe dictionary containing no PII for analytics logging - var analyticPayload: [String: Any] { - var payload = [String: Any]() - payload["allows_delayed_payment_methods"] = allowsDelayedPaymentMethods - payload["apple_pay_config"] = applePay != nil - payload["style"] = style.rawValue - payload["customer"] = customer != nil - payload["customer_access_provider"] = customer?.customerAccessProvider.analyticValue - payload["return_url"] = returnURL != nil - payload["default_billing_details"] = defaultBillingDetails != PaymentSheet.BillingDetails() - payload["save_payment_method_opt_in_behavior"] = savePaymentMethodOptInBehavior.description - payload["appearance"] = appearance.analyticPayload - payload["billing_details_collection_configuration"] = billingDetailsCollectionConfiguration.analyticPayload - payload["preferred_networks"] = preferredNetworks?.map({ STPCardBrandUtilities.apiValue(from: $0) }).joined(separator: ", ") - payload["form_sheet_action"] = formSheetAction.analyticValue - payload["hide_mandate_text"] = hidesMandateText - - return payload - } -} - -extension EmbeddedPaymentElement.Configuration.FormSheetAction { - var analyticValue: String { - switch self { - case .confirm: - return "confirm" - case .continue: - return "continue" - } - } -} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/STPAPIClient+PaymentSheet.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/STPAPIClient+PaymentSheet.swift index e33c8b5d524..cd38d21173d 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/STPAPIClient+PaymentSheet.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/STPAPIClient+PaymentSheet.swift @@ -67,7 +67,7 @@ extension STPAPIClient { func retrieveElementsSession( paymentIntentClientSecret: String, clientDefaultPaymentMethod: String?, - configuration: IntegrationConfigurable + configuration: PaymentElementConfiguration ) async throws -> (STPPaymentIntent, STPElementsSession) { let elementsSession = try await APIRequest.getWith( self, @@ -90,7 +90,7 @@ extension STPAPIClient { func retrieveElementsSession( setupIntentClientSecret: String, clientDefaultPaymentMethod: String?, - configuration: IntegrationConfigurable + configuration: PaymentElementConfiguration ) async throws -> (STPSetupIntent, STPElementsSession) { let elementsSession = try await APIRequest.getWith( self, @@ -113,7 +113,7 @@ extension STPAPIClient { func retrieveDeferredElementsSession( withIntentConfig intentConfig: PaymentSheet.IntentConfiguration, clientDefaultPaymentMethod: String?, - configuration: IntegrationConfigurable + configuration: PaymentElementConfiguration ) async throws -> STPElementsSession { let parameters = makeElementsSessionsParams(mode: .deferredIntent(intentConfig), epmConfiguration: configuration.externalPaymentMethodConfiguration, diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/CustomerSheet/CustomerAddPaymentMethodViewController.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/CustomerSheet/CustomerAddPaymentMethodViewController.swift index 1f54be6ec8f..bd163ff6345 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/CustomerSheet/CustomerAddPaymentMethodViewController.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/CustomerSheet/CustomerAddPaymentMethodViewController.swift @@ -244,7 +244,7 @@ class CustomerAddPaymentMethodViewController: UIViewController { isSettingUp: true, countryCode: nil, savePaymentMethodConsentBehavior: savePaymentMethodConsentBehavior, - analyticsHelper: .init(isCustom: false, configuration: PaymentSheet.Configuration.init()) // Just use a dummy analytics helper; we don't look at these analytics. + analyticsHelper: .init(isCustom: false, configuration: PaymentSheet.Configuration.init()) // TODO(MOBILESDK-2548) Just use a dummy analytics helper; we don't look at these analytics. ).make() formElement.delegate = self return formElement diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElement.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElement.swift index d5976bf0340..59cfb636b38 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElement.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElement.swift @@ -55,8 +55,8 @@ public class EmbeddedPaymentElement { intentConfiguration: IntentConfiguration, configuration: Configuration ) async throws -> EmbeddedPaymentElement { - // TODO(porter) When we do analytics decide how to handle `isCustom` - let analyticsHelper = PaymentSheetAnalyticsHelper(isCustom: true, configuration: configuration) + // TODO(porter) Should we create a new analytics helper specific to embedded? Figured this out when we do analytics. + let analyticsHelper = PaymentSheetAnalyticsHelper(isCustom: true, configuration: PaymentSheet.Configuration()) AnalyticsHelper.shared.generateSessionID() let loadResult = try await PaymentSheetLoader.load(mode: .deferredIntent(intentConfiguration), diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/IntegrationConfigurable.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentElementConfiguration.swift similarity index 85% rename from StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/IntegrationConfigurable.swift rename to StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentElementConfiguration.swift index 7b39f83f04b..4ede6b9b50d 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/IntegrationConfigurable.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentElementConfiguration.swift @@ -1,5 +1,5 @@ // -// IntegrationConfigurable.swift +// PaymentElementConfiguration.swift // StripePaymentSheet // // Created by Nick Porter on 10/1/24. @@ -10,9 +10,9 @@ import UIKit @_spi(STP) import StripePayments /// Represents shared configuration properties between integration surfaces in mobile payment element. -/// - Note: See the concrete implementations of `IntegrationConfigurable` for detailed doc comments. +/// - Note: See the concrete implementations of `PaymentElementConfiguration` for detailed doc comments. /// - Note: Not currently used by CustomerSheet. -protocol IntegrationConfigurable: PaymentMethodRequirementProvider { +protocol PaymentElementConfiguration: PaymentMethodRequirementProvider { var allowsDelayedPaymentMethods: Bool { get set } var allowsPaymentMethodsRequiringShippingAddress: Bool { get set } var apiClient: STPAPIClient { get set } @@ -34,10 +34,9 @@ protocol IntegrationConfigurable: PaymentMethodRequirementProvider { var externalPaymentMethodConfiguration: PaymentSheet.ExternalPaymentMethodConfiguration? { get set } var paymentMethodOrder: [String]? { get set } var allowsRemovalOfLastSavedPaymentMethod: Bool { get set } - var analyticPayload: [String: Any] { get } } -extension IntegrationConfigurable { +extension PaymentElementConfiguration { /// Returns `true` if the merchant requires the collection of _any_ billing detail fields - name, phone, email, address. func requiresBillingDetailCollection() -> Bool { @@ -59,5 +58,5 @@ extension IntegrationConfigurable { } } -extension PaymentSheet.Configuration: IntegrationConfigurable {} -extension EmbeddedPaymentElement.Configuration: IntegrationConfigurable {} +extension PaymentSheet.Configuration: PaymentElementConfiguration {} +extension EmbeddedPaymentElement.Configuration: PaymentElementConfiguration {} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentMethodType.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentMethodType.swift index 90c04b54a6a..7e5bac9bea2 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentMethodType.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentMethodType.swift @@ -129,7 +129,7 @@ extension PaymentSheet { /// - Parameters: /// - intent: An `intent` to extract `PaymentMethodType`s from. /// - configuration: A `PaymentSheet` configuration. - static func filteredPaymentMethodTypes(from intent: Intent, elementsSession: STPElementsSession, configuration: IntegrationConfigurable, logAvailability: Bool = false) -> [PaymentMethodType] + static func filteredPaymentMethodTypes(from intent: Intent, elementsSession: STPElementsSession, configuration: PaymentElementConfiguration, logAvailability: Bool = false) -> [PaymentMethodType] { var recommendedStripePaymentMethodTypes = elementsSession.orderedPaymentMethodTypes recommendedStripePaymentMethodTypes = recommendedStripePaymentMethodTypes.filter { paymentMethodType in @@ -245,7 +245,7 @@ extension PaymentSheet { /// - Returns: a `PaymentMethodAvailabilityStatus` detailing why or why not this payment method can be added static func supportsAdding( paymentMethod: STPPaymentMethodType, - configuration: IntegrationConfigurable, + configuration: PaymentElementConfiguration, intent: Intent, elementsSession: STPElementsSession, supportedPaymentMethods: [STPPaymentMethodType] = PaymentSheet.supportedPaymentMethods @@ -344,7 +344,7 @@ extension PaymentSheet { /// - Returns: a `PaymentMethodAvailabilityStatus` detailing why or why not this payment method can be added static func configurationSatisfiesRequirements( requirements: [PaymentMethodTypeRequirement], - configuration: IntegrationConfigurable, + configuration: PaymentElementConfiguration, intent: Intent ) -> PaymentMethodAvailabilityStatus { let fulfilledRequirements = [configuration, intent].reduce([]) { @@ -373,7 +373,7 @@ extension PaymentSheet { static func configurationSupports( paymentMethod: STPPaymentMethodType, requirements: [PaymentMethodTypeRequirement], - configuration: IntegrationConfigurable, + configuration: PaymentElementConfiguration, intent: Intent, elementsSession: STPElementsSession, supportedPaymentMethods: [STPPaymentMethodType] @@ -414,7 +414,7 @@ extension STPPaymentMethod { /// Returns whether or not saved PaymentMethods of this type should be displayed as an option to customers /// This should only return true if saved PMs of this type can be successfully used to `/confirm` the given `intent` /// - Warning: This doesn't quite work as advertised. We've hardcoded `PaymentSheet+API.swift` to only fetch saved cards and us bank accounts. - func supportsSavedPaymentMethod(configuration: IntegrationConfigurable, intent: Intent, elementsSession: STPElementsSession) -> Bool { + func supportsSavedPaymentMethod(configuration: PaymentElementConfiguration, intent: Intent, elementsSession: STPElementsSession) -> Bool { let requirements: [PaymentMethodTypeRequirement] = { switch type { case .card: diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheet+PaymentMethodAvailability.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheet+PaymentMethodAvailability.swift index c8cd207f73f..55cdcbf7f0c 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheet+PaymentMethodAvailability.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheet+PaymentMethodAvailability.swift @@ -42,14 +42,14 @@ extension PaymentSheet { ] /// Canonical source of truth for whether Apple Pay is enabled - static func isApplePayEnabled(elementsSession: STPElementsSession, configuration: IntegrationConfigurable) -> Bool { + static func isApplePayEnabled(elementsSession: STPElementsSession, configuration: PaymentElementConfiguration) -> Bool { return StripeAPI.deviceSupportsApplePay() && configuration.applePay != nil && elementsSession.isApplePayEnabled } /// Canonical source of truth for whether Link is enabled - static func isLinkEnabled(elementsSession: STPElementsSession, configuration: IntegrationConfigurable) -> Bool { + static func isLinkEnabled(elementsSession: STPElementsSession, configuration: PaymentElementConfiguration) -> Bool { guard elementsSession.supportsLink else { return false } diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetLoader.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetLoader.swift index 44dd92644f1..6b3ff64520e 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetLoader.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetLoader.swift @@ -45,7 +45,7 @@ final class PaymentSheetLoader { /// Fetches the PaymentIntent or SetupIntent and Customer's saved PaymentMethods static func load( mode: PaymentSheet.InitializationMode, - configuration: IntegrationConfigurable, + configuration: PaymentElementConfiguration, analyticsHelper: PaymentSheetAnalyticsHelper, integrationShape: IntegrationShape, completion: @escaping (Result) -> Void @@ -143,7 +143,7 @@ final class PaymentSheetLoader { public static func load( mode: PaymentSheet.InitializationMode, - configuration: IntegrationConfigurable, + configuration: PaymentElementConfiguration, analyticsHelper: PaymentSheetAnalyticsHelper, integrationShape: IntegrationShape ) async throws -> LoadResult { @@ -183,7 +183,7 @@ final class PaymentSheetLoader { } } - static func lookupLinkAccount(elementsSession: STPElementsSession, configuration: IntegrationConfigurable) async throws -> PaymentSheetLinkAccount? { + static func lookupLinkAccount(elementsSession: STPElementsSession, configuration: PaymentElementConfiguration) async throws -> PaymentSheetLinkAccount? { // Only lookup the consumer account if Link is supported guard PaymentSheet.isLinkEnabled(elementsSession: elementsSession, configuration: configuration) else { return nil @@ -217,7 +217,7 @@ final class PaymentSheetLoader { } typealias ElementSessionAndIntent = (elementsSession: STPElementsSession, intent: Intent) - static func fetchElementsSessionAndIntent(mode: PaymentSheet.InitializationMode, configuration: IntegrationConfigurable, analyticsHelper: PaymentSheetAnalyticsHelper) async throws -> ElementSessionAndIntent { + static func fetchElementsSessionAndIntent(mode: PaymentSheet.InitializationMode, configuration: PaymentElementConfiguration, analyticsHelper: PaymentSheetAnalyticsHelper) async throws -> ElementSessionAndIntent { let intent: Intent let elementsSession: STPElementsSession let clientDefaultPaymentMethod = defaultStripePaymentMethodId(forCustomerID: configuration.customer?.id) @@ -298,7 +298,7 @@ final class PaymentSheetLoader { } static let savedPaymentMethodTypes: [STPPaymentMethodType] = [.card, .USBankAccount, .SEPADebit] - static func fetchSavedPaymentMethods(elementsSession: STPElementsSession, configuration: IntegrationConfigurable) async throws -> [STPPaymentMethod] { + static func fetchSavedPaymentMethods(elementsSession: STPElementsSession, configuration: PaymentElementConfiguration) async throws -> [STPPaymentMethod] { // Retrieve the payment methods from ElementsSession or by making direct API calls var savedPaymentMethods: [STPPaymentMethod] if let elementsSessionPaymentMethods = elementsSession.customer?.paymentMethods { @@ -321,7 +321,7 @@ final class PaymentSheetLoader { return savedPaymentMethods } - static func fetchSavedPaymentMethodsUsingApiClient(configuration: IntegrationConfigurable) async throws -> [STPPaymentMethod] { + static func fetchSavedPaymentMethodsUsingApiClient(configuration: PaymentElementConfiguration) async throws -> [STPPaymentMethod] { guard let customerID = configuration.customer?.id, let ephemeralKey = configuration.customer?.ephemeralKeySecret, !ephemeralKey.isEmpty else { From d86a5e1f9be6fb114db1fbefbce819db6896ebae Mon Sep 17 00:00:00 2001 From: Nick Porter Date: Wed, 2 Oct 2024 15:06:16 -0600 Subject: [PATCH 7/7] lint --- .../ExampleEmbeddedElementCheckoutViewController.swift | 2 +- .../Source/PaymentSheet/PaymentElementConfiguration.swift | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Example/PaymentSheet Example/PaymentSheet Example/ExampleEmbeddedElementCheckoutViewController.swift b/Example/PaymentSheet Example/PaymentSheet Example/ExampleEmbeddedElementCheckoutViewController.swift index 6e4e5eb2b51..ab37bb43f78 100644 --- a/Example/PaymentSheet Example/PaymentSheet Example/ExampleEmbeddedElementCheckoutViewController.swift +++ b/Example/PaymentSheet Example/PaymentSheet Example/ExampleEmbeddedElementCheckoutViewController.swift @@ -227,7 +227,7 @@ class ExampleEmbeddedElementCheckoutViewController: UIViewController { "salad_count": saladStepper.value, "is_subscribing": subscribeSwitch.isOn, ] - + do { request.httpBody = try JSONSerialization.data(withJSONObject: body, options: []) weak var weakSelf = self diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentElementConfiguration.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentElementConfiguration.swift index 4ede6b9b50d..b8a6331d042 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentElementConfiguration.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentElementConfiguration.swift @@ -6,8 +6,8 @@ // import Foundation -import UIKit @_spi(STP) import StripePayments +import UIKit /// Represents shared configuration properties between integration surfaces in mobile payment element. /// - Note: See the concrete implementations of `PaymentElementConfiguration` for detailed doc comments. @@ -37,7 +37,7 @@ protocol PaymentElementConfiguration: PaymentMethodRequirementProvider { } extension PaymentElementConfiguration { - + /// Returns `true` if the merchant requires the collection of _any_ billing detail fields - name, phone, email, address. func requiresBillingDetailCollection() -> Bool { return billingDetailsCollectionConfiguration.name == .always @@ -45,7 +45,7 @@ extension PaymentElementConfiguration { || billingDetailsCollectionConfiguration.email == .always || billingDetailsCollectionConfiguration.address == .full } - + var fulfilledRequirements: [PaymentMethodTypeRequirement] { var reqs = [PaymentMethodTypeRequirement]() if returnURL != nil { reqs.append(.returnURL) }