Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert Delegation Pattern to Completion Handler #293

Merged
merged 15 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,18 @@ struct PayPalVaultView: View {
)
SetupTokenResultView(vaultViewModel: paypalVaultViewModel)
if let setupTokenID = paypalVaultViewModel.state.setupToken?.id {
Button("Vault PayPal") {
Task {
await paypalVaultViewModel.vault(setupTokenID: setupTokenID)
ZStack {
Button("Vault PayPal") {
Task {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

random q: would it be cleaner if we created the Task within the paypalVaultViewModel.vault() method?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Button actions are synchronous contexts, so I need to create a Task block there to call an async/await function.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes sense what you are saying, make the views look cleaner. Let me add that to demo app refactor ticket.

await paypalVaultViewModel.vault(setupTokenID: setupTokenID)
}
}
.buttonStyle(RoundedBlueButtonStyle())
.padding()
if case .loading = paypalVaultViewModel.state.paypalVaultTokenResponse {
CircularProgressView()
}
}
.buttonStyle(RoundedBlueButtonStyle())
.padding()
}
PayPalVaultResultView(viewModel: paypalVaultViewModel)
if let paypalVaultResult = paypalVaultViewModel.state.paypalVaultToken {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import CorePayments
import PayPalWebPayments
import FraudProtection

class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate {
class PayPalWebViewModel: ObservableObject {

@Published var state: CurrentState = .idle
@Published var intent: Intent = .authorize
Expand Down Expand Up @@ -63,15 +63,21 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate {
Task {
do {
payPalWebCheckoutClient = try await getPayPalClient()
payPalWebCheckoutClient?.delegate = self
guard let payPalWebCheckoutClient else {
print("Error initializing PayPalWebCheckoutClient")
return
}

if let orderID {
let payPalRequest = PayPalWebCheckoutRequest(orderID: orderID, fundingSource: funding)
payPalWebCheckoutClient.start(request: payPalRequest)
payPalWebCheckoutClient.start(request: payPalRequest) { result, error in
if let error {
self.updateState(.error(message: error.localizedDescription))
} else {
self.updateState(.success)
self.checkoutResult = result
}
}
}
updateState(.success)
} catch {
Expand Down
21 changes: 16 additions & 5 deletions Demo/Demo/ViewModels/CardPaymentViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import CardPayments
import CorePayments
import FraudProtection

class CardPaymentViewModel: ObservableObject, CardDelegate {
class CardPaymentViewModel: ObservableObject {

@Published var state = CardPaymentState()
private var payPalDataCollector: PayPalDataCollector?
Expand Down Expand Up @@ -117,11 +117,22 @@ class CardPaymentViewModel: ObservableObject, CardDelegate {
let config = try await configManager.getCoreConfig()
cardClient = CardClient(config: config)
payPalDataCollector = PayPalDataCollector(config: config)
cardClient?.delegate = self
let cardRequest = CardRequest(orderID: orderID, card: card, sca: sca)
cardClient?.approveOrder(request: cardRequest)
cardClient?.approveOrder(request: cardRequest) { result, error in
if let error {
self.setUpdateSetupTokenFailureResult(vaultError: error)
} else if let result {
self.approveResultSuccessResult(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

qq: should this method be named approveOrderSuccessResult()?

Copy link
Collaborator Author

@KunJeongPark KunJeongPark Oct 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good call. There are many changes I want to make on the demo app, but I stuck to ones relevant to the conversion.
Like needing the loading progressView where I forgot them, to see if there were delays introduced in PayPal vault.

approveResult: CardPaymentState.CardResult(
id: result.orderID,
status: result.status,
didAttemptThreeDSecureAuthentication: result.didAttemptThreeDSecureAuthentication
)
)
}
}
} catch {
self.state.approveResultResponse = .error(message: error.localizedDescription)
setUpdateSetupTokenFailureResult(vaultError: error)
print("failed in checkout with card. \(error.localizedDescription)")
}
}
Expand All @@ -134,7 +145,7 @@ class CardPaymentViewModel: ObservableObject, CardDelegate {
}
}

func setUpdateSetupTokenFailureResult(vaultError: CorePayments.CoreSDKError) {
func setUpdateSetupTokenFailureResult(vaultError: Error) {
DispatchQueue.main.async {
self.state.approveResultResponse = .error(message: vaultError.localizedDescription)
}
Expand Down
42 changes: 10 additions & 32 deletions Demo/Demo/ViewModels/CardVaultViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Foundation
import CardPayments
import CorePayments

class CardVaultViewModel: VaultViewModel, CardVaultDelegate {
class CardVaultViewModel: VaultViewModel {

let configManager = CoreConfigManager(domain: "Card Vault")

Expand All @@ -13,11 +13,16 @@ class CardVaultViewModel: VaultViewModel, CardVaultDelegate {
do {
let config = try await configManager.getCoreConfig()
let cardClient = CardClient(config: config)
cardClient.vaultDelegate = self
let cardVaultRequest = CardVaultRequest(card: card, setupTokenID: setupToken)
cardClient.vault(cardVaultRequest)
cardClient.vault(cardVaultRequest) { result, error in
if let result {
self.setUpdateSetupTokenResult(vaultResult: result, vaultError: nil)
} else if let error {
self.setUpdateSetupTokenResult(vaultResult: nil, vaultError: error)
}
}
} catch {
self.state.updateSetupTokenResponse = .error(message: error.localizedDescription)
self.setUpdateSetupTokenResult(vaultResult: nil, vaultError: error)
print("failed in updating setup token. \(error.localizedDescription)")
}
}
Expand All @@ -31,7 +36,7 @@ class CardVaultViewModel: VaultViewModel, CardVaultDelegate {
return enabled
}

func setUpdateSetupTokenResult(vaultResult: CardVaultResult? = nil, vaultError: CoreSDKError? = nil) {
func setUpdateSetupTokenResult(vaultResult: CardVaultResult? = nil, vaultError: Error? = nil) {
DispatchQueue.main.async {
if let vaultResult {
self.state.updateSetupTokenResponse = .loaded(
Expand All @@ -46,31 +51,4 @@ class CardVaultViewModel: VaultViewModel, CardVaultDelegate {
}
}
}

// MARK: - CardVault Delegate

func card(_ cardClient: CardPayments.CardClient, didFinishWithVaultResult vaultResult: CardPayments.CardVaultResult) {
print("vaultResult: \(vaultResult)")
setUpdateSetupTokenResult(vaultResult: vaultResult)
}

func card(_ cardClient: CardPayments.CardClient, didFinishWithVaultError vaultError: CorePayments.CoreSDKError) {
print("error: \(vaultError.errorDescription ?? "")")
setUpdateSetupTokenResult(vaultError: vaultError)
}

func cardThreeDSecureDidCancel(_ cardClient: CardClient) {
DispatchQueue.main.async {
self.state.updateSetupTokenResponse = .idle
self.state.updateSetupToken = nil
}
}

func cardThreeDSecureWillLaunch(_ cardClient: CardPayments.CardClient) {
print("About to launch 3DS")
}

func cardThreeDSecureDidFinish(_ cardClient: CardPayments.CardClient) {
print("Finished 3DS")
}
}
43 changes: 15 additions & 28 deletions Demo/Demo/ViewModels/PayPalVaultViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import UIKit
import PayPalWebPayments
import CorePayments

class PayPalVaultViewModel: VaultViewModel, PayPalVaultDelegate {
class PayPalVaultViewModel: VaultViewModel {

let configManager = CoreConfigManager(domain: "PayPal Vault")

Expand All @@ -13,36 +13,23 @@ class PayPalVaultViewModel: VaultViewModel, PayPalVaultDelegate {
do {
let config = try await configManager.getCoreConfig()
let paypalClient = PayPalWebCheckoutClient(config: config)
paypalClient.vaultDelegate = self
let vaultRequest = PayPalVaultRequest(setupTokenID: setupTokenID)
paypalClient.vault(vaultRequest)
paypalClient.vault(vaultRequest) { result, error in
if let error {
DispatchQueue.main.async {
self.state.paypalVaultTokenResponse = .error(message: error.localizedDescription)
}
} else if let result {
DispatchQueue.main.async {
self.state.paypalVaultTokenResponse = .loaded(result)
}
}
}
} catch {
print("Error in vaulting PayPal Payment")
DispatchQueue.main.async {
self.state.paypalVaultTokenResponse = .error(message: error.localizedDescription)
}
}
}

// MARK: - PayPalVault Delegate

func paypal(
_ paypalWebClient: PayPalWebPayments.PayPalWebCheckoutClient,
didFinishWithVaultResult paypalVaultResult: PayPalVaultResult
) {
DispatchQueue.main.async {
self.state.paypalVaultTokenResponse = .loaded(paypalVaultResult)
}
}

func paypal(
_ paypalWebClient: PayPalWebPayments.PayPalWebCheckoutClient,
didFinishWithVaultError vaultError: CorePayments.CoreSDKError
) {

DispatchQueue.main.async {
self.state.paypalVaultTokenResponse = .error(message: vaultError.localizedDescription)
}
}

func paypalDidCancel(_ payPalWebClient: PayPalWebCheckoutClient) {
print("PayPal Checkout Canceled")
}
}
Loading
Loading