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

v2 migration guide #295

Merged
merged 16 commits into from
Nov 13, 2024
Merged
Changes from 15 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
196 changes: 196 additions & 0 deletions v2_MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
# Migrating from Delegates to Completion Handlers

## Overview
Version 2.0-beta of the SDK transitions from the delgate-based flows to completion handler-based flows. This change simplifies the integration and provides better compatibility with modern async/await patterns.
KunJeongPark marked this conversation as resolved.
Show resolved Hide resolved

### Key Changes

### Important Change: Cancellation Handling
In v2.0-beta, cancellations (e.g., 3DS cancellations, PayPal web flow cancellations) are now returned as errors rather than as separate delegate methods. There are new helper methods, static functions, to help you discern threeDSecure cancellation errors and PayPal web flow cancellation errors.
KunJeongPark marked this conversation as resolved.
Show resolved Hide resolved
- `CardError.threeDSecureCanceled(Error)` will return true for user cancellation during 3DS verification during card payment or card vaulting flows.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
- `CardError.threeDSecureCanceled(Error)` will return true for user cancellation during 3DS verification during card payment or card vaulting flows.
- `CardError.threeDSecureCanceled(Error)` will return true for 3DS cancellation errors received during card payment or card vaulting flows.

- `PayPalError.isCheckoutCanceled(Error)` will return true for user cancellation during PayPalWebCheckout session.
- `PayPalError.isVaultCanceled(Error)` will return true for user cancellation during PayPal vault session.

### CardClient Changes

```swift
// Old Delgate-based
class MyViewController: CardDelegate {
func setupPayment() {
let cardClient = CardClient(config: config)
cardClient.delegate = self
cardClient.approveOrder(request: cardRequest)
}

func card(_ cardClient: CardClient, didFinishWithResult result: CardResult) {
// Handle success
}

func card(_ cardClient: CardClient, didFinishWithError error: Error) {
// Handle error
}

func cardDidCancel(_ cardClient: CardClient) {
// Handle cancellation
}
}

// New (Completion-based)
class MyViewController {
func setupPayment() {
let cardClient = CardClient(config: config)
cardClient.approveOrder(request: cardRequest) { [weak self] result, error in
if let error = error {
// if threeDSecure is canceled by user
if CardError.isThreeDSecureCanceled(error) {
// handle cancel error
} else {
// handle other errors
}
return
}
if let result = result {
// handle success
}
}
}
}
```

### PayPalWebCheckoutClient Changes

```Swift
// Old (Delegate-based)
class MyViewController: PayPalWebCheckoutDelegate {
func startPayPalFlow() {
let payPalClient = PayPalWebCheckoutClient(config: config)
payPalClient.delegate = self
payPalClient.approveOrder(request: paypalRequest)
}

func payPal(_ payPalClient: PayPalWebCheckoutClient, didFinishWithResult result: PayPalWebCheckoutResult) {
// Handle success
}

func payPal(_ payPalClient: PayPalWebCheckoutClient, didFinishWithError error: Error) {
// Handle error
}

func payPalDidCancel(_ payPalClient: PayPalCheckoutClient) {
// Handle cancellation
}
}

// New (Completion-based)
class MyViewController {
func setupPayment() {
let payPalClient = PayPalWebCheckoutClient(config: config)
payPalClient.start(request: paypalRequest) { [weak self] result, error in
if let error = error {
// if PayPal webflow is canceled by user
if PayPalError.isCheckoutCanceled(error) {
// handle cancel error
} else {
// handle all other errors
}
return
}
if let result = result {
// handle success
}
}
}
}
```

## Async/Await
The SDK now provides async/await support, offering a more concise way to handle asynchronous operations.

### CardClient
```swift
class MyViewController {
func setupPayment() async {
let cardClient = CardClient(config: config)
do {
let result = try await cardClient.approveOrder(request: cardRequest)
// payment successful
handleSuccess(result)
} catch {
handleError(error)
}
}
}
```

### PayPalWebCheckoutClient
```swift
class MyViewController {
func startPayPalFlow() async {
let payPalClient = PayPalWebCheckoutClient(config: config)
do {
let result = try await payPalClient.start(request: paypalRequest)
// Payment successful
handleSuccess(result)
} catch {
handleError()
}
}
}
```

## Migration Steps

### 1. Update SDK Version
- Update your dependency manager (CocoaPods or SPM) to the latest SDK version

### 2. Remove Delegate Implementation
```diff
// Remove delegate protocol conformance
- class MyViewController: CardDelegate {
+ class MyViewController {

// Remove delegate property assignment
-cardClient.delegate = self

// Remove delegate methods
- func card(_ cardClient: CardClient, didFinishWithResult result: CardResult) {
- func card(_ cardClient: CardClient, didFinishWithError error: Error) {
- func cardDidCancel(_ cardClient: CardClient ) {
```

### 3. Update SDK Flow Implementation

Option 1: Using completion handlers
```swift
func processPayment() {
showLoadingIndicator()

cardClient.approveOrder(request: cardRequest) { [weak self] result, error in
guard let self = self else { return }
removeLoadingIndicator()

if let error = error {
handleError()
return
}

if let result = result {
handleSuccess(result)
}
}
}
```
Option 2: Using async/await
```swift
func processPayment() async {
showLaodingIndicator()
KunJeongPark marked this conversation as resolved.
Show resolved Hide resolved
defer { removeLoadingIndicator() }

do {
let result = try await cardClient.approveOrder(request: cardRequest)
handleSuccess(result)
} catch {
handleError()
}
}
```
Loading