From b34ed3fcece87ab78409f91f285e2640175f3af2 Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Fri, 17 Nov 2023 11:14:37 -0600 Subject: [PATCH 01/31] consolidate order states in PayPal Web views --- .../CreateOrderPayPalWebView.swift | 2 +- .../OrderCreatePayPalWebResultView.swift | 2 +- .../PayPalOrderActionButton.swift | 3 +-- .../PayPalWebOrderCompletionResultView.swift | 15 +++-------- .../PayPalWebOrderCompletionView.swift | 2 +- .../PayPalWebViews/PayPalWebView.swift | 2 +- Demo/Demo/ViewModels/PayPalWebState.swift | 26 +++---------------- Demo/Demo/ViewModels/PayPalWebViewModel.swift | 22 ++++++++-------- 8 files changed, 23 insertions(+), 51 deletions(-) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/CreateOrderPayPalWebView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/CreateOrderPayPalWebView.swift index 1286a53ae..2298c1b37 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/CreateOrderPayPalWebView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebViews/CreateOrderPayPalWebView.swift @@ -37,7 +37,7 @@ struct CreateOrderPayPalWebView: View { } } .buttonStyle(RoundedBlueButtonStyle()) - if case .loading = paypalWebViewModel.state.createdOrderResponse { + if case .loading = paypalWebViewModel.state.orderResponse { CircularProgressView() } } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/OrderCreatePayPalWebResultView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/OrderCreatePayPalWebResultView.swift index 609f7b327..41e2932c8 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/OrderCreatePayPalWebResultView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebViews/OrderCreatePayPalWebResultView.swift @@ -5,7 +5,7 @@ struct OrderCreatePayPalWebResultView: View { @ObservedObject var paypalWebViewModel: PayPalWebViewModel var body: some View { - switch paypalWebViewModel.state.createdOrderResponse { + switch paypalWebViewModel.state.orderResponse { case .idle, .loading: EmptyView() case .loaded(let createOrderResponse): diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalOrderActionButton.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalOrderActionButton.swift index 8b27a7e83..4aa38e4dd 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalOrderActionButton.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalOrderActionButton.swift @@ -16,8 +16,7 @@ struct PayPalOrderActionButton: View { .buttonStyle(RoundedBlueButtonStyle()) .padding() - if .loading == paypalWebViewModel.state.authorizedOrderResponse || - .loading == paypalWebViewModel.state.capturedOrderResponse { + if .loading == paypalWebViewModel.state.orderResponse { CircularProgressView() } } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionResultView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionResultView.swift index 86431e208..128dabf6c 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionResultView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionResultView.swift @@ -5,20 +5,11 @@ struct PayPalWebOrderCompletionResultView: View { @ObservedObject var paypalWebViewModel: PayPalWebViewModel var body: some View { - switch paypalWebViewModel.state.authorizedOrderResponse { + switch paypalWebViewModel.state.orderResponse { case .idle, .loading: EmptyView() - case .loaded(let authorizedOrderResponse): - getOrderSuccessView(orderResponse: authorizedOrderResponse, intent: "Authorized") - case .error(let errorMessage): - ErrorView(errorMessage: errorMessage) - } - - switch paypalWebViewModel.state.capturedOrderResponse { - case .idle, .loading: - EmptyView() - case .loaded(let capturedOrderResponse): - getOrderSuccessView(orderResponse: capturedOrderResponse, intent: "Captured") + case .loaded(let orderResponse): + getOrderSuccessView(orderResponse: orderResponse, intent: paypalWebViewModel.state.intent.rawValue) case .error(let errorMessage): ErrorView(errorMessage: errorMessage) } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionView.swift index 609d8d856..47845b886 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionView.swift @@ -20,7 +20,7 @@ struct PayPalWebOrderCompletionView: View { ) } - if state.authorizedOrder != nil || state.capturedOrder != nil { + if state.order != nil { PayPalWebOrderCompletionResultView(paypalWebViewModel: payPalWebViewModel) } Text("") diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebView.swift index c1ae6f2fa..96b06ae0b 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebView.swift @@ -12,7 +12,7 @@ struct PayPalWebView: View { paypalWebViewModel: paypalWebViewModel, selectedMerchantIntegration: DemoSettings.merchantIntegration ) - if let order = paypalWebViewModel.state.createOrder { + if let order = paypalWebViewModel.state.order { OrderCreatePayPalWebResultView(paypalWebViewModel: paypalWebViewModel) NavigationLink { PayPalTransactionView(paypalWebViewModel: paypalWebViewModel, orderID: order.id) diff --git a/Demo/Demo/ViewModels/PayPalWebState.swift b/Demo/Demo/ViewModels/PayPalWebState.swift index 04f94d0b6..4dc31b3c4 100644 --- a/Demo/Demo/ViewModels/PayPalWebState.swift +++ b/Demo/Demo/ViewModels/PayPalWebState.swift @@ -9,16 +9,14 @@ struct PayPalWebState: Equatable { let payerID: String } - var createOrder: Order? + var order: Order? var intent: Intent = .authorize var checkoutResult: CheckoutResult? - var authorizedOrder: Order? - var capturedOrder: Order? - var createdOrderResponse: LoadingState = .idle { + var orderResponse: LoadingState = .idle { didSet { - if case .loaded(let value) = createdOrderResponse { - createOrder = value + if case .loaded(let value) = orderResponse { + order = value } } } @@ -30,20 +28,4 @@ struct PayPalWebState: Equatable { } } } - - 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/ViewModels/PayPalWebViewModel.swift b/Demo/Demo/ViewModels/PayPalWebViewModel.swift index 4019517a1..734c24db6 100644 --- a/Demo/Demo/ViewModels/PayPalWebViewModel.swift +++ b/Demo/Demo/ViewModels/PayPalWebViewModel.swift @@ -23,18 +23,18 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { do { DispatchQueue.main.async { - self.state.createdOrderResponse = .loading + self.state.orderResponse = .loading } let order = try await DemoMerchantAPI.sharedService.createOrder( orderParams: orderRequestParams, selectedMerchantIntegration: selectedMerchantIntegration ) DispatchQueue.main.async { - self.state.createdOrderResponse = .loaded(order) + self.state.orderResponse = .loaded(order) print("✅ fetched orderID: \(order.id) with status: \(order.status)") } } catch { DispatchQueue.main.async { - self.state.createdOrderResponse = .error(message: error.localizedDescription) + self.state.orderResponse = .error(message: error.localizedDescription) print("❌ failed to fetch orderID: \(error)") } } @@ -86,28 +86,28 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { switch intent { case .capture: try await captureOrder(orderID: orderID, selectedMerchantIntegration: selectedMerchantIntegration) - print("Order Captured. ID: \(state.capturedOrder?.id ?? "")") + print("Order Captured. ID: \(state.order?.id ?? "")") case .authorize: try await authorizeOrder(orderID: orderID, selectedMerchantIntegration: selectedMerchantIntegration) - print("Order Authorized. ID: \(state.authorizedOrder?.id ?? "")") + print("Order Authorized. ID: \(state.order?.id ?? "")") } } func captureOrder(orderID: String, selectedMerchantIntegration: MerchantIntegration) async throws { do { DispatchQueue.main.async { - self.state.capturedOrderResponse = .loading + self.state.orderResponse = .loading } let order = try await DemoMerchantAPI.sharedService.captureOrder( orderID: orderID, selectedMerchantIntegration: selectedMerchantIntegration ) DispatchQueue.main.async { - self.state.capturedOrderResponse = .loaded(order) + self.state.orderResponse = .loaded(order) } } catch { DispatchQueue.main.async { - self.state.capturedOrderResponse = .error(message: error.localizedDescription) + self.state.orderResponse = .error(message: error.localizedDescription) } print("Error capturing order: \(error.localizedDescription)") } @@ -116,18 +116,18 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { func authorizeOrder(orderID: String, selectedMerchantIntegration: MerchantIntegration) async throws { do { DispatchQueue.main.async { - self.state.authorizedOrderResponse = .loading + self.state.orderResponse = .loading } let order = try await DemoMerchantAPI.sharedService.authorizeOrder( orderID: orderID, selectedMerchantIntegration: selectedMerchantIntegration ) DispatchQueue.main.async { - self.state.authorizedOrderResponse = .loaded(order) + self.state.orderResponse = .loaded(order) } } catch { DispatchQueue.main.async { - self.state.authorizedOrderResponse = .error(message: error.localizedDescription) + self.state.orderResponse = .error(message: error.localizedDescription) } print("Error authorizing order: \(error.localizedDescription)") } From 32c4b9b79365c6ca98274750942076d7c6617029 Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Fri, 17 Nov 2023 11:43:00 -0600 Subject: [PATCH 02/31] add generic SuccessView --- Demo/Demo.xcodeproj/project.pbxproj | 4 ++ .../PayPalWebOrderCompletionResultView.swift | 31 +-------------- Demo/Demo/SwiftUIComponents/SuccessView.swift | 39 +++++++++++++++++++ 3 files changed, 45 insertions(+), 29 deletions(-) create mode 100644 Demo/Demo/SwiftUIComponents/SuccessView.swift diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index 73a9be1e5..bea557f7a 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -71,6 +71,7 @@ BC9D4D2627C6D1720089E5B1 /* XCUIElement+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC9D4D2527C6D1720089E5B1 /* XCUIElement+Helpers.swift */; }; BE1766B326F911A2007EF438 /* URLResponseError.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE1766B226F911A2007EF438 /* URLResponseError.swift */; }; BE1766D926FA7BC8007EF438 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = BE1766D826FA7BC8007EF438 /* Settings.bundle */; }; + BE8117602B07D755009867B9 /* SuccessView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE81175F2B07D755009867B9 /* SuccessView.swift */; }; BE9F36D82745490400AFC7DA /* FloatingLabelTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE9F36D72745490400AFC7DA /* FloatingLabelTextField.swift */; }; BECD84A027036DC2007CCAE4 /* Environment.swift in Sources */ = {isa = PBXBuildFile; fileRef = BECD849F27036DC2007CCAE4 /* Environment.swift */; }; BECD84A227036DDB007CCAE4 /* Intent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BECD84A127036DDB007CCAE4 /* Intent.swift */; }; @@ -199,6 +200,7 @@ BE1766B226F911A2007EF438 /* URLResponseError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLResponseError.swift; sourceTree = ""; }; 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; }; + BE81175F2B07D755009867B9 /* SuccessView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuccessView.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 = ""; }; BECD84A127036DDB007CCAE4 /* Intent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Intent.swift; sourceTree = ""; }; @@ -460,6 +462,7 @@ CB9ED44D28411B110081F4DE /* SwiftUIPaymentButtonDemo.swift */, 536A5CA72898AA2A005C053D /* SwiftUINativeCheckoutDemo.swift */, 3BCCFE4A2A9D985F00C5102F /* FeatureSelectionView.swift */, + BE81175F2B07D755009867B9 /* SuccessView.swift */, ); path = SwiftUIComponents; sourceTree = ""; @@ -632,6 +635,7 @@ 3B2027452A8AA78B0007907E /* UpdateSetupTokenView.swift in Sources */, 3BA56FF82A9FDB5A0081D14F /* CardPaymentOrderCompletionView.swift in Sources */, 3B8EF4DB2A932DA300A70D0B /* ErrorView.swift in Sources */, + BE8117602B07D755009867B9 /* SuccessView.swift in Sources */, 3B6472A32AFAE5E3004745C4 /* PayPalWebOrderCompletionView.swift in Sources */, 3BF9997A2A8AE12C009CBDF2 /* PaymentTokenResultView.swift in Sources */, 3BA56FFC2A9FEFE90081D14F /* PayPalWebViewModel.swift in Sources */, diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionResultView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionResultView.swift index 128dabf6c..180abac5e 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionResultView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionResultView.swift @@ -8,37 +8,10 @@ struct PayPalWebOrderCompletionResultView: View { switch paypalWebViewModel.state.orderResponse { case .idle, .loading: EmptyView() - case .loaded(let orderResponse): - getOrderSuccessView(orderResponse: orderResponse, intent: paypalWebViewModel.state.intent.rawValue) + case .loaded(let order): + SuccessView(order: order, intent: paypalWebViewModel.state.intent) case .error(let errorMessage): ErrorView(errorMessage: errorMessage) } } - - func getOrderSuccessView(orderResponse: Order, intent: String) -> some View { - VStack(spacing: 16) { - HStack { - Text("Order \(intent)") - .font(.system(size: 20)) - Spacer() - } - LeadingText("Order ID", weight: .bold) - LeadingText("\(orderResponse.id)") - LeadingText("Status", weight: .bold) - LeadingText("\(orderResponse.status)") - if let email = orderResponse.paymentSource?.paypal?.emailAddress { - LeadingText("Email", weight: .bold) - LeadingText("\(email)") - } - Text("") - .id("bottomView") - } - .frame(maxWidth: .infinity) - .padding() - .background( - RoundedRectangle(cornerRadius: 10) - .stroke(.gray, lineWidth: 2) - .padding(5) - ) - } } diff --git a/Demo/Demo/SwiftUIComponents/SuccessView.swift b/Demo/Demo/SwiftUIComponents/SuccessView.swift new file mode 100644 index 000000000..be9577274 --- /dev/null +++ b/Demo/Demo/SwiftUIComponents/SuccessView.swift @@ -0,0 +1,39 @@ +import SwiftUI + +struct SuccessView: View { + + var order: Order + var intent: Intent + + init(order: Order, intent: Intent) { + self.order = order + self.intent = intent + } + + var body: some View { + VStack(spacing: 16) { + HStack { + Text("Order \(intent.rawValue)") + .font(.system(size: 20)) + Spacer() + } + LeadingText("Order ID", weight: .bold) + LeadingText("\(order.id)") + LeadingText("Status", weight: .bold) + LeadingText("\(order.status)") + if let email = order.paymentSource?.paypal?.emailAddress { + LeadingText("Email", weight: .bold) + LeadingText("\(email)") + } + Text("") + .id("bottomView") + } + .frame(maxWidth: .infinity) + .padding() + .background( + RoundedRectangle(cornerRadius: 10) + .stroke(.gray, lineWidth: 2) + .padding(5) + ) + } +} From e327686c14779f4b98ba7c6e0c7b7f298d723513 Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Fri, 17 Nov 2023 12:30:42 -0600 Subject: [PATCH 03/31] WIP - shared result view --- Demo/Demo.xcodeproj/project.pbxproj | 4 ++ Demo/Demo/Models/Order.swift | 8 ++- .../OrderCreatePayPalWebResultView.swift | 25 +------- .../PayPalTransactionView.swift | 5 +- .../PayPalWebApprovalResultView.swift | 29 +-------- .../PayPalWebOrderCompletionView.swift | 2 +- .../PayPalWebViews/PayPalWebResultView.swift | 62 +++++++++++++++++++ Demo/Demo/SwiftUIComponents/SuccessView.swift | 16 +++-- Demo/Demo/ViewModels/PayPalWebState.swift | 15 ----- Demo/Demo/ViewModels/PayPalWebViewModel.swift | 12 ++-- 10 files changed, 99 insertions(+), 79 deletions(-) create mode 100644 Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebResultView.swift diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index bea557f7a..1403671b0 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -72,6 +72,7 @@ BE1766B326F911A2007EF438 /* URLResponseError.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE1766B226F911A2007EF438 /* URLResponseError.swift */; }; BE1766D926FA7BC8007EF438 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = BE1766D826FA7BC8007EF438 /* Settings.bundle */; }; BE8117602B07D755009867B9 /* SuccessView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE81175F2B07D755009867B9 /* SuccessView.swift */; }; + BE8117642B07E778009867B9 /* PayPalWebResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE8117632B07E778009867B9 /* PayPalWebResultView.swift */; }; BE9F36D82745490400AFC7DA /* FloatingLabelTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE9F36D72745490400AFC7DA /* FloatingLabelTextField.swift */; }; BECD84A027036DC2007CCAE4 /* Environment.swift in Sources */ = {isa = PBXBuildFile; fileRef = BECD849F27036DC2007CCAE4 /* Environment.swift */; }; BECD84A227036DDB007CCAE4 /* Intent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BECD84A127036DDB007CCAE4 /* Intent.swift */; }; @@ -201,6 +202,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; }; BE81175F2B07D755009867B9 /* SuccessView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuccessView.swift; sourceTree = ""; }; + BE8117632B07E778009867B9 /* PayPalWebResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalWebResultView.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 = ""; }; BECD84A127036DDB007CCAE4 /* Intent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Intent.swift; sourceTree = ""; }; @@ -286,6 +288,7 @@ 3BA570042AA0BBF10081D14F /* OrderCreatePayPalWebResultView.swift */, 3BA570062AA0DF330081D14F /* PayPalTransactionView.swift */, 3BA570082AA0E8340081D14F /* PayPalWebApprovalResultView.swift */, + BE8117632B07E778009867B9 /* PayPalWebResultView.swift */, ); path = PayPalWebViews; sourceTree = ""; @@ -597,6 +600,7 @@ 3BA570092AA0E8340081D14F /* PayPalWebApprovalResultView.swift in Sources */, 80F33CED26F8E7A9006811B1 /* Order.swift in Sources */, 3B4DD9A02A892A7000F4A716 /* CardVaultView.swift in Sources */, + BE8117642B07E778009867B9 /* PayPalWebResultView.swift in Sources */, 3BA56FF62A9E9AAB0081D14F /* CardOrderActionButton.swift in Sources */, 3BC622092A97198500251B85 /* LeadingText.swift in Sources */, 3B80D5102A291CB100D2EAC4 /* ClientIDResponse.swift in Sources */, diff --git a/Demo/Demo/Models/Order.swift b/Demo/Demo/Models/Order.swift index ff225dbce..75a21627b 100644 --- a/Demo/Demo/Models/Order.swift +++ b/Demo/Demo/Models/Order.swift @@ -2,18 +2,20 @@ struct Order: Codable, Equatable { let id: String let status: String - var paymentSource: PaymentSource? - + let payerID: String? + let paymentSource: PaymentSource? + struct PaymentSource: Codable, Equatable { let card: Card? let paypal: PayPal? } - init(id: String, status: String, paymentSource: PaymentSource? = nil) { + init(id: String, status: String, paymentSource: PaymentSource? = nil, payerID: String? = nil) { self.id = id self.status = status self.paymentSource = paymentSource + self.payerID = payerID } struct Card: Codable, Equatable { diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/OrderCreatePayPalWebResultView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/OrderCreatePayPalWebResultView.swift index 41e2932c8..4b429b6ad 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/OrderCreatePayPalWebResultView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebViews/OrderCreatePayPalWebResultView.swift @@ -8,31 +8,10 @@ struct OrderCreatePayPalWebResultView: View { switch paypalWebViewModel.state.orderResponse { case .idle, .loading: EmptyView() - case .loaded(let createOrderResponse): - getSuccessView(createOrderResponse: createOrderResponse) + case .loaded(let order): + SuccessView(order: order, intent: paypalWebViewModel.state.intent) case .error(let errorMessage): ErrorView(errorMessage: errorMessage) } } - - func getSuccessView(createOrderResponse: Order) -> some View { - VStack(spacing: 16) { - HStack { - Text("Order") - .font(.system(size: 20)) - Spacer() - } - LeadingText("Order ID", weight: .bold) - LeadingText("\(createOrderResponse.id)") - LeadingText("Status", weight: .bold) - LeadingText("\(createOrderResponse.status)") - } - .frame(maxWidth: .infinity) - .padding() - .background( - RoundedRectangle(cornerRadius: 10) - .stroke(.gray, lineWidth: 2) - .padding(5) - ) - } } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalTransactionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalTransactionView.swift index 5bf0c212e..6abacf26d 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalTransactionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalTransactionView.swift @@ -29,8 +29,9 @@ struct PayPalTransactionView: View { .stroke(.gray, lineWidth: 2) .padding(5) ) - PayPalWebApprovalResultView(paypalWebViewModel: paypalWebViewModel) - if paypalWebViewModel.state.checkoutResult != nil { + // TODO: fix force unwrap + PayPalWebResultView(payPalWebViewModel: paypalWebViewModel, status: .approved, order: paypalWebViewModel.state.order!) + if paypalWebViewModel.state.orderResponse != nil { NavigationLink { PayPalWebOrderCompletionView(orderID: orderID, payPalWebViewModel: paypalWebViewModel) } label: { diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebApprovalResultView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebApprovalResultView.swift index 8f692dbbf..b7fe1c788 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebApprovalResultView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebApprovalResultView.swift @@ -5,36 +5,13 @@ struct PayPalWebApprovalResultView: View { @ObservedObject var paypalWebViewModel: PayPalWebViewModel var body: some View { - switch paypalWebViewModel.state.checkoutResultResponse { + switch paypalWebViewModel.state.orderResponse { case .idle, .loading: EmptyView() - case .loaded(let checkoutResponse): - getCheckoutSuccessView(checkoutResult: checkoutResponse) + case .loaded(let order): + PayPalWebResultView(payPalWebViewModel: paypalWebViewModel, status: .approved, order: order) case .error(let errorMessage): ErrorView(errorMessage: errorMessage) } } - - func getCheckoutSuccessView(checkoutResult: PayPalWebState.CheckoutResult) -> some View { - VStack(spacing: 16) { - HStack { - Text("Order Approved") - .font(.system(size: 20)) - Spacer() - } - LeadingText("Intent", weight: .bold) - LeadingText("\(paypalWebViewModel.state.intent)") - LeadingText("Order ID", weight: .bold) - LeadingText("\(checkoutResult.id)") - LeadingText("Payer ID", weight: .bold) - LeadingText("\(checkoutResult.payerID)") - } - .frame(maxWidth: .infinity) - .padding() - .background( - RoundedRectangle(cornerRadius: 10) - .stroke(.gray, lineWidth: 2) - .padding(5) - ) - } } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionView.swift index 47845b886..0089a26a1 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionView.swift @@ -11,7 +11,7 @@ struct PayPalWebOrderCompletionView: View { ScrollViewReader { scrollView in VStack { PayPalWebApprovalResultView(paypalWebViewModel: payPalWebViewModel) - if state.checkoutResult != nil { + if state.orderResponse != nil { PayPalOrderActionButton( intent: state.intent, orderID: orderID, diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebResultView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebResultView.swift new file mode 100644 index 000000000..f75847c86 --- /dev/null +++ b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebResultView.swift @@ -0,0 +1,62 @@ +import SwiftUI + +enum Status { + case started + case approved + case completed +} + +struct PayPalWebResultView: View { + + @ObservedObject var payPalWebViewModel: PayPalWebViewModel + + var status: Status + var order: Order + + var body: some View { + VStack(spacing: 16) { + switch status { + case .started: + HStack { + Text("Order") + .font(.system(size: 20)) + Spacer() + } + LeadingText("Order ID", weight: .bold) + LeadingText("\(order.id)") + LeadingText("Status", weight: .bold) + LeadingText("\(order.status)") + case .approved: + HStack { + Text("Order Approved") + .font(.system(size: 20)) + Spacer() + } + LeadingText("Intent", weight: .bold) + LeadingText("\(payPalWebViewModel.state.intent)") + LeadingText("Order ID", weight: .bold) + LeadingText("\(order.id)") + LeadingText("Payer ID", weight: .bold) +// LeadingText("\(order.payerID)") // TODO: find out where to get this + case .completed: + HStack { + Text("Order \(payPalWebViewModel.state.intent.rawValue)") + .font(.system(size: 20)) + Spacer() + } + 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/SwiftUIComponents/SuccessView.swift b/Demo/Demo/SwiftUIComponents/SuccessView.swift index be9577274..1f15dcfd4 100644 --- a/Demo/Demo/SwiftUIComponents/SuccessView.swift +++ b/Demo/Demo/SwiftUIComponents/SuccessView.swift @@ -13,7 +13,7 @@ struct SuccessView: View { var body: some View { VStack(spacing: 16) { HStack { - Text("Order \(intent.rawValue)") + Text("Order \(intent.rawValue.lowercased())") .font(.system(size: 20)) Spacer() } @@ -21,9 +21,8 @@ struct SuccessView: View { LeadingText("\(order.id)") LeadingText("Status", weight: .bold) LeadingText("\(order.status)") - if let email = order.paymentSource?.paypal?.emailAddress { - LeadingText("Email", weight: .bold) - LeadingText("\(email)") + if order.paymentSource?.paypal != nil { + appendPayPalDetails() } Text("") .id("bottomView") @@ -36,4 +35,13 @@ struct SuccessView: View { .padding(5) ) } + + func appendPayPalDetails() -> some View { + VStack(spacing: 16) { + if let email = order.paymentSource?.paypal?.emailAddress { + LeadingText("Email", weight: .bold) + LeadingText("\(email)") + } + } + } } diff --git a/Demo/Demo/ViewModels/PayPalWebState.swift b/Demo/Demo/ViewModels/PayPalWebState.swift index 4dc31b3c4..9796526cc 100644 --- a/Demo/Demo/ViewModels/PayPalWebState.swift +++ b/Demo/Demo/ViewModels/PayPalWebState.swift @@ -3,15 +3,8 @@ import PayPalWebPayments struct PayPalWebState: Equatable { - struct CheckoutResult: Decodable, Equatable { - - let id: String - let payerID: String - } - var order: Order? var intent: Intent = .authorize - var checkoutResult: CheckoutResult? var orderResponse: LoadingState = .idle { didSet { @@ -20,12 +13,4 @@ struct PayPalWebState: Equatable { } } } - - var checkoutResultResponse: LoadingState = .idle { - didSet { - if case .loaded(let value) = checkoutResultResponse { - checkoutResult = value - } - } - } } diff --git a/Demo/Demo/ViewModels/PayPalWebViewModel.swift b/Demo/Demo/ViewModels/PayPalWebViewModel.swift index 734c24db6..360385996 100644 --- a/Demo/Demo/ViewModels/PayPalWebViewModel.swift +++ b/Demo/Demo/ViewModels/PayPalWebViewModel.swift @@ -57,7 +57,7 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { client.start(request: payPalRequest) } catch { print("Error in starting paypal webcheckout client") - state.checkoutResultResponse = .error(message: error.localizedDescription) + state.orderResponse = .error(message: error.localizedDescription) } } } @@ -70,15 +70,16 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { } } - func paypalWebCheckoutSuccessResult(checkoutResult: PayPalWebState.CheckoutResult) { + func paypalWebCheckoutSuccessResult() { DispatchQueue.main.async { - self.state.checkoutResultResponse = .loaded(checkoutResult) + // TODO: fix force unwrap + self.state.orderResponse = .loaded(self.state.order!) } } func paypalWebCheckoutFailureResult(checkoutError: CorePayments.CoreSDKError) { DispatchQueue.main.async { - self.state.checkoutResultResponse = .error(message: checkoutError.localizedDescription) + self.state.orderResponse = .error(message: checkoutError.localizedDescription) } } @@ -139,7 +140,8 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { _ payPalClient: PayPalWebPayments.PayPalWebCheckoutClient, didFinishWithResult result: PayPalWebPayments.PayPalWebCheckoutResult ) { - paypalWebCheckoutSuccessResult(checkoutResult: PayPalWebState.CheckoutResult(id: result.orderID, payerID: result.payerID)) + // TODO: fix force unwrap + PayPalWebResultView(payPalWebViewModel: self, status: .completed, order: state.order!) } func payPal(_ payPalClient: PayPalWebPayments.PayPalWebCheckoutClient, didFinishWithError error: CorePayments.CoreSDKError) { From 9d956dd5479efb3d6e7122e86a3ac74c1bfc6ea6 Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Fri, 17 Nov 2023 13:37:53 -0600 Subject: [PATCH 04/31] WIP - start consolidating result views --- Demo/Demo.xcodeproj/project.pbxproj | 12 --- .../OrderCreatePayPalWebResultView.swift | 17 ---- .../PayPalTransactionView.swift | 3 +- .../PayPalWebApprovalResultView.swift | 17 ---- .../PayPalWebOrderCompletionResultView.swift | 17 ---- .../PayPalWebOrderCompletionView.swift | 4 +- .../PayPalWebViews/PayPalWebResultView.swift | 90 ++++++++++--------- .../PayPalWebViews/PayPalWebView.swift | 10 +-- Demo/Demo/ViewModels/PayPalWebViewModel.swift | 3 +- 9 files changed, 57 insertions(+), 116 deletions(-) delete mode 100644 Demo/Demo/SwiftUIComponents/PayPalWebViews/OrderCreatePayPalWebResultView.swift delete mode 100644 Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebApprovalResultView.swift delete mode 100644 Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionResultView.swift diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index 1403671b0..a8e5c9159 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -17,7 +17,6 @@ 3B4DD9A02A892A7000F4A716 /* CardVaultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B4DD99F2A892A7000F4A716 /* CardVaultView.swift */; }; 3B4DD9A22A8982B000F4A716 /* CardFormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B4DD9A12A8982B000F4A716 /* CardFormView.swift */; }; 3B6472A32AFAE5E3004745C4 /* PayPalWebOrderCompletionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B6472A22AFAE5E3004745C4 /* PayPalWebOrderCompletionView.swift */; }; - 3B6472A52AFAEB1E004745C4 /* PayPalWebOrderCompletionResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B6472A42AFAEB1E004745C4 /* PayPalWebOrderCompletionResultView.swift */; }; 3B6472A72AFAEB3A004745C4 /* PayPalOrderActionButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B6472A62AFAEB3A004745C4 /* PayPalOrderActionButton.swift */; }; 3B80D50E2A291C0800D2EAC4 /* ClientIDRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B80D50D2A291C0800D2EAC4 /* ClientIDRequest.swift */; }; 3B80D5102A291CB100D2EAC4 /* ClientIDResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B80D50F2A291CB100D2EAC4 /* ClientIDResponse.swift */; }; @@ -36,9 +35,7 @@ 3BA56FFE2A9FF4DA0081D14F /* PayPalWebState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA56FFD2A9FF4DA0081D14F /* PayPalWebState.swift */; }; 3BA570012AA052E80081D14F /* PayPalWebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA570002AA052E80081D14F /* PayPalWebView.swift */; }; 3BA570032AA053AE0081D14F /* CreateOrderPayPalWebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA570022AA053AE0081D14F /* CreateOrderPayPalWebView.swift */; }; - 3BA570052AA0BBF10081D14F /* OrderCreatePayPalWebResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA570042AA0BBF10081D14F /* OrderCreatePayPalWebResultView.swift */; }; 3BA570072AA0DF330081D14F /* PayPalTransactionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA570062AA0DF330081D14F /* PayPalTransactionView.swift */; }; - 3BA570092AA0E8340081D14F /* PayPalWebApprovalResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA570082AA0E8340081D14F /* PayPalWebApprovalResultView.swift */; }; 3BA5700B2AA13C1C0081D14F /* CoreConfigManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA5700A2AA13C1C0081D14F /* CoreConfigManager.swift */; }; 3BB7A9772A5CA6FD00C05140 /* MerchantIntegration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BB7A9762A5CA6FD00C05140 /* MerchantIntegration.swift */; }; 3BC622072A97115700251B85 /* RoundedBlueButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BC622062A97115700251B85 /* RoundedBlueButtonStyle.swift */; }; @@ -140,7 +137,6 @@ 3B4DD99F2A892A7000F4A716 /* CardVaultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardVaultView.swift; sourceTree = ""; }; 3B4DD9A12A8982B000F4A716 /* CardFormView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardFormView.swift; sourceTree = ""; }; 3B6472A22AFAE5E3004745C4 /* PayPalWebOrderCompletionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PayPalWebOrderCompletionView.swift; sourceTree = ""; }; - 3B6472A42AFAEB1E004745C4 /* PayPalWebOrderCompletionResultView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PayPalWebOrderCompletionResultView.swift; sourceTree = ""; }; 3B6472A62AFAEB3A004745C4 /* PayPalOrderActionButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PayPalOrderActionButton.swift; sourceTree = ""; }; 3B80D50D2A291C0800D2EAC4 /* ClientIDRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientIDRequest.swift; sourceTree = ""; }; 3B80D50F2A291CB100D2EAC4 /* ClientIDResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientIDResponse.swift; sourceTree = ""; }; @@ -159,9 +155,7 @@ 3BA56FFD2A9FF4DA0081D14F /* PayPalWebState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalWebState.swift; sourceTree = ""; }; 3BA570002AA052E80081D14F /* PayPalWebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalWebView.swift; sourceTree = ""; }; 3BA570022AA053AE0081D14F /* CreateOrderPayPalWebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateOrderPayPalWebView.swift; sourceTree = ""; }; - 3BA570042AA0BBF10081D14F /* OrderCreatePayPalWebResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderCreatePayPalWebResultView.swift; sourceTree = ""; }; 3BA570062AA0DF330081D14F /* PayPalTransactionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalTransactionView.swift; sourceTree = ""; }; - 3BA570082AA0E8340081D14F /* PayPalWebApprovalResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalWebApprovalResultView.swift; sourceTree = ""; }; 3BA5700A2AA13C1C0081D14F /* CoreConfigManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreConfigManager.swift; sourceTree = ""; }; 3BB7A9762A5CA6FD00C05140 /* MerchantIntegration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MerchantIntegration.swift; sourceTree = ""; }; 3BC622062A97115700251B85 /* RoundedBlueButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundedBlueButtonStyle.swift; sourceTree = ""; }; @@ -281,13 +275,10 @@ isa = PBXGroup; children = ( 3B6472A62AFAEB3A004745C4 /* PayPalOrderActionButton.swift */, - 3B6472A42AFAEB1E004745C4 /* PayPalWebOrderCompletionResultView.swift */, 3B6472A22AFAE5E3004745C4 /* PayPalWebOrderCompletionView.swift */, 3BA570002AA052E80081D14F /* PayPalWebView.swift */, 3BA570022AA053AE0081D14F /* CreateOrderPayPalWebView.swift */, - 3BA570042AA0BBF10081D14F /* OrderCreatePayPalWebResultView.swift */, 3BA570062AA0DF330081D14F /* PayPalTransactionView.swift */, - 3BA570082AA0E8340081D14F /* PayPalWebApprovalResultView.swift */, BE8117632B07E778009867B9 /* PayPalWebResultView.swift */, ); path = PayPalWebViews; @@ -597,7 +588,6 @@ files = ( 3BA56FE92A9DCA520081D14F /* CardPaymentState.swift in Sources */, 3B2027412A8A72050007907E /* CardVaultState.swift in Sources */, - 3BA570092AA0E8340081D14F /* PayPalWebApprovalResultView.swift in Sources */, 80F33CED26F8E7A9006811B1 /* Order.swift in Sources */, 3B4DD9A02A892A7000F4A716 /* CardVaultView.swift in Sources */, BE8117642B07E778009867B9 /* PayPalWebResultView.swift in Sources */, @@ -651,9 +641,7 @@ 3BA56FF42A9DCD790081D14F /* CardPaymentView.swift in Sources */, BE9F36D82745490400AFC7DA /* FloatingLabelTextField.swift in Sources */, 3B20273D2A89E3F00007907E /* CreateSetupTokenView.swift in Sources */, - 3BA570052AA0BBF10081D14F /* OrderCreatePayPalWebResultView.swift in Sources */, 3B22E8BA2A842D8900962E34 /* PaymentTokenRequest.swift in Sources */, - 3B6472A52AFAEB1E004745C4 /* PayPalWebOrderCompletionResultView.swift in Sources */, 3BA570072AA0DF330081D14F /* PayPalTransactionView.swift in Sources */, 3BCCFE492A9D96CA00C5102F /* DemoApp.swift in Sources */, 3BA56FEC2A9DCBF30081D14F /* CreateOrderCardPaymentView.swift in Sources */, diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/OrderCreatePayPalWebResultView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/OrderCreatePayPalWebResultView.swift deleted file mode 100644 index 4b429b6ad..000000000 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/OrderCreatePayPalWebResultView.swift +++ /dev/null @@ -1,17 +0,0 @@ -import SwiftUI - -struct OrderCreatePayPalWebResultView: View { - - @ObservedObject var paypalWebViewModel: PayPalWebViewModel - - var body: some View { - switch paypalWebViewModel.state.orderResponse { - case .idle, .loading: - EmptyView() - case .loaded(let order): - SuccessView(order: order, intent: paypalWebViewModel.state.intent) - case .error(let errorMessage): - ErrorView(errorMessage: errorMessage) - } - } -} diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalTransactionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalTransactionView.swift index 6abacf26d..2cffc8c00 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalTransactionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalTransactionView.swift @@ -29,8 +29,7 @@ struct PayPalTransactionView: View { .stroke(.gray, lineWidth: 2) .padding(5) ) - // TODO: fix force unwrap - PayPalWebResultView(payPalWebViewModel: paypalWebViewModel, status: .approved, order: paypalWebViewModel.state.order!) + PayPalWebResultView(payPalWebViewModel: paypalWebViewModel, status: .approved) if paypalWebViewModel.state.orderResponse != nil { NavigationLink { PayPalWebOrderCompletionView(orderID: orderID, payPalWebViewModel: paypalWebViewModel) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebApprovalResultView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebApprovalResultView.swift deleted file mode 100644 index b7fe1c788..000000000 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebApprovalResultView.swift +++ /dev/null @@ -1,17 +0,0 @@ -import SwiftUI - -struct PayPalWebApprovalResultView: View { - - @ObservedObject var paypalWebViewModel: PayPalWebViewModel - - var body: some View { - switch paypalWebViewModel.state.orderResponse { - case .idle, .loading: - EmptyView() - case .loaded(let order): - PayPalWebResultView(payPalWebViewModel: paypalWebViewModel, status: .approved, order: order) - case .error(let errorMessage): - ErrorView(errorMessage: errorMessage) - } - } -} diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionResultView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionResultView.swift deleted file mode 100644 index 180abac5e..000000000 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionResultView.swift +++ /dev/null @@ -1,17 +0,0 @@ -import SwiftUI - -struct PayPalWebOrderCompletionResultView: View { - - @ObservedObject var paypalWebViewModel: PayPalWebViewModel - - var body: some View { - switch paypalWebViewModel.state.orderResponse { - case .idle, .loading: - EmptyView() - case .loaded(let order): - SuccessView(order: order, intent: paypalWebViewModel.state.intent) - case .error(let errorMessage): - ErrorView(errorMessage: errorMessage) - } - } -} diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionView.swift index 0089a26a1..062f457f7 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionView.swift @@ -10,7 +10,7 @@ struct PayPalWebOrderCompletionView: View { ScrollView { ScrollViewReader { scrollView in VStack { - PayPalWebApprovalResultView(paypalWebViewModel: payPalWebViewModel) + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .started) if state.orderResponse != nil { PayPalOrderActionButton( intent: state.intent, @@ -21,7 +21,7 @@ struct PayPalWebOrderCompletionView: View { } if state.order != nil { - PayPalWebOrderCompletionResultView(paypalWebViewModel: payPalWebViewModel) + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .started) } Text("") .id("bottomView") diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebResultView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebResultView.swift index f75847c86..0738784e1 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebResultView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebResultView.swift @@ -11,52 +11,58 @@ struct PayPalWebResultView: View { @ObservedObject var payPalWebViewModel: PayPalWebViewModel var status: Status - var order: Order var body: some View { - VStack(spacing: 16) { - switch status { - case .started: - HStack { - Text("Order") - .font(.system(size: 20)) - Spacer() - } - LeadingText("Order ID", weight: .bold) - LeadingText("\(order.id)") - LeadingText("Status", weight: .bold) - LeadingText("\(order.status)") - case .approved: - HStack { - Text("Order Approved") - .font(.system(size: 20)) - Spacer() - } - LeadingText("Intent", weight: .bold) - LeadingText("\(payPalWebViewModel.state.intent)") - LeadingText("Order ID", weight: .bold) - LeadingText("\(order.id)") - LeadingText("Payer ID", weight: .bold) -// LeadingText("\(order.payerID)") // TODO: find out where to get this - case .completed: - HStack { - Text("Order \(payPalWebViewModel.state.intent.rawValue)") - .font(.system(size: 20)) - Spacer() - } - LeadingText("Order ID", weight: .bold) - LeadingText("\(order.id)") - LeadingText("Status", weight: .bold) - LeadingText("\(order.status)") + switch payPalWebViewModel.state.orderResponse { + case .idle, .loading: + EmptyView() + case .loaded(let order): + VStack(spacing: 16) { + switch status { + case .started: + HStack { + Text("Order") + .font(.system(size: 20)) + Spacer() + } + LeadingText("Order ID", weight: .bold) + LeadingText("\(order.id)") + LeadingText("Status", weight: .bold) + LeadingText("\(order.status)") + case .approved: + HStack { + Text("Order Approved") + .font(.system(size: 20)) + Spacer() + } + LeadingText("Intent", weight: .bold) + LeadingText("\(payPalWebViewModel.state.intent)") + LeadingText("Order ID", weight: .bold) + LeadingText("\(order.id)") + LeadingText("Payer ID", weight: .bold) + // LeadingText("\(order.payerID)") // TODO: find out where to get this + case .completed: + HStack { + Text("Order \(payPalWebViewModel.state.intent.rawValue)") + .font(.system(size: 20)) + Spacer() + } + 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) + ) + case .error(let errorMessage): + ErrorView(errorMessage: errorMessage) } - .frame(maxWidth: .infinity) - .padding() - .background( - RoundedRectangle(cornerRadius: 10) - .stroke(.gray, lineWidth: 2) - .padding(5) - ) } } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebView.swift index 96b06ae0b..5f60c70d6 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebView.swift @@ -3,19 +3,19 @@ import PaymentButtons struct PayPalWebView: View { - @StateObject var paypalWebViewModel = PayPalWebViewModel() + @StateObject var payPalWebViewModel = PayPalWebViewModel() var body: some View { ScrollView { VStack(spacing: 16) { CreateOrderPayPalWebView( - paypalWebViewModel: paypalWebViewModel, + paypalWebViewModel: payPalWebViewModel, selectedMerchantIntegration: DemoSettings.merchantIntegration ) - if let order = paypalWebViewModel.state.order { - OrderCreatePayPalWebResultView(paypalWebViewModel: paypalWebViewModel) + if let order = payPalWebViewModel.state.order { + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .started) NavigationLink { - PayPalTransactionView(paypalWebViewModel: paypalWebViewModel, orderID: order.id) + PayPalTransactionView(paypalWebViewModel: payPalWebViewModel, orderID: order.id) .navigationTitle("PayPal Transactions") } label: { Text("PayPal Transactions") diff --git a/Demo/Demo/ViewModels/PayPalWebViewModel.swift b/Demo/Demo/ViewModels/PayPalWebViewModel.swift index 360385996..601bc904b 100644 --- a/Demo/Demo/ViewModels/PayPalWebViewModel.swift +++ b/Demo/Demo/ViewModels/PayPalWebViewModel.swift @@ -140,8 +140,7 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { _ payPalClient: PayPalWebPayments.PayPalWebCheckoutClient, didFinishWithResult result: PayPalWebPayments.PayPalWebCheckoutResult ) { - // TODO: fix force unwrap - PayPalWebResultView(payPalWebViewModel: self, status: .completed, order: state.order!) + PayPalWebResultView(payPalWebViewModel: self, status: .started) } func payPal(_ payPalClient: PayPalWebPayments.PayPalWebCheckoutClient, didFinishWithError error: CorePayments.CoreSDKError) { From bc4a9e34b24787616a7515e89e0126fa5b84058e Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Fri, 17 Nov 2023 15:18:59 -0600 Subject: [PATCH 05/31] WIP - continue refactoring state for PayPal Web --- Demo/Demo.xcodeproj/project.pbxproj | 16 +++--- .../Demo/SwiftUIComponents/CurrentState.swift | 9 ++++ .../CreateOrderPayPalWebView.swift | 4 +- .../PayPalOrderActionButton.swift | 2 +- .../PayPalTransactionView.swift | 4 +- .../PayPalWebOrderCompletionView.swift | 20 +++---- .../PayPalWebViews/PayPalWebResultView.swift | 48 ++--------------- .../PayPalWebViews/PayPalWebStatusView.swift | 54 +++++++++++++++++++ .../PayPalWebViews/PayPalWebView.swift | 19 ++++--- Demo/Demo/SwiftUIComponents/SuccessView.swift | 47 ---------------- Demo/Demo/ViewModels/PayPalWebState.swift | 16 ------ Demo/Demo/ViewModels/PayPalWebViewModel.swift | 33 ++++++------ 12 files changed, 111 insertions(+), 161 deletions(-) create mode 100644 Demo/Demo/SwiftUIComponents/CurrentState.swift create mode 100644 Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebStatusView.swift delete mode 100644 Demo/Demo/SwiftUIComponents/SuccessView.swift delete mode 100644 Demo/Demo/ViewModels/PayPalWebState.swift diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index a8e5c9159..3ac95d057 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -32,7 +32,6 @@ 3BA56FF82A9FDB5A0081D14F /* CardPaymentOrderCompletionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA56FF72A9FDB5A0081D14F /* CardPaymentOrderCompletionView.swift */; }; 3BA56FFA2A9FE4180081D14F /* CardOrderCompletionResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA56FF92A9FE4180081D14F /* CardOrderCompletionResultView.swift */; }; 3BA56FFC2A9FEFE90081D14F /* PayPalWebViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA56FFB2A9FEFE90081D14F /* PayPalWebViewModel.swift */; }; - 3BA56FFE2A9FF4DA0081D14F /* PayPalWebState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA56FFD2A9FF4DA0081D14F /* PayPalWebState.swift */; }; 3BA570012AA052E80081D14F /* PayPalWebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA570002AA052E80081D14F /* PayPalWebView.swift */; }; 3BA570032AA053AE0081D14F /* CreateOrderPayPalWebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA570022AA053AE0081D14F /* CreateOrderPayPalWebView.swift */; }; 3BA570072AA0DF330081D14F /* PayPalTransactionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA570062AA0DF330081D14F /* PayPalTransactionView.swift */; }; @@ -68,8 +67,9 @@ BC9D4D2627C6D1720089E5B1 /* XCUIElement+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC9D4D2527C6D1720089E5B1 /* XCUIElement+Helpers.swift */; }; BE1766B326F911A2007EF438 /* URLResponseError.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE1766B226F911A2007EF438 /* URLResponseError.swift */; }; BE1766D926FA7BC8007EF438 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = BE1766D826FA7BC8007EF438 /* Settings.bundle */; }; - BE8117602B07D755009867B9 /* SuccessView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE81175F2B07D755009867B9 /* SuccessView.swift */; }; BE8117642B07E778009867B9 /* PayPalWebResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE8117632B07E778009867B9 /* PayPalWebResultView.swift */; }; + BE8117662B080202009867B9 /* PayPalWebStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE8117652B080202009867B9 /* PayPalWebStatusView.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 */; }; BECD84A227036DDB007CCAE4 /* Intent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BECD84A127036DDB007CCAE4 /* Intent.swift */; }; @@ -152,7 +152,6 @@ 3BA56FF72A9FDB5A0081D14F /* CardPaymentOrderCompletionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardPaymentOrderCompletionView.swift; sourceTree = ""; }; 3BA56FF92A9FE4180081D14F /* CardOrderCompletionResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardOrderCompletionResultView.swift; sourceTree = ""; }; 3BA56FFB2A9FEFE90081D14F /* PayPalWebViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalWebViewModel.swift; sourceTree = ""; }; - 3BA56FFD2A9FF4DA0081D14F /* PayPalWebState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalWebState.swift; sourceTree = ""; }; 3BA570002AA052E80081D14F /* PayPalWebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalWebView.swift; sourceTree = ""; }; 3BA570022AA053AE0081D14F /* CreateOrderPayPalWebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateOrderPayPalWebView.swift; sourceTree = ""; }; 3BA570062AA0DF330081D14F /* PayPalTransactionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalTransactionView.swift; sourceTree = ""; }; @@ -195,8 +194,9 @@ BE1766B226F911A2007EF438 /* URLResponseError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLResponseError.swift; sourceTree = ""; }; 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; }; - BE81175F2B07D755009867B9 /* SuccessView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuccessView.swift; sourceTree = ""; }; BE8117632B07E778009867B9 /* PayPalWebResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalWebResultView.swift; sourceTree = ""; }; + BE8117652B080202009867B9 /* PayPalWebStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalWebStatusView.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 = ""; }; BECD84A127036DDB007CCAE4 /* Intent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Intent.swift; sourceTree = ""; }; @@ -280,6 +280,7 @@ 3BA570022AA053AE0081D14F /* CreateOrderPayPalWebView.swift */, 3BA570062AA0DF330081D14F /* PayPalTransactionView.swift */, BE8117632B07E778009867B9 /* PayPalWebResultView.swift */, + BE8117652B080202009867B9 /* PayPalWebStatusView.swift */, ); path = PayPalWebViews; sourceTree = ""; @@ -422,7 +423,6 @@ 3BA56FE62A9DC9D70081D14F /* CardPaymentViewModel.swift */, 3BA56FE82A9DCA520081D14F /* CardPaymentState.swift */, 3BA56FFB2A9FEFE90081D14F /* PayPalWebViewModel.swift */, - 3BA56FFD2A9FF4DA0081D14F /* PayPalWebState.swift */, ); path = ViewModels; sourceTree = ""; @@ -456,7 +456,7 @@ CB9ED44D28411B110081F4DE /* SwiftUIPaymentButtonDemo.swift */, 536A5CA72898AA2A005C053D /* SwiftUINativeCheckoutDemo.swift */, 3BCCFE4A2A9D985F00C5102F /* FeatureSelectionView.swift */, - BE81175F2B07D755009867B9 /* SuccessView.swift */, + BE8117672B080472009867B9 /* CurrentState.swift */, ); path = SwiftUIComponents; sourceTree = ""; @@ -604,7 +604,6 @@ 3B22E8BC2A84397600962E34 /* PaymentTokenResponse.swift in Sources */, 3B2027432A8A95EF0007907E /* SetupTokenResultView.swift in Sources */, 3BF999762A8AC093009CBDF2 /* UpdateSetupTokenResultView.swift in Sources */, - 3BA56FFE2A9FF4DA0081D14F /* PayPalWebState.swift in Sources */, BECD84A027036DC2007CCAE4 /* Environment.swift in Sources */, 80F33CF126F8E7D9006811B1 /* ProcessOrderParams.swift in Sources */, 53B9E8EA28C93B4400719239 /* OrderRequestHelpers.swift in Sources */, @@ -613,9 +612,11 @@ BED041B1270CB33900C80954 /* CustomTextField.swift in Sources */, 3B80D50E2A291C0800D2EAC4 /* ClientIDRequest.swift in Sources */, 3BA56FF02A9DCCFD0081D14F /* CardOrderApproveView.swift in Sources */, + BE8117682B080472009867B9 /* CurrentState.swift in Sources */, 3BDB348E2A7CB02C008100D7 /* SetupTokenRequest.swift in Sources */, 80F33CF326F8EA50006811B1 /* DemoSettings.swift in Sources */, 3BA56FE72A9DC9D70081D14F /* CardPaymentViewModel.swift in Sources */, + BE8117662B080202009867B9 /* PayPalWebStatusView.swift in Sources */, 3BA5700B2AA13C1C0081D14F /* CoreConfigManager.swift in Sources */, 80E4300C2AD82C8D003CA748 /* ShippingPreference.swift in Sources */, BEDE304A275EA33500D275FD /* UIViewController+Extension.swift in Sources */, @@ -629,7 +630,6 @@ 3B2027452A8AA78B0007907E /* UpdateSetupTokenView.swift in Sources */, 3BA56FF82A9FDB5A0081D14F /* CardPaymentOrderCompletionView.swift in Sources */, 3B8EF4DB2A932DA300A70D0B /* ErrorView.swift in Sources */, - BE8117602B07D755009867B9 /* SuccessView.swift in Sources */, 3B6472A32AFAE5E3004745C4 /* PayPalWebOrderCompletionView.swift in Sources */, 3BF9997A2A8AE12C009CBDF2 /* PaymentTokenResultView.swift in Sources */, 3BA56FFC2A9FEFE90081D14F /* PayPalWebViewModel.swift in Sources */, diff --git a/Demo/Demo/SwiftUIComponents/CurrentState.swift b/Demo/Demo/SwiftUIComponents/CurrentState.swift new file mode 100644 index 000000000..bbb53c10c --- /dev/null +++ b/Demo/Demo/SwiftUIComponents/CurrentState.swift @@ -0,0 +1,9 @@ +import Foundation + +enum CurrentState: Equatable { + + case idle + case loading + case error(message: String) + case loaded(_ order: Order) +} diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/CreateOrderPayPalWebView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/CreateOrderPayPalWebView.swift index 2298c1b37..514efddcd 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/CreateOrderPayPalWebView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebViews/CreateOrderPayPalWebView.swift @@ -26,7 +26,7 @@ struct CreateOrderPayPalWebView: View { Button("Create an Order") { Task { do { - paypalWebViewModel.state.intent = selectedIntent + paypalWebViewModel.intent = selectedIntent try await paypalWebViewModel.createOrder( amount: "10.00", selectedMerchantIntegration: DemoSettings.merchantIntegration, @@ -37,7 +37,7 @@ struct CreateOrderPayPalWebView: View { } } .buttonStyle(RoundedBlueButtonStyle()) - if case .loading = paypalWebViewModel.state.orderResponse { + if case .loading = paypalWebViewModel.state { CircularProgressView() } } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalOrderActionButton.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalOrderActionButton.swift index 4aa38e4dd..3c7c07027 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalOrderActionButton.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalOrderActionButton.swift @@ -16,7 +16,7 @@ struct PayPalOrderActionButton: View { .buttonStyle(RoundedBlueButtonStyle()) .padding() - if .loading == paypalWebViewModel.state.orderResponse { + if paypalWebViewModel.state == .loading { CircularProgressView() } } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalTransactionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalTransactionView.swift index 2cffc8c00..743d3c4e4 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalTransactionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalTransactionView.swift @@ -29,8 +29,7 @@ struct PayPalTransactionView: View { .stroke(.gray, lineWidth: 2) .padding(5) ) - PayPalWebResultView(payPalWebViewModel: paypalWebViewModel, status: .approved) - if paypalWebViewModel.state.orderResponse != nil { + PayPalWebResultView(payPalWebViewModel: paypalWebViewModel, status: .completed) NavigationLink { PayPalWebOrderCompletionView(orderID: orderID, payPalWebViewModel: paypalWebViewModel) } label: { @@ -38,7 +37,6 @@ struct PayPalTransactionView: View { } .buttonStyle(RoundedBlueButtonStyle()) .padding() - } Spacer() } } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionView.swift index 062f457f7..8045899dd 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionView.swift @@ -10,19 +10,15 @@ struct PayPalWebOrderCompletionView: View { ScrollView { ScrollViewReader { scrollView in VStack { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .started) - if state.orderResponse != nil { - PayPalOrderActionButton( - intent: state.intent, - orderID: orderID, - selectedMerchantIntegration: DemoSettings.merchantIntegration, - paypalWebViewModel: payPalWebViewModel - ) - } + // TODO: figure out sending intent - maybe in VM? + PayPalOrderActionButton( + intent: .authorize, + orderID: orderID, + selectedMerchantIntegration: DemoSettings.merchantIntegration, + paypalWebViewModel: payPalWebViewModel + ) - if state.order != nil { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .started) - } + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .started) Text("") .id("bottomView") Spacer() diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebResultView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebResultView.swift index 0738784e1..43b5760f8 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebResultView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebResultView.swift @@ -13,54 +13,12 @@ struct PayPalWebResultView: View { var status: Status var body: some View { - switch payPalWebViewModel.state.orderResponse { + switch payPalWebViewModel.state { case .idle, .loading: EmptyView() case .loaded(let order): - VStack(spacing: 16) { - switch status { - case .started: - HStack { - Text("Order") - .font(.system(size: 20)) - Spacer() - } - LeadingText("Order ID", weight: .bold) - LeadingText("\(order.id)") - LeadingText("Status", weight: .bold) - LeadingText("\(order.status)") - case .approved: - HStack { - Text("Order Approved") - .font(.system(size: 20)) - Spacer() - } - LeadingText("Intent", weight: .bold) - LeadingText("\(payPalWebViewModel.state.intent)") - LeadingText("Order ID", weight: .bold) - LeadingText("\(order.id)") - LeadingText("Payer ID", weight: .bold) - // LeadingText("\(order.payerID)") // TODO: find out where to get this - case .completed: - HStack { - Text("Order \(payPalWebViewModel.state.intent.rawValue)") - .font(.system(size: 20)) - Spacer() - } - 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) - ) + // TODO: figure out sending intent + PayPalWebStatusView(status: status, order: order, intent: .authorize) case .error(let errorMessage): ErrorView(errorMessage: errorMessage) } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebStatusView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebStatusView.swift new file mode 100644 index 000000000..82419d626 --- /dev/null +++ b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebStatusView.swift @@ -0,0 +1,54 @@ +import SwiftUI + +struct PayPalWebStatusView: View { + + var status: Status + var order: Order + var intent: Intent + + var body: some View { + VStack(spacing: 16) { + switch status { + case .started: + HStack { + Text("Order") + .font(.system(size: 20)) + Spacer() + } + LeadingText("Order ID", weight: .bold) + LeadingText("\(order.id)") + LeadingText("Status", weight: .bold) + LeadingText("\(order.status)") + case .approved: + HStack { + Text("Order Approved") + .font(.system(size: 20)) + Spacer() + } + LeadingText("Intent", weight: .bold) + LeadingText("\(intent)") + LeadingText("Order ID", weight: .bold) + LeadingText("\(order.id)") + LeadingText("Payer ID", weight: .bold) + // LeadingText("\(order.payerID)") // TODO: find out where to get this + case .completed: + HStack { + Text("Order \(intent.rawValue)") + .font(.system(size: 20)) + Spacer() + } + 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/SwiftUIComponents/PayPalWebViews/PayPalWebView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebView.swift index 5f60c70d6..c253c8adc 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebView.swift @@ -12,17 +12,16 @@ struct PayPalWebView: View { paypalWebViewModel: payPalWebViewModel, selectedMerchantIntegration: DemoSettings.merchantIntegration ) - if let order = payPalWebViewModel.state.order { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .started) - NavigationLink { - PayPalTransactionView(paypalWebViewModel: payPalWebViewModel, orderID: order.id) - .navigationTitle("PayPal Transactions") - } label: { - Text("PayPal Transactions") - } - .buttonStyle(RoundedBlueButtonStyle()) - .padding() + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .started) + NavigationLink { + // TODO: figure this out +// PayPalTransactionView(paypalWebViewModel: payPalWebViewModel, orderID: payPalWebViewModel.id) +// .navigationTitle("PayPal Transactions") + } label: { + Text("PayPal Transactions") } + .buttonStyle(RoundedBlueButtonStyle()) + .padding() } } } diff --git a/Demo/Demo/SwiftUIComponents/SuccessView.swift b/Demo/Demo/SwiftUIComponents/SuccessView.swift deleted file mode 100644 index 1f15dcfd4..000000000 --- a/Demo/Demo/SwiftUIComponents/SuccessView.swift +++ /dev/null @@ -1,47 +0,0 @@ -import SwiftUI - -struct SuccessView: View { - - var order: Order - var intent: Intent - - init(order: Order, intent: Intent) { - self.order = order - self.intent = intent - } - - var body: some View { - VStack(spacing: 16) { - HStack { - Text("Order \(intent.rawValue.lowercased())") - .font(.system(size: 20)) - Spacer() - } - LeadingText("Order ID", weight: .bold) - LeadingText("\(order.id)") - LeadingText("Status", weight: .bold) - LeadingText("\(order.status)") - if order.paymentSource?.paypal != nil { - appendPayPalDetails() - } - Text("") - .id("bottomView") - } - .frame(maxWidth: .infinity) - .padding() - .background( - RoundedRectangle(cornerRadius: 10) - .stroke(.gray, lineWidth: 2) - .padding(5) - ) - } - - func appendPayPalDetails() -> some View { - VStack(spacing: 16) { - if let email = order.paymentSource?.paypal?.emailAddress { - LeadingText("Email", weight: .bold) - LeadingText("\(email)") - } - } - } -} diff --git a/Demo/Demo/ViewModels/PayPalWebState.swift b/Demo/Demo/ViewModels/PayPalWebState.swift deleted file mode 100644 index 9796526cc..000000000 --- a/Demo/Demo/ViewModels/PayPalWebState.swift +++ /dev/null @@ -1,16 +0,0 @@ -import Foundation -import PayPalWebPayments - -struct PayPalWebState: Equatable { - - var order: Order? - var intent: Intent = .authorize - - var orderResponse: LoadingState = .idle { - didSet { - if case .loaded(let value) = orderResponse { - order = value - } - } - } -} diff --git a/Demo/Demo/ViewModels/PayPalWebViewModel.swift b/Demo/Demo/ViewModels/PayPalWebViewModel.swift index 601bc904b..3ac314c3c 100644 --- a/Demo/Demo/ViewModels/PayPalWebViewModel.swift +++ b/Demo/Demo/ViewModels/PayPalWebViewModel.swift @@ -4,7 +4,8 @@ import PayPalWebPayments class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { - @Published var state = PayPalWebState() + @Published var state: CurrentState = .idle + @Published var intent: Intent = .authorize var payPalWebCheckoutClient: PayPalWebCheckoutClient? @@ -23,18 +24,18 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { do { DispatchQueue.main.async { - self.state.orderResponse = .loading + self.state = .loading } let order = try await DemoMerchantAPI.sharedService.createOrder( orderParams: orderRequestParams, selectedMerchantIntegration: selectedMerchantIntegration ) DispatchQueue.main.async { - self.state.orderResponse = .loaded(order) + self.state = .loaded(order) print("✅ fetched orderID: \(order.id) with status: \(order.status)") } } catch { DispatchQueue.main.async { - self.state.orderResponse = .error(message: error.localizedDescription) + self.state = .error(message: error.localizedDescription) print("❌ failed to fetch orderID: \(error)") } } @@ -57,7 +58,7 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { client.start(request: payPalRequest) } catch { print("Error in starting paypal webcheckout client") - state.orderResponse = .error(message: error.localizedDescription) + state = .error(message: error.localizedDescription) } } } @@ -72,14 +73,14 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { func paypalWebCheckoutSuccessResult() { DispatchQueue.main.async { - // TODO: fix force unwrap - self.state.orderResponse = .loaded(self.state.order!) + // TODO: fix this + self.state = .loaded(Order(id: "1111", status: "yes")) } } func paypalWebCheckoutFailureResult(checkoutError: CorePayments.CoreSDKError) { DispatchQueue.main.async { - self.state.orderResponse = .error(message: checkoutError.localizedDescription) + self.state = .error(message: checkoutError.localizedDescription) } } @@ -87,28 +88,26 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { switch intent { case .capture: try await captureOrder(orderID: orderID, selectedMerchantIntegration: selectedMerchantIntegration) - print("Order Captured. ID: \(state.order?.id ?? "")") case .authorize: try await authorizeOrder(orderID: orderID, selectedMerchantIntegration: selectedMerchantIntegration) - print("Order Authorized. ID: \(state.order?.id ?? "")") } } func captureOrder(orderID: String, selectedMerchantIntegration: MerchantIntegration) async throws { do { DispatchQueue.main.async { - self.state.orderResponse = .loading + self.state = .loading } let order = try await DemoMerchantAPI.sharedService.captureOrder( orderID: orderID, selectedMerchantIntegration: selectedMerchantIntegration ) DispatchQueue.main.async { - self.state.orderResponse = .loaded(order) + self.state = .loaded(order) } } catch { DispatchQueue.main.async { - self.state.orderResponse = .error(message: error.localizedDescription) + self.state = .error(message: error.localizedDescription) } print("Error capturing order: \(error.localizedDescription)") } @@ -117,18 +116,18 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { func authorizeOrder(orderID: String, selectedMerchantIntegration: MerchantIntegration) async throws { do { DispatchQueue.main.async { - self.state.orderResponse = .loading + self.state = .loading } let order = try await DemoMerchantAPI.sharedService.authorizeOrder( orderID: orderID, selectedMerchantIntegration: selectedMerchantIntegration ) DispatchQueue.main.async { - self.state.orderResponse = .loaded(order) + self.state = .loaded(order) } } catch { DispatchQueue.main.async { - self.state.orderResponse = .error(message: error.localizedDescription) + self.state = .error(message: error.localizedDescription) } print("Error authorizing order: \(error.localizedDescription)") } @@ -140,7 +139,7 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { _ payPalClient: PayPalWebPayments.PayPalWebCheckoutClient, didFinishWithResult result: PayPalWebPayments.PayPalWebCheckoutResult ) { - PayPalWebResultView(payPalWebViewModel: self, status: .started) + paypalWebCheckoutSuccessResult() } func payPal(_ payPalClient: PayPalWebPayments.PayPalWebCheckoutClient, didFinishWithError error: CorePayments.CoreSDKError) { From d685080cceb1d3eb35f7a7181079eb9fde190823 Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Mon, 20 Nov 2023 10:05:40 -0600 Subject: [PATCH 06/31] WIP - continued paypal web demo app refactor --- .../Demo/SwiftUIComponents/CurrentState.swift | 2 +- .../PayPalOrderActionButton.swift | 16 ++++--- .../PayPalTransactionView.swift | 16 ++++--- .../PayPalWebOrderCompletionView.swift | 32 +++++++------- .../PayPalWebViews/PayPalWebResultView.swift | 5 +-- .../PayPalWebViews/PayPalWebStatusView.swift | 44 +++++++++++-------- .../PayPalWebViews/PayPalWebView.swift | 19 ++++---- Demo/Demo/ViewModels/PayPalWebViewModel.swift | 30 ++++++------- 8 files changed, 84 insertions(+), 80 deletions(-) diff --git a/Demo/Demo/SwiftUIComponents/CurrentState.swift b/Demo/Demo/SwiftUIComponents/CurrentState.swift index bbb53c10c..c2fa43d24 100644 --- a/Demo/Demo/SwiftUIComponents/CurrentState.swift +++ b/Demo/Demo/SwiftUIComponents/CurrentState.swift @@ -5,5 +5,5 @@ enum CurrentState: Equatable { case idle case loading case error(message: String) - case loaded(_ order: Order) + case loaded } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalOrderActionButton.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalOrderActionButton.swift index 3c7c07027..3fe849478 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalOrderActionButton.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalOrderActionButton.swift @@ -6,26 +6,28 @@ struct PayPalOrderActionButton: View { let orderID: String let selectedMerchantIntegration: MerchantIntegration - @ObservedObject var paypalWebViewModel: PayPalWebViewModel + @ObservedObject var payPalWebViewModel: PayPalWebViewModel var body: some View { - ZStack { + VStack { + if payPalWebViewModel.state == .loading { + CircularProgressView() + } else if payPalWebViewModel.state == .loaded { + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .approved) + } + Button("\(intent.rawValue)") { completeOrder() } .buttonStyle(RoundedBlueButtonStyle()) .padding() - - if paypalWebViewModel.state == .loading { - CircularProgressView() - } } } private func completeOrder() { Task { do { - try await paypalWebViewModel.completeOrder( + try await payPalWebViewModel.completeOrder( with: intent, orderID: orderID, selectedMerchantIntegration: selectedMerchantIntegration diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalTransactionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalTransactionView.swift index 743d3c4e4..74a1cd1c5 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalTransactionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalTransactionView.swift @@ -3,22 +3,21 @@ import PaymentButtons struct PayPalTransactionView: View { - @ObservedObject var paypalWebViewModel: PayPalWebViewModel - let orderID: String + @ObservedObject var payPalWebViewModel: PayPalWebViewModel var body: some View { VStack { VStack(alignment: .center, spacing: 40) { PayPalButton.Representable(color: .blue, size: .mini) { - paypalWebViewModel.paymentButtonTapped(orderID: orderID, funding: .paypal) + payPalWebViewModel.paymentButtonTapped(funding: .paypal) } .frame(maxWidth: .infinity, maxHeight: 40) PayPalCreditButton.Representable(color: .black, edges: .softEdges, size: .expanded) { - paypalWebViewModel.paymentButtonTapped(orderID: orderID, funding: .paypalCredit) + payPalWebViewModel.paymentButtonTapped(funding: .paypalCredit) } .frame(maxWidth: .infinity, maxHeight: 40) PayPalPayLaterButton.Representable(color: .silver, edges: .rounded, size: .full) { - paypalWebViewModel.paymentButtonTapped(orderID: orderID, funding: .paylater) + payPalWebViewModel.paymentButtonTapped(funding: .paylater) } .frame(maxWidth: .infinity, maxHeight: 40) } @@ -29,14 +28,17 @@ struct PayPalTransactionView: View { .stroke(.gray, lineWidth: 2) .padding(5) ) - PayPalWebResultView(payPalWebViewModel: paypalWebViewModel, status: .completed) + + if payPalWebViewModel.checkoutResult != nil { + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .approved) NavigationLink { - PayPalWebOrderCompletionView(orderID: orderID, payPalWebViewModel: paypalWebViewModel) + PayPalWebOrderCompletionView(payPalWebViewModel: payPalWebViewModel) } label: { Text("Complete Order Transaction") } .buttonStyle(RoundedBlueButtonStyle()) .padding() + } Spacer() } } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionView.swift index 8045899dd..f0ba1085f 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionView.swift @@ -2,7 +2,6 @@ import SwiftUI struct PayPalWebOrderCompletionView: View { - let orderID: String @ObservedObject var payPalWebViewModel: PayPalWebViewModel var body: some View { @@ -10,22 +9,21 @@ struct PayPalWebOrderCompletionView: View { ScrollView { ScrollViewReader { scrollView in VStack { - // TODO: figure out sending intent - maybe in VM? - PayPalOrderActionButton( - intent: .authorize, - orderID: orderID, - selectedMerchantIntegration: DemoSettings.merchantIntegration, - paypalWebViewModel: payPalWebViewModel - ) - - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .started) - Text("") - .id("bottomView") - Spacer() - } - .onChange(of: state) { _ in - withAnimation { - scrollView.scrollTo("bottomView") + if let orderID = payPalWebViewModel.order?.id { + PayPalOrderActionButton( + intent: payPalWebViewModel.intent, + orderID: orderID, + selectedMerchantIntegration: DemoSettings.merchantIntegration, + payPalWebViewModel: payPalWebViewModel + ) + Text("") + .id("bottomView") + Spacer() + .onChange(of: state) { _ in + withAnimation { + scrollView.scrollTo("bottomView") + } + } } } } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebResultView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebResultView.swift index 43b5760f8..0d4d721c4 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebResultView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebResultView.swift @@ -16,9 +16,8 @@ struct PayPalWebResultView: View { switch payPalWebViewModel.state { case .idle, .loading: EmptyView() - case .loaded(let order): - // TODO: figure out sending intent - PayPalWebStatusView(status: status, order: order, intent: .authorize) + case .loaded: + PayPalWebStatusView(status: status, intent: payPalWebViewModel.intent, payPalViewModel: payPalWebViewModel) case .error(let errorMessage): ErrorView(errorMessage: errorMessage) } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebStatusView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebStatusView.swift index 82419d626..b77b656ab 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebStatusView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebStatusView.swift @@ -3,8 +3,8 @@ import SwiftUI struct PayPalWebStatusView: View { var status: Status - var order: Order var intent: Intent + var payPalViewModel: PayPalWebViewModel var body: some View { VStack(spacing: 16) { @@ -15,32 +15,38 @@ struct PayPalWebStatusView: View { .font(.system(size: 20)) Spacer() } - LeadingText("Order ID", weight: .bold) - LeadingText("\(order.id)") - LeadingText("Status", weight: .bold) - LeadingText("\(order.status)") + if let order = payPalViewModel.order { + LeadingText("Order ID", weight: .bold) + LeadingText("\(order.id)") + LeadingText("Status", weight: .bold) + LeadingText("\(order.status)") + } case .approved: HStack { Text("Order Approved") .font(.system(size: 20)) Spacer() } - LeadingText("Intent", weight: .bold) - LeadingText("\(intent)") - LeadingText("Order ID", weight: .bold) - LeadingText("\(order.id)") - LeadingText("Payer ID", weight: .bold) - // LeadingText("\(order.payerID)") // TODO: find out where to get this + if let order = payPalViewModel.order { + LeadingText("Intent", weight: .bold) + LeadingText("\(intent)") + LeadingText("Order ID", weight: .bold) + LeadingText("\(order.id)") + LeadingText("Payer ID", weight: .bold) + LeadingText("\(payPalViewModel.checkoutResult?.payerID ?? "")") + } case .completed: - HStack { - Text("Order \(intent.rawValue)") - .font(.system(size: 20)) - Spacer() + if let order = payPalViewModel.order { + HStack { + Text("Order \(intent.rawValue)") + .font(.system(size: 20)) + Spacer() + } + LeadingText("Order ID", weight: .bold) + LeadingText("\(order.id)") + LeadingText("Status", weight: .bold) + LeadingText("\(order.status)") } - LeadingText("Order ID", weight: .bold) - LeadingText("\(order.id)") - LeadingText("Status", weight: .bold) - LeadingText("\(order.status)") } } .frame(maxWidth: .infinity) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebView.swift index c253c8adc..7b05e16c4 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebView.swift @@ -12,16 +12,17 @@ struct PayPalWebView: View { paypalWebViewModel: payPalWebViewModel, selectedMerchantIntegration: DemoSettings.merchantIntegration ) - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .started) - NavigationLink { - // TODO: figure this out -// PayPalTransactionView(paypalWebViewModel: payPalWebViewModel, orderID: payPalWebViewModel.id) -// .navigationTitle("PayPal Transactions") - } label: { - Text("PayPal Transactions") + if let order = payPalWebViewModel.order { + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .started) + NavigationLink { + PayPalTransactionView(payPalWebViewModel: payPalWebViewModel) + .navigationTitle("PayPal Transactions") + } label: { + Text("PayPal Transactions") + } + .buttonStyle(RoundedBlueButtonStyle()) + .padding() } - .buttonStyle(RoundedBlueButtonStyle()) - .padding() } } } diff --git a/Demo/Demo/ViewModels/PayPalWebViewModel.swift b/Demo/Demo/ViewModels/PayPalWebViewModel.swift index 3ac314c3c..2cda64b49 100644 --- a/Demo/Demo/ViewModels/PayPalWebViewModel.swift +++ b/Demo/Demo/ViewModels/PayPalWebViewModel.swift @@ -6,14 +6,14 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { @Published var state: CurrentState = .idle @Published var intent: Intent = .authorize + @Published var order: Order? + @Published var checkoutResult: PayPalWebCheckoutResult? var payPalWebCheckoutClient: PayPalWebCheckoutClient? let configManager = CoreConfigManager(domain: "PayPalWeb Payments") func createOrder(amount: String, selectedMerchantIntegration: MerchantIntegration, intent: String) async throws { - // might need to pass in payee as payee object or as auth header - let amountRequest = Amount(currencyCode: "USD", value: amount) // TODO: might need to pass in payee as payee object or as auth header let orderRequestParams = CreateOrderParams( @@ -30,7 +30,8 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { orderParams: orderRequestParams, selectedMerchantIntegration: selectedMerchantIntegration ) DispatchQueue.main.async { - self.state = .loaded(order) + self.state = .loaded + self.order = order print("✅ fetched orderID: \(order.id) with status: \(order.status)") } } catch { @@ -41,8 +42,10 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { } } - func paymentButtonTapped(orderID: String, funding: PayPalWebCheckoutFundingSource) { - checkoutWithPayPal(orderID: orderID, funding: funding) + func paymentButtonTapped(funding: PayPalWebCheckoutFundingSource) { + if let orderID = order?.id { + checkoutWithPayPal(orderID: orderID, funding: funding) + } } func checkoutWithPayPal(orderID: String, funding: PayPalWebCheckoutFundingSource) { @@ -71,13 +74,6 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { } } - func paypalWebCheckoutSuccessResult() { - DispatchQueue.main.async { - // TODO: fix this - self.state = .loaded(Order(id: "1111", status: "yes")) - } - } - func paypalWebCheckoutFailureResult(checkoutError: CorePayments.CoreSDKError) { DispatchQueue.main.async { self.state = .error(message: checkoutError.localizedDescription) @@ -103,7 +99,7 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { selectedMerchantIntegration: selectedMerchantIntegration ) DispatchQueue.main.async { - self.state = .loaded(order) + self.state = .loaded } } catch { DispatchQueue.main.async { @@ -123,7 +119,7 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { selectedMerchantIntegration: selectedMerchantIntegration ) DispatchQueue.main.async { - self.state = .loaded(order) + self.state = .loaded } } catch { DispatchQueue.main.async { @@ -136,10 +132,10 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { // MARK: - PayPalWeb Checkout Delegate func payPal( - _ payPalClient: PayPalWebPayments.PayPalWebCheckoutClient, - didFinishWithResult result: PayPalWebPayments.PayPalWebCheckoutResult + _ payPalClient: PayPalWebCheckoutClient, + didFinishWithResult result: PayPalWebCheckoutResult ) { - paypalWebCheckoutSuccessResult() + checkoutResult = result } func payPal(_ payPalClient: PayPalWebPayments.PayPalWebCheckoutClient, didFinishWithError error: CorePayments.CoreSDKError) { From 8aed08156fd29fbacc17be878eea88e33076bccf Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Mon, 20 Nov 2023 11:36:10 -0600 Subject: [PATCH 07/31] WIP - start cleaning up file names; method signatures; etc for PayPal Web --- Demo/Demo.xcodeproj/project.pbxproj | 38 +++++++++---------- .../FeatureSelectionView.swift | 6 +-- .../PayPalWebButtonsView.swift} | 4 +- .../PayPalWebCompleteTransactionView.swift} | 23 ++++------- .../PayPalWebCreateOrderView.swift} | 7 +--- .../PayPalWebDemoView.swift} | 10 ++--- .../PayPalWebOrderCompletionView.swift | 12 +++--- .../PayPalWebResultView.swift | 0 .../PayPalWebStatusView.swift | 4 +- Demo/Demo/ViewModels/PayPalWebViewModel.swift | 22 +++++------ 10 files changed, 57 insertions(+), 69 deletions(-) rename Demo/Demo/SwiftUIComponents/{PayPalWebViews/PayPalTransactionView.swift => PayPalWeb/PayPalWebButtonsView.swift} (94%) rename Demo/Demo/SwiftUIComponents/{PayPalWebViews/PayPalOrderActionButton.swift => PayPalWeb/PayPalWebCompleteTransactionView.swift} (51%) rename Demo/Demo/SwiftUIComponents/{PayPalWebViews/CreateOrderPayPalWebView.swift => PayPalWeb/PayPalWebCreateOrderView.swift} (85%) rename Demo/Demo/SwiftUIComponents/{PayPalWebViews/PayPalWebView.swift => PayPalWeb/PayPalWebDemoView.swift} (72%) rename Demo/Demo/SwiftUIComponents/{PayPalWebViews => PayPalWeb}/PayPalWebOrderCompletionView.swift (66%) rename Demo/Demo/SwiftUIComponents/{PayPalWebViews => PayPalWeb}/PayPalWebResultView.swift (100%) rename Demo/Demo/SwiftUIComponents/{PayPalWebViews => PayPalWeb}/PayPalWebStatusView.swift (94%) diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index 3ac95d057..01b9f10ea 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -17,7 +17,7 @@ 3B4DD9A02A892A7000F4A716 /* CardVaultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B4DD99F2A892A7000F4A716 /* CardVaultView.swift */; }; 3B4DD9A22A8982B000F4A716 /* CardFormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B4DD9A12A8982B000F4A716 /* CardFormView.swift */; }; 3B6472A32AFAE5E3004745C4 /* PayPalWebOrderCompletionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B6472A22AFAE5E3004745C4 /* PayPalWebOrderCompletionView.swift */; }; - 3B6472A72AFAEB3A004745C4 /* PayPalOrderActionButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B6472A62AFAEB3A004745C4 /* PayPalOrderActionButton.swift */; }; + 3B6472A72AFAEB3A004745C4 /* PayPalWebCompleteTransactionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B6472A62AFAEB3A004745C4 /* PayPalWebCompleteTransactionView.swift */; }; 3B80D50E2A291C0800D2EAC4 /* ClientIDRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B80D50D2A291C0800D2EAC4 /* ClientIDRequest.swift */; }; 3B80D5102A291CB100D2EAC4 /* ClientIDResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B80D50F2A291CB100D2EAC4 /* ClientIDResponse.swift */; }; 3B8EF4DB2A932DA300A70D0B /* ErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B8EF4DA2A932DA300A70D0B /* ErrorView.swift */; }; @@ -32,9 +32,9 @@ 3BA56FF82A9FDB5A0081D14F /* CardPaymentOrderCompletionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA56FF72A9FDB5A0081D14F /* CardPaymentOrderCompletionView.swift */; }; 3BA56FFA2A9FE4180081D14F /* CardOrderCompletionResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA56FF92A9FE4180081D14F /* CardOrderCompletionResultView.swift */; }; 3BA56FFC2A9FEFE90081D14F /* PayPalWebViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA56FFB2A9FEFE90081D14F /* PayPalWebViewModel.swift */; }; - 3BA570012AA052E80081D14F /* PayPalWebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA570002AA052E80081D14F /* PayPalWebView.swift */; }; - 3BA570032AA053AE0081D14F /* CreateOrderPayPalWebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA570022AA053AE0081D14F /* CreateOrderPayPalWebView.swift */; }; - 3BA570072AA0DF330081D14F /* PayPalTransactionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA570062AA0DF330081D14F /* PayPalTransactionView.swift */; }; + 3BA570012AA052E80081D14F /* PayPalWebDemoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA570002AA052E80081D14F /* PayPalWebDemoView.swift */; }; + 3BA570032AA053AE0081D14F /* PayPalWebCreateOrderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA570022AA053AE0081D14F /* PayPalWebCreateOrderView.swift */; }; + 3BA570072AA0DF330081D14F /* PayPalWebButtonsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA570062AA0DF330081D14F /* PayPalWebButtonsView.swift */; }; 3BA5700B2AA13C1C0081D14F /* CoreConfigManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA5700A2AA13C1C0081D14F /* CoreConfigManager.swift */; }; 3BB7A9772A5CA6FD00C05140 /* MerchantIntegration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BB7A9762A5CA6FD00C05140 /* MerchantIntegration.swift */; }; 3BC622072A97115700251B85 /* RoundedBlueButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BC622062A97115700251B85 /* RoundedBlueButtonStyle.swift */; }; @@ -137,7 +137,7 @@ 3B4DD99F2A892A7000F4A716 /* CardVaultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardVaultView.swift; sourceTree = ""; }; 3B4DD9A12A8982B000F4A716 /* CardFormView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardFormView.swift; sourceTree = ""; }; 3B6472A22AFAE5E3004745C4 /* PayPalWebOrderCompletionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PayPalWebOrderCompletionView.swift; sourceTree = ""; }; - 3B6472A62AFAEB3A004745C4 /* PayPalOrderActionButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PayPalOrderActionButton.swift; sourceTree = ""; }; + 3B6472A62AFAEB3A004745C4 /* PayPalWebCompleteTransactionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PayPalWebCompleteTransactionView.swift; sourceTree = ""; }; 3B80D50D2A291C0800D2EAC4 /* ClientIDRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientIDRequest.swift; sourceTree = ""; }; 3B80D50F2A291CB100D2EAC4 /* ClientIDResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientIDResponse.swift; sourceTree = ""; }; 3B8EF4DA2A932DA300A70D0B /* ErrorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorView.swift; sourceTree = ""; }; @@ -152,9 +152,9 @@ 3BA56FF72A9FDB5A0081D14F /* CardPaymentOrderCompletionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardPaymentOrderCompletionView.swift; sourceTree = ""; }; 3BA56FF92A9FE4180081D14F /* CardOrderCompletionResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardOrderCompletionResultView.swift; sourceTree = ""; }; 3BA56FFB2A9FEFE90081D14F /* PayPalWebViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalWebViewModel.swift; sourceTree = ""; }; - 3BA570002AA052E80081D14F /* PayPalWebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalWebView.swift; sourceTree = ""; }; - 3BA570022AA053AE0081D14F /* CreateOrderPayPalWebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateOrderPayPalWebView.swift; sourceTree = ""; }; - 3BA570062AA0DF330081D14F /* PayPalTransactionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalTransactionView.swift; sourceTree = ""; }; + 3BA570002AA052E80081D14F /* PayPalWebDemoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalWebDemoView.swift; sourceTree = ""; }; + 3BA570022AA053AE0081D14F /* PayPalWebCreateOrderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalWebCreateOrderView.swift; sourceTree = ""; }; + 3BA570062AA0DF330081D14F /* PayPalWebButtonsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalWebButtonsView.swift; sourceTree = ""; }; 3BA5700A2AA13C1C0081D14F /* CoreConfigManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreConfigManager.swift; sourceTree = ""; }; 3BB7A9762A5CA6FD00C05140 /* MerchantIntegration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MerchantIntegration.swift; sourceTree = ""; }; 3BC622062A97115700251B85 /* RoundedBlueButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundedBlueButtonStyle.swift; sourceTree = ""; }; @@ -271,18 +271,18 @@ path = CardPaymentViews; sourceTree = ""; }; - 3BA56FFF2A9FF6630081D14F /* PayPalWebViews */ = { + 3BA56FFF2A9FF6630081D14F /* PayPalWeb */ = { isa = PBXGroup; children = ( - 3B6472A62AFAEB3A004745C4 /* PayPalOrderActionButton.swift */, + 3B6472A62AFAEB3A004745C4 /* PayPalWebCompleteTransactionView.swift */, 3B6472A22AFAE5E3004745C4 /* PayPalWebOrderCompletionView.swift */, - 3BA570002AA052E80081D14F /* PayPalWebView.swift */, - 3BA570022AA053AE0081D14F /* CreateOrderPayPalWebView.swift */, - 3BA570062AA0DF330081D14F /* PayPalTransactionView.swift */, + 3BA570002AA052E80081D14F /* PayPalWebDemoView.swift */, + 3BA570022AA053AE0081D14F /* PayPalWebCreateOrderView.swift */, + 3BA570062AA0DF330081D14F /* PayPalWebButtonsView.swift */, BE8117632B07E778009867B9 /* PayPalWebResultView.swift */, BE8117652B080202009867B9 /* PayPalWebStatusView.swift */, ); - path = PayPalWebViews; + path = PayPalWeb; sourceTree = ""; }; 3BCCFE472A9D962E00C5102F /* CommonComponents */ = { @@ -449,7 +449,7 @@ BEDE3047275E998700D275FD /* SwiftUIComponents */ = { isa = PBXGroup; children = ( - 3BA56FFF2A9FF6630081D14F /* PayPalWebViews */, + 3BA56FFF2A9FF6630081D14F /* PayPalWeb */, 3BA56FEA2A9DCBB30081D14F /* CardPaymentViews */, 3BCCFE472A9D962E00C5102F /* CommonComponents */, 3B43290F2A8FD7FD00C5441A /* CardVaultViews */, @@ -600,7 +600,7 @@ 3B4DD9A22A8982B000F4A716 /* CardFormView.swift in Sources */, BED04233271084DF00C80954 /* CardFormatter.swift in Sources */, CB9ED44E28411B120081F4DE /* SwiftUIPaymentButtonDemo.swift in Sources */, - 3BA570032AA053AE0081D14F /* CreateOrderPayPalWebView.swift in Sources */, + 3BA570032AA053AE0081D14F /* PayPalWebCreateOrderView.swift in Sources */, 3B22E8BC2A84397600962E34 /* PaymentTokenResponse.swift in Sources */, 3B2027432A8A95EF0007907E /* SetupTokenResultView.swift in Sources */, 3BF999762A8AC093009CBDF2 /* UpdateSetupTokenResultView.swift in Sources */, @@ -635,14 +635,14 @@ 3BA56FFC2A9FEFE90081D14F /* PayPalWebViewModel.swift in Sources */, 3BDB34922A7CB5DE008100D7 /* SetupTokenResponse.swift in Sources */, 3BA56FF22A9DCD440081D14F /* CardApprovalResultView.swift in Sources */, - 3BA570012AA052E80081D14F /* PayPalWebView.swift in Sources */, + 3BA570012AA052E80081D14F /* PayPalWebDemoView.swift in Sources */, CBC16DD929ED90B600307117 /* UpdateOrderParams.swift in Sources */, 3BA56FFA2A9FE4180081D14F /* CardOrderCompletionResultView.swift in Sources */, 3BA56FF42A9DCD790081D14F /* CardPaymentView.swift in Sources */, BE9F36D82745490400AFC7DA /* FloatingLabelTextField.swift in Sources */, 3B20273D2A89E3F00007907E /* CreateSetupTokenView.swift in Sources */, 3B22E8BA2A842D8900962E34 /* PaymentTokenRequest.swift in Sources */, - 3BA570072AA0DF330081D14F /* PayPalTransactionView.swift in Sources */, + 3BA570072AA0DF330081D14F /* PayPalWebButtonsView.swift in Sources */, 3BCCFE492A9D96CA00C5102F /* DemoApp.swift in Sources */, 3BA56FEC2A9DCBF30081D14F /* CreateOrderCardPaymentView.swift in Sources */, 536A5CA82898AA2A005C053D /* SwiftUINativeCheckoutDemo.swift in Sources */, @@ -650,7 +650,7 @@ BC6460CD2A12A2A0002B974B /* EmptyBodyParams.swift in Sources */, 3BF999782A8AD072009CBDF2 /* CreatePaymentTokenView.swift in Sources */, BED042312710833F00C80954 /* CardType.swift in Sources */, - 3B6472A72AFAEB3A004745C4 /* PayPalOrderActionButton.swift in Sources */, + 3B6472A72AFAEB3A004745C4 /* PayPalWebCompleteTransactionView.swift in Sources */, 5301468C28918B4D00184F22 /* ApprovalResult.swift in Sources */, 3BC6220B2A97204E00251B85 /* CircularProgressView.swift in Sources */, ); diff --git a/Demo/Demo/SwiftUIComponents/FeatureSelectionView.swift b/Demo/Demo/SwiftUIComponents/FeatureSelectionView.swift index 9ee0771f4..dac2876fa 100644 --- a/Demo/Demo/SwiftUIComponents/FeatureSelectionView.swift +++ b/Demo/Demo/SwiftUIComponents/FeatureSelectionView.swift @@ -38,10 +38,10 @@ struct FeatureSelectionView: View { Text("Card Vaulting") } NavigationLink { - PayPalWebView() - .navigationTitle("PayPalWeb Payment") + PayPalWebDemoView() + .navigationTitle("PayPal Web") } label: { - Text("PayPalWeb Payment") + Text("PayPal Web") } NavigationLink { SwiftUINativeCheckoutDemo() diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalTransactionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift similarity index 94% rename from Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalTransactionView.swift rename to Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift index 74a1cd1c5..bcccbddf9 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalTransactionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift @@ -1,7 +1,7 @@ import SwiftUI import PaymentButtons -struct PayPalTransactionView: View { +struct PayPalWebButtonsView: View { @ObservedObject var payPalWebViewModel: PayPalWebViewModel @@ -34,7 +34,7 @@ struct PayPalTransactionView: View { NavigationLink { PayPalWebOrderCompletionView(payPalWebViewModel: payPalWebViewModel) } label: { - Text("Complete Order Transaction") + Text("Complete Transaction") } .buttonStyle(RoundedBlueButtonStyle()) .padding() diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalOrderActionButton.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCompleteTransactionView.swift similarity index 51% rename from Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalOrderActionButton.swift rename to Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCompleteTransactionView.swift index 3fe849478..0ed879925 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalOrderActionButton.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCompleteTransactionView.swift @@ -1,37 +1,30 @@ import SwiftUI -struct PayPalOrderActionButton: View { +struct PayPalWebCompleteTransactionView: View { let intent: Intent let orderID: String - let selectedMerchantIntegration: MerchantIntegration @ObservedObject var payPalWebViewModel: PayPalWebViewModel var body: some View { VStack { - if payPalWebViewModel.state == .loading { - CircularProgressView() - } else if payPalWebViewModel.state == .loaded { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .approved) - } - + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .approved) Button("\(intent.rawValue)") { - completeOrder() + completeTransaction() } .buttonStyle(RoundedBlueButtonStyle()) .padding() + if payPalWebViewModel.state == .loading { + CircularProgressView() + } } } - private func completeOrder() { + private func completeTransaction() { Task { do { - try await payPalWebViewModel.completeOrder( - with: intent, - orderID: orderID, - selectedMerchantIntegration: selectedMerchantIntegration - ) + try await payPalWebViewModel.completeOrder(with: intent, orderID: orderID) } catch { print("Error capturing order: \(error.localizedDescription)") } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/CreateOrderPayPalWebView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCreateOrderView.swift similarity index 85% rename from Demo/Demo/SwiftUIComponents/PayPalWebViews/CreateOrderPayPalWebView.swift rename to Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCreateOrderView.swift index 514efddcd..bb760fa6f 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/CreateOrderPayPalWebView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCreateOrderView.swift @@ -1,6 +1,6 @@ import SwiftUI -struct CreateOrderPayPalWebView: View { +struct PayPalWebCreateOrderView: View { @ObservedObject var paypalWebViewModel: PayPalWebViewModel @@ -27,10 +27,7 @@ struct CreateOrderPayPalWebView: View { Task { do { paypalWebViewModel.intent = selectedIntent - try await paypalWebViewModel.createOrder( - amount: "10.00", - selectedMerchantIntegration: DemoSettings.merchantIntegration, - intent: selectedIntent.rawValue) + try await paypalWebViewModel.createOrder(amount: "10.00", intent: selectedIntent.rawValue) } catch { print("Error in getting setup token. \(error.localizedDescription)") } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebDemoView.swift similarity index 72% rename from Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebView.swift rename to Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebDemoView.swift index 7b05e16c4..eb6f2696d 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebDemoView.swift @@ -1,24 +1,24 @@ import SwiftUI import PaymentButtons -struct PayPalWebView: View { +struct PayPalWebDemoView: View { @StateObject var payPalWebViewModel = PayPalWebViewModel() var body: some View { ScrollView { VStack(spacing: 16) { - CreateOrderPayPalWebView( + PayPalWebCreateOrderView( paypalWebViewModel: payPalWebViewModel, selectedMerchantIntegration: DemoSettings.merchantIntegration ) if let order = payPalWebViewModel.order { PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .started) NavigationLink { - PayPalTransactionView(payPalWebViewModel: payPalWebViewModel) - .navigationTitle("PayPal Transactions") + PayPalWebButtonsView(payPalWebViewModel: payPalWebViewModel) + .navigationTitle("Checkout with PayPal") } label: { - Text("PayPal Transactions") + Text("Checkout with PayPal") } .buttonStyle(RoundedBlueButtonStyle()) .padding() diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebOrderCompletionView.swift similarity index 66% rename from Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionView.swift rename to Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebOrderCompletionView.swift index f0ba1085f..3c17be0a5 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebOrderCompletionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebOrderCompletionView.swift @@ -5,25 +5,23 @@ struct PayPalWebOrderCompletionView: View { @ObservedObject var payPalWebViewModel: PayPalWebViewModel var body: some View { - let state = payPalWebViewModel.state ScrollView { ScrollViewReader { scrollView in VStack { if let orderID = payPalWebViewModel.order?.id { - PayPalOrderActionButton( + PayPalWebCompleteTransactionView( intent: payPalWebViewModel.intent, orderID: orderID, - selectedMerchantIntegration: DemoSettings.merchantIntegration, payPalWebViewModel: payPalWebViewModel ) Text("") .id("bottomView") Spacer() - .onChange(of: state) { _ in - withAnimation { - scrollView.scrollTo("bottomView") + .onChange(of: payPalWebViewModel.state) { _ in + withAnimation { + scrollView.scrollTo("bottomView") + } } - } } } } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebResultView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift similarity index 100% rename from Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebResultView.swift rename to Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebStatusView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift similarity index 94% rename from Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebStatusView.swift rename to Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift index b77b656ab..a986f7efe 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebViews/PayPalWebStatusView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift @@ -11,7 +11,7 @@ struct PayPalWebStatusView: View { switch status { case .started: HStack { - Text("Order") + Text("Order Created") .font(.system(size: 20)) Spacer() } @@ -38,7 +38,7 @@ struct PayPalWebStatusView: View { case .completed: if let order = payPalViewModel.order { HStack { - Text("Order \(intent.rawValue)") + Text("Order \(intent.rawValue.lowercased())") .font(.system(size: 20)) Spacer() } diff --git a/Demo/Demo/ViewModels/PayPalWebViewModel.swift b/Demo/Demo/ViewModels/PayPalWebViewModel.swift index 2cda64b49..d588be5ff 100644 --- a/Demo/Demo/ViewModels/PayPalWebViewModel.swift +++ b/Demo/Demo/ViewModels/PayPalWebViewModel.swift @@ -13,7 +13,7 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { let configManager = CoreConfigManager(domain: "PayPalWeb Payments") - func createOrder(amount: String, selectedMerchantIntegration: MerchantIntegration, intent: String) async throws { + func createOrder(amount: String, intent: String) async throws { let amountRequest = Amount(currencyCode: "USD", value: amount) // TODO: might need to pass in payee as payee object or as auth header let orderRequestParams = CreateOrderParams( @@ -27,7 +27,7 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { self.state = .loading } let order = try await DemoMerchantAPI.sharedService.createOrder( - orderParams: orderRequestParams, selectedMerchantIntegration: selectedMerchantIntegration + orderParams: orderRequestParams, selectedMerchantIntegration: DemoSettings.merchantIntegration ) DispatchQueue.main.async { self.state = .loaded @@ -80,23 +80,23 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { } } - func completeOrder(with intent: Intent, orderID: String, selectedMerchantIntegration: MerchantIntegration) async throws { + func completeOrder(with intent: Intent, orderID: String) async throws { switch intent { case .capture: - try await captureOrder(orderID: orderID, selectedMerchantIntegration: selectedMerchantIntegration) + try await captureOrder(orderID: orderID) case .authorize: - try await authorizeOrder(orderID: orderID, selectedMerchantIntegration: selectedMerchantIntegration) + try await authorizeOrder(orderID: orderID) } } - func captureOrder(orderID: String, selectedMerchantIntegration: MerchantIntegration) async throws { + func captureOrder(orderID: String) async throws { do { DispatchQueue.main.async { self.state = .loading } - let order = try await DemoMerchantAPI.sharedService.captureOrder( + try await DemoMerchantAPI.sharedService.captureOrder( orderID: orderID, - selectedMerchantIntegration: selectedMerchantIntegration + selectedMerchantIntegration: DemoSettings.merchantIntegration ) DispatchQueue.main.async { self.state = .loaded @@ -109,14 +109,14 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { } } - func authorizeOrder(orderID: String, selectedMerchantIntegration: MerchantIntegration) async throws { + func authorizeOrder(orderID: String) async throws { do { DispatchQueue.main.async { self.state = .loading } - let order = try await DemoMerchantAPI.sharedService.authorizeOrder( + try await DemoMerchantAPI.sharedService.authorizeOrder( orderID: orderID, - selectedMerchantIntegration: selectedMerchantIntegration + selectedMerchantIntegration: DemoSettings.merchantIntegration ) DispatchQueue.main.async { self.state = .loaded From 4474449b7207fa958c03bcb6a587925c2a31dc8a Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Mon, 20 Nov 2023 11:58:18 -0600 Subject: [PATCH 08/31] cleanup how data is passed --- Demo/Demo.xcodeproj/project.pbxproj | 6 ++--- .../PayPalWeb/PayPalWebButtonsView.swift | 2 +- .../PayPalWebCompleteTransactionView.swift | 7 ++---- .../PayPalWeb/PayPalWebCreateOrderView.swift | 2 -- .../PayPalWeb/PayPalWebDemoView.swift | 5 +---- .../PayPalWebOrderCompletionView.swift | 22 +++++++------------ Demo/Demo/ViewModels/PayPalWebViewModel.swift | 14 +++++++----- 7 files changed, 23 insertions(+), 35 deletions(-) diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index 01b9f10ea..59f38fb6f 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -274,11 +274,11 @@ 3BA56FFF2A9FF6630081D14F /* PayPalWeb */ = { isa = PBXGroup; children = ( + 3BA570062AA0DF330081D14F /* PayPalWebButtonsView.swift */, 3B6472A62AFAEB3A004745C4 /* PayPalWebCompleteTransactionView.swift */, - 3B6472A22AFAE5E3004745C4 /* PayPalWebOrderCompletionView.swift */, - 3BA570002AA052E80081D14F /* PayPalWebDemoView.swift */, 3BA570022AA053AE0081D14F /* PayPalWebCreateOrderView.swift */, - 3BA570062AA0DF330081D14F /* PayPalWebButtonsView.swift */, + 3BA570002AA052E80081D14F /* PayPalWebDemoView.swift */, + 3B6472A22AFAE5E3004745C4 /* PayPalWebOrderCompletionView.swift */, BE8117632B07E778009867B9 /* PayPalWebResultView.swift */, BE8117652B080202009867B9 /* PayPalWebStatusView.swift */, ); diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift index bcccbddf9..26ec13597 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift @@ -3,7 +3,7 @@ import PaymentButtons struct PayPalWebButtonsView: View { - @ObservedObject var payPalWebViewModel: PayPalWebViewModel + @ObservedObject var payPalWebViewModel = PayPalWebViewModel() var body: some View { VStack { diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCompleteTransactionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCompleteTransactionView.swift index 0ed879925..5dd03a2e6 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCompleteTransactionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCompleteTransactionView.swift @@ -2,15 +2,12 @@ import SwiftUI struct PayPalWebCompleteTransactionView: View { - let intent: Intent - let orderID: String - @ObservedObject var payPalWebViewModel: PayPalWebViewModel var body: some View { VStack { PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .approved) - Button("\(intent.rawValue)") { + Button("\(payPalWebViewModel.intent.rawValue)") { completeTransaction() } .buttonStyle(RoundedBlueButtonStyle()) @@ -24,7 +21,7 @@ struct PayPalWebCompleteTransactionView: View { private func completeTransaction() { Task { do { - try await payPalWebViewModel.completeOrder(with: intent, orderID: orderID) + try await payPalWebViewModel.completeOrder() } catch { print("Error capturing order: \(error.localizedDescription)") } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCreateOrderView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCreateOrderView.swift index bb760fa6f..29479106b 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCreateOrderView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCreateOrderView.swift @@ -6,8 +6,6 @@ struct PayPalWebCreateOrderView: View { @State private var selectedIntent: Intent = .authorize - let selectedMerchantIntegration: MerchantIntegration - var body: some View { VStack(spacing: 16) { HStack { diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebDemoView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebDemoView.swift index eb6f2696d..e2d03194b 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebDemoView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebDemoView.swift @@ -8,10 +8,7 @@ struct PayPalWebDemoView: View { var body: some View { ScrollView { VStack(spacing: 16) { - PayPalWebCreateOrderView( - paypalWebViewModel: payPalWebViewModel, - selectedMerchantIntegration: DemoSettings.merchantIntegration - ) + PayPalWebCreateOrderView(paypalWebViewModel: payPalWebViewModel) if let order = payPalWebViewModel.order { PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .started) NavigationLink { diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebOrderCompletionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebOrderCompletionView.swift index 3c17be0a5..50ec0d894 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebOrderCompletionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebOrderCompletionView.swift @@ -8,21 +8,15 @@ struct PayPalWebOrderCompletionView: View { ScrollView { ScrollViewReader { scrollView in VStack { - if let orderID = payPalWebViewModel.order?.id { - PayPalWebCompleteTransactionView( - intent: payPalWebViewModel.intent, - orderID: orderID, - payPalWebViewModel: payPalWebViewModel - ) - Text("") - .id("bottomView") - Spacer() - .onChange(of: payPalWebViewModel.state) { _ in - withAnimation { - scrollView.scrollTo("bottomView") - } + PayPalWebCompleteTransactionView(payPalWebViewModel: payPalWebViewModel) + Text("") + .id("bottomView") + Spacer() + .onChange(of: payPalWebViewModel.state) { _ in + withAnimation { + scrollView.scrollTo("bottomView") } - } + } } } } diff --git a/Demo/Demo/ViewModels/PayPalWebViewModel.swift b/Demo/Demo/ViewModels/PayPalWebViewModel.swift index d588be5ff..109c28fd7 100644 --- a/Demo/Demo/ViewModels/PayPalWebViewModel.swift +++ b/Demo/Demo/ViewModels/PayPalWebViewModel.swift @@ -80,12 +80,14 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { } } - func completeOrder(with intent: Intent, orderID: String) async throws { - switch intent { - case .capture: - try await captureOrder(orderID: orderID) - case .authorize: - try await authorizeOrder(orderID: orderID) + func completeOrder() async throws { + if let orderID = order?.id { + switch intent { + case .capture: + try await captureOrder(orderID: orderID) + case .authorize: + try await authorizeOrder(orderID: orderID) + } } } From 72aaa7a1572327bac9f891ac83d709352bfa1bec Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Mon, 20 Nov 2023 14:19:40 -0600 Subject: [PATCH 09/31] add new state and general cleanup --- .../Demo/SwiftUIComponents/CurrentState.swift | 3 +- .../PayPalWeb/PayPalWebButtonsView.swift | 2 +- .../PayPalWebCompleteTransactionView.swift | 18 ++++--- .../PayPalWeb/PayPalWebCreateOrderView.swift | 2 +- .../PayPalWeb/PayPalWebDemoView.swift | 2 +- .../PayPalWeb/PayPalWebResultView.swift | 2 +- .../PayPalWeb/PayPalWebStatusView.swift | 7 ++- Demo/Demo/ViewModels/PayPalWebViewModel.swift | 50 +++++++++---------- 8 files changed, 47 insertions(+), 39 deletions(-) diff --git a/Demo/Demo/SwiftUIComponents/CurrentState.swift b/Demo/Demo/SwiftUIComponents/CurrentState.swift index c2fa43d24..a5eb2bdb7 100644 --- a/Demo/Demo/SwiftUIComponents/CurrentState.swift +++ b/Demo/Demo/SwiftUIComponents/CurrentState.swift @@ -4,6 +4,7 @@ enum CurrentState: Equatable { case idle case loading - case error(message: String) case loaded + case success + case error(message: String) } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift index 26ec13597..bcccbddf9 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift @@ -3,7 +3,7 @@ import PaymentButtons struct PayPalWebButtonsView: View { - @ObservedObject var payPalWebViewModel = PayPalWebViewModel() + @ObservedObject var payPalWebViewModel: PayPalWebViewModel var body: some View { VStack { diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCompleteTransactionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCompleteTransactionView.swift index 5dd03a2e6..b3f161c0a 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCompleteTransactionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCompleteTransactionView.swift @@ -5,15 +5,21 @@ struct PayPalWebCompleteTransactionView: View { @ObservedObject var payPalWebViewModel: PayPalWebViewModel var body: some View { - VStack { + VStack(spacing: 16) { PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .approved) - Button("\(payPalWebViewModel.intent.rawValue)") { - completeTransaction() + ZStack { + Button("\(payPalWebViewModel.intent.rawValue)") { + completeTransaction() + } + .buttonStyle(RoundedBlueButtonStyle()) + if payPalWebViewModel.state == .loading { + CircularProgressView() + } } - .buttonStyle(RoundedBlueButtonStyle()) .padding() - if payPalWebViewModel.state == .loading { - CircularProgressView() + + if payPalWebViewModel.state == .success { + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .completed) } } } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCreateOrderView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCreateOrderView.swift index 29479106b..e83ade226 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCreateOrderView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCreateOrderView.swift @@ -25,7 +25,7 @@ struct PayPalWebCreateOrderView: View { Task { do { paypalWebViewModel.intent = selectedIntent - try await paypalWebViewModel.createOrder(amount: "10.00", intent: selectedIntent.rawValue) + try await paypalWebViewModel.createOrder() } catch { print("Error in getting setup token. \(error.localizedDescription)") } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebDemoView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebDemoView.swift index e2d03194b..9bd222f75 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebDemoView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebDemoView.swift @@ -9,7 +9,7 @@ struct PayPalWebDemoView: View { ScrollView { VStack(spacing: 16) { PayPalWebCreateOrderView(paypalWebViewModel: payPalWebViewModel) - if let order = payPalWebViewModel.order { + if payPalWebViewModel.order != nil { PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .started) NavigationLink { PayPalWebButtonsView(payPalWebViewModel: payPalWebViewModel) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift index 0d4d721c4..ec96c8fa0 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift @@ -16,7 +16,7 @@ struct PayPalWebResultView: View { switch payPalWebViewModel.state { case .idle, .loading: EmptyView() - case .loaded: + case .loaded, .success: PayPalWebStatusView(status: status, intent: payPalWebViewModel.intent, payPalViewModel: payPalWebViewModel) case .error(let errorMessage): ErrorView(errorMessage: errorMessage) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift index a986f7efe..4fe24bf25 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift @@ -38,7 +38,7 @@ struct PayPalWebStatusView: View { case .completed: if let order = payPalViewModel.order { HStack { - Text("Order \(intent.rawValue.lowercased())") + Text("Order \(intent.rawValue.capitalized)d") .font(.system(size: 20)) Spacer() } @@ -46,6 +46,11 @@ struct PayPalWebStatusView: View { LeadingText("\(order.id)") LeadingText("Status", weight: .bold) LeadingText("\(order.status)") + + if let emailAddress = payPalViewModel.order?.paymentSource?.paypal?.emailAddress { + LeadingText("Email", weight: .bold) + LeadingText("\(emailAddress)") + } } } } diff --git a/Demo/Demo/ViewModels/PayPalWebViewModel.swift b/Demo/Demo/ViewModels/PayPalWebViewModel.swift index 109c28fd7..697f41290 100644 --- a/Demo/Demo/ViewModels/PayPalWebViewModel.swift +++ b/Demo/Demo/ViewModels/PayPalWebViewModel.swift @@ -13,12 +13,12 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { let configManager = CoreConfigManager(domain: "PayPalWeb Payments") - func createOrder(amount: String, intent: String) async throws { - let amountRequest = Amount(currencyCode: "USD", value: amount) + func createOrder() async throws { + let amountRequest = Amount(currencyCode: "USD", value: "10.00") // TODO: might need to pass in payee as payee object or as auth header let orderRequestParams = CreateOrderParams( applicationContext: nil, - intent: intent, + intent: intent.rawValue, purchaseUnits: [PurchaseUnit(amount: amountRequest)] ) @@ -27,7 +27,8 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { self.state = .loading } let order = try await DemoMerchantAPI.sharedService.createOrder( - orderParams: orderRequestParams, selectedMerchantIntegration: DemoSettings.merchantIntegration + orderParams: orderRequestParams, + selectedMerchantIntegration: DemoSettings.merchantIntegration ) DispatchQueue.main.async { self.state = .loaded @@ -37,30 +38,27 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { } catch { DispatchQueue.main.async { self.state = .error(message: error.localizedDescription) - print("❌ failed to fetch orderID: \(error)") + print("❌ failed to fetch orderID with error: \(error.localizedDescription)") } } } func paymentButtonTapped(funding: PayPalWebCheckoutFundingSource) { - if let orderID = order?.id { - checkoutWithPayPal(orderID: orderID, funding: funding) - } - } - - func checkoutWithPayPal(orderID: String, funding: PayPalWebCheckoutFundingSource) { Task { do { payPalWebCheckoutClient = try await getPayPalClient() payPalWebCheckoutClient?.delegate = self guard let client = payPalWebCheckoutClient else { - print("Error in initializing paypal webcheckout client") + print("Error initializing PayPalWebCheckoutClient") return } - let payPalRequest = PayPalWebCheckoutRequest(orderID: orderID, fundingSource: funding) - client.start(request: payPalRequest) + + if let orderID = order?.id { + let payPalRequest = PayPalWebCheckoutRequest(orderID: orderID, fundingSource: funding) + client.start(request: payPalRequest) + } } catch { - print("Error in starting paypal webcheckout client") + print("Error starting PayPalWebCheckoutClient") state = .error(message: error.localizedDescription) } } @@ -74,12 +72,6 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { } } - func paypalWebCheckoutFailureResult(checkoutError: CorePayments.CoreSDKError) { - DispatchQueue.main.async { - self.state = .error(message: checkoutError.localizedDescription) - } - } - func completeOrder() async throws { if let orderID = order?.id { switch intent { @@ -96,18 +88,19 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { DispatchQueue.main.async { self.state = .loading } - try await DemoMerchantAPI.sharedService.captureOrder( + let order = try await DemoMerchantAPI.sharedService.captureOrder( orderID: orderID, selectedMerchantIntegration: DemoSettings.merchantIntegration ) DispatchQueue.main.async { - self.state = .loaded + self.order = order + self.state = .success } } catch { DispatchQueue.main.async { self.state = .error(message: error.localizedDescription) } - print("Error capturing order: \(error.localizedDescription)") + print("Error capturing order with error: \(error.localizedDescription)") } } @@ -116,12 +109,13 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { DispatchQueue.main.async { self.state = .loading } - try await DemoMerchantAPI.sharedService.authorizeOrder( + let order = try await DemoMerchantAPI.sharedService.authorizeOrder( orderID: orderID, selectedMerchantIntegration: DemoSettings.merchantIntegration ) DispatchQueue.main.async { - self.state = .loaded + self.order = order + self.state = .success } } catch { DispatchQueue.main.async { @@ -141,7 +135,9 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { } func payPal(_ payPalClient: PayPalWebPayments.PayPalWebCheckoutClient, didFinishWithError error: CorePayments.CoreSDKError) { - paypalWebCheckoutFailureResult(checkoutError: error) + DispatchQueue.main.async { + self.state = .error(message: error.localizedDescription) + } } func payPalDidCancel(_ payPalClient: PayPalWebPayments.PayPalWebCheckoutClient) { From 5a0209058384373836c4e4914b7942c94ae0f75a Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Mon, 20 Nov 2023 15:17:29 -0600 Subject: [PATCH 10/31] cleanup funding source name, remove redundant types --- .../PayPalWeb/PayPalWebButtonsView.swift | 2 +- .../PayPalWebCompleteTransactionView.swift | 19 +++++++------------ .../PayPalWeb/PayPalWebCreateOrderView.swift | 10 +++++----- .../PayPalWeb/PayPalWebDemoView.swift | 2 +- .../PayPalWebOrderCompletionView.swift | 11 ++++++++++- Demo/Demo/ViewModels/PayPalWebViewModel.swift | 4 ++-- .../PayPalWebCheckoutFundingSource.swift | 2 +- 7 files changed, 27 insertions(+), 23 deletions(-) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift index bcccbddf9..bdbe2d576 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift @@ -17,7 +17,7 @@ struct PayPalWebButtonsView: View { } .frame(maxWidth: .infinity, maxHeight: 40) PayPalPayLaterButton.Representable(color: .silver, edges: .rounded, size: .full) { - payPalWebViewModel.paymentButtonTapped(funding: .paylater) + payPalWebViewModel.paymentButtonTapped(funding: .payLater) } .frame(maxWidth: .infinity, maxHeight: 40) } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCompleteTransactionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCompleteTransactionView.swift index b3f161c0a..7e0a35341 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCompleteTransactionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCompleteTransactionView.swift @@ -1,25 +1,20 @@ import SwiftUI +// TODO: maybe button view? struct PayPalWebCompleteTransactionView: View { @ObservedObject var payPalWebViewModel: PayPalWebViewModel var body: some View { - VStack(spacing: 16) { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .approved) - ZStack { - Button("\(payPalWebViewModel.intent.rawValue)") { - completeTransaction() - } - .buttonStyle(RoundedBlueButtonStyle()) - if payPalWebViewModel.state == .loading { - CircularProgressView() - } + ZStack { + Button("\(payPalWebViewModel.intent.rawValue)") { + completeTransaction() } + .buttonStyle(RoundedBlueButtonStyle()) .padding() - if payPalWebViewModel.state == .success { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .completed) + if payPalWebViewModel.state == .loading { + CircularProgressView() } } } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCreateOrderView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCreateOrderView.swift index e83ade226..b6910f854 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCreateOrderView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCreateOrderView.swift @@ -2,12 +2,12 @@ import SwiftUI struct PayPalWebCreateOrderView: View { - @ObservedObject var paypalWebViewModel: PayPalWebViewModel + @ObservedObject var payPalWebViewModel: PayPalWebViewModel @State private var selectedIntent: Intent = .authorize var body: some View { - VStack(spacing: 16) { + VStack { HStack { Text("Create an Order") .font(.system(size: 20)) @@ -24,15 +24,15 @@ struct PayPalWebCreateOrderView: View { Button("Create an Order") { Task { do { - paypalWebViewModel.intent = selectedIntent - try await paypalWebViewModel.createOrder() + payPalWebViewModel.intent = selectedIntent + try await payPalWebViewModel.createOrder() } catch { print("Error in getting setup token. \(error.localizedDescription)") } } } .buttonStyle(RoundedBlueButtonStyle()) - if case .loading = paypalWebViewModel.state { + if payPalWebViewModel.state == .loading { CircularProgressView() } } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebDemoView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebDemoView.swift index 9bd222f75..8e860365e 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebDemoView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebDemoView.swift @@ -8,7 +8,7 @@ struct PayPalWebDemoView: View { var body: some View { ScrollView { VStack(spacing: 16) { - PayPalWebCreateOrderView(paypalWebViewModel: payPalWebViewModel) + PayPalWebCreateOrderView(payPalWebViewModel: payPalWebViewModel) if payPalWebViewModel.order != nil { PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .started) NavigationLink { diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebOrderCompletionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebOrderCompletionView.swift index 50ec0d894..ecf11ab6f 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebOrderCompletionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebOrderCompletionView.swift @@ -1,5 +1,6 @@ import SwiftUI +// TODO: maybe transaction view struct PayPalWebOrderCompletionView: View { @ObservedObject var payPalWebViewModel: PayPalWebViewModel @@ -8,7 +9,15 @@ struct PayPalWebOrderCompletionView: View { ScrollView { ScrollViewReader { scrollView in VStack { - PayPalWebCompleteTransactionView(payPalWebViewModel: payPalWebViewModel) + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .approved) + + if payPalWebViewModel.checkoutResult != nil { + PayPalWebCompleteTransactionView(payPalWebViewModel: payPalWebViewModel) + } + + if payPalWebViewModel.state == .success { + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .completed) + } Text("") .id("bottomView") Spacer() diff --git a/Demo/Demo/ViewModels/PayPalWebViewModel.swift b/Demo/Demo/ViewModels/PayPalWebViewModel.swift index 697f41290..c483e0db3 100644 --- a/Demo/Demo/ViewModels/PayPalWebViewModel.swift +++ b/Demo/Demo/ViewModels/PayPalWebViewModel.swift @@ -134,13 +134,13 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { checkoutResult = result } - func payPal(_ payPalClient: PayPalWebPayments.PayPalWebCheckoutClient, didFinishWithError error: CorePayments.CoreSDKError) { + func payPal(_ payPalClient: PayPalWebCheckoutClient, didFinishWithError error: CoreSDKError) { DispatchQueue.main.async { self.state = .error(message: error.localizedDescription) } } - func payPalDidCancel(_ payPalClient: PayPalWebPayments.PayPalWebCheckoutClient) { + func payPalDidCancel(_ payPalClient: PayPalWebCheckoutClient) { print("PayPal Checkout Canceled") } } diff --git a/Sources/PayPalWebPayments/PayPalWebCheckoutFundingSource.swift b/Sources/PayPalWebPayments/PayPalWebCheckoutFundingSource.swift index 3f0edf218..48fcd877c 100644 --- a/Sources/PayPalWebPayments/PayPalWebCheckoutFundingSource.swift +++ b/Sources/PayPalWebPayments/PayPalWebCheckoutFundingSource.swift @@ -8,7 +8,7 @@ public enum PayPalWebCheckoutFundingSource: String { /// PayLater will launch the web checkout flow and display Pay Later offers to eligible customers, /// which include short-term, interest-free payments and other special financing options - case paylater = "paylater" + case payLater = "paylater" /// PayPal will launch the web checkout for a one-time PayPal Checkout flow case paypal = "paypal" From 9e8019b11420ae10f0955d32bc9cd180ff7f324d Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Tue, 21 Nov 2023 08:06:18 -0600 Subject: [PATCH 11/31] cleanup views and remove order completion view --- Demo/Demo.xcodeproj/project.pbxproj | 4 -- .../PayPalWeb/PayPalWebButtonsView.swift | 3 +- .../PayPalWebCompleteTransactionView.swift | 37 ++++++++++--------- .../PayPalWebOrderCompletionView.swift | 33 ----------------- 4 files changed, 21 insertions(+), 56 deletions(-) delete mode 100644 Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebOrderCompletionView.swift diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index 59f38fb6f..4e9723f3b 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -16,7 +16,6 @@ 3B22E8BC2A84397600962E34 /* PaymentTokenResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B22E8BB2A84397600962E34 /* PaymentTokenResponse.swift */; }; 3B4DD9A02A892A7000F4A716 /* CardVaultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B4DD99F2A892A7000F4A716 /* CardVaultView.swift */; }; 3B4DD9A22A8982B000F4A716 /* CardFormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B4DD9A12A8982B000F4A716 /* CardFormView.swift */; }; - 3B6472A32AFAE5E3004745C4 /* PayPalWebOrderCompletionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B6472A22AFAE5E3004745C4 /* PayPalWebOrderCompletionView.swift */; }; 3B6472A72AFAEB3A004745C4 /* PayPalWebCompleteTransactionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B6472A62AFAEB3A004745C4 /* PayPalWebCompleteTransactionView.swift */; }; 3B80D50E2A291C0800D2EAC4 /* ClientIDRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B80D50D2A291C0800D2EAC4 /* ClientIDRequest.swift */; }; 3B80D5102A291CB100D2EAC4 /* ClientIDResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B80D50F2A291CB100D2EAC4 /* ClientIDResponse.swift */; }; @@ -136,7 +135,6 @@ 3B22E8BB2A84397600962E34 /* PaymentTokenResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaymentTokenResponse.swift; sourceTree = ""; }; 3B4DD99F2A892A7000F4A716 /* CardVaultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardVaultView.swift; sourceTree = ""; }; 3B4DD9A12A8982B000F4A716 /* CardFormView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardFormView.swift; sourceTree = ""; }; - 3B6472A22AFAE5E3004745C4 /* PayPalWebOrderCompletionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PayPalWebOrderCompletionView.swift; sourceTree = ""; }; 3B6472A62AFAEB3A004745C4 /* PayPalWebCompleteTransactionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PayPalWebCompleteTransactionView.swift; sourceTree = ""; }; 3B80D50D2A291C0800D2EAC4 /* ClientIDRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientIDRequest.swift; sourceTree = ""; }; 3B80D50F2A291CB100D2EAC4 /* ClientIDResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientIDResponse.swift; sourceTree = ""; }; @@ -278,7 +276,6 @@ 3B6472A62AFAEB3A004745C4 /* PayPalWebCompleteTransactionView.swift */, 3BA570022AA053AE0081D14F /* PayPalWebCreateOrderView.swift */, 3BA570002AA052E80081D14F /* PayPalWebDemoView.swift */, - 3B6472A22AFAE5E3004745C4 /* PayPalWebOrderCompletionView.swift */, BE8117632B07E778009867B9 /* PayPalWebResultView.swift */, BE8117652B080202009867B9 /* PayPalWebStatusView.swift */, ); @@ -630,7 +627,6 @@ 3B2027452A8AA78B0007907E /* UpdateSetupTokenView.swift in Sources */, 3BA56FF82A9FDB5A0081D14F /* CardPaymentOrderCompletionView.swift in Sources */, 3B8EF4DB2A932DA300A70D0B /* ErrorView.swift in Sources */, - 3B6472A32AFAE5E3004745C4 /* PayPalWebOrderCompletionView.swift in Sources */, 3BF9997A2A8AE12C009CBDF2 /* PaymentTokenResultView.swift in Sources */, 3BA56FFC2A9FEFE90081D14F /* PayPalWebViewModel.swift in Sources */, 3BDB34922A7CB5DE008100D7 /* SetupTokenResponse.swift in Sources */, diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift index bdbe2d576..1af7f4a23 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift @@ -32,7 +32,8 @@ struct PayPalWebButtonsView: View { if payPalWebViewModel.checkoutResult != nil { PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .approved) NavigationLink { - PayPalWebOrderCompletionView(payPalWebViewModel: payPalWebViewModel) + PayPalWebCompleteTransactionView(payPalWebViewModel: payPalWebViewModel) + .navigationTitle("Complete Transaction") } label: { Text("Complete Transaction") } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCompleteTransactionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCompleteTransactionView.swift index 7e0a35341..7c27639f9 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCompleteTransactionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCompleteTransactionView.swift @@ -1,30 +1,31 @@ import SwiftUI -// TODO: maybe button view? struct PayPalWebCompleteTransactionView: View { @ObservedObject var payPalWebViewModel: PayPalWebViewModel var body: some View { - ZStack { - Button("\(payPalWebViewModel.intent.rawValue)") { - completeTransaction() + VStack { + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .approved) + ZStack { + Button("\(payPalWebViewModel.intent.rawValue)") { + Task { + do { + try await payPalWebViewModel.completeOrder() + } catch { + print("Error capturing order: \(error.localizedDescription)") + } + } + } + .buttonStyle(RoundedBlueButtonStyle()) + .padding() + if payPalWebViewModel.state == .loading { + CircularProgressView() + } } - .buttonStyle(RoundedBlueButtonStyle()) - .padding() - if payPalWebViewModel.state == .loading { - CircularProgressView() - } - } - } - - private func completeTransaction() { - Task { - do { - try await payPalWebViewModel.completeOrder() - } catch { - print("Error capturing order: \(error.localizedDescription)") + if payPalWebViewModel.state == .success { + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .completed) } } } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebOrderCompletionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebOrderCompletionView.swift deleted file mode 100644 index ecf11ab6f..000000000 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebOrderCompletionView.swift +++ /dev/null @@ -1,33 +0,0 @@ -import SwiftUI - -// TODO: maybe transaction view -struct PayPalWebOrderCompletionView: View { - - @ObservedObject var payPalWebViewModel: PayPalWebViewModel - - var body: some View { - ScrollView { - ScrollViewReader { scrollView in - VStack { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .approved) - - if payPalWebViewModel.checkoutResult != nil { - PayPalWebCompleteTransactionView(payPalWebViewModel: payPalWebViewModel) - } - - if payPalWebViewModel.state == .success { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .completed) - } - Text("") - .id("bottomView") - Spacer() - .onChange(of: payPalWebViewModel.state) { _ in - withAnimation { - scrollView.scrollTo("bottomView") - } - } - } - } - } - } -} From d96b21672e55642a73b6a016a42e5ac901f7ef5d Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Tue, 21 Nov 2023 08:24:06 -0600 Subject: [PATCH 12/31] rename PayPalWebCompleteTransactionView to PayPalWebTransactionView; replace result view with status view so they do not dissapear on change for transaction view --- Demo/Demo.xcodeproj/project.pbxproj | 8 ++++---- .../PayPalWeb/PayPalWebButtonsView.swift | 2 +- ...ansactionView.swift => PayPalWebTransactionView.swift} | 7 ++++--- 3 files changed, 9 insertions(+), 8 deletions(-) rename Demo/Demo/SwiftUIComponents/PayPalWeb/{PayPalWebCompleteTransactionView.swift => PayPalWebTransactionView.swift} (72%) diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index 4e9723f3b..b08090419 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -16,7 +16,7 @@ 3B22E8BC2A84397600962E34 /* PaymentTokenResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B22E8BB2A84397600962E34 /* PaymentTokenResponse.swift */; }; 3B4DD9A02A892A7000F4A716 /* CardVaultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B4DD99F2A892A7000F4A716 /* CardVaultView.swift */; }; 3B4DD9A22A8982B000F4A716 /* CardFormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B4DD9A12A8982B000F4A716 /* CardFormView.swift */; }; - 3B6472A72AFAEB3A004745C4 /* PayPalWebCompleteTransactionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B6472A62AFAEB3A004745C4 /* PayPalWebCompleteTransactionView.swift */; }; + 3B6472A72AFAEB3A004745C4 /* PayPalWebTransactionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B6472A62AFAEB3A004745C4 /* PayPalWebTransactionView.swift */; }; 3B80D50E2A291C0800D2EAC4 /* ClientIDRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B80D50D2A291C0800D2EAC4 /* ClientIDRequest.swift */; }; 3B80D5102A291CB100D2EAC4 /* ClientIDResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B80D50F2A291CB100D2EAC4 /* ClientIDResponse.swift */; }; 3B8EF4DB2A932DA300A70D0B /* ErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B8EF4DA2A932DA300A70D0B /* ErrorView.swift */; }; @@ -135,7 +135,7 @@ 3B22E8BB2A84397600962E34 /* PaymentTokenResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaymentTokenResponse.swift; sourceTree = ""; }; 3B4DD99F2A892A7000F4A716 /* CardVaultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardVaultView.swift; sourceTree = ""; }; 3B4DD9A12A8982B000F4A716 /* CardFormView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardFormView.swift; sourceTree = ""; }; - 3B6472A62AFAEB3A004745C4 /* PayPalWebCompleteTransactionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PayPalWebCompleteTransactionView.swift; sourceTree = ""; }; + 3B6472A62AFAEB3A004745C4 /* PayPalWebTransactionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PayPalWebTransactionView.swift; sourceTree = ""; }; 3B80D50D2A291C0800D2EAC4 /* ClientIDRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientIDRequest.swift; sourceTree = ""; }; 3B80D50F2A291CB100D2EAC4 /* ClientIDResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientIDResponse.swift; sourceTree = ""; }; 3B8EF4DA2A932DA300A70D0B /* ErrorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorView.swift; sourceTree = ""; }; @@ -273,7 +273,7 @@ isa = PBXGroup; children = ( 3BA570062AA0DF330081D14F /* PayPalWebButtonsView.swift */, - 3B6472A62AFAEB3A004745C4 /* PayPalWebCompleteTransactionView.swift */, + 3B6472A62AFAEB3A004745C4 /* PayPalWebTransactionView.swift */, 3BA570022AA053AE0081D14F /* PayPalWebCreateOrderView.swift */, 3BA570002AA052E80081D14F /* PayPalWebDemoView.swift */, BE8117632B07E778009867B9 /* PayPalWebResultView.swift */, @@ -646,7 +646,7 @@ BC6460CD2A12A2A0002B974B /* EmptyBodyParams.swift in Sources */, 3BF999782A8AD072009CBDF2 /* CreatePaymentTokenView.swift in Sources */, BED042312710833F00C80954 /* CardType.swift in Sources */, - 3B6472A72AFAEB3A004745C4 /* PayPalWebCompleteTransactionView.swift in Sources */, + 3B6472A72AFAEB3A004745C4 /* PayPalWebTransactionView.swift in Sources */, 5301468C28918B4D00184F22 /* ApprovalResult.swift in Sources */, 3BC6220B2A97204E00251B85 /* CircularProgressView.swift in Sources */, ); diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift index 1af7f4a23..5e0e6ee18 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift @@ -32,7 +32,7 @@ struct PayPalWebButtonsView: View { if payPalWebViewModel.checkoutResult != nil { PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .approved) NavigationLink { - PayPalWebCompleteTransactionView(payPalWebViewModel: payPalWebViewModel) + PayPalWebTransactionView(payPalWebViewModel: payPalWebViewModel) .navigationTitle("Complete Transaction") } label: { Text("Complete Transaction") diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCompleteTransactionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift similarity index 72% rename from Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCompleteTransactionView.swift rename to Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift index 7c27639f9..dd7ff108a 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCompleteTransactionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift @@ -1,12 +1,12 @@ import SwiftUI -struct PayPalWebCompleteTransactionView: View { +struct PayPalWebTransactionView: View { @ObservedObject var payPalWebViewModel: PayPalWebViewModel var body: some View { VStack { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .approved) + PayPalWebStatusView(status: .approved, intent: payPalWebViewModel.intent, payPalViewModel: payPalWebViewModel) ZStack { Button("\(payPalWebViewModel.intent.rawValue)") { Task { @@ -25,8 +25,9 @@ struct PayPalWebCompleteTransactionView: View { } if payPalWebViewModel.state == .success { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .completed) + PayPalWebStatusView(status: .completed, intent: payPalWebViewModel.intent, payPalViewModel: payPalWebViewModel) } } + Spacer() } } From 994a3ace7f1284f91a61d69e916736e9b47d6c4e Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Tue, 21 Nov 2023 09:52:56 -0600 Subject: [PATCH 13/31] update funding source --- Demo/Demo/Models/Order.swift | 4 +--- .../SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift | 2 +- .../PayPalWeb/PayPalWebTransactionView.swift | 4 ++-- .../PayPalWebPayments/PayPalWebCheckoutFundingSource.swift | 3 ++- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Demo/Demo/Models/Order.swift b/Demo/Demo/Models/Order.swift index 75a21627b..8f0e346ea 100644 --- a/Demo/Demo/Models/Order.swift +++ b/Demo/Demo/Models/Order.swift @@ -2,7 +2,6 @@ struct Order: Codable, Equatable { let id: String let status: String - let payerID: String? let paymentSource: PaymentSource? struct PaymentSource: Codable, Equatable { @@ -11,11 +10,10 @@ struct Order: Codable, Equatable { let paypal: PayPal? } - init(id: String, status: String, paymentSource: PaymentSource? = nil, payerID: String? = nil) { + init(id: String, status: String, paymentSource: PaymentSource? = nil) { self.id = id self.status = status self.paymentSource = paymentSource - self.payerID = payerID } struct Card: Codable, Equatable { diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift index 5e0e6ee18..c53f8801c 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift @@ -17,7 +17,7 @@ struct PayPalWebButtonsView: View { } .frame(maxWidth: .infinity, maxHeight: 40) PayPalPayLaterButton.Representable(color: .silver, edges: .rounded, size: .full) { - payPalWebViewModel.paymentButtonTapped(funding: .payLater) + payPalWebViewModel.paymentButtonTapped(funding: .paylater) } .frame(maxWidth: .infinity, maxHeight: 40) } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift index dd7ff108a..b8367461e 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift @@ -6,7 +6,7 @@ struct PayPalWebTransactionView: View { var body: some View { VStack { - PayPalWebStatusView(status: .approved, intent: payPalWebViewModel.intent, payPalViewModel: payPalWebViewModel) + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .approved) ZStack { Button("\(payPalWebViewModel.intent.rawValue)") { Task { @@ -25,7 +25,7 @@ struct PayPalWebTransactionView: View { } if payPalWebViewModel.state == .success { - PayPalWebStatusView(status: .completed, intent: payPalWebViewModel.intent, payPalViewModel: payPalWebViewModel) + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .completed) } } Spacer() diff --git a/Sources/PayPalWebPayments/PayPalWebCheckoutFundingSource.swift b/Sources/PayPalWebPayments/PayPalWebCheckoutFundingSource.swift index 48fcd877c..b64f53e28 100644 --- a/Sources/PayPalWebPayments/PayPalWebCheckoutFundingSource.swift +++ b/Sources/PayPalWebPayments/PayPalWebCheckoutFundingSource.swift @@ -6,9 +6,10 @@ public enum PayPalWebCheckoutFundingSource: String { /// Eligible costumers receive a revolving line of credit that they can use to pay over time. case paypalCredit = "credit" + // NEXT_MAJOR_VERSION: rename to `payLater` /// PayLater will launch the web checkout flow and display Pay Later offers to eligible customers, /// which include short-term, interest-free payments and other special financing options - case payLater = "paylater" + case paylater = "paylater" /// PayPal will launch the web checkout for a one-time PayPal Checkout flow case paypal = "paypal" From 3dd128e3030121da374bc4e679ca51ac2501dfd0 Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Tue, 21 Nov 2023 10:07:57 -0600 Subject: [PATCH 14/31] extract intent from view model directly --- .../SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift | 2 +- .../SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift | 5 ++--- .../PayPalWeb/PayPalWebTransactionView.swift | 2 +- Demo/Demo/ViewModels/PayPalWebViewModel.swift | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift index ec96c8fa0..3fad712c3 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift @@ -17,7 +17,7 @@ struct PayPalWebResultView: View { case .idle, .loading: EmptyView() case .loaded, .success: - PayPalWebStatusView(status: status, intent: payPalWebViewModel.intent, payPalViewModel: payPalWebViewModel) + PayPalWebStatusView(status: status, payPalViewModel: payPalWebViewModel) case .error(let errorMessage): ErrorView(errorMessage: errorMessage) } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift index 4fe24bf25..4860bf8cc 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift @@ -3,7 +3,6 @@ import SwiftUI struct PayPalWebStatusView: View { var status: Status - var intent: Intent var payPalViewModel: PayPalWebViewModel var body: some View { @@ -29,7 +28,7 @@ struct PayPalWebStatusView: View { } if let order = payPalViewModel.order { LeadingText("Intent", weight: .bold) - LeadingText("\(intent)") + LeadingText("\(payPalViewModel.intent)") LeadingText("Order ID", weight: .bold) LeadingText("\(order.id)") LeadingText("Payer ID", weight: .bold) @@ -38,7 +37,7 @@ struct PayPalWebStatusView: View { case .completed: if let order = payPalViewModel.order { HStack { - Text("Order \(intent.rawValue.capitalized)d") + Text("Order \(payPalViewModel.intent.rawValue.capitalized)d") .font(.system(size: 20)) Spacer() } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift index b8367461e..b5febb9b8 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift @@ -8,7 +8,7 @@ struct PayPalWebTransactionView: View { VStack { PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .approved) ZStack { - Button("\(payPalWebViewModel.intent.rawValue)") { + Button("\(payPalWebViewModel.intent.rawValue.capitalized) Order") { Task { do { try await payPalWebViewModel.completeOrder() diff --git a/Demo/Demo/ViewModels/PayPalWebViewModel.swift b/Demo/Demo/ViewModels/PayPalWebViewModel.swift index c483e0db3..b8330f1a9 100644 --- a/Demo/Demo/ViewModels/PayPalWebViewModel.swift +++ b/Demo/Demo/ViewModels/PayPalWebViewModel.swift @@ -100,7 +100,7 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { DispatchQueue.main.async { self.state = .error(message: error.localizedDescription) } - print("Error capturing order with error: \(error.localizedDescription)") + print("Error capturing order: \(error.localizedDescription)") } } From c01d5c566eacdb79323c1ffc017ac7260d167233 Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Tue, 21 Nov 2023 10:21:06 -0600 Subject: [PATCH 15/31] minor cleanup --- .../SwiftUIComponents/PayPalWeb/PayPalWebCreateOrderView.swift | 2 +- Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebDemoView.swift | 1 - .../SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift | 3 ++- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCreateOrderView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCreateOrderView.swift index b6910f854..f6fb605ab 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCreateOrderView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCreateOrderView.swift @@ -7,7 +7,7 @@ struct PayPalWebCreateOrderView: View { @State private var selectedIntent: Intent = .authorize var body: some View { - VStack { + VStack(spacing: 16) { HStack { Text("Create an Order") .font(.system(size: 20)) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebDemoView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebDemoView.swift index 8e860365e..b0ff946b2 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebDemoView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebDemoView.swift @@ -1,5 +1,4 @@ import SwiftUI -import PaymentButtons struct PayPalWebDemoView: View { diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift index b5febb9b8..b715ca43e 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift @@ -6,7 +6,7 @@ struct PayPalWebTransactionView: View { var body: some View { VStack { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .approved) + PayPalWebStatusView(status: .approved, payPalViewModel: payPalWebViewModel) ZStack { Button("\(payPalWebViewModel.intent.rawValue.capitalized) Order") { Task { @@ -19,6 +19,7 @@ struct PayPalWebTransactionView: View { } .buttonStyle(RoundedBlueButtonStyle()) .padding() + if payPalWebViewModel.state == .loading { CircularProgressView() } From 664f56c6f03c1fbe57ed88f073edfc456a937c82 Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Tue, 21 Nov 2023 10:48:20 -0600 Subject: [PATCH 16/31] sort paypal web files by name --- Demo/Demo.xcodeproj/project.pbxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index b08090419..e284e1a46 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -273,11 +273,11 @@ isa = PBXGroup; children = ( 3BA570062AA0DF330081D14F /* PayPalWebButtonsView.swift */, - 3B6472A62AFAEB3A004745C4 /* PayPalWebTransactionView.swift */, 3BA570022AA053AE0081D14F /* PayPalWebCreateOrderView.swift */, 3BA570002AA052E80081D14F /* PayPalWebDemoView.swift */, BE8117632B07E778009867B9 /* PayPalWebResultView.swift */, BE8117652B080202009867B9 /* PayPalWebStatusView.swift */, + 3B6472A62AFAEB3A004745C4 /* PayPalWebTransactionView.swift */, ); path = PayPalWeb; sourceTree = ""; From e1faf501f30dfd3424d0f2449d62a560afb961b5 Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Tue, 21 Nov 2023 11:22:33 -0600 Subject: [PATCH 17/31] cleanup authorize/capture order into singular method --- Demo/Demo/Networking/DemoMerchantAPI.swift | 16 +++++- .../Demo/SwiftUIComponents/CurrentState.swift | 1 - .../PayPalWeb/PayPalWebTransactionView.swift | 2 +- Demo/Demo/ViewModels/PayPalWebViewModel.swift | 49 ++++--------------- 4 files changed, 25 insertions(+), 43 deletions(-) diff --git a/Demo/Demo/Networking/DemoMerchantAPI.swift b/Demo/Demo/Networking/DemoMerchantAPI.swift index 7165d5d56..cc0a9eff9 100644 --- a/Demo/Demo/Networking/DemoMerchantAPI.swift +++ b/Demo/Demo/Networking/DemoMerchantAPI.swift @@ -53,7 +53,21 @@ final class DemoMerchantAPI { throw error } } - + + func completeOrder(intent: Intent, orderID: String) async throws -> Order { + let intent = intent == .authorize ? "authorize" : "capture" + guard let url = buildBaseURL( + with: "/orders/\(orderID)/\(intent)", + selectedMerchantIntegration: DemoSettings.merchantIntegration + ) else { + throw URLResponseError.invalidURL + } + + let urlRequest = buildURLRequest(method: "POST", url: url, body: EmptyBodyParams()) + let data = try await data(for: urlRequest) + return try parse(from: data) + } + func captureOrder(orderID: String, selectedMerchantIntegration: MerchantIntegration) async throws -> Order { guard let url = buildBaseURL(with: "/orders/\(orderID)/capture", selectedMerchantIntegration: selectedMerchantIntegration) else { throw URLResponseError.invalidURL diff --git a/Demo/Demo/SwiftUIComponents/CurrentState.swift b/Demo/Demo/SwiftUIComponents/CurrentState.swift index a5eb2bdb7..ffc6e9944 100644 --- a/Demo/Demo/SwiftUIComponents/CurrentState.swift +++ b/Demo/Demo/SwiftUIComponents/CurrentState.swift @@ -1,7 +1,6 @@ import Foundation enum CurrentState: Equatable { - case idle case loading case loaded diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift index b715ca43e..e5e7b68d4 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift @@ -11,7 +11,7 @@ struct PayPalWebTransactionView: View { Button("\(payPalWebViewModel.intent.rawValue.capitalized) Order") { Task { do { - try await payPalWebViewModel.completeOrder() + try await payPalWebViewModel.completeTransaction() } catch { print("Error capturing order: \(error.localizedDescription)") } diff --git a/Demo/Demo/ViewModels/PayPalWebViewModel.swift b/Demo/Demo/ViewModels/PayPalWebViewModel.swift index b8330f1a9..2c9a46aea 100644 --- a/Demo/Demo/ViewModels/PayPalWebViewModel.swift +++ b/Demo/Demo/ViewModels/PayPalWebViewModel.swift @@ -72,56 +72,25 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { } } - func completeOrder() async throws { - if let orderID = order?.id { - switch intent { - case .capture: - try await captureOrder(orderID: orderID) - case .authorize: - try await authorizeOrder(orderID: orderID) - } - } - } - - func captureOrder(orderID: String) async throws { + func completeTransaction() async throws { do { DispatchQueue.main.async { self.state = .loading } - let order = try await DemoMerchantAPI.sharedService.captureOrder( - orderID: orderID, - selectedMerchantIntegration: DemoSettings.merchantIntegration - ) - DispatchQueue.main.async { - self.order = order - self.state = .success - } - } catch { - DispatchQueue.main.async { - self.state = .error(message: error.localizedDescription) - } - print("Error capturing order: \(error.localizedDescription)") - } - } - func authorizeOrder(orderID: String) async throws { - do { - DispatchQueue.main.async { - self.state = .loading - } - let order = try await DemoMerchantAPI.sharedService.authorizeOrder( - orderID: orderID, - selectedMerchantIntegration: DemoSettings.merchantIntegration - ) - DispatchQueue.main.async { - self.order = order - self.state = .success + if let orderID = order?.id { + let order = try await DemoMerchantAPI.sharedService.completeOrder(intent: intent, orderID: orderID) + + DispatchQueue.main.async { + self.order = order + self.state = .success + } } } catch { DispatchQueue.main.async { self.state = .error(message: error.localizedDescription) } - print("Error authorizing order: \(error.localizedDescription)") + print("Error with \(intent) order: \(error.localizedDescription)") } } From a7b9b64a46f2d4e2c29f8950f676fa806711ab6f Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Fri, 1 Dec 2023 08:32:27 -0600 Subject: [PATCH 18/31] add logic to reset state; combine loaded and success state; extract update logic into methods --- .../Demo/SwiftUIComponents/CurrentState.swift | 1 - .../PayPalWeb/PayPalWebButtonsView.swift | 5 +- .../PayPalWeb/PayPalWebResultView.swift | 2 +- .../PayPalWeb/PayPalWebTransactionView.swift | 3 + Demo/Demo/ViewModels/PayPalWebViewModel.swift | 55 ++++++++++--------- 5 files changed, 38 insertions(+), 28 deletions(-) diff --git a/Demo/Demo/SwiftUIComponents/CurrentState.swift b/Demo/Demo/SwiftUIComponents/CurrentState.swift index ffc6e9944..818dc1651 100644 --- a/Demo/Demo/SwiftUIComponents/CurrentState.swift +++ b/Demo/Demo/SwiftUIComponents/CurrentState.swift @@ -3,7 +3,6 @@ import Foundation enum CurrentState: Equatable { case idle case loading - case loaded case success case error(message: String) } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift index c53f8801c..5cf50ed23 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift @@ -29,7 +29,7 @@ struct PayPalWebButtonsView: View { .padding(5) ) - if payPalWebViewModel.checkoutResult != nil { + if payPalWebViewModel.state == .success && payPalWebViewModel.checkoutResult != nil { PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .approved) NavigationLink { PayPalWebTransactionView(payPalWebViewModel: payPalWebViewModel) @@ -42,5 +42,8 @@ struct PayPalWebButtonsView: View { } Spacer() } + .onAppear { + payPalWebViewModel.resetState() + } } } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift index 3fad712c3..76cce5fb5 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift @@ -16,7 +16,7 @@ struct PayPalWebResultView: View { switch payPalWebViewModel.state { case .idle, .loading: EmptyView() - case .loaded, .success: + case .success: PayPalWebStatusView(status: status, payPalViewModel: payPalWebViewModel) case .error(let errorMessage): ErrorView(errorMessage: errorMessage) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift index e5e7b68d4..4c8803265 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift @@ -29,6 +29,9 @@ struct PayPalWebTransactionView: View { PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .completed) } } + .onAppear { + payPalWebViewModel.resetState() + } Spacer() } } diff --git a/Demo/Demo/ViewModels/PayPalWebViewModel.swift b/Demo/Demo/ViewModels/PayPalWebViewModel.swift index 2c9a46aea..4906952cb 100644 --- a/Demo/Demo/ViewModels/PayPalWebViewModel.swift +++ b/Demo/Demo/ViewModels/PayPalWebViewModel.swift @@ -23,23 +23,18 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { ) do { - DispatchQueue.main.async { - self.state = .loading - } + updateState(.loading) let order = try await DemoMerchantAPI.sharedService.createOrder( orderParams: orderRequestParams, selectedMerchantIntegration: DemoSettings.merchantIntegration ) - DispatchQueue.main.async { - self.state = .loaded - self.order = order - print("✅ fetched orderID: \(order.id) with status: \(order.status)") - } + + updateOrder(order) + updateState(.success) + print("✅ fetched orderID: \(order.id) with status: \(order.status)") } catch { - DispatchQueue.main.async { - self.state = .error(message: error.localizedDescription) - print("❌ failed to fetch orderID with error: \(error.localizedDescription)") - } + updateState(.error(message: error.localizedDescription)) + print("❌ failed to fetch orderID with error: \(error.localizedDescription)") } } @@ -48,14 +43,14 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { do { payPalWebCheckoutClient = try await getPayPalClient() payPalWebCheckoutClient?.delegate = self - guard let client = payPalWebCheckoutClient else { + guard let payPalWebCheckoutClient else { print("Error initializing PayPalWebCheckoutClient") return } if let orderID = order?.id { let payPalRequest = PayPalWebCheckoutRequest(orderID: orderID, fundingSource: funding) - client.start(request: payPalRequest) + payPalWebCheckoutClient.start(request: payPalRequest) } } catch { print("Error starting PayPalWebCheckoutClient") @@ -74,32 +69,42 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { func completeTransaction() async throws { do { - DispatchQueue.main.async { - self.state = .loading - } + updateState(.loading) if let orderID = order?.id { let order = try await DemoMerchantAPI.sharedService.completeOrder(intent: intent, orderID: orderID) - - DispatchQueue.main.async { - self.order = order - self.state = .success - } + updateOrder(order) + updateState(.success) } } catch { - DispatchQueue.main.async { - self.state = .error(message: error.localizedDescription) - } + updateState(.error(message: error.localizedDescription)) print("Error with \(intent) order: \(error.localizedDescription)") } } + func resetState() { + updateState(.idle) + } + + private func updateOrder(_ order: Order) { + DispatchQueue.main.async { + self.order = order + } + } + + private func updateState(_ state: CurrentState) { + DispatchQueue.main.async { + self.state = state + } + } + // MARK: - PayPalWeb Checkout Delegate func payPal( _ payPalClient: PayPalWebCheckoutClient, didFinishWithResult result: PayPalWebCheckoutResult ) { + updateState(.success) checkoutResult = result } From 5f95aa4deab069684793cb1d30c328202bd7921d Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Fri, 1 Dec 2023 08:51:21 -0600 Subject: [PATCH 19/31] merge main into demo-app-refactor --- .../PayPalWeb/PayPalWebStatusView.swift | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift index 4860bf8cc..900b42cb9 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift @@ -50,6 +50,16 @@ struct PayPalWebStatusView: View { LeadingText("Email", weight: .bold) LeadingText("\(emailAddress)") } + + if let vaultID = payPalViewModel.order?.paymentSource?.paypal?.attributes?.vault.id { + LeadingText("Vault ID / Payment Token", weight: .bold) + LeadingText("\(vaultID)") + } + + if let customerID = payPalViewModel.order?.paymentSource?.paypal?.attributes?.vault.customer.id { + LeadingText("Customer ID", weight: .bold) + LeadingText("\(customerID)") + } } } } From ee4f5dac3d5069f4d550121df63249979ab4c5b0 Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Fri, 1 Dec 2023 08:53:09 -0600 Subject: [PATCH 20/31] add ScrollView to PayPalWebTransactionView --- .../PayPalWeb/PayPalWebTransactionView.swift | 44 ++++++++++--------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift index 4c8803265..a03bd0406 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift @@ -5,33 +5,35 @@ struct PayPalWebTransactionView: View { @ObservedObject var payPalWebViewModel: PayPalWebViewModel var body: some View { - VStack { - PayPalWebStatusView(status: .approved, payPalViewModel: payPalWebViewModel) - ZStack { - Button("\(payPalWebViewModel.intent.rawValue.capitalized) Order") { - Task { - do { - try await payPalWebViewModel.completeTransaction() - } catch { - print("Error capturing order: \(error.localizedDescription)") + ScrollView { + VStack { + PayPalWebStatusView(status: .approved, payPalViewModel: payPalWebViewModel) + ZStack { + Button("\(payPalWebViewModel.intent.rawValue.capitalized) Order") { + Task { + do { + try await payPalWebViewModel.completeTransaction() + } catch { + print("Error capturing order: \(error.localizedDescription)") + } } } + .buttonStyle(RoundedBlueButtonStyle()) + .padding() + + if payPalWebViewModel.state == .loading { + CircularProgressView() + } } - .buttonStyle(RoundedBlueButtonStyle()) - .padding() - - if payPalWebViewModel.state == .loading { - CircularProgressView() + + if payPalWebViewModel.state == .success { + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .completed) } } - - if payPalWebViewModel.state == .success { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .completed) + .onAppear { + payPalWebViewModel.resetState() } + Spacer() } - .onAppear { - payPalWebViewModel.resetState() - } - Spacer() } } From 6c304140b0fa866b668711c44eb6c7411b5a437a Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Fri, 1 Dec 2023 08:55:17 -0600 Subject: [PATCH 21/31] PR feedback: rename Status enum to OrderStatus --- .../SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift | 4 ++-- .../SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift index 76cce5fb5..35d54b92c 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift @@ -1,6 +1,6 @@ import SwiftUI -enum Status { +enum OrderStatus { case started case approved case completed @@ -10,7 +10,7 @@ struct PayPalWebResultView: View { @ObservedObject var payPalWebViewModel: PayPalWebViewModel - var status: Status + var status: OrderStatus var body: some View { switch payPalWebViewModel.state { diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift index 900b42cb9..f3d51adc8 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift @@ -2,7 +2,7 @@ import SwiftUI struct PayPalWebStatusView: View { - var status: Status + var status: OrderStatus var payPalViewModel: PayPalWebViewModel var body: some View { From 94f8f9b51a6e5e640a238996751ddadbcac0134d Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Fri, 1 Dec 2023 09:50:37 -0600 Subject: [PATCH 22/31] PR feedback: rely on status instead or resetting state --- .../PayPalWeb/PayPalWebButtonsView.swift | 3 --- .../PayPalWeb/PayPalWebTransactionView.swift | 9 +++------ Demo/Demo/ViewModels/PayPalWebViewModel.swift | 4 ---- 3 files changed, 3 insertions(+), 13 deletions(-) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift index 5cf50ed23..e6f496706 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift @@ -42,8 +42,5 @@ struct PayPalWebButtonsView: View { } Spacer() } - .onAppear { - payPalWebViewModel.resetState() - } } } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift index a03bd0406..7e0aa55cf 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift @@ -20,19 +20,16 @@ struct PayPalWebTransactionView: View { } .buttonStyle(RoundedBlueButtonStyle()) .padding() - + if payPalWebViewModel.state == .loading { CircularProgressView() } } - - if payPalWebViewModel.state == .success { + + if payPalWebViewModel.state == .success && payPalWebViewModel.order?.status == "COMPLETED" { PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .completed) } } - .onAppear { - payPalWebViewModel.resetState() - } Spacer() } } diff --git a/Demo/Demo/ViewModels/PayPalWebViewModel.swift b/Demo/Demo/ViewModels/PayPalWebViewModel.swift index 94d3a4764..e2cced194 100644 --- a/Demo/Demo/ViewModels/PayPalWebViewModel.swift +++ b/Demo/Demo/ViewModels/PayPalWebViewModel.swift @@ -97,10 +97,6 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { } } - func resetState() { - updateState(.idle) - } - private func updateOrder(_ order: Order) { DispatchQueue.main.async { self.order = order From bb5596fe113078039d8a0f8dbc6995ed616ea7ca Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Fri, 1 Dec 2023 11:29:58 -0600 Subject: [PATCH 23/31] update name of payPalViewModel to payPalWebViewModel --- .../PayPalWeb/PayPalWebResultView.swift | 2 +- .../PayPalWeb/PayPalWebStatusView.swift | 20 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift index 35d54b92c..a28f2b908 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift @@ -17,7 +17,7 @@ struct PayPalWebResultView: View { case .idle, .loading: EmptyView() case .success: - PayPalWebStatusView(status: status, payPalViewModel: payPalWebViewModel) + PayPalWebStatusView(status: status, payPalWebViewModel: payPalWebViewModel) case .error(let errorMessage): ErrorView(errorMessage: errorMessage) } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift index f3d51adc8..ed352e585 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift @@ -3,7 +3,7 @@ import SwiftUI struct PayPalWebStatusView: View { var status: OrderStatus - var payPalViewModel: PayPalWebViewModel + var payPalWebViewModel: PayPalWebViewModel var body: some View { VStack(spacing: 16) { @@ -14,7 +14,7 @@ struct PayPalWebStatusView: View { .font(.system(size: 20)) Spacer() } - if let order = payPalViewModel.order { + if let order = payPalWebViewModel.order { LeadingText("Order ID", weight: .bold) LeadingText("\(order.id)") LeadingText("Status", weight: .bold) @@ -26,18 +26,18 @@ struct PayPalWebStatusView: View { .font(.system(size: 20)) Spacer() } - if let order = payPalViewModel.order { + if let order = payPalWebViewModel.order { LeadingText("Intent", weight: .bold) - LeadingText("\(payPalViewModel.intent)") + LeadingText("\(payPalWebViewModel.intent)") LeadingText("Order ID", weight: .bold) LeadingText("\(order.id)") LeadingText("Payer ID", weight: .bold) - LeadingText("\(payPalViewModel.checkoutResult?.payerID ?? "")") + LeadingText("\(payPalWebViewModel.checkoutResult?.payerID ?? "")") } case .completed: - if let order = payPalViewModel.order { + if let order = payPalWebViewModel.order { HStack { - Text("Order \(payPalViewModel.intent.rawValue.capitalized)d") + Text("Order \(payPalWebViewModel.intent.rawValue.capitalized)d") .font(.system(size: 20)) Spacer() } @@ -46,17 +46,17 @@ struct PayPalWebStatusView: View { LeadingText("Status", weight: .bold) LeadingText("\(order.status)") - if let emailAddress = payPalViewModel.order?.paymentSource?.paypal?.emailAddress { + if let emailAddress = payPalWebViewModel.order?.paymentSource?.paypal?.emailAddress { LeadingText("Email", weight: .bold) LeadingText("\(emailAddress)") } - if let vaultID = payPalViewModel.order?.paymentSource?.paypal?.attributes?.vault.id { + if let vaultID = payPalWebViewModel.order?.paymentSource?.paypal?.attributes?.vault.id { LeadingText("Vault ID / Payment Token", weight: .bold) LeadingText("\(vaultID)") } - if let customerID = payPalViewModel.order?.paymentSource?.paypal?.attributes?.vault.customer.id { + if let customerID = payPalWebViewModel.order?.paymentSource?.paypal?.attributes?.vault.customer.id { LeadingText("Customer ID", weight: .bold) LeadingText("\(customerID)") } From c2785ae8e63b361b7052c57590639683cd54a3a8 Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Fri, 1 Dec 2023 11:34:18 -0600 Subject: [PATCH 24/31] add scroll to bottom of PayPalWebTransactionView on vault with purchase --- .../PayPalWeb/PayPalWebTransactionView.swift | 42 +++++++++++-------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift index 7e0aa55cf..4795b1694 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift @@ -6,31 +6,39 @@ struct PayPalWebTransactionView: View { var body: some View { ScrollView { - VStack { - PayPalWebStatusView(status: .approved, payPalViewModel: payPalWebViewModel) - ZStack { - Button("\(payPalWebViewModel.intent.rawValue.capitalized) Order") { - Task { - do { - try await payPalWebViewModel.completeTransaction() - } catch { - print("Error capturing order: \(error.localizedDescription)") + ScrollViewReader { scrollView in + VStack { + PayPalWebStatusView(status: .approved, payPalWebViewModel: payPalWebViewModel) + ZStack { + Button("\(payPalWebViewModel.intent.rawValue.capitalized) Order") { + Task { + do { + try await payPalWebViewModel.completeTransaction() + } catch { + print("Error capturing order: \(error.localizedDescription)") + } } } + .buttonStyle(RoundedBlueButtonStyle()) + .padding() + + if payPalWebViewModel.state == .loading { + CircularProgressView() + } } - .buttonStyle(RoundedBlueButtonStyle()) - .padding() - if payPalWebViewModel.state == .loading { - CircularProgressView() + if payPalWebViewModel.state == .success && payPalWebViewModel.order?.status == "COMPLETED" { + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .completed) + .id("bottomView") } } - - if payPalWebViewModel.state == .success && payPalWebViewModel.order?.status == "COMPLETED" { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .completed) + .onChange(of: payPalWebViewModel.order) { _ in + withAnimation { + scrollView.scrollTo("bottomView") + } } + Spacer() } - Spacer() } } } From fa6cd088d7df74aa2b35b335f895491d98cbaf84 Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Fri, 1 Dec 2023 11:39:03 -0600 Subject: [PATCH 25/31] update order status from started to created to more accurately refect status --- Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebDemoView.swift | 2 +- Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift | 2 +- Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebDemoView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebDemoView.swift index b0ff946b2..289ffe4c3 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebDemoView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebDemoView.swift @@ -9,7 +9,7 @@ struct PayPalWebDemoView: View { VStack(spacing: 16) { PayPalWebCreateOrderView(payPalWebViewModel: payPalWebViewModel) if payPalWebViewModel.order != nil { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .started) + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .created) NavigationLink { PayPalWebButtonsView(payPalWebViewModel: payPalWebViewModel) .navigationTitle("Checkout with PayPal") diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift index a28f2b908..c668a2362 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift @@ -1,7 +1,7 @@ import SwiftUI enum OrderStatus { - case started + case created case approved case completed } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift index ed352e585..068bb3c50 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift @@ -8,7 +8,7 @@ struct PayPalWebStatusView: View { var body: some View { VStack(spacing: 16) { switch status { - case .started: + case .created: HStack { Text("Order Created") .font(.system(size: 20)) From 0a3305eeac2a745cfee4c5896af817872b88bbfc Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Fri, 1 Dec 2023 11:40:47 -0600 Subject: [PATCH 26/31] update PayPalWebDemoView to PayPalWebPaymentsView --- Demo/Demo.xcodeproj/project.pbxproj | 14 +++++++------- .../SwiftUIComponents/FeatureSelectionView.swift | 2 +- .../PayPalWebButtonsView.swift | 0 .../PayPalWebCreateOrderView.swift | 0 .../PayPalWebPaymentsView.swift} | 2 +- .../PayPalWebResultView.swift | 0 .../PayPalWebStatusView.swift | 0 .../PayPalWebTransactionView.swift | 0 8 files changed, 9 insertions(+), 9 deletions(-) rename Demo/Demo/SwiftUIComponents/{PayPalWeb => PayPalWebPayments}/PayPalWebButtonsView.swift (100%) rename Demo/Demo/SwiftUIComponents/{PayPalWeb => PayPalWebPayments}/PayPalWebCreateOrderView.swift (100%) rename Demo/Demo/SwiftUIComponents/{PayPalWeb/PayPalWebDemoView.swift => PayPalWebPayments/PayPalWebPaymentsView.swift} (95%) rename Demo/Demo/SwiftUIComponents/{PayPalWeb => PayPalWebPayments}/PayPalWebResultView.swift (100%) rename Demo/Demo/SwiftUIComponents/{PayPalWeb => PayPalWebPayments}/PayPalWebStatusView.swift (100%) rename Demo/Demo/SwiftUIComponents/{PayPalWeb => PayPalWebPayments}/PayPalWebTransactionView.swift (100%) diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index e284e1a46..fe8cffcf2 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -31,7 +31,7 @@ 3BA56FF82A9FDB5A0081D14F /* CardPaymentOrderCompletionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA56FF72A9FDB5A0081D14F /* CardPaymentOrderCompletionView.swift */; }; 3BA56FFA2A9FE4180081D14F /* CardOrderCompletionResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA56FF92A9FE4180081D14F /* CardOrderCompletionResultView.swift */; }; 3BA56FFC2A9FEFE90081D14F /* PayPalWebViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA56FFB2A9FEFE90081D14F /* PayPalWebViewModel.swift */; }; - 3BA570012AA052E80081D14F /* PayPalWebDemoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA570002AA052E80081D14F /* PayPalWebDemoView.swift */; }; + 3BA570012AA052E80081D14F /* PayPalWebPaymentsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA570002AA052E80081D14F /* PayPalWebPaymentsView.swift */; }; 3BA570032AA053AE0081D14F /* PayPalWebCreateOrderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA570022AA053AE0081D14F /* PayPalWebCreateOrderView.swift */; }; 3BA570072AA0DF330081D14F /* PayPalWebButtonsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA570062AA0DF330081D14F /* PayPalWebButtonsView.swift */; }; 3BA5700B2AA13C1C0081D14F /* CoreConfigManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA5700A2AA13C1C0081D14F /* CoreConfigManager.swift */; }; @@ -150,7 +150,7 @@ 3BA56FF72A9FDB5A0081D14F /* CardPaymentOrderCompletionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardPaymentOrderCompletionView.swift; sourceTree = ""; }; 3BA56FF92A9FE4180081D14F /* CardOrderCompletionResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardOrderCompletionResultView.swift; sourceTree = ""; }; 3BA56FFB2A9FEFE90081D14F /* PayPalWebViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalWebViewModel.swift; sourceTree = ""; }; - 3BA570002AA052E80081D14F /* PayPalWebDemoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalWebDemoView.swift; sourceTree = ""; }; + 3BA570002AA052E80081D14F /* PayPalWebPaymentsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalWebPaymentsView.swift; sourceTree = ""; }; 3BA570022AA053AE0081D14F /* PayPalWebCreateOrderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalWebCreateOrderView.swift; sourceTree = ""; }; 3BA570062AA0DF330081D14F /* PayPalWebButtonsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalWebButtonsView.swift; sourceTree = ""; }; 3BA5700A2AA13C1C0081D14F /* CoreConfigManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreConfigManager.swift; sourceTree = ""; }; @@ -269,17 +269,17 @@ path = CardPaymentViews; sourceTree = ""; }; - 3BA56FFF2A9FF6630081D14F /* PayPalWeb */ = { + 3BA56FFF2A9FF6630081D14F /* PayPalWebPayments */ = { isa = PBXGroup; children = ( 3BA570062AA0DF330081D14F /* PayPalWebButtonsView.swift */, 3BA570022AA053AE0081D14F /* PayPalWebCreateOrderView.swift */, - 3BA570002AA052E80081D14F /* PayPalWebDemoView.swift */, + 3BA570002AA052E80081D14F /* PayPalWebPaymentsView.swift */, BE8117632B07E778009867B9 /* PayPalWebResultView.swift */, BE8117652B080202009867B9 /* PayPalWebStatusView.swift */, 3B6472A62AFAEB3A004745C4 /* PayPalWebTransactionView.swift */, ); - path = PayPalWeb; + path = PayPalWebPayments; sourceTree = ""; }; 3BCCFE472A9D962E00C5102F /* CommonComponents */ = { @@ -446,7 +446,7 @@ BEDE3047275E998700D275FD /* SwiftUIComponents */ = { isa = PBXGroup; children = ( - 3BA56FFF2A9FF6630081D14F /* PayPalWeb */, + 3BA56FFF2A9FF6630081D14F /* PayPalWebPayments */, 3BA56FEA2A9DCBB30081D14F /* CardPaymentViews */, 3BCCFE472A9D962E00C5102F /* CommonComponents */, 3B43290F2A8FD7FD00C5441A /* CardVaultViews */, @@ -631,7 +631,7 @@ 3BA56FFC2A9FEFE90081D14F /* PayPalWebViewModel.swift in Sources */, 3BDB34922A7CB5DE008100D7 /* SetupTokenResponse.swift in Sources */, 3BA56FF22A9DCD440081D14F /* CardApprovalResultView.swift in Sources */, - 3BA570012AA052E80081D14F /* PayPalWebDemoView.swift in Sources */, + 3BA570012AA052E80081D14F /* PayPalWebPaymentsView.swift in Sources */, CBC16DD929ED90B600307117 /* UpdateOrderParams.swift in Sources */, 3BA56FFA2A9FE4180081D14F /* CardOrderCompletionResultView.swift in Sources */, 3BA56FF42A9DCD790081D14F /* CardPaymentView.swift in Sources */, diff --git a/Demo/Demo/SwiftUIComponents/FeatureSelectionView.swift b/Demo/Demo/SwiftUIComponents/FeatureSelectionView.swift index dac2876fa..76b28afc9 100644 --- a/Demo/Demo/SwiftUIComponents/FeatureSelectionView.swift +++ b/Demo/Demo/SwiftUIComponents/FeatureSelectionView.swift @@ -38,7 +38,7 @@ struct FeatureSelectionView: View { Text("Card Vaulting") } NavigationLink { - PayPalWebDemoView() + PayPalWebPaymentsView() .navigationTitle("PayPal Web") } label: { Text("PayPal Web") diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift similarity index 100% rename from Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebButtonsView.swift rename to Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCreateOrderView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebCreateOrderView.swift similarity index 100% rename from Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebCreateOrderView.swift rename to Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebCreateOrderView.swift diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebDemoView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift similarity index 95% rename from Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebDemoView.swift rename to Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift index 289ffe4c3..c7f233cf3 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebDemoView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift @@ -1,6 +1,6 @@ import SwiftUI -struct PayPalWebDemoView: View { +struct PayPalWebPaymentsView: View { @StateObject var payPalWebViewModel = PayPalWebViewModel() diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift similarity index 100% rename from Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebResultView.swift rename to Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebStatusView.swift similarity index 100% rename from Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebStatusView.swift rename to Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebStatusView.swift diff --git a/Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebTransactionView.swift similarity index 100% rename from Demo/Demo/SwiftUIComponents/PayPalWeb/PayPalWebTransactionView.swift rename to Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebTransactionView.swift From c137eb7819d7e4cd055566feb02a1679188c1071 Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Fri, 1 Dec 2023 11:52:18 -0600 Subject: [PATCH 27/31] add navigationViewStyle --- .../PayPalWebPayments/PayPalWebButtonsView.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift index e6f496706..a06c8258b 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift @@ -37,6 +37,7 @@ struct PayPalWebButtonsView: View { } label: { Text("Complete Transaction") } + .navigationViewStyle(StackNavigationViewStyle()) .buttonStyle(RoundedBlueButtonStyle()) .padding() } From 8cd8cd287a557523ba8ff82d8a88a027c8e57565 Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Fri, 1 Dec 2023 11:52:34 -0600 Subject: [PATCH 28/31] update delegate to use updateState --- Demo/Demo/ViewModels/PayPalWebViewModel.swift | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Demo/Demo/ViewModels/PayPalWebViewModel.swift b/Demo/Demo/ViewModels/PayPalWebViewModel.swift index e2cced194..2ff57cbef 100644 --- a/Demo/Demo/ViewModels/PayPalWebViewModel.swift +++ b/Demo/Demo/ViewModels/PayPalWebViewModel.swift @@ -120,9 +120,7 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { } func payPal(_ payPalClient: PayPalWebCheckoutClient, didFinishWithError error: CoreSDKError) { - DispatchQueue.main.async { - self.state = .error(message: error.localizedDescription) - } + updateState(.error(message: error.localizedDescription)) } func payPalDidCancel(_ payPalClient: PayPalWebCheckoutClient) { From 5a957651b375af45307874a19ff23a8b900bcc8b Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Fri, 1 Dec 2023 15:58:39 -0600 Subject: [PATCH 29/31] move PayPalWebViewModel into PayPalWebPayments feature directory --- Demo/Demo.xcodeproj/project.pbxproj | 2 +- .../PayPalWebPayments}/PayPalWebViewModel.swift | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename Demo/Demo/{ViewModels => SwiftUIComponents/PayPalWebPayments}/PayPalWebViewModel.swift (100%) diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index fe8cffcf2..215f6a85a 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -278,6 +278,7 @@ BE8117632B07E778009867B9 /* PayPalWebResultView.swift */, BE8117652B080202009867B9 /* PayPalWebStatusView.swift */, 3B6472A62AFAEB3A004745C4 /* PayPalWebTransactionView.swift */, + 3BA56FFB2A9FEFE90081D14F /* PayPalWebViewModel.swift */, ); path = PayPalWebPayments; sourceTree = ""; @@ -419,7 +420,6 @@ 3B2027402A8A72050007907E /* CardVaultState.swift */, 3BA56FE62A9DC9D70081D14F /* CardPaymentViewModel.swift */, 3BA56FE82A9DCA520081D14F /* CardPaymentState.swift */, - 3BA56FFB2A9FEFE90081D14F /* PayPalWebViewModel.swift */, ); path = ViewModels; sourceTree = ""; diff --git a/Demo/Demo/ViewModels/PayPalWebViewModel.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift similarity index 100% rename from Demo/Demo/ViewModels/PayPalWebViewModel.swift rename to Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift From af04b83865daba47ea5707a03f9fa03258a3c32a Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Mon, 4 Dec 2023 08:42:50 -0600 Subject: [PATCH 30/31] remove OrderStatus and add cases to CurrentState --- Demo/Demo/SwiftUIComponents/CurrentState.swift | 4 +++- .../PayPalWebPayments/PayPalWebButtonsView.swift | 4 ++-- .../PayPalWebPayments/PayPalWebPaymentsView.swift | 2 +- .../PayPalWebPayments/PayPalWebResultView.swift | 12 ++---------- .../PayPalWebPayments/PayPalWebStatusView.swift | 11 ++++++----- .../PayPalWebPayments/PayPalWebTransactionView.swift | 6 +++--- .../PayPalWebPayments/PayPalWebViewModel.swift | 6 +++--- 7 files changed, 20 insertions(+), 25 deletions(-) diff --git a/Demo/Demo/SwiftUIComponents/CurrentState.swift b/Demo/Demo/SwiftUIComponents/CurrentState.swift index 818dc1651..1f5b8d2f4 100644 --- a/Demo/Demo/SwiftUIComponents/CurrentState.swift +++ b/Demo/Demo/SwiftUIComponents/CurrentState.swift @@ -3,6 +3,8 @@ import Foundation enum CurrentState: Equatable { case idle case loading - case success + case orderSuccess + case orderApproved + case transactionSuccess case error(message: String) } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift index a06c8258b..4e9b975c8 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift @@ -29,8 +29,8 @@ struct PayPalWebButtonsView: View { .padding(5) ) - if payPalWebViewModel.state == .success && payPalWebViewModel.checkoutResult != nil { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .approved) + if payPalWebViewModel.checkoutResult != nil { + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel) NavigationLink { PayPalWebTransactionView(payPalWebViewModel: payPalWebViewModel) .navigationTitle("Complete Transaction") diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift index c7f233cf3..aae0f3d84 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift @@ -9,7 +9,7 @@ struct PayPalWebPaymentsView: View { VStack(spacing: 16) { PayPalWebCreateOrderView(payPalWebViewModel: payPalWebViewModel) if payPalWebViewModel.order != nil { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .created) + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel) NavigationLink { PayPalWebButtonsView(payPalWebViewModel: payPalWebViewModel) .navigationTitle("Checkout with PayPal") diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift index c668a2362..6d249804e 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift @@ -1,23 +1,15 @@ import SwiftUI -enum OrderStatus { - case created - case approved - case completed -} - struct PayPalWebResultView: View { @ObservedObject var payPalWebViewModel: PayPalWebViewModel - var status: OrderStatus - var body: some View { switch payPalWebViewModel.state { case .idle, .loading: EmptyView() - case .success: - PayPalWebStatusView(status: status, payPalWebViewModel: payPalWebViewModel) + case .orderSuccess, .orderApproved, .transactionSuccess: + PayPalWebStatusView(payPalWebViewModel: payPalWebViewModel) case .error(let errorMessage): ErrorView(errorMessage: errorMessage) } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebStatusView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebStatusView.swift index 068bb3c50..eae541bcb 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebStatusView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebStatusView.swift @@ -2,13 +2,12 @@ import SwiftUI struct PayPalWebStatusView: View { - var status: OrderStatus var payPalWebViewModel: PayPalWebViewModel var body: some View { VStack(spacing: 16) { - switch status { - case .created: + switch payPalWebViewModel.state { + case .orderSuccess: HStack { Text("Order Created") .font(.system(size: 20)) @@ -20,7 +19,7 @@ struct PayPalWebStatusView: View { LeadingText("Status", weight: .bold) LeadingText("\(order.status)") } - case .approved: + case .orderApproved: HStack { Text("Order Approved") .font(.system(size: 20)) @@ -34,7 +33,7 @@ struct PayPalWebStatusView: View { LeadingText("Payer ID", weight: .bold) LeadingText("\(payPalWebViewModel.checkoutResult?.payerID ?? "")") } - case .completed: + case .transactionSuccess: if let order = payPalWebViewModel.order { HStack { Text("Order \(payPalWebViewModel.intent.rawValue.capitalized)d") @@ -61,6 +60,8 @@ struct PayPalWebStatusView: View { LeadingText("\(customerID)") } } + default: + Text("") } } .frame(maxWidth: .infinity) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebTransactionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebTransactionView.swift index 4795b1694..97e7b268a 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebTransactionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebTransactionView.swift @@ -8,7 +8,7 @@ struct PayPalWebTransactionView: View { ScrollView { ScrollViewReader { scrollView in VStack { - PayPalWebStatusView(status: .approved, payPalWebViewModel: payPalWebViewModel) + PayPalWebStatusView(payPalWebViewModel: payPalWebViewModel) ZStack { Button("\(payPalWebViewModel.intent.rawValue.capitalized) Order") { Task { @@ -27,8 +27,8 @@ struct PayPalWebTransactionView: View { } } - if payPalWebViewModel.state == .success && payPalWebViewModel.order?.status == "COMPLETED" { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .completed) + if payPalWebViewModel.state == .transactionSuccess { + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel) .id("bottomView") } } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift index 2ff57cbef..f0e450112 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift @@ -45,7 +45,7 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { ) updateOrder(order) - updateState(.success) + updateState(.orderSuccess) print("✅ fetched orderID: \(order.id) with status: \(order.status)") } catch { updateState(.error(message: error.localizedDescription)) @@ -89,7 +89,7 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { if let orderID = order?.id { let order = try await DemoMerchantAPI.sharedService.completeOrder(intent: intent, orderID: orderID) updateOrder(order) - updateState(.success) + updateState(.transactionSuccess) } } catch { updateState(.error(message: error.localizedDescription)) @@ -115,7 +115,7 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { _ payPalClient: PayPalWebCheckoutClient, didFinishWithResult result: PayPalWebCheckoutResult ) { - updateState(.success) + updateState(.orderApproved) checkoutResult = result } From 518e8ec831deb384f4fae6881f33aef2d7dded10 Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Mon, 4 Dec 2023 09:49:53 -0600 Subject: [PATCH 31/31] refactor current state; add back in OrderStatus; fix bug with ErrorView --- .../Demo/SwiftUIComponents/CurrentState.swift | 4 +-- .../PayPalWebButtonsView.swift | 6 ++-- .../PayPalWebPaymentsView.swift | 6 ++-- .../PayPalWebResultView.swift | 13 ++++++-- .../PayPalWebStatusView.swift | 21 ++++++------- .../PayPalWebTransactionView.swift | 10 ++++--- .../PayPalWebViewModel.swift | 30 ++++++++++--------- 7 files changed, 53 insertions(+), 37 deletions(-) diff --git a/Demo/Demo/SwiftUIComponents/CurrentState.swift b/Demo/Demo/SwiftUIComponents/CurrentState.swift index 1f5b8d2f4..818dc1651 100644 --- a/Demo/Demo/SwiftUIComponents/CurrentState.swift +++ b/Demo/Demo/SwiftUIComponents/CurrentState.swift @@ -3,8 +3,6 @@ import Foundation enum CurrentState: Equatable { case idle case loading - case orderSuccess - case orderApproved - case transactionSuccess + case success case error(message: String) } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift index 4e9b975c8..e213cb94e 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift @@ -29,8 +29,8 @@ struct PayPalWebButtonsView: View { .padding(5) ) - if payPalWebViewModel.checkoutResult != nil { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel) + if payPalWebViewModel.checkoutResult != nil && payPalWebViewModel.state == .success { + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .approved) NavigationLink { PayPalWebTransactionView(payPalWebViewModel: payPalWebViewModel) .navigationTitle("Complete Transaction") @@ -40,6 +40,8 @@ struct PayPalWebButtonsView: View { .navigationViewStyle(StackNavigationViewStyle()) .buttonStyle(RoundedBlueButtonStyle()) .padding() + } else if case .error = payPalWebViewModel.state { + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .error) } Spacer() } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift index aae0f3d84..88a03e406 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift @@ -8,8 +8,8 @@ struct PayPalWebPaymentsView: View { ScrollView { VStack(spacing: 16) { PayPalWebCreateOrderView(payPalWebViewModel: payPalWebViewModel) - if payPalWebViewModel.order != nil { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel) + if payPalWebViewModel.createOrderResult != nil && payPalWebViewModel.state == .success { + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .created) NavigationLink { PayPalWebButtonsView(payPalWebViewModel: payPalWebViewModel) .navigationTitle("Checkout with PayPal") @@ -18,6 +18,8 @@ struct PayPalWebPaymentsView: View { } .buttonStyle(RoundedBlueButtonStyle()) .padding() + } else if case .error = payPalWebViewModel.state { + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .error) } } } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift index 6d249804e..85cd823c0 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift @@ -1,15 +1,24 @@ import SwiftUI +enum OrderStatus { + case created + case approved + case completed + case error +} + struct PayPalWebResultView: View { @ObservedObject var payPalWebViewModel: PayPalWebViewModel + var status: OrderStatus + var body: some View { switch payPalWebViewModel.state { case .idle, .loading: EmptyView() - case .orderSuccess, .orderApproved, .transactionSuccess: - PayPalWebStatusView(payPalWebViewModel: payPalWebViewModel) + case .success: + PayPalWebStatusView(status: status, payPalWebViewModel: payPalWebViewModel) case .error(let errorMessage): ErrorView(errorMessage: errorMessage) } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebStatusView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebStatusView.swift index eae541bcb..2ec377e39 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebStatusView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebStatusView.swift @@ -2,30 +2,31 @@ import SwiftUI struct PayPalWebStatusView: View { + var status: OrderStatus var payPalWebViewModel: PayPalWebViewModel var body: some View { VStack(spacing: 16) { - switch payPalWebViewModel.state { - case .orderSuccess: + switch status { + case .created: HStack { Text("Order Created") .font(.system(size: 20)) Spacer() } - if let order = payPalWebViewModel.order { + if let order = payPalWebViewModel.createOrderResult { LeadingText("Order ID", weight: .bold) LeadingText("\(order.id)") LeadingText("Status", weight: .bold) LeadingText("\(order.status)") } - case .orderApproved: + case .approved: HStack { Text("Order Approved") .font(.system(size: 20)) Spacer() } - if let order = payPalWebViewModel.order { + if let order = payPalWebViewModel.createOrderResult { LeadingText("Intent", weight: .bold) LeadingText("\(payPalWebViewModel.intent)") LeadingText("Order ID", weight: .bold) @@ -33,8 +34,8 @@ struct PayPalWebStatusView: View { LeadingText("Payer ID", weight: .bold) LeadingText("\(payPalWebViewModel.checkoutResult?.payerID ?? "")") } - case .transactionSuccess: - if let order = payPalWebViewModel.order { + case .completed: + if let order = payPalWebViewModel.transactionResult { HStack { Text("Order \(payPalWebViewModel.intent.rawValue.capitalized)d") .font(.system(size: 20)) @@ -45,17 +46,17 @@ struct PayPalWebStatusView: View { LeadingText("Status", weight: .bold) LeadingText("\(order.status)") - if let emailAddress = payPalWebViewModel.order?.paymentSource?.paypal?.emailAddress { + if let emailAddress = order.paymentSource?.paypal?.emailAddress { LeadingText("Email", weight: .bold) LeadingText("\(emailAddress)") } - if let vaultID = payPalWebViewModel.order?.paymentSource?.paypal?.attributes?.vault.id { + if let vaultID = order.paymentSource?.paypal?.attributes?.vault.id { LeadingText("Vault ID / Payment Token", weight: .bold) LeadingText("\(vaultID)") } - if let customerID = payPalWebViewModel.order?.paymentSource?.paypal?.attributes?.vault.customer.id { + if let customerID = order.paymentSource?.paypal?.attributes?.vault.customer.id { LeadingText("Customer ID", weight: .bold) LeadingText("\(customerID)") } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebTransactionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebTransactionView.swift index 97e7b268a..88b075434 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebTransactionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebTransactionView.swift @@ -8,7 +8,7 @@ struct PayPalWebTransactionView: View { ScrollView { ScrollViewReader { scrollView in VStack { - PayPalWebStatusView(payPalWebViewModel: payPalWebViewModel) + PayPalWebStatusView(status: .approved, payPalWebViewModel: payPalWebViewModel) ZStack { Button("\(payPalWebViewModel.intent.rawValue.capitalized) Order") { Task { @@ -27,12 +27,14 @@ struct PayPalWebTransactionView: View { } } - if payPalWebViewModel.state == .transactionSuccess { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel) + if payPalWebViewModel.transactionResult != nil && payPalWebViewModel.state == .success { + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .completed) .id("bottomView") + } else if case .error = payPalWebViewModel.state { + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .error) } } - .onChange(of: payPalWebViewModel.order) { _ in + .onChange(of: payPalWebViewModel.transactionResult) { _ in withAnimation { scrollView.scrollTo("bottomView") } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift index f0e450112..4b2f4b0be 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift @@ -6,10 +6,12 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { @Published var state: CurrentState = .idle @Published var intent: Intent = .authorize - @Published var order: Order? + @Published var createOrderResult: Order? + @Published var transactionResult: Order? @Published var checkoutResult: PayPalWebCheckoutResult? var payPalWebCheckoutClient: PayPalWebCheckoutClient? + var orderID: String? let configManager = CoreConfigManager(domain: "PayPalWeb Payments") @@ -44,8 +46,12 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { selectedMerchantIntegration: DemoSettings.merchantIntegration ) - updateOrder(order) - updateState(.orderSuccess) + self.orderID = order.id + + DispatchQueue.main.async { + self.createOrderResult = order + } + updateState(.success) print("✅ fetched orderID: \(order.id) with status: \(order.status)") } catch { updateState(.error(message: error.localizedDescription)) @@ -63,7 +69,7 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { return } - if let orderID = order?.id { + if let orderID { let payPalRequest = PayPalWebCheckoutRequest(orderID: orderID, fundingSource: funding) payPalWebCheckoutClient.start(request: payPalRequest) } @@ -86,10 +92,12 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { do { updateState(.loading) - if let orderID = order?.id { + if let orderID { let order = try await DemoMerchantAPI.sharedService.completeOrder(intent: intent, orderID: orderID) - updateOrder(order) - updateState(.transactionSuccess) + DispatchQueue.main.async { + self.transactionResult = order + } + updateState(.success) } } catch { updateState(.error(message: error.localizedDescription)) @@ -97,12 +105,6 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { } } - private func updateOrder(_ order: Order) { - DispatchQueue.main.async { - self.order = order - } - } - private func updateState(_ state: CurrentState) { DispatchQueue.main.async { self.state = state @@ -115,7 +117,7 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { _ payPalClient: PayPalWebCheckoutClient, didFinishWithResult result: PayPalWebCheckoutResult ) { - updateState(.orderApproved) + updateState(.success) checkoutResult = result }