From 61b222a36ca0e9d897620e1e10f73f58d5e144a5 Mon Sep 17 00:00:00 2001 From: "Georgi Malkhasyan (CW)" Date: Tue, 3 Dec 2024 12:49:18 -0800 Subject: [PATCH 01/22] [DTPP-142] PayPalWebPayments show stages of order --- .../CardPaymentState.swift | 47 +++++++ .../PayPalWebButtonsView.swift | 2 +- .../PayPalWebCreateOrderView.swift | 5 +- .../PayPalWebPaymentsView.swift | 2 +- .../PayPalWebResultView.swift | 27 ++-- .../PayPalWebTransactionView.swift | 2 +- .../PayPalWebViewModel.swift | 117 +++++++++++++----- 7 files changed, 149 insertions(+), 53 deletions(-) diff --git a/Demo/Demo/CardPayments/CardPaymentViewModel/CardPaymentState.swift b/Demo/Demo/CardPayments/CardPaymentViewModel/CardPaymentState.swift index 135cb4624..99140916a 100644 --- a/Demo/Demo/CardPayments/CardPaymentViewModel/CardPaymentState.swift +++ b/Demo/Demo/CardPayments/CardPaymentViewModel/CardPaymentState.swift @@ -49,3 +49,50 @@ struct CardPaymentState: Equatable { } } } + +struct PayPalPaymentState: Equatable { + + struct ApprovalResult: Decodable, Equatable { + let id: String + let status: String? + + } + var createOrder: Order? + var authorizedOrder: Order? + var capturedOrder: Order? + var intent: Intent = .authorize + var approveResult: ApprovalResult? + + var createdOrderResponse: LoadingState = .idle { + didSet { + if case .loaded(let value) = createdOrderResponse { + createOrder = value + } + } + } + + var approveResultResponse: LoadingState = .idle { + didSet { + if case .loaded(let value) = approveResultResponse { + + approveResult = value + } + } + } + + var capturedOrderResponse: LoadingState = .idle { + didSet { + if case .loaded(let value) = capturedOrderResponse { + capturedOrder = value + } + } + } + + var authorizedOrderResponse: LoadingState = .idle { + didSet { + if case .loaded(let value) = authorizedOrderResponse { + authorizedOrder = value + } + } + } +} diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebButtonsView.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebButtonsView.swift index 03ad1a02b..32640604f 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebButtonsView.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebButtonsView.swift @@ -39,7 +39,7 @@ struct PayPalWebButtonsView: View { payPalWebViewModel.paymentButtonTapped(funding: .paypal) } } - if payPalWebViewModel.state == .loading && + if payPalWebViewModel.state.createdOrderResponse == .loading && payPalWebViewModel.checkoutResult == nil && payPalWebViewModel.orderID != nil { CircularProgressView() diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebCreateOrderView.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebCreateOrderView.swift index 4b5adc2dd..e5bffae23 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebCreateOrderView.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebCreateOrderView.swift @@ -40,7 +40,10 @@ struct PayPalWebCreateOrderView: View { } } .buttonStyle(RoundedBlueButtonStyle()) - if payPalWebViewModel.state == .loading && payPalWebViewModel.checkoutResult == nil && payPalWebViewModel.orderID == nil { +// if payPalWebViewModel.state == .loading && payPalWebViewModel.checkoutResult == nil && payPalWebViewModel.orderID == nil { +// CircularProgressView() +// } + if case .loading = payPalWebViewModel.state.createdOrderResponse { CircularProgressView() } } diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebPaymentsView.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebPaymentsView.swift index 3b47ac991..33249f2fb 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebPaymentsView.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebPaymentsView.swift @@ -10,7 +10,7 @@ struct PayPalWebPaymentsView: View { VStack(spacing: 16) { PayPalWebCreateOrderView(payPalWebViewModel: payPalWebViewModel) - if payPalWebViewModel.orderID != nil { + if payPalWebViewModel.state.createOrder?.id != nil { PayPalWebButtonsView(payPalWebViewModel: payPalWebViewModel) } diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebResultView.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebResultView.swift index e1d9f744a..6f9634764 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebResultView.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebResultView.swift @@ -5,44 +5,41 @@ struct PayPalWebResultView: View { @ObservedObject var payPalWebViewModel: PayPalWebViewModel var body: some View { - switch payPalWebViewModel.state { + switch payPalWebViewModel.state.createdOrderResponse { case .idle, .loading: EmptyView() - case .success: - successView + case .loaded(let createOrderResponse): + getSuccessView(createOrderResponse: createOrderResponse) case .error(let errorMessage): ErrorView(errorMessage: errorMessage) } } - var successView: some View { + func getSuccessView(createOrderResponse: Order) -> some View { VStack(alignment: .leading, spacing: 16) { HStack { Text("Order Details") .font(.system(size: 20)) Spacer() } - if let orderID = payPalWebViewModel.orderID { - LabelViewText("Order ID:", bodyText: orderID) - } - - if let status = payPalWebViewModel.order?.status { - LabelViewText("Status:", bodyText: status) - } + + LabelViewText("Order ID:", bodyText: createOrderResponse.id) + + LabelViewText("Status:", bodyText: createOrderResponse.status) if let payerID = payPalWebViewModel.checkoutResult?.payerID { - LabelViewText("Payer ID:", bodyText: payerID) + LabelViewText("Payer ID:", bodyText: createOrderResponse.status) } - if let emailAddress = payPalWebViewModel.order?.paymentSource?.paypal?.emailAddress { + if let emailAddress = createOrderResponse.paymentSource?.paypal?.emailAddress { LabelViewText("Email:", bodyText: emailAddress) } - if let vaultID = payPalWebViewModel.order?.paymentSource?.paypal?.attributes?.vault.id { + if let vaultID = createOrderResponse.paymentSource?.paypal?.attributes?.vault.id { LabelViewText("Payment Token:", bodyText: vaultID) } - if let customerID = payPalWebViewModel.order?.paymentSource?.paypal?.attributes?.vault.customer?.id { + if let customerID = createOrderResponse.paymentSource?.paypal?.attributes?.vault.customer?.id { LabelViewText("Customer ID:", bodyText: customerID) } } diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebTransactionView.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebTransactionView.swift index e8b0a132e..e002962aa 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebTransactionView.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebTransactionView.swift @@ -19,7 +19,7 @@ struct PayPalWebTransactionView: View { .buttonStyle(RoundedBlueButtonStyle()) .padding() - if payPalWebViewModel.state == .loading { + if payPalWebViewModel.state.capturedOrderResponse == .loading { CircularProgressView() } } diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift index 0381d4338..be557399e 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift @@ -5,7 +5,7 @@ import FraudProtection class PayPalWebViewModel: ObservableObject { - @Published var state: CurrentState = .idle + @Published var state = PayPalPaymentState() @Published var intent: Intent = .authorize @Published var order: Order? @Published var checkoutResult: PayPalWebCheckoutResult? @@ -44,25 +44,75 @@ class PayPalWebViewModel: ObservableObject { ) do { - updateState(.loading) + DispatchQueue.main.async { + self.state.createdOrderResponse = .loading + } let order = try await DemoMerchantAPI.sharedService.createOrder( orderParams: orderRequestParams, selectedMerchantIntegration: DemoSettings.merchantIntegration ) - - updateOrder(order) - updateState(.success) + DispatchQueue.main.async { + self.state.createdOrderResponse = .loaded(order) + } +// updateOrder(order) +// updateState(.success) print("✅ fetched orderID: \(order.id) with status: \(order.status)") } catch { - updateState(.error(message: error.localizedDescription)) + DispatchQueue.main.async { + self.state.createdOrderResponse = .error(message: error.localizedDescription) + } print("❌ failed to fetch orderID with error: \(error.localizedDescription)") } } + + func captureOrder(orderID: String, selectedMerchantIntegration: MerchantIntegration) async { + do { + self.state.capturedOrderResponse = .loading + let payPalClientMetadataID = payPalDataCollector?.collectDeviceData() + let order = try await DemoMerchantAPI.sharedService.captureOrder( + orderID: orderID, + selectedMerchantIntegration: selectedMerchantIntegration, + payPalClientMetadataID: payPalClientMetadataID + ) + DispatchQueue.main.async { + self.state.capturedOrderResponse = .loaded(order) + } + } catch { + DispatchQueue.main.async { + self.state.capturedOrderResponse = .error(message: error.localizedDescription) + } + print("❌ Failed to capture order: \(error.localizedDescription)") + } + } + + func authorizeOrder(orderID: String, selectedMerchantIntegration: MerchantIntegration) async { + do { + DispatchQueue.main.async { + self.state.authorizedOrderResponse = .loading + } + let payPalClientMetadataID = payPalDataCollector?.collectDeviceData() + let order = try await DemoMerchantAPI.sharedService.authorizeOrder( + orderID: orderID, + selectedMerchantIntegration: selectedMerchantIntegration, + payPalClientMetadataID: payPalClientMetadataID + ) + DispatchQueue.main.async { + self.state.authorizedOrderResponse = .loaded(order) + } + } catch { + DispatchQueue.main.async { + self.state.authorizedOrderResponse = .error(message: error.localizedDescription) + } + print("❌ Failed to authorize order: \(error.localizedDescription)") + } + } func paymentButtonTapped(funding: PayPalWebCheckoutFundingSource) { Task { do { - self.updateState(.loading) + DispatchQueue.main.async { + self.state.createdOrderResponse = .loading + } payPalWebCheckoutClient = try await getPayPalClient() guard let payPalWebCheckoutClient else { print("Error initializing PayPalWebCheckoutClient") @@ -73,22 +123,28 @@ class PayPalWebViewModel: ObservableObject { let payPalRequest = PayPalWebCheckoutRequest(orderID: orderID, fundingSource: funding) payPalWebCheckoutClient.start(request: payPalRequest) { result, error in if let error { - if error == PayPalError.checkoutCanceledError { - print("Canceled") - self.updateState(.idle) - } else { - self.updateState(.error(message: error.localizedDescription)) + DispatchQueue.main.async { + if error == PayPalError.checkoutCanceledError { + print("Canceled") + self.state.createdOrderResponse = .idle + } else { + self.state.createdOrderResponse = .error(message: error.localizedDescription) + } } } else { - self.updateState(.success) - self.checkoutResult = result +// self.updateState(.success) + DispatchQueue.main.async { + self.state.createdOrderResponse = .loaded(Order(id: orderID, status: "COMPLETED")) + self.checkoutResult = result + print("✅ Checkout result: \(String(describing: result))") + } } } } - updateState(.success) +// updateState(.success) } catch { print("Error starting PayPalWebCheckoutClient") - updateState(.error(message: error.localizedDescription)) + self.state.createdOrderResponse = .error(message: error.localizedDescription) } } } @@ -100,7 +156,9 @@ class PayPalWebViewModel: ObservableObject { payPalDataCollector = PayPalDataCollector(config: config) return payPalClient } catch { - updateState(.error(message: error.localizedDescription)) + DispatchQueue.main.async { + self.state.createdOrderResponse = .error(message: error.localizedDescription) + } print("❌ failed to create PayPalWebCheckoutClient with error: \(error.localizedDescription)") return nil } @@ -108,7 +166,7 @@ class PayPalWebViewModel: ObservableObject { func completeTransaction() async throws { do { - updateState(.loading) + self.state.authorizedOrderResponse = .loading let payPalClientMetadataID = payPalDataCollector?.collectDeviceData() if let orderID { @@ -117,30 +175,21 @@ class PayPalWebViewModel: ObservableObject { orderID: orderID, payPalClientMetadataID: payPalClientMetadataID ) - updateOrder(order) - updateState(.success) + DispatchQueue.main.async { + self.state.authorizedOrderResponse = .loaded(order) + } } } catch { - updateState(.error(message: error.localizedDescription)) + DispatchQueue.main.async { + self.state.authorizedOrderResponse = .error(message: error.localizedDescription) + } print("Error with \(intent) order: \(error.localizedDescription)") } } func resetState() { - updateState(.idle) + self.state = PayPalPaymentState() order = nil checkoutResult = nil } - - private func updateOrder(_ order: Order) { - DispatchQueue.main.async { - self.order = order - } - } - - private func updateState(_ state: CurrentState) { - DispatchQueue.main.async { - self.state = state - } - } } From 9381efaa5bad4fb42806901072d0eb583a075429 Mon Sep 17 00:00:00 2001 From: "Georgi Malkhasyan (CW)" Date: Tue, 3 Dec 2024 13:01:05 -0800 Subject: [PATCH 02/22] Refactoring --- .../PayPalWebPaymentsView/PayPalWebCreateOrderView.swift | 3 --- .../PayPalWebPaymentsView/PayPalWebResultView.swift | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebCreateOrderView.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebCreateOrderView.swift index e5bffae23..821cdd6cb 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebCreateOrderView.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebCreateOrderView.swift @@ -40,9 +40,6 @@ struct PayPalWebCreateOrderView: View { } } .buttonStyle(RoundedBlueButtonStyle()) -// if payPalWebViewModel.state == .loading && payPalWebViewModel.checkoutResult == nil && payPalWebViewModel.orderID == nil { -// CircularProgressView() -// } if case .loading = payPalWebViewModel.state.createdOrderResponse { CircularProgressView() } diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebResultView.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebResultView.swift index 6f9634764..578bc1f03 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebResultView.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebResultView.swift @@ -28,7 +28,7 @@ struct PayPalWebResultView: View { LabelViewText("Status:", bodyText: createOrderResponse.status) if let payerID = payPalWebViewModel.checkoutResult?.payerID { - LabelViewText("Payer ID:", bodyText: createOrderResponse.status) + LabelViewText("Payer ID:", bodyText: payerID) } if let emailAddress = createOrderResponse.paymentSource?.paypal?.emailAddress { From d184d26e022f77e08f792dc287beb7edcc345101 Mon Sep 17 00:00:00 2001 From: "Georgi Malkhasyan (CW)" Date: Tue, 3 Dec 2024 13:07:50 -0800 Subject: [PATCH 03/22] cleanup --- .../PayPalWebViewModel/PayPalWebViewModel.swift | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift index be557399e..d1b9cd787 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift @@ -54,8 +54,6 @@ class PayPalWebViewModel: ObservableObject { DispatchQueue.main.async { self.state.createdOrderResponse = .loaded(order) } -// updateOrder(order) -// updateState(.success) print("✅ fetched orderID: \(order.id) with status: \(order.status)") } catch { DispatchQueue.main.async { @@ -132,7 +130,6 @@ class PayPalWebViewModel: ObservableObject { } } } else { -// self.updateState(.success) DispatchQueue.main.async { self.state.createdOrderResponse = .loaded(Order(id: orderID, status: "COMPLETED")) self.checkoutResult = result @@ -141,7 +138,6 @@ class PayPalWebViewModel: ObservableObject { } } } -// updateState(.success) } catch { print("Error starting PayPalWebCheckoutClient") self.state.createdOrderResponse = .error(message: error.localizedDescription) From ce7847737fdf57938d1f4651e871aa3fcc84c978 Mon Sep 17 00:00:00 2001 From: "Georgi Malkhasyan (CW)" Date: Tue, 3 Dec 2024 13:58:00 -0800 Subject: [PATCH 04/22] refactoring --- .../PayPalWebPaymentsView/PayPalWebButtonsView.swift | 2 +- .../PayPalWebViewModel/PayPalWebViewModel.swift | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebButtonsView.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebButtonsView.swift index 32640604f..bac812076 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebButtonsView.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebButtonsView.swift @@ -39,7 +39,7 @@ struct PayPalWebButtonsView: View { payPalWebViewModel.paymentButtonTapped(funding: .paypal) } } - if payPalWebViewModel.state.createdOrderResponse == .loading && + if payPalWebViewModel.state.approveResultResponse == .loading && payPalWebViewModel.checkoutResult == nil && payPalWebViewModel.orderID != nil { CircularProgressView() diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift index d1b9cd787..0a6e64b35 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift @@ -109,7 +109,7 @@ class PayPalWebViewModel: ObservableObject { Task { do { DispatchQueue.main.async { - self.state.createdOrderResponse = .loading + self.state.approveResultResponse = .loading } payPalWebCheckoutClient = try await getPayPalClient() guard let payPalWebCheckoutClient else { @@ -124,9 +124,9 @@ class PayPalWebViewModel: ObservableObject { DispatchQueue.main.async { if error == PayPalError.checkoutCanceledError { print("Canceled") - self.state.createdOrderResponse = .idle + self.state.approveResultResponse = .idle } else { - self.state.createdOrderResponse = .error(message: error.localizedDescription) + self.state.approveResultResponse = .error(message: error.localizedDescription) } } } else { From c3188c3f19f4936141b49b60dd07342fe1c02d24 Mon Sep 17 00:00:00 2001 From: "Georgi Malkhasyan (CW)" Date: Tue, 3 Dec 2024 15:13:39 -0800 Subject: [PATCH 05/22] refactoring --- Demo/Demo.xcodeproj/project.pbxproj | 4 ++ .../CardPaymentState.swift | 47 ------------------ .../PayPalPaymentState.swift | 49 +++++++++++++++++++ .../PayPalWebViewModel.swift | 2 +- 4 files changed, 54 insertions(+), 48 deletions(-) create mode 100644 Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalPaymentState.swift diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index 01e44b68e..972f4befa 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 1001E2C12CFFC72E0023A03C /* PayPalPaymentState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1001E2C02CFFC72E0023A03C /* PayPalPaymentState.swift */; }; 3B20273D2A89E3F00007907E /* CreateSetupTokenView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B20273C2A89E3F00007907E /* CreateSetupTokenView.swift */; }; 3B20273F2A89F24E0007907E /* CardVaultViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B20273E2A89F24E0007907E /* CardVaultViewModel.swift */; }; 3B2027412A8A72050007907E /* VaultState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B2027402A8A72050007907E /* VaultState.swift */; }; @@ -118,6 +119,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 1001E2C02CFFC72E0023A03C /* PayPalPaymentState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalPaymentState.swift; sourceTree = ""; }; 3B20273C2A89E3F00007907E /* CreateSetupTokenView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateSetupTokenView.swift; sourceTree = ""; }; 3B20273E2A89F24E0007907E /* CardVaultViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardVaultViewModel.swift; sourceTree = ""; }; 3B2027402A8A72050007907E /* VaultState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VaultState.swift; sourceTree = ""; }; @@ -267,6 +269,7 @@ isa = PBXGroup; children = ( 3BA56FFB2A9FEFE90081D14F /* PayPalWebViewModel.swift */, + 1001E2C02CFFC72E0023A03C /* PayPalPaymentState.swift */, ); path = PayPalWebViewModel; sourceTree = ""; @@ -657,6 +660,7 @@ 3B2027432A8A95EF0007907E /* SetupTokenResultView.swift in Sources */, 3BF999762A8AC093009CBDF2 /* UpdateSetupTokenResultView.swift in Sources */, BECD84A027036DC2007CCAE4 /* Environment.swift in Sources */, + 1001E2C12CFFC72E0023A03C /* PayPalPaymentState.swift in Sources */, 3BCCFE4B2A9D985F00C5102F /* FeatureSelectionView.swift in Sources */, CB9ED44C283FDA900081F4DE /* PaymentButtonEnums+Extension.swift in Sources */, 3BB60B552B1FA00C00A298CF /* PayPalVaultViewModel.swift in Sources */, diff --git a/Demo/Demo/CardPayments/CardPaymentViewModel/CardPaymentState.swift b/Demo/Demo/CardPayments/CardPaymentViewModel/CardPaymentState.swift index 99140916a..135cb4624 100644 --- a/Demo/Demo/CardPayments/CardPaymentViewModel/CardPaymentState.swift +++ b/Demo/Demo/CardPayments/CardPaymentViewModel/CardPaymentState.swift @@ -49,50 +49,3 @@ struct CardPaymentState: Equatable { } } } - -struct PayPalPaymentState: Equatable { - - struct ApprovalResult: Decodable, Equatable { - let id: String - let status: String? - - } - var createOrder: Order? - var authorizedOrder: Order? - var capturedOrder: Order? - var intent: Intent = .authorize - var approveResult: ApprovalResult? - - var createdOrderResponse: LoadingState = .idle { - didSet { - if case .loaded(let value) = createdOrderResponse { - createOrder = value - } - } - } - - var approveResultResponse: LoadingState = .idle { - didSet { - if case .loaded(let value) = approveResultResponse { - - approveResult = value - } - } - } - - var capturedOrderResponse: LoadingState = .idle { - didSet { - if case .loaded(let value) = capturedOrderResponse { - capturedOrder = value - } - } - } - - var authorizedOrderResponse: LoadingState = .idle { - didSet { - if case .loaded(let value) = authorizedOrderResponse { - authorizedOrder = value - } - } - } -} diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalPaymentState.swift b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalPaymentState.swift new file mode 100644 index 000000000..428f502ad --- /dev/null +++ b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalPaymentState.swift @@ -0,0 +1,49 @@ +import Foundation +import PayPalWebPayments + +struct PayPalPaymentState: Equatable { + + struct ApprovalResult: Decodable, Equatable { + let id: String + let status: String? + + } + var createOrder: Order? + var authorizedOrder: Order? + var capturedOrder: Order? + var intent: Intent = .authorize + var approveResult: ApprovalResult? + + var createdOrderResponse: LoadingState = .idle { + didSet { + if case .loaded(let value) = createdOrderResponse { + createOrder = value + } + } + } + + var approveResultResponse: LoadingState = .idle { + didSet { + if case .loaded(let value) = approveResultResponse { + + approveResult = value + } + } + } + + var capturedOrderResponse: LoadingState = .idle { + didSet { + if case .loaded(let value) = capturedOrderResponse { + capturedOrder = value + } + } + } + + var authorizedOrderResponse: LoadingState = .idle { + didSet { + if case .loaded(let value) = authorizedOrderResponse { + authorizedOrder = value + } + } + } +} diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift index 0a6e64b35..3d99786e3 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift @@ -131,7 +131,7 @@ class PayPalWebViewModel: ObservableObject { } } else { DispatchQueue.main.async { - self.state.createdOrderResponse = .loaded(Order(id: orderID, status: "COMPLETED")) + self.state.approveResultResponse = .loaded(PayPalPaymentState.ApprovalResult(id: orderID, status: "COMPLETED")) self.checkoutResult = result print("✅ Checkout result: \(String(describing: result))") } From d60f6dd9cfa2dacca75218fda68fb18523229a33 Mon Sep 17 00:00:00 2001 From: "Georgi Malkhasyan (CW)" Date: Tue, 3 Dec 2024 17:21:23 -0800 Subject: [PATCH 06/22] Created individual views for each step of order process --- Demo/Demo.xcodeproj/project.pbxproj | 16 +++++++--- .../PayPalApprovalResultView.swift | 30 +++++++++++++++++++ .../PayPalOrderCompletionResultView.swift | 28 +++++++++++++++++ ...wift => PayPalOrderCreateResultView.swift} | 2 +- .../PayPalWebPaymentsView.swift | 25 +++++++++++----- .../PayPalWebViewModel.swift | 2 +- 6 files changed, 89 insertions(+), 14 deletions(-) create mode 100644 Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalApprovalResultView.swift create mode 100644 Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalOrderCompletionResultView.swift rename Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/{PayPalWebResultView.swift => PayPalOrderCreateResultView.swift} (97%) diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index 972f4befa..e7433eeaf 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -8,6 +8,8 @@ /* Begin PBXBuildFile section */ 1001E2C12CFFC72E0023A03C /* PayPalPaymentState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1001E2C02CFFC72E0023A03C /* PayPalPaymentState.swift */; }; + 1001E2C52CFFD2800023A03C /* PayPalApprovalResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1001E2C42CFFD2800023A03C /* PayPalApprovalResultView.swift */; }; + 1001E2C72CFFD2A30023A03C /* PayPalOrderCompletionResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1001E2C62CFFD2A20023A03C /* PayPalOrderCompletionResultView.swift */; }; 3B20273D2A89E3F00007907E /* CreateSetupTokenView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B20273C2A89E3F00007907E /* CreateSetupTokenView.swift */; }; 3B20273F2A89F24E0007907E /* CardVaultViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B20273E2A89F24E0007907E /* CardVaultViewModel.swift */; }; 3B2027412A8A72050007907E /* VaultState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B2027402A8A72050007907E /* VaultState.swift */; }; @@ -68,7 +70,7 @@ BE1766B326F911A2007EF438 /* URLResponseError.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE1766B226F911A2007EF438 /* URLResponseError.swift */; }; BE1766D926FA7BC8007EF438 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = BE1766D826FA7BC8007EF438 /* Settings.bundle */; }; BE5898952B2B91F800AA196E /* LabelViewText.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE5898942B2B91F800AA196E /* LabelViewText.swift */; }; - BE8117642B07E778009867B9 /* PayPalWebResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE8117632B07E778009867B9 /* PayPalWebResultView.swift */; }; + BE8117642B07E778009867B9 /* PayPalOrderCreateResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE8117632B07E778009867B9 /* PayPalOrderCreateResultView.swift */; }; BE8117682B080472009867B9 /* CurrentState.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE8117672B080472009867B9 /* CurrentState.swift */; }; BE9F36D82745490400AFC7DA /* FloatingLabelTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE9F36D72745490400AFC7DA /* FloatingLabelTextField.swift */; }; BECD84A027036DC2007CCAE4 /* Environment.swift in Sources */ = {isa = PBXBuildFile; fileRef = BECD849F27036DC2007CCAE4 /* Environment.swift */; }; @@ -120,6 +122,8 @@ /* Begin PBXFileReference section */ 1001E2C02CFFC72E0023A03C /* PayPalPaymentState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalPaymentState.swift; sourceTree = ""; }; + 1001E2C42CFFD2800023A03C /* PayPalApprovalResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalApprovalResultView.swift; sourceTree = ""; }; + 1001E2C62CFFD2A20023A03C /* PayPalOrderCompletionResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalOrderCompletionResultView.swift; sourceTree = ""; }; 3B20273C2A89E3F00007907E /* CreateSetupTokenView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateSetupTokenView.swift; sourceTree = ""; }; 3B20273E2A89F24E0007907E /* CardVaultViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardVaultViewModel.swift; sourceTree = ""; }; 3B2027402A8A72050007907E /* VaultState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VaultState.swift; sourceTree = ""; }; @@ -188,7 +192,7 @@ BE1766D826FA7BC8007EF438 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = ""; }; BE420F3628189A7A00D8D66A /* PayPalUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = PayPalUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; BE5898942B2B91F800AA196E /* LabelViewText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelViewText.swift; sourceTree = ""; }; - BE8117632B07E778009867B9 /* PayPalWebResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalWebResultView.swift; sourceTree = ""; }; + BE8117632B07E778009867B9 /* PayPalOrderCreateResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalOrderCreateResultView.swift; sourceTree = ""; }; BE8117672B080472009867B9 /* CurrentState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrentState.swift; sourceTree = ""; }; BE9F36D72745490400AFC7DA /* FloatingLabelTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatingLabelTextField.swift; sourceTree = ""; }; BECD849F27036DC2007CCAE4 /* Environment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Environment.swift; sourceTree = ""; }; @@ -359,8 +363,10 @@ 3BA570062AA0DF330081D14F /* PayPalWebButtonsView.swift */, 3BA570022AA053AE0081D14F /* PayPalWebCreateOrderView.swift */, 3BA570002AA052E80081D14F /* PayPalWebPaymentsView.swift */, - BE8117632B07E778009867B9 /* PayPalWebResultView.swift */, 3B6472A62AFAEB3A004745C4 /* PayPalWebTransactionView.swift */, + BE8117632B07E778009867B9 /* PayPalOrderCreateResultView.swift */, + 1001E2C42CFFD2800023A03C /* PayPalApprovalResultView.swift */, + 1001E2C62CFFD2A20023A03C /* PayPalOrderCompletionResultView.swift */, ); path = PayPalWebPaymentsView; sourceTree = ""; @@ -645,7 +651,7 @@ 3B2027412A8A72050007907E /* VaultState.swift in Sources */, 80F33CED26F8E7A9006811B1 /* Order.swift in Sources */, 3B4DD9A02A892A7000F4A716 /* CardVaultView.swift in Sources */, - BE8117642B07E778009867B9 /* PayPalWebResultView.swift in Sources */, + BE8117642B07E778009867B9 /* PayPalOrderCreateResultView.swift in Sources */, 3BA56FF62A9E9AAB0081D14F /* CardOrderActionButton.swift in Sources */, 3BC622092A97198500251B85 /* LeadingText.swift in Sources */, 3B80D5102A291CB100D2EAC4 /* ClientIDResponse.swift in Sources */, @@ -668,10 +674,12 @@ 3B80D50E2A291C0800D2EAC4 /* ClientIDRequest.swift in Sources */, 3BA56FF02A9DCCFD0081D14F /* CardOrderApproveView.swift in Sources */, BE8117682B080472009867B9 /* CurrentState.swift in Sources */, + 1001E2C72CFFD2A30023A03C /* PayPalOrderCompletionResultView.swift in Sources */, 3BDB348E2A7CB02C008100D7 /* CreateSetupTokenParam.swift in Sources */, 3BA0A58B2B1E240300330681 /* VaultViewModel.swift in Sources */, 80F33CF326F8EA50006811B1 /* DemoSettings.swift in Sources */, 3BA56FE72A9DC9D70081D14F /* CardPaymentViewModel.swift in Sources */, + 1001E2C52CFFD2800023A03C /* PayPalApprovalResultView.swift in Sources */, 3BA5700B2AA13C1C0081D14F /* CoreConfigManager.swift in Sources */, 80F33CE826F8DE29006811B1 /* DemoMerchantAPI.swift in Sources */, 80F33CEF26F8E7CC006811B1 /* CreateOrderParams.swift in Sources */, diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalApprovalResultView.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalApprovalResultView.swift new file mode 100644 index 000000000..685e649be --- /dev/null +++ b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalApprovalResultView.swift @@ -0,0 +1,30 @@ +import SwiftUI + +struct PayPalApprovalResultView: View { + @ObservedObject var payPalWebViewModel: PayPalWebViewModel + + var body: some View { + switch payPalWebViewModel.state.approveResultResponse { + case .idle, .loading: + EmptyView() + case .error(let message): + ErrorView(errorMessage: message) + case .loaded(let approvalResult): + getApprovalSuccessView(approvalResult: approvalResult) + } + } + + func getApprovalSuccessView(approvalResult: PayPalPaymentState.ApprovalResult) -> some View { + VStack(spacing: 16) { + Text("Approval Result") + .font(.headline) + LeadingText("Approval ID", weight: .bold) + + LeadingText(approvalResult.id) + if let status = approvalResult.status { + LeadingText("Status", weight: .bold) + LeadingText(status) + } + } + } +} diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalOrderCompletionResultView.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalOrderCompletionResultView.swift new file mode 100644 index 000000000..baeab0775 --- /dev/null +++ b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalOrderCompletionResultView.swift @@ -0,0 +1,28 @@ +import SwiftUI + +struct PayPalOrderCompletionResultView: View { + @ObservedObject var payPalWebViewModel: PayPalWebViewModel + + var body: some View { + VStack { + if case .loaded(let authorizedOrder) = payPalWebViewModel.state.authorizedOrderResponse { + getCompletionSuccessView(order: authorizedOrder, intent: "Authorized") + } + if case .loaded(let capturedOrder) = payPalWebViewModel.state.capturedOrderResponse { + getCompletionSuccessView(order: capturedOrder, intent: "Captured") + } + } + } + + func getCompletionSuccessView(order: Order, intent: String) -> some View { + VStack(spacing: 16) { + Text("Order \(intent) Successfully") + .font(.headline) + + LeadingText("Order ID", weight: .bold) + LeadingText(order.id) + LeadingText("Status", weight: .bold) + LeadingText(order.status) + } + } +} diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebResultView.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalOrderCreateResultView.swift similarity index 97% rename from Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebResultView.swift rename to Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalOrderCreateResultView.swift index 578bc1f03..a9e693fb6 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebResultView.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalOrderCreateResultView.swift @@ -1,6 +1,6 @@ import SwiftUI -struct PayPalWebResultView: View { +struct PayPalOrderCreateResultView: View { @ObservedObject var payPalWebViewModel: PayPalWebViewModel diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebPaymentsView.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebPaymentsView.swift index 33249f2fb..fd06336c5 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebPaymentsView.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebPaymentsView.swift @@ -1,22 +1,25 @@ import SwiftUI struct PayPalWebPaymentsView: View { - + @StateObject var payPalWebViewModel = PayPalWebViewModel() - + var body: some View { ScrollView { ScrollViewReader { scrollView in VStack(spacing: 16) { + PayPalWebCreateOrderView(payPalWebViewModel: payPalWebViewModel) - - if payPalWebViewModel.state.createOrder?.id != nil { + + if case .loaded(let order) = payPalWebViewModel.state.createdOrderResponse { + PayPalOrderCreateResultView(payPalWebViewModel: payPalWebViewModel) + PayPalWebButtonsView(payPalWebViewModel: payPalWebViewModel) } - - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel) - - if payPalWebViewModel.checkoutResult != nil { + + if case .loaded = payPalWebViewModel.state.approveResultResponse { + PayPalApprovalResultView(payPalWebViewModel: payPalWebViewModel) + PayPalWebTransactionView(payPalWebViewModel: payPalWebViewModel) .padding(.bottom, 20) .id("bottomView") @@ -26,6 +29,12 @@ struct PayPalWebPaymentsView: View { } } } + + if case .loaded = payPalWebViewModel.state.capturedOrderResponse { + PayPalOrderCompletionResultView(payPalWebViewModel: payPalWebViewModel) + } else if case .loaded = payPalWebViewModel.state.authorizedOrderResponse { + PayPalOrderCreateResultView(payPalWebViewModel: payPalWebViewModel) + } } .onChange(of: payPalWebViewModel.state) { _ in withAnimation { diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift index 3d99786e3..c4042cd8b 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift @@ -117,7 +117,7 @@ class PayPalWebViewModel: ObservableObject { return } - if let orderID { + if let orderID = state.createOrder?.id { let payPalRequest = PayPalWebCheckoutRequest(orderID: orderID, fundingSource: funding) payPalWebCheckoutClient.start(request: payPalRequest) { result, error in if let error { From 34095091e73882cb9d0ba3b15dd67a907a13a64a Mon Sep 17 00:00:00 2001 From: "Georgi Malkhasyan (CW)" Date: Wed, 4 Dec 2024 10:10:11 -0800 Subject: [PATCH 07/22] refactoring --- .../PayPalWebPaymentsView/PayPalWebPaymentsView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebPaymentsView.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebPaymentsView.swift index fd06336c5..bfc276739 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebPaymentsView.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebPaymentsView.swift @@ -33,7 +33,7 @@ struct PayPalWebPaymentsView: View { if case .loaded = payPalWebViewModel.state.capturedOrderResponse { PayPalOrderCompletionResultView(payPalWebViewModel: payPalWebViewModel) } else if case .loaded = payPalWebViewModel.state.authorizedOrderResponse { - PayPalOrderCreateResultView(payPalWebViewModel: payPalWebViewModel) + PayPalOrderCompletionResultView(payPalWebViewModel: payPalWebViewModel) } } .onChange(of: payPalWebViewModel.state) { _ in From 6b00a1530a140f7388e93efcf0daa6bbf202a721 Mon Sep 17 00:00:00 2001 From: "Georgi Malkhasyan (CW)" Date: Wed, 4 Dec 2024 13:09:42 -0800 Subject: [PATCH 08/22] update the state in the main traid --- .../PayPalWebViewModel/PayPalWebViewModel.swift | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift index c4042cd8b..64ca48efd 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift @@ -65,7 +65,9 @@ class PayPalWebViewModel: ObservableObject { func captureOrder(orderID: String, selectedMerchantIntegration: MerchantIntegration) async { do { - self.state.capturedOrderResponse = .loading + DispatchQueue.main.async { + self.state.capturedOrderResponse = .loading + } let payPalClientMetadataID = payPalDataCollector?.collectDeviceData() let order = try await DemoMerchantAPI.sharedService.captureOrder( orderID: orderID, @@ -162,8 +164,9 @@ class PayPalWebViewModel: ObservableObject { func completeTransaction() async throws { do { - self.state.authorizedOrderResponse = .loading - + DispatchQueue.main.async { + self.state.authorizedOrderResponse = .loading + } let payPalClientMetadataID = payPalDataCollector?.collectDeviceData() if let orderID { let order = try await DemoMerchantAPI.sharedService.completeOrder( From 1aaa2ad0472fe308576721068b49c5f3469c1f59 Mon Sep 17 00:00:00 2001 From: "Georgi Malkhasyan (CW)" Date: Wed, 4 Dec 2024 13:48:17 -0800 Subject: [PATCH 09/22] refactoring --- .../PayPalWebViewModel/PayPalPaymentState.swift | 1 - .../PayPalWebViewModel/PayPalWebViewModel.swift | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalPaymentState.swift b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalPaymentState.swift index 428f502ad..6174c8457 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalPaymentState.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalPaymentState.swift @@ -25,7 +25,6 @@ struct PayPalPaymentState: Equatable { var approveResultResponse: LoadingState = .idle { didSet { if case .loaded(let value) = approveResultResponse { - approveResult = value } } diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift index 64ca48efd..34f79e9a5 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift @@ -167,8 +167,8 @@ class PayPalWebViewModel: ObservableObject { DispatchQueue.main.async { self.state.authorizedOrderResponse = .loading } - let payPalClientMetadataID = payPalDataCollector?.collectDeviceData() - if let orderID { + if let orderID = state.createOrder?.id, !orderID.isEmpty { + let payPalClientMetadataID = payPalDataCollector?.collectDeviceData() let order = try await DemoMerchantAPI.sharedService.completeOrder( intent: intent, orderID: orderID, From 1f13d48164a8d5d03ff37dd230ca6e9615246742 Mon Sep 17 00:00:00 2001 From: "Georgi Malkhasyan (CW)" Date: Wed, 4 Dec 2024 15:09:50 -0800 Subject: [PATCH 10/22] checking intent (authorize || capture) --- .../PayPalWebPaymentsView.swift | 2 +- .../PayPalWebTransactionView.swift | 2 +- .../PayPalWebViewModel.swift | 47 +++++++++++++++---- 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebPaymentsView.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebPaymentsView.swift index bfc276739..4c3f3677a 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebPaymentsView.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebPaymentsView.swift @@ -11,7 +11,7 @@ struct PayPalWebPaymentsView: View { PayPalWebCreateOrderView(payPalWebViewModel: payPalWebViewModel) - if case .loaded(let order) = payPalWebViewModel.state.createdOrderResponse { + if case .loaded(_) = payPalWebViewModel.state.createdOrderResponse { PayPalOrderCreateResultView(payPalWebViewModel: payPalWebViewModel) PayPalWebButtonsView(payPalWebViewModel: payPalWebViewModel) diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebTransactionView.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebTransactionView.swift index e002962aa..8c50f9f6a 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebTransactionView.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebTransactionView.swift @@ -19,7 +19,7 @@ struct PayPalWebTransactionView: View { .buttonStyle(RoundedBlueButtonStyle()) .padding() - if payPalWebViewModel.state.capturedOrderResponse == .loading { + if payPalWebViewModel.state.capturedOrderResponse == .loading || payPalWebViewModel.state.authorizedOrderResponse == .loading { CircularProgressView() } } diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift index 34f79e9a5..6cc4ee770 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift @@ -164,27 +164,54 @@ class PayPalWebViewModel: ObservableObject { func completeTransaction() async throws { do { - DispatchQueue.main.async { - self.state.authorizedOrderResponse = .loading - } - if let orderID = state.createOrder?.id, !orderID.isEmpty { + setLoadingState() + if let orderID = state.createOrder?.id { let payPalClientMetadataID = payPalDataCollector?.collectDeviceData() let order = try await DemoMerchantAPI.sharedService.completeOrder( intent: intent, orderID: orderID, payPalClientMetadataID: payPalClientMetadataID ) - DispatchQueue.main.async { - self.state.authorizedOrderResponse = .loaded(order) - } + setLoadingState(order: order) } } catch { - DispatchQueue.main.async { - self.state.authorizedOrderResponse = .error(message: error.localizedDescription) - } + setErrorState(message: error.localizedDescription) print("Error with \(intent) order: \(error.localizedDescription)") } } + + private func setLoadingState() { + DispatchQueue.main.async { + switch self.intent { + case .authorize: + self.state.authorizedOrderResponse = .loading + case .capture: + self.state.capturedOrderResponse = .loading + } + } + } + + private func setLoadingState(order: Order) { + DispatchQueue.main.async { + switch self.intent { + case .authorize: + self.state.authorizedOrderResponse = .loaded(order) + case .capture: + self.state.capturedOrderResponse = .loaded(order) + } + } + } + + private func setErrorState(message: String) { + DispatchQueue.main.async { + switch self.intent { + case .authorize: + self.state.authorizedOrderResponse = .error(message: message) + case .capture: + self.state.capturedOrderResponse = .error(message: message) + } + } + } func resetState() { self.state = PayPalPaymentState() From aaf4ef6c43f9020be213394f0edddefa07e72a01 Mon Sep 17 00:00:00 2001 From: "Georgi Malkhasyan (CW)" Date: Wed, 4 Dec 2024 18:22:31 -0800 Subject: [PATCH 11/22] refactoring --- Demo/Demo.xcodeproj/project.pbxproj | 4 ++ .../PayPalApprovalResultView.swift | 12 ++++- .../PayPalOrderCompletionResultView.swift | 11 ++++- .../PayPalWebOrderActionButton.swift | 45 +++++++++++++++++++ .../PayPalWebViewModel.swift | 5 ++- 5 files changed, 71 insertions(+), 6 deletions(-) create mode 100644 Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebOrderActionButton.swift diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index e7433eeaf..1b9204f51 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 1001E2C12CFFC72E0023A03C /* PayPalPaymentState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1001E2C02CFFC72E0023A03C /* PayPalPaymentState.swift */; }; 1001E2C52CFFD2800023A03C /* PayPalApprovalResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1001E2C42CFFD2800023A03C /* PayPalApprovalResultView.swift */; }; 1001E2C72CFFD2A30023A03C /* PayPalOrderCompletionResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1001E2C62CFFD2A20023A03C /* PayPalOrderCompletionResultView.swift */; }; + 1001E2C92D01456B0023A03C /* PayPalWebOrderActionButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1001E2C82D01456B0023A03C /* PayPalWebOrderActionButton.swift */; }; 3B20273D2A89E3F00007907E /* CreateSetupTokenView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B20273C2A89E3F00007907E /* CreateSetupTokenView.swift */; }; 3B20273F2A89F24E0007907E /* CardVaultViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B20273E2A89F24E0007907E /* CardVaultViewModel.swift */; }; 3B2027412A8A72050007907E /* VaultState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B2027402A8A72050007907E /* VaultState.swift */; }; @@ -124,6 +125,7 @@ 1001E2C02CFFC72E0023A03C /* PayPalPaymentState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalPaymentState.swift; sourceTree = ""; }; 1001E2C42CFFD2800023A03C /* PayPalApprovalResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalApprovalResultView.swift; sourceTree = ""; }; 1001E2C62CFFD2A20023A03C /* PayPalOrderCompletionResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalOrderCompletionResultView.swift; sourceTree = ""; }; + 1001E2C82D01456B0023A03C /* PayPalWebOrderActionButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalWebOrderActionButton.swift; sourceTree = ""; }; 3B20273C2A89E3F00007907E /* CreateSetupTokenView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateSetupTokenView.swift; sourceTree = ""; }; 3B20273E2A89F24E0007907E /* CardVaultViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardVaultViewModel.swift; sourceTree = ""; }; 3B2027402A8A72050007907E /* VaultState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VaultState.swift; sourceTree = ""; }; @@ -366,6 +368,7 @@ 3B6472A62AFAEB3A004745C4 /* PayPalWebTransactionView.swift */, BE8117632B07E778009867B9 /* PayPalOrderCreateResultView.swift */, 1001E2C42CFFD2800023A03C /* PayPalApprovalResultView.swift */, + 1001E2C82D01456B0023A03C /* PayPalWebOrderActionButton.swift */, 1001E2C62CFFD2A20023A03C /* PayPalOrderCompletionResultView.swift */, ); path = PayPalWebPaymentsView; @@ -654,6 +657,7 @@ BE8117642B07E778009867B9 /* PayPalOrderCreateResultView.swift in Sources */, 3BA56FF62A9E9AAB0081D14F /* CardOrderActionButton.swift in Sources */, 3BC622092A97198500251B85 /* LeadingText.swift in Sources */, + 1001E2C92D01456B0023A03C /* PayPalWebOrderActionButton.swift in Sources */, 3B80D5102A291CB100D2EAC4 /* ClientIDResponse.swift in Sources */, 3BCCFE462A9D47AC00C5102F /* CardExtensions.swift in Sources */, BE5898952B2B91F800AA196E /* LabelViewText.swift in Sources */, diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalApprovalResultView.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalApprovalResultView.swift index 685e649be..6b84c4d38 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalApprovalResultView.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalApprovalResultView.swift @@ -15,16 +15,24 @@ struct PayPalApprovalResultView: View { } func getApprovalSuccessView(approvalResult: PayPalPaymentState.ApprovalResult) -> some View { - VStack(spacing: 16) { + VStack(alignment: .leading, spacing: 16) { Text("Approval Result") .font(.headline) LeadingText("Approval ID", weight: .bold) + .font(.system(size: 20)) LeadingText(approvalResult.id) if let status = approvalResult.status { LeadingText("Status", weight: .bold) LeadingText(status) } - } + } + .frame(maxWidth: .infinity) + .padding() + .background( + RoundedRectangle(cornerRadius: 10) + .stroke(.gray, lineWidth: 2) + .padding(5) + ) } } diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalOrderCompletionResultView.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalOrderCompletionResultView.swift index baeab0775..fd2e15eaf 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalOrderCompletionResultView.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalOrderCompletionResultView.swift @@ -15,14 +15,21 @@ struct PayPalOrderCompletionResultView: View { } func getCompletionSuccessView(order: Order, intent: String) -> some View { - VStack(spacing: 16) { + VStack(alignment: .leading, spacing: 16) { Text("Order \(intent) Successfully") - .font(.headline) + .font(.system(size: 20)) LeadingText("Order ID", weight: .bold) LeadingText(order.id) LeadingText("Status", weight: .bold) LeadingText(order.status) } + .frame(maxWidth: .infinity) + .padding() + .background( + RoundedRectangle(cornerRadius: 10) + .stroke(.gray, lineWidth: 2) + .padding(5) + ) } } diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebOrderActionButton.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebOrderActionButton.swift new file mode 100644 index 000000000..d82547cfa --- /dev/null +++ b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebOrderActionButton.swift @@ -0,0 +1,45 @@ +import SwiftUI + +struct PayPalWebOrderActionButton: View { + let intent: Intent + let orderID: String + let selectedMerchantIntegration: MerchantIntegration + + @ObservedObject var payPalWebViewModel: PayPalWebViewModel + + var body: some View { + ZStack { + Button("\(intent.rawValue.capitalized) Order") { + completeOrder() + } + .buttonStyle(RoundedBlueButtonStyle()) + .padding() + if intent == .authorize && payPalWebViewModel.state.authorizedOrderResponse == .loading || + intent == .capture && payPalWebViewModel.state.capturedOrderResponse == .loading { + CircularProgressView() + } + } + } + + private func completeOrder() { + Task { + do { + if intent == .capture { + try await payPalWebViewModel.captureOrder( + orderID: orderID, + selectedMerchantIntegration: selectedMerchantIntegration + ) + print("Order Captured. ID: \(payPalWebViewModel.state.capturedOrder?.id ?? "")") + } else if intent == .authorize { + try await payPalWebViewModel.authorizeOrder( + orderID: orderID, + selectedMerchantIntegration: selectedMerchantIntegration + ) + print("Order Authorized. ID: \(payPalWebViewModel.state.authorizedOrder?.id ?? "")") + } + } catch { + print("Error completing \(intent.rawValue.capitalized) order: \(error.localizedDescription)") + } + } + } +} diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift index 6cc4ee770..5bc668fd9 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift @@ -52,6 +52,7 @@ class PayPalWebViewModel: ObservableObject { selectedMerchantIntegration: DemoSettings.merchantIntegration ) DispatchQueue.main.async { + self.order = order self.state.createdOrderResponse = .loaded(order) } print("✅ fetched orderID: \(order.id) with status: \(order.status)") @@ -63,7 +64,7 @@ class PayPalWebViewModel: ObservableObject { } } - func captureOrder(orderID: String, selectedMerchantIntegration: MerchantIntegration) async { + func captureOrder(orderID: String, selectedMerchantIntegration: MerchantIntegration) async throws { do { DispatchQueue.main.async { self.state.capturedOrderResponse = .loading @@ -85,7 +86,7 @@ class PayPalWebViewModel: ObservableObject { } } - func authorizeOrder(orderID: String, selectedMerchantIntegration: MerchantIntegration) async { + func authorizeOrder(orderID: String, selectedMerchantIntegration: MerchantIntegration) async throws { do { DispatchQueue.main.async { self.state.authorizedOrderResponse = .loading From 625f5c79deeb1d1d5acea2d9f1c803ecb8db2a0e Mon Sep 17 00:00:00 2001 From: "Georgi Malkhasyan (CW)" Date: Wed, 4 Dec 2024 19:29:28 -0800 Subject: [PATCH 12/22] removing PayPalWebOrderActionButton file --- Demo/Demo.xcodeproj/project.pbxproj | 4 -- .../PayPalWebOrderActionButton.swift | 45 ------------------- 2 files changed, 49 deletions(-) delete mode 100644 Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebOrderActionButton.swift diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index 1b9204f51..e7433eeaf 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -10,7 +10,6 @@ 1001E2C12CFFC72E0023A03C /* PayPalPaymentState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1001E2C02CFFC72E0023A03C /* PayPalPaymentState.swift */; }; 1001E2C52CFFD2800023A03C /* PayPalApprovalResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1001E2C42CFFD2800023A03C /* PayPalApprovalResultView.swift */; }; 1001E2C72CFFD2A30023A03C /* PayPalOrderCompletionResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1001E2C62CFFD2A20023A03C /* PayPalOrderCompletionResultView.swift */; }; - 1001E2C92D01456B0023A03C /* PayPalWebOrderActionButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1001E2C82D01456B0023A03C /* PayPalWebOrderActionButton.swift */; }; 3B20273D2A89E3F00007907E /* CreateSetupTokenView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B20273C2A89E3F00007907E /* CreateSetupTokenView.swift */; }; 3B20273F2A89F24E0007907E /* CardVaultViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B20273E2A89F24E0007907E /* CardVaultViewModel.swift */; }; 3B2027412A8A72050007907E /* VaultState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B2027402A8A72050007907E /* VaultState.swift */; }; @@ -125,7 +124,6 @@ 1001E2C02CFFC72E0023A03C /* PayPalPaymentState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalPaymentState.swift; sourceTree = ""; }; 1001E2C42CFFD2800023A03C /* PayPalApprovalResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalApprovalResultView.swift; sourceTree = ""; }; 1001E2C62CFFD2A20023A03C /* PayPalOrderCompletionResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalOrderCompletionResultView.swift; sourceTree = ""; }; - 1001E2C82D01456B0023A03C /* PayPalWebOrderActionButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalWebOrderActionButton.swift; sourceTree = ""; }; 3B20273C2A89E3F00007907E /* CreateSetupTokenView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateSetupTokenView.swift; sourceTree = ""; }; 3B20273E2A89F24E0007907E /* CardVaultViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardVaultViewModel.swift; sourceTree = ""; }; 3B2027402A8A72050007907E /* VaultState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VaultState.swift; sourceTree = ""; }; @@ -368,7 +366,6 @@ 3B6472A62AFAEB3A004745C4 /* PayPalWebTransactionView.swift */, BE8117632B07E778009867B9 /* PayPalOrderCreateResultView.swift */, 1001E2C42CFFD2800023A03C /* PayPalApprovalResultView.swift */, - 1001E2C82D01456B0023A03C /* PayPalWebOrderActionButton.swift */, 1001E2C62CFFD2A20023A03C /* PayPalOrderCompletionResultView.swift */, ); path = PayPalWebPaymentsView; @@ -657,7 +654,6 @@ BE8117642B07E778009867B9 /* PayPalOrderCreateResultView.swift in Sources */, 3BA56FF62A9E9AAB0081D14F /* CardOrderActionButton.swift in Sources */, 3BC622092A97198500251B85 /* LeadingText.swift in Sources */, - 1001E2C92D01456B0023A03C /* PayPalWebOrderActionButton.swift in Sources */, 3B80D5102A291CB100D2EAC4 /* ClientIDResponse.swift in Sources */, 3BCCFE462A9D47AC00C5102F /* CardExtensions.swift in Sources */, BE5898952B2B91F800AA196E /* LabelViewText.swift in Sources */, diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebOrderActionButton.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebOrderActionButton.swift deleted file mode 100644 index d82547cfa..000000000 --- a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebOrderActionButton.swift +++ /dev/null @@ -1,45 +0,0 @@ -import SwiftUI - -struct PayPalWebOrderActionButton: View { - let intent: Intent - let orderID: String - let selectedMerchantIntegration: MerchantIntegration - - @ObservedObject var payPalWebViewModel: PayPalWebViewModel - - var body: some View { - ZStack { - Button("\(intent.rawValue.capitalized) Order") { - completeOrder() - } - .buttonStyle(RoundedBlueButtonStyle()) - .padding() - if intent == .authorize && payPalWebViewModel.state.authorizedOrderResponse == .loading || - intent == .capture && payPalWebViewModel.state.capturedOrderResponse == .loading { - CircularProgressView() - } - } - } - - private func completeOrder() { - Task { - do { - if intent == .capture { - try await payPalWebViewModel.captureOrder( - orderID: orderID, - selectedMerchantIntegration: selectedMerchantIntegration - ) - print("Order Captured. ID: \(payPalWebViewModel.state.capturedOrder?.id ?? "")") - } else if intent == .authorize { - try await payPalWebViewModel.authorizeOrder( - orderID: orderID, - selectedMerchantIntegration: selectedMerchantIntegration - ) - print("Order Authorized. ID: \(payPalWebViewModel.state.authorizedOrder?.id ?? "")") - } - } catch { - print("Error completing \(intent.rawValue.capitalized) order: \(error.localizedDescription)") - } - } - } -} From ba35d43b2d78ffb3849f44061cc38a3341b1d307 Mon Sep 17 00:00:00 2001 From: "Georgi Malkhasyan (CW)" Date: Wed, 4 Dec 2024 23:15:46 -0800 Subject: [PATCH 13/22] intent process --- .../PayPalWebViewModel/PayPalWebViewModel.swift | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift index 5bc668fd9..81ee95032 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift @@ -166,6 +166,9 @@ class PayPalWebViewModel: ObservableObject { func completeTransaction() async throws { do { setLoadingState() + + try await processIntent(orderID: orderID ?? "") + if let orderID = state.createOrder?.id { let payPalClientMetadataID = payPalDataCollector?.collectDeviceData() let order = try await DemoMerchantAPI.sharedService.completeOrder( @@ -181,6 +184,15 @@ class PayPalWebViewModel: ObservableObject { } } + private func processIntent(orderID: String) async throws { + switch intent { + case .authorize: + try await authorizeOrder(orderID: orderID, selectedMerchantIntegration: DemoSettings.merchantIntegration) + case .capture: + try await captureOrder(orderID: orderID, selectedMerchantIntegration: DemoSettings.merchantIntegration) + } + } + private func setLoadingState() { DispatchQueue.main.async { switch self.intent { From 5e2f5aa97d76b58f0749acebc871b9616ef3e49e Mon Sep 17 00:00:00 2001 From: "Georgi Malkhasyan (CW)" Date: Thu, 5 Dec 2024 08:20:36 -0800 Subject: [PATCH 14/22] refactoring --- .../PayPalWebViewModel/PayPalWebViewModel.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift index 81ee95032..f219bb1ab 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift @@ -176,7 +176,7 @@ class PayPalWebViewModel: ObservableObject { orderID: orderID, payPalClientMetadataID: payPalClientMetadataID ) - setLoadingState(order: order) + setOrderCompletionLoadedState(order: order) } } catch { setErrorState(message: error.localizedDescription) @@ -204,7 +204,7 @@ class PayPalWebViewModel: ObservableObject { } } - private func setLoadingState(order: Order) { + private func setOrderCompletionLoadedState(order: Order) { DispatchQueue.main.async { switch self.intent { case .authorize: From 88aeb2ae69b3db4fb69a4abd0310e811782e7458 Mon Sep 17 00:00:00 2001 From: "Georgi Malkhasyan (CW)" Date: Thu, 5 Dec 2024 09:56:42 -0800 Subject: [PATCH 15/22] refactoring --- .../PayPalWebViewModel.swift | 58 +------------------ 1 file changed, 1 insertion(+), 57 deletions(-) diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift index f219bb1ab..fb3c33bfb 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift @@ -63,50 +63,6 @@ class PayPalWebViewModel: ObservableObject { print("❌ failed to fetch orderID with error: \(error.localizedDescription)") } } - - func captureOrder(orderID: String, selectedMerchantIntegration: MerchantIntegration) async throws { - do { - DispatchQueue.main.async { - self.state.capturedOrderResponse = .loading - } - let payPalClientMetadataID = payPalDataCollector?.collectDeviceData() - let order = try await DemoMerchantAPI.sharedService.captureOrder( - orderID: orderID, - selectedMerchantIntegration: selectedMerchantIntegration, - payPalClientMetadataID: payPalClientMetadataID - ) - DispatchQueue.main.async { - self.state.capturedOrderResponse = .loaded(order) - } - } catch { - DispatchQueue.main.async { - self.state.capturedOrderResponse = .error(message: error.localizedDescription) - } - print("❌ Failed to capture order: \(error.localizedDescription)") - } - } - - func authorizeOrder(orderID: String, selectedMerchantIntegration: MerchantIntegration) async throws { - do { - DispatchQueue.main.async { - self.state.authorizedOrderResponse = .loading - } - let payPalClientMetadataID = payPalDataCollector?.collectDeviceData() - let order = try await DemoMerchantAPI.sharedService.authorizeOrder( - orderID: orderID, - selectedMerchantIntegration: selectedMerchantIntegration, - payPalClientMetadataID: payPalClientMetadataID - ) - DispatchQueue.main.async { - self.state.authorizedOrderResponse = .loaded(order) - } - } catch { - DispatchQueue.main.async { - self.state.authorizedOrderResponse = .error(message: error.localizedDescription) - } - print("❌ Failed to authorize order: \(error.localizedDescription)") - } - } func paymentButtonTapped(funding: PayPalWebCheckoutFundingSource) { Task { @@ -134,7 +90,7 @@ class PayPalWebViewModel: ObservableObject { } } else { DispatchQueue.main.async { - self.state.approveResultResponse = .loaded(PayPalPaymentState.ApprovalResult(id: orderID, status: "COMPLETED")) + self.state.approveResultResponse = .loaded(PayPalPaymentState.ApprovalResult(id: orderID, status: "APPROVED")) self.checkoutResult = result print("✅ Checkout result: \(String(describing: result))") } @@ -166,9 +122,6 @@ class PayPalWebViewModel: ObservableObject { func completeTransaction() async throws { do { setLoadingState() - - try await processIntent(orderID: orderID ?? "") - if let orderID = state.createOrder?.id { let payPalClientMetadataID = payPalDataCollector?.collectDeviceData() let order = try await DemoMerchantAPI.sharedService.completeOrder( @@ -184,15 +137,6 @@ class PayPalWebViewModel: ObservableObject { } } - private func processIntent(orderID: String) async throws { - switch intent { - case .authorize: - try await authorizeOrder(orderID: orderID, selectedMerchantIntegration: DemoSettings.merchantIntegration) - case .capture: - try await captureOrder(orderID: orderID, selectedMerchantIntegration: DemoSettings.merchantIntegration) - } - } - private func setLoadingState() { DispatchQueue.main.async { switch self.intent { From 750411223d8f6ff5567088715c0024a81375b9dd Mon Sep 17 00:00:00 2001 From: "Georgi Malkhasyan (CW)" Date: Thu, 5 Dec 2024 10:48:55 -0800 Subject: [PATCH 16/22] Refactoring --- Demo/Demo.xcodeproj/project.pbxproj | 6 ++--- .../PayPalApprovalResultView.swift | 1 + .../PayPalOrderCompletionResultView.swift | 23 +++++++++++++++---- .../PayPalWebPaymentsView.swift | 8 ++----- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index e7433eeaf..b3219e949 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -360,13 +360,13 @@ 3BA56FFF2A9FF6630081D14F /* PayPalWebPaymentsView */ = { isa = PBXGroup; children = ( - 3BA570062AA0DF330081D14F /* PayPalWebButtonsView.swift */, 3BA570022AA053AE0081D14F /* PayPalWebCreateOrderView.swift */, - 3BA570002AA052E80081D14F /* PayPalWebPaymentsView.swift */, - 3B6472A62AFAEB3A004745C4 /* PayPalWebTransactionView.swift */, BE8117632B07E778009867B9 /* PayPalOrderCreateResultView.swift */, + 3BA570062AA0DF330081D14F /* PayPalWebButtonsView.swift */, 1001E2C42CFFD2800023A03C /* PayPalApprovalResultView.swift */, 1001E2C62CFFD2A20023A03C /* PayPalOrderCompletionResultView.swift */, + 3BA570002AA052E80081D14F /* PayPalWebPaymentsView.swift */, + 3B6472A62AFAEB3A004745C4 /* PayPalWebTransactionView.swift */, ); path = PayPalWebPaymentsView; sourceTree = ""; diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalApprovalResultView.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalApprovalResultView.swift index 6b84c4d38..3cf996929 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalApprovalResultView.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalApprovalResultView.swift @@ -1,6 +1,7 @@ import SwiftUI struct PayPalApprovalResultView: View { + @ObservedObject var payPalWebViewModel: PayPalWebViewModel var body: some View { diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalOrderCompletionResultView.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalOrderCompletionResultView.swift index fd2e15eaf..6b693c361 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalOrderCompletionResultView.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalOrderCompletionResultView.swift @@ -19,10 +19,25 @@ struct PayPalOrderCompletionResultView: View { Text("Order \(intent) Successfully") .font(.system(size: 20)) - LeadingText("Order ID", weight: .bold) - LeadingText(order.id) - LeadingText("Status", weight: .bold) - LeadingText(order.status) + LabelViewText("Order ID:", bodyText: order.id) + + LabelViewText("Status:", bodyText: order.status) + + if let payerID = payPalWebViewModel.checkoutResult?.payerID { + LabelViewText("Payer ID:", bodyText: payerID) + } + + if let emailAddress = order.paymentSource?.paypal?.emailAddress { + LabelViewText("Email:", bodyText: emailAddress) + } + + if let vaultID = order.paymentSource?.paypal?.attributes?.vault.id { + LabelViewText("Payment Token:", bodyText: vaultID) + } + + if let customerID = order.paymentSource?.paypal?.attributes?.vault.customer?.id { + LabelViewText("Customer ID:", bodyText: customerID) + } } .frame(maxWidth: .infinity) .padding() diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebPaymentsView.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebPaymentsView.swift index 4c3f3677a..f1714d403 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebPaymentsView.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebPaymentsView.swift @@ -22,12 +22,6 @@ struct PayPalWebPaymentsView: View { PayPalWebTransactionView(payPalWebViewModel: payPalWebViewModel) .padding(.bottom, 20) - .id("bottomView") - .onAppear { - withAnimation { - scrollView.scrollTo("bottomView") - } - } } if case .loaded = payPalWebViewModel.state.capturedOrderResponse { @@ -35,6 +29,8 @@ struct PayPalWebPaymentsView: View { } else if case .loaded = payPalWebViewModel.state.authorizedOrderResponse { PayPalOrderCompletionResultView(payPalWebViewModel: payPalWebViewModel) } + Text("") + .id("bottomView") } .onChange(of: payPalWebViewModel.state) { _ in withAnimation { From f8be52a80c80ff32a7b151fefa09efa258bc064c Mon Sep 17 00:00:00 2001 From: "Georgi Malkhasyan (CW)" Date: Thu, 5 Dec 2024 12:24:17 -0800 Subject: [PATCH 17/22] fixing lint format --- .../PayPalWebPaymentsView/PayPalOrderCompletionResultView.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalOrderCompletionResultView.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalOrderCompletionResultView.swift index 6b693c361..2f1549196 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalOrderCompletionResultView.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalOrderCompletionResultView.swift @@ -1,6 +1,7 @@ import SwiftUI struct PayPalOrderCompletionResultView: View { + @ObservedObject var payPalWebViewModel: PayPalWebViewModel var body: some View { From 6df255898e7c3cc73aa21f03af9dc02013f9758b Mon Sep 17 00:00:00 2001 From: "Georgi Malkhasyan (CW)" Date: Fri, 6 Dec 2024 07:34:06 -0800 Subject: [PATCH 18/22] fixing swift lint --- .../PayPalWebPaymentsView/PayPalWebPaymentsView.swift | 2 +- .../PayPalWebViewModel/PayPalPaymentState.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebPaymentsView.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebPaymentsView.swift index f1714d403..533eefd76 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebPaymentsView.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebPaymentsView.swift @@ -11,7 +11,7 @@ struct PayPalWebPaymentsView: View { PayPalWebCreateOrderView(payPalWebViewModel: payPalWebViewModel) - if case .loaded(_) = payPalWebViewModel.state.createdOrderResponse { + if case .loaded = payPalWebViewModel.state.createdOrderResponse { PayPalOrderCreateResultView(payPalWebViewModel: payPalWebViewModel) PayPalWebButtonsView(payPalWebViewModel: payPalWebViewModel) diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalPaymentState.swift b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalPaymentState.swift index 6174c8457..433cd549c 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalPaymentState.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalPaymentState.swift @@ -6,8 +6,8 @@ struct PayPalPaymentState: Equatable { struct ApprovalResult: Decodable, Equatable { let id: String let status: String? - } + var createOrder: Order? var authorizedOrder: Order? var capturedOrder: Order? From 4fd409bf94cb320300f9554a63e499c77b2cc429 Mon Sep 17 00:00:00 2001 From: "Georgi Malkhasyan (CW)" Date: Fri, 6 Dec 2024 08:02:42 -0800 Subject: [PATCH 19/22] Fixing swiftlint --- .../PayPalWebPaymentsView/PayPalApprovalResultView.swift | 2 +- .../PayPalWebPaymentsView/PayPalWebTransactionView.swift | 3 ++- .../PayPalWebViewModel/PayPalPaymentState.swift | 1 + .../PayPalWebViewModel/PayPalWebViewModel.swift | 8 +++++++- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalApprovalResultView.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalApprovalResultView.swift index 3cf996929..8971283d9 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalApprovalResultView.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalApprovalResultView.swift @@ -27,7 +27,7 @@ struct PayPalApprovalResultView: View { LeadingText("Status", weight: .bold) LeadingText(status) } - } + } .frame(maxWidth: .infinity) .padding() .background( diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebTransactionView.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebTransactionView.swift index 8c50f9f6a..965509ab9 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebTransactionView.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebTransactionView.swift @@ -19,7 +19,8 @@ struct PayPalWebTransactionView: View { .buttonStyle(RoundedBlueButtonStyle()) .padding() - if payPalWebViewModel.state.capturedOrderResponse == .loading || payPalWebViewModel.state.authorizedOrderResponse == .loading { + if payPalWebViewModel.state.capturedOrderResponse == .loading || + payPalWebViewModel.state.authorizedOrderResponse == .loading { CircularProgressView() } } diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalPaymentState.swift b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalPaymentState.swift index 433cd549c..7734ed63a 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalPaymentState.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalPaymentState.swift @@ -4,6 +4,7 @@ import PayPalWebPayments struct PayPalPaymentState: Equatable { struct ApprovalResult: Decodable, Equatable { + let id: String let status: String? } diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift index fb3c33bfb..f655578c0 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift @@ -27,7 +27,13 @@ class PayPalWebViewModel: ObservableObject { if shouldVault { let attributes = Attributes(vault: Vault(storeInVault: "ON_SUCCESS", usageType: "MERCHANT", customerType: "CONSUMER")) // The returnURL is not used in our mobile SDK, but a required field for create order with PayPal payment source. DTPPCPSDK-1492 to track this issue - let paypal = VaultPayPal(attributes: attributes, experienceContext: ExperienceContext(returnURL: "https://example.com/returnUrl", cancelURL: "https://example.com/cancelUrl")) + let paypal = VaultPayPal( + attributes: attributes, + experienceContext: ExperienceContext( + returnURL: "https://example.com/returnUrl", + cancelURL: "https://example.com/cancelUrl" + ) + ) vaultPayPalPaymentSource = VaultPayPalPaymentSource(paypal: paypal) } From 90919c99387a5004fe8b0fc793da28a3d51d69e8 Mon Sep 17 00:00:00 2001 From: "Georgi Malkhasyan (CW)" Date: Fri, 6 Dec 2024 08:14:28 -0800 Subject: [PATCH 20/22] refactoring --- .../PayPalWebViewModel/PayPalWebViewModel.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift index f655578c0..73570fcaf 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift @@ -96,7 +96,9 @@ class PayPalWebViewModel: ObservableObject { } } else { DispatchQueue.main.async { - self.state.approveResultResponse = .loaded(PayPalPaymentState.ApprovalResult(id: orderID, status: "APPROVED")) + self.state.approveResultResponse = .loaded( + PayPalPaymentState.ApprovalResult(id: orderID, status: "APPROVED") + ) self.checkoutResult = result print("✅ Checkout result: \(String(describing: result))") } From 55f4a5e96b92a95ab34fd655cbc69b25dc14900e Mon Sep 17 00:00:00 2001 From: "Georgi Malkhasyan (CW)" Date: Fri, 6 Dec 2024 11:11:13 -0800 Subject: [PATCH 21/22] PayPalWebPayments restructure --- Demo/Demo.xcodeproj/project.pbxproj | 20 +++++++++++++------ .../PayPalApprovalResultView.swift | 0 .../PayPalOrderCompletionResultView.swift | 0 .../PayPalOrderCreateResultView.swift | 0 .../PayPalWebTransactionView.swift | 0 5 files changed, 14 insertions(+), 6 deletions(-) rename Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/{ => PayPalWebResultViews}/PayPalApprovalResultView.swift (100%) rename Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/{ => PayPalWebResultViews}/PayPalOrderCompletionResultView.swift (100%) rename Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/{ => PayPalWebResultViews}/PayPalOrderCreateResultView.swift (100%) rename Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/{ => PayPalWebResultViews}/PayPalWebTransactionView.swift (100%) diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index b3219e949..6b593e4ca 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -321,6 +321,17 @@ path = Vault; sourceTree = ""; }; + 1001E2CB2D03836D0023A03C /* PayPalWebResultViews */ = { + isa = PBXGroup; + children = ( + BE8117632B07E778009867B9 /* PayPalOrderCreateResultView.swift */, + 1001E2C42CFFD2800023A03C /* PayPalApprovalResultView.swift */, + 3B6472A62AFAEB3A004745C4 /* PayPalWebTransactionView.swift */, + 1001E2C62CFFD2A20023A03C /* PayPalOrderCompletionResultView.swift */, + ); + path = PayPalWebResultViews; + sourceTree = ""; + }; 3B2501052B2679F000903EAB /* VaultViews */ = { isa = PBXGroup; children = ( @@ -360,13 +371,10 @@ 3BA56FFF2A9FF6630081D14F /* PayPalWebPaymentsView */ = { isa = PBXGroup; children = ( - 3BA570022AA053AE0081D14F /* PayPalWebCreateOrderView.swift */, - BE8117632B07E778009867B9 /* PayPalOrderCreateResultView.swift */, - 3BA570062AA0DF330081D14F /* PayPalWebButtonsView.swift */, - 1001E2C42CFFD2800023A03C /* PayPalApprovalResultView.swift */, - 1001E2C62CFFD2A20023A03C /* PayPalOrderCompletionResultView.swift */, + 1001E2CB2D03836D0023A03C /* PayPalWebResultViews */, 3BA570002AA052E80081D14F /* PayPalWebPaymentsView.swift */, - 3B6472A62AFAEB3A004745C4 /* PayPalWebTransactionView.swift */, + 3BA570062AA0DF330081D14F /* PayPalWebButtonsView.swift */, + 3BA570022AA053AE0081D14F /* PayPalWebCreateOrderView.swift */, ); path = PayPalWebPaymentsView; sourceTree = ""; diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalApprovalResultView.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebResultViews/PayPalApprovalResultView.swift similarity index 100% rename from Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalApprovalResultView.swift rename to Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebResultViews/PayPalApprovalResultView.swift diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalOrderCompletionResultView.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebResultViews/PayPalOrderCompletionResultView.swift similarity index 100% rename from Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalOrderCompletionResultView.swift rename to Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebResultViews/PayPalOrderCompletionResultView.swift diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalOrderCreateResultView.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebResultViews/PayPalOrderCreateResultView.swift similarity index 100% rename from Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalOrderCreateResultView.swift rename to Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebResultViews/PayPalOrderCreateResultView.swift diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebTransactionView.swift b/Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebResultViews/PayPalWebTransactionView.swift similarity index 100% rename from Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebTransactionView.swift rename to Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebResultViews/PayPalWebTransactionView.swift From 06e4c80cd2189221b4ca00b5803b3cfe478e77ac Mon Sep 17 00:00:00 2001 From: "Georgi Malkhasyan (CW)" Date: Fri, 6 Dec 2024 12:48:58 -0800 Subject: [PATCH 22/22] refactoring --- .../PayPalWebViewModel/PayPalWebViewModel.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift index 73570fcaf..77eeead06 100644 --- a/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift +++ b/Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift @@ -107,7 +107,9 @@ class PayPalWebViewModel: ObservableObject { } } catch { print("Error starting PayPalWebCheckoutClient") - self.state.createdOrderResponse = .error(message: error.localizedDescription) + DispatchQueue.main.async { + self.state.createdOrderResponse = .error(message: error.localizedDescription) + } } } }