Skip to content

Commit c7a789d

Browse files
authored
[DTPP-142] PayPalWebPayments show stages of order (#311)
* [DTPP-142] PayPalWebPayments show stages of order
1 parent 8194323 commit c7a789d

File tree

10 files changed

+279
-75
lines changed

10 files changed

+279
-75
lines changed

Demo/Demo.xcodeproj/project.pbxproj

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
1001E2C12CFFC72E0023A03C /* PayPalPaymentState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1001E2C02CFFC72E0023A03C /* PayPalPaymentState.swift */; };
11+
1001E2C52CFFD2800023A03C /* PayPalApprovalResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1001E2C42CFFD2800023A03C /* PayPalApprovalResultView.swift */; };
12+
1001E2C72CFFD2A30023A03C /* PayPalOrderCompletionResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1001E2C62CFFD2A20023A03C /* PayPalOrderCompletionResultView.swift */; };
1013
3B20273D2A89E3F00007907E /* CreateSetupTokenView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B20273C2A89E3F00007907E /* CreateSetupTokenView.swift */; };
1114
3B20273F2A89F24E0007907E /* CardVaultViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B20273E2A89F24E0007907E /* CardVaultViewModel.swift */; };
1215
3B2027412A8A72050007907E /* VaultState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B2027402A8A72050007907E /* VaultState.swift */; };
@@ -67,7 +70,7 @@
6770
BE1766B326F911A2007EF438 /* URLResponseError.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE1766B226F911A2007EF438 /* URLResponseError.swift */; };
6871
BE1766D926FA7BC8007EF438 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = BE1766D826FA7BC8007EF438 /* Settings.bundle */; };
6972
BE5898952B2B91F800AA196E /* LabelViewText.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE5898942B2B91F800AA196E /* LabelViewText.swift */; };
70-
BE8117642B07E778009867B9 /* PayPalWebResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE8117632B07E778009867B9 /* PayPalWebResultView.swift */; };
73+
BE8117642B07E778009867B9 /* PayPalOrderCreateResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE8117632B07E778009867B9 /* PayPalOrderCreateResultView.swift */; };
7174
BE8117682B080472009867B9 /* CurrentState.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE8117672B080472009867B9 /* CurrentState.swift */; };
7275
BE9F36D82745490400AFC7DA /* FloatingLabelTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE9F36D72745490400AFC7DA /* FloatingLabelTextField.swift */; };
7376
BECD84A027036DC2007CCAE4 /* Environment.swift in Sources */ = {isa = PBXBuildFile; fileRef = BECD849F27036DC2007CCAE4 /* Environment.swift */; };
@@ -118,6 +121,9 @@
118121
/* End PBXCopyFilesBuildPhase section */
119122

120123
/* Begin PBXFileReference section */
124+
1001E2C02CFFC72E0023A03C /* PayPalPaymentState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalPaymentState.swift; sourceTree = "<group>"; };
125+
1001E2C42CFFD2800023A03C /* PayPalApprovalResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalApprovalResultView.swift; sourceTree = "<group>"; };
126+
1001E2C62CFFD2A20023A03C /* PayPalOrderCompletionResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalOrderCompletionResultView.swift; sourceTree = "<group>"; };
121127
3B20273C2A89E3F00007907E /* CreateSetupTokenView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateSetupTokenView.swift; sourceTree = "<group>"; };
122128
3B20273E2A89F24E0007907E /* CardVaultViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardVaultViewModel.swift; sourceTree = "<group>"; };
123129
3B2027402A8A72050007907E /* VaultState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VaultState.swift; sourceTree = "<group>"; };
@@ -186,7 +192,7 @@
186192
BE1766D826FA7BC8007EF438 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = "<group>"; };
187193
BE420F3628189A7A00D8D66A /* PayPalUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = PayPalUI.framework; sourceTree = BUILT_PRODUCTS_DIR; };
188194
BE5898942B2B91F800AA196E /* LabelViewText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelViewText.swift; sourceTree = "<group>"; };
189-
BE8117632B07E778009867B9 /* PayPalWebResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalWebResultView.swift; sourceTree = "<group>"; };
195+
BE8117632B07E778009867B9 /* PayPalOrderCreateResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalOrderCreateResultView.swift; sourceTree = "<group>"; };
190196
BE8117672B080472009867B9 /* CurrentState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrentState.swift; sourceTree = "<group>"; };
191197
BE9F36D72745490400AFC7DA /* FloatingLabelTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatingLabelTextField.swift; sourceTree = "<group>"; };
192198
BECD849F27036DC2007CCAE4 /* Environment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Environment.swift; sourceTree = "<group>"; };
@@ -267,6 +273,7 @@
267273
isa = PBXGroup;
268274
children = (
269275
3BA56FFB2A9FEFE90081D14F /* PayPalWebViewModel.swift */,
276+
1001E2C02CFFC72E0023A03C /* PayPalPaymentState.swift */,
270277
);
271278
path = PayPalWebViewModel;
272279
sourceTree = "<group>";
@@ -314,6 +321,17 @@
314321
path = Vault;
315322
sourceTree = "<group>";
316323
};
324+
1001E2CB2D03836D0023A03C /* PayPalWebResultViews */ = {
325+
isa = PBXGroup;
326+
children = (
327+
BE8117632B07E778009867B9 /* PayPalOrderCreateResultView.swift */,
328+
1001E2C42CFFD2800023A03C /* PayPalApprovalResultView.swift */,
329+
3B6472A62AFAEB3A004745C4 /* PayPalWebTransactionView.swift */,
330+
1001E2C62CFFD2A20023A03C /* PayPalOrderCompletionResultView.swift */,
331+
);
332+
path = PayPalWebResultViews;
333+
sourceTree = "<group>";
334+
};
317335
3B2501052B2679F000903EAB /* VaultViews */ = {
318336
isa = PBXGroup;
319337
children = (
@@ -353,11 +371,10 @@
353371
3BA56FFF2A9FF6630081D14F /* PayPalWebPaymentsView */ = {
354372
isa = PBXGroup;
355373
children = (
374+
1001E2CB2D03836D0023A03C /* PayPalWebResultViews */,
375+
3BA570002AA052E80081D14F /* PayPalWebPaymentsView.swift */,
356376
3BA570062AA0DF330081D14F /* PayPalWebButtonsView.swift */,
357377
3BA570022AA053AE0081D14F /* PayPalWebCreateOrderView.swift */,
358-
3BA570002AA052E80081D14F /* PayPalWebPaymentsView.swift */,
359-
BE8117632B07E778009867B9 /* PayPalWebResultView.swift */,
360-
3B6472A62AFAEB3A004745C4 /* PayPalWebTransactionView.swift */,
361378
);
362379
path = PayPalWebPaymentsView;
363380
sourceTree = "<group>";
@@ -642,7 +659,7 @@
642659
3B2027412A8A72050007907E /* VaultState.swift in Sources */,
643660
80F33CED26F8E7A9006811B1 /* Order.swift in Sources */,
644661
3B4DD9A02A892A7000F4A716 /* CardVaultView.swift in Sources */,
645-
BE8117642B07E778009867B9 /* PayPalWebResultView.swift in Sources */,
662+
BE8117642B07E778009867B9 /* PayPalOrderCreateResultView.swift in Sources */,
646663
3BA56FF62A9E9AAB0081D14F /* CardOrderActionButton.swift in Sources */,
647664
3BC622092A97198500251B85 /* LeadingText.swift in Sources */,
648665
3B80D5102A291CB100D2EAC4 /* ClientIDResponse.swift in Sources */,
@@ -657,17 +674,20 @@
657674
3B2027432A8A95EF0007907E /* SetupTokenResultView.swift in Sources */,
658675
3BF999762A8AC093009CBDF2 /* UpdateSetupTokenResultView.swift in Sources */,
659676
BECD84A027036DC2007CCAE4 /* Environment.swift in Sources */,
677+
1001E2C12CFFC72E0023A03C /* PayPalPaymentState.swift in Sources */,
660678
3BCCFE4B2A9D985F00C5102F /* FeatureSelectionView.swift in Sources */,
661679
CB9ED44C283FDA900081F4DE /* PaymentButtonEnums+Extension.swift in Sources */,
662680
3BB60B552B1FA00C00A298CF /* PayPalVaultViewModel.swift in Sources */,
663681
3BB60B532B1F9F1100A298CF /* PayPalVaultView.swift in Sources */,
664682
3B80D50E2A291C0800D2EAC4 /* ClientIDRequest.swift in Sources */,
665683
3BA56FF02A9DCCFD0081D14F /* CardOrderApproveView.swift in Sources */,
666684
BE8117682B080472009867B9 /* CurrentState.swift in Sources */,
685+
1001E2C72CFFD2A30023A03C /* PayPalOrderCompletionResultView.swift in Sources */,
667686
3BDB348E2A7CB02C008100D7 /* CreateSetupTokenParam.swift in Sources */,
668687
3BA0A58B2B1E240300330681 /* VaultViewModel.swift in Sources */,
669688
80F33CF326F8EA50006811B1 /* DemoSettings.swift in Sources */,
670689
3BA56FE72A9DC9D70081D14F /* CardPaymentViewModel.swift in Sources */,
690+
1001E2C52CFFD2800023A03C /* PayPalApprovalResultView.swift in Sources */,
671691
3BA5700B2AA13C1C0081D14F /* CoreConfigManager.swift in Sources */,
672692
80F33CE826F8DE29006811B1 /* DemoMerchantAPI.swift in Sources */,
673693
80F33CEF26F8E7CC006811B1 /* CreateOrderParams.swift in Sources */,

Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebButtonsView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ struct PayPalWebButtonsView: View {
3939
payPalWebViewModel.paymentButtonTapped(funding: .paypal)
4040
}
4141
}
42-
if payPalWebViewModel.state == .loading &&
42+
if payPalWebViewModel.state.approveResultResponse == .loading &&
4343
payPalWebViewModel.checkoutResult == nil &&
4444
payPalWebViewModel.orderID != nil {
4545
CircularProgressView()

Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebCreateOrderView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ struct PayPalWebCreateOrderView: View {
4040
}
4141
}
4242
.buttonStyle(RoundedBlueButtonStyle())
43-
if payPalWebViewModel.state == .loading && payPalWebViewModel.checkoutResult == nil && payPalWebViewModel.orderID == nil {
43+
if case .loading = payPalWebViewModel.state.createdOrderResponse {
4444
CircularProgressView()
4545
}
4646
}

Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebPaymentsView.swift

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,36 @@
11
import SwiftUI
22

33
struct PayPalWebPaymentsView: View {
4-
4+
55
@StateObject var payPalWebViewModel = PayPalWebViewModel()
6-
6+
77
var body: some View {
88
ScrollView {
99
ScrollViewReader { scrollView in
1010
VStack(spacing: 16) {
11+
1112
PayPalWebCreateOrderView(payPalWebViewModel: payPalWebViewModel)
12-
13-
if payPalWebViewModel.orderID != nil {
13+
14+
if case .loaded = payPalWebViewModel.state.createdOrderResponse {
15+
PayPalOrderCreateResultView(payPalWebViewModel: payPalWebViewModel)
16+
1417
PayPalWebButtonsView(payPalWebViewModel: payPalWebViewModel)
1518
}
16-
17-
PayPalWebResultView(payPalWebViewModel: payPalWebViewModel)
18-
19-
if payPalWebViewModel.checkoutResult != nil {
19+
20+
if case .loaded = payPalWebViewModel.state.approveResultResponse {
21+
PayPalApprovalResultView(payPalWebViewModel: payPalWebViewModel)
22+
2023
PayPalWebTransactionView(payPalWebViewModel: payPalWebViewModel)
2124
.padding(.bottom, 20)
22-
.id("bottomView")
23-
.onAppear {
24-
withAnimation {
25-
scrollView.scrollTo("bottomView")
26-
}
27-
}
2825
}
26+
27+
if case .loaded = payPalWebViewModel.state.capturedOrderResponse {
28+
PayPalOrderCompletionResultView(payPalWebViewModel: payPalWebViewModel)
29+
} else if case .loaded = payPalWebViewModel.state.authorizedOrderResponse {
30+
PayPalOrderCompletionResultView(payPalWebViewModel: payPalWebViewModel)
31+
}
32+
Text("")
33+
.id("bottomView")
2934
}
3035
.onChange(of: payPalWebViewModel.state) { _ in
3136
withAnimation {
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import SwiftUI
2+
3+
struct PayPalApprovalResultView: View {
4+
5+
@ObservedObject var payPalWebViewModel: PayPalWebViewModel
6+
7+
var body: some View {
8+
switch payPalWebViewModel.state.approveResultResponse {
9+
case .idle, .loading:
10+
EmptyView()
11+
case .error(let message):
12+
ErrorView(errorMessage: message)
13+
case .loaded(let approvalResult):
14+
getApprovalSuccessView(approvalResult: approvalResult)
15+
}
16+
}
17+
18+
func getApprovalSuccessView(approvalResult: PayPalPaymentState.ApprovalResult) -> some View {
19+
VStack(alignment: .leading, spacing: 16) {
20+
Text("Approval Result")
21+
.font(.headline)
22+
LeadingText("Approval ID", weight: .bold)
23+
.font(.system(size: 20))
24+
25+
LeadingText(approvalResult.id)
26+
if let status = approvalResult.status {
27+
LeadingText("Status", weight: .bold)
28+
LeadingText(status)
29+
}
30+
}
31+
.frame(maxWidth: .infinity)
32+
.padding()
33+
.background(
34+
RoundedRectangle(cornerRadius: 10)
35+
.stroke(.gray, lineWidth: 2)
36+
.padding(5)
37+
)
38+
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import SwiftUI
2+
3+
struct PayPalOrderCompletionResultView: View {
4+
5+
@ObservedObject var payPalWebViewModel: PayPalWebViewModel
6+
7+
var body: some View {
8+
VStack {
9+
if case .loaded(let authorizedOrder) = payPalWebViewModel.state.authorizedOrderResponse {
10+
getCompletionSuccessView(order: authorizedOrder, intent: "Authorized")
11+
}
12+
if case .loaded(let capturedOrder) = payPalWebViewModel.state.capturedOrderResponse {
13+
getCompletionSuccessView(order: capturedOrder, intent: "Captured")
14+
}
15+
}
16+
}
17+
18+
func getCompletionSuccessView(order: Order, intent: String) -> some View {
19+
VStack(alignment: .leading, spacing: 16) {
20+
Text("Order \(intent) Successfully")
21+
.font(.system(size: 20))
22+
23+
LabelViewText("Order ID:", bodyText: order.id)
24+
25+
LabelViewText("Status:", bodyText: order.status)
26+
27+
if let payerID = payPalWebViewModel.checkoutResult?.payerID {
28+
LabelViewText("Payer ID:", bodyText: payerID)
29+
}
30+
31+
if let emailAddress = order.paymentSource?.paypal?.emailAddress {
32+
LabelViewText("Email:", bodyText: emailAddress)
33+
}
34+
35+
if let vaultID = order.paymentSource?.paypal?.attributes?.vault.id {
36+
LabelViewText("Payment Token:", bodyText: vaultID)
37+
}
38+
39+
if let customerID = order.paymentSource?.paypal?.attributes?.vault.customer?.id {
40+
LabelViewText("Customer ID:", bodyText: customerID)
41+
}
42+
}
43+
.frame(maxWidth: .infinity)
44+
.padding()
45+
.background(
46+
RoundedRectangle(cornerRadius: 10)
47+
.stroke(.gray, lineWidth: 2)
48+
.padding(5)
49+
)
50+
}
51+
}

Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebResultView.swift renamed to Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebResultViews/PayPalOrderCreateResultView.swift

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,45 @@
11
import SwiftUI
22

3-
struct PayPalWebResultView: View {
3+
struct PayPalOrderCreateResultView: View {
44

55
@ObservedObject var payPalWebViewModel: PayPalWebViewModel
66

77
var body: some View {
8-
switch payPalWebViewModel.state {
8+
switch payPalWebViewModel.state.createdOrderResponse {
99
case .idle, .loading:
1010
EmptyView()
11-
case .success:
12-
successView
11+
case .loaded(let createOrderResponse):
12+
getSuccessView(createOrderResponse: createOrderResponse)
1313
case .error(let errorMessage):
1414
ErrorView(errorMessage: errorMessage)
1515
}
1616
}
1717

18-
var successView: some View {
18+
func getSuccessView(createOrderResponse: Order) -> some View {
1919
VStack(alignment: .leading, spacing: 16) {
2020
HStack {
2121
Text("Order Details")
2222
.font(.system(size: 20))
2323
Spacer()
2424
}
25-
if let orderID = payPalWebViewModel.orderID {
26-
LabelViewText("Order ID:", bodyText: orderID)
27-
}
28-
29-
if let status = payPalWebViewModel.order?.status {
30-
LabelViewText("Status:", bodyText: status)
31-
}
25+
26+
LabelViewText("Order ID:", bodyText: createOrderResponse.id)
27+
28+
LabelViewText("Status:", bodyText: createOrderResponse.status)
3229

3330
if let payerID = payPalWebViewModel.checkoutResult?.payerID {
3431
LabelViewText("Payer ID:", bodyText: payerID)
3532
}
3633

37-
if let emailAddress = payPalWebViewModel.order?.paymentSource?.paypal?.emailAddress {
34+
if let emailAddress = createOrderResponse.paymentSource?.paypal?.emailAddress {
3835
LabelViewText("Email:", bodyText: emailAddress)
3936
}
4037

41-
if let vaultID = payPalWebViewModel.order?.paymentSource?.paypal?.attributes?.vault.id {
38+
if let vaultID = createOrderResponse.paymentSource?.paypal?.attributes?.vault.id {
4239
LabelViewText("Payment Token:", bodyText: vaultID)
4340
}
4441

45-
if let customerID = payPalWebViewModel.order?.paymentSource?.paypal?.attributes?.vault.customer?.id {
42+
if let customerID = createOrderResponse.paymentSource?.paypal?.attributes?.vault.customer?.id {
4643
LabelViewText("Customer ID:", bodyText: customerID)
4744
}
4845
}

Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebTransactionView.swift renamed to Demo/Demo/PayPalWebPayments/PayPalWebPaymentsView/PayPalWebResultViews/PayPalWebTransactionView.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ struct PayPalWebTransactionView: View {
1919
.buttonStyle(RoundedBlueButtonStyle())
2020
.padding()
2121

22-
if payPalWebViewModel.state == .loading {
22+
if payPalWebViewModel.state.capturedOrderResponse == .loading ||
23+
payPalWebViewModel.state.authorizedOrderResponse == .loading {
2324
CircularProgressView()
2425
}
2526
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import Foundation
2+
import PayPalWebPayments
3+
4+
struct PayPalPaymentState: Equatable {
5+
6+
struct ApprovalResult: Decodable, Equatable {
7+
8+
let id: String
9+
let status: String?
10+
}
11+
12+
var createOrder: Order?
13+
var authorizedOrder: Order?
14+
var capturedOrder: Order?
15+
var intent: Intent = .authorize
16+
var approveResult: ApprovalResult?
17+
18+
var createdOrderResponse: LoadingState<Order> = .idle {
19+
didSet {
20+
if case .loaded(let value) = createdOrderResponse {
21+
createOrder = value
22+
}
23+
}
24+
}
25+
26+
var approveResultResponse: LoadingState<ApprovalResult> = .idle {
27+
didSet {
28+
if case .loaded(let value) = approveResultResponse {
29+
approveResult = value
30+
}
31+
}
32+
}
33+
34+
var capturedOrderResponse: LoadingState<Order> = .idle {
35+
didSet {
36+
if case .loaded(let value) = capturedOrderResponse {
37+
capturedOrder = value
38+
}
39+
}
40+
}
41+
42+
var authorizedOrderResponse: LoadingState<Order> = .idle {
43+
didSet {
44+
if case .loaded(let value) = authorizedOrderResponse {
45+
authorizedOrder = value
46+
}
47+
}
48+
}
49+
}

0 commit comments

Comments
 (0)