Repository navigation
Checkout action callback - #2755
Conversation
There was a problem hiding this comment.
Code Review
This pull request refactors action presentation across the SDK by removing the public PresentationDelegate protocol and the presentationDelegate parameter from Checkout.setup(...) in favor of a new closure-based onAction(_:) callback on all checkout flows. It also introduces ActionData and ActionType to describe the actions being presented. A critical issue was identified in BACSDirectDebitComponent where discarding the confirmation view controller and removing the presentation delegate will prevent the BACS Direct Debit confirmation screen from being presented, which breaks the payment flow.
…_Checkout_action_callback # Conflicts: # MIGRATION.md
|
ℹ️ No baseline data found for 'develop'.
|
Aligns the property name with the ActionPresentationDelegate protocol it holds, so action-presentation plumbing is distinguishable from other delegate properties at call sites. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
erenbesel
left a comment
There was a problem hiding this comment.
Love to see it! some notes
# Summary Renames the public callback typealiases so they are all prefixed with `Checkout`, preventing name collisions with integrator types. Also documents the renames in the migration guide. ## Release Notes <changed> - Renamed `SubmitHandler`, `AdditionalDetailsHandler` and `BeforeSubmitHandler` to `CheckoutSubmitHandler`, `CheckoutAdditionalDetailsHandler` and `CheckoutBeforeSubmitHandler`. </changed> ## Technical Information Handlers already containing `Checkout` (`CheckoutActionHandler`, `SessionCheckoutCompletionHandler`, `AdvancedCheckoutCompletionHandler`, `CheckoutFailureHandler`) are unchanged. ## Checklist - [x] Tested changes locally - [ ] Added/updated unit tests - [x] Verified against acceptance criteria - [ ] Aligned public API changes with other platforms (if applicable)
|
| ❇️ | 7 Additions |
| 🔀 | 7 Modifications |
| ❌ | 4 Removals |
Adyen
❇️ Added
public struct ActionData: Swift.Equatable, Swift.Sendable {
public init(type: Adyen.ActionType)
public let type: Adyen.ActionType { get }
public static func ==(
a: Adyen.ActionData,
b: Adyen.ActionData
) -> Swift.Bool
}public struct ActionType: Swift.Decodable, Swift.Hashable, Swift.RawRepresentable, Swift.Sendable {
public init(from decoder: any Swift.Decoder) throws
public init(rawValue: Swift.String)
public let rawValue: Swift.String { get }
public static let await: Adyen.ActionType { get }
public static let nativeRedirect: Adyen.ActionType { get }
public static let qrCode: Adyen.ActionType { get }
public static let redirect: Adyen.ActionType { get }
public static let sdk: Adyen.ActionType { get }
public static let threeDS2: Adyen.ActionType { get }
public static let voucher: Adyen.ActionType { get }
public typealias RawValue = Swift.String
}public typealias CheckoutActionHandler = @_Concurrency.MainActor @Sendable (_ actionData: Adyen.ActionData, _ actionViewController: UIKit.UIViewController) -> Swift.Voidpublic typealias CheckoutAdditionalDetailsHandler = @_Concurrency.MainActor @Sendable (_ data: Adyen.ActionComponentData) async -> Adyen.AdditionalDetailsResultpublic typealias CheckoutBeforeSubmitHandler = @_Concurrency.MainActor @Sendable (_ data: Adyen.BeforeSubmitData) async -> Adyen.BeforeSubmitResultpublic typealias CheckoutSubmitHandler = @_Concurrency.MainActor @Sendable (_ data: Adyen.PaymentComponentData) async -> Adyen.SubmitResult❌ Removed
@_Concurrency.MainActor
public protocol PresentationDelegate: AnyObject {
@_Concurrency.MainActor
func present(viewController: UIKit.UIViewController) -> Swift.Void
}public typealias AdditionalDetailsHandler = @_Concurrency.MainActor @Sendable (_ data: Adyen.ActionComponentData) async -> Adyen.AdditionalDetailsResultpublic typealias BeforeSubmitHandler = @_Concurrency.MainActor @Sendable (_ data: Adyen.BeforeSubmitData) async -> Adyen.BeforeSubmitResultpublic typealias SubmitHandler = @_Concurrency.MainActor @Sendable (_ data: Adyen.PaymentComponentData) async -> Adyen.SubmitResultAdyenCheckout
ActionOnlyCheckout
🔀 Modified
// From
@_Concurrency.MainActor
final public func onAdditionalDetails(_ handler: @escaping Adyen.AdditionalDetailsHandler) -> Self
// To
@_Concurrency.MainActor
final public func onAdditionalDetails(_ handler: @escaping Adyen.CheckoutAdditionalDetailsHandler) -> Self
/**
Changes:
- Modified parameter `_`: Changed type from `@escaping Adyen.AdditionalDetailsHandler` to `@escaping Adyen.CheckoutAdditionalDetailsHandler`
*/AdvancedCheckout
🔀 Modified
// From
@_Concurrency.MainActor
final public func onAdditionalDetails(_ handler: @escaping Adyen.AdditionalDetailsHandler) -> Self
// To
@_Concurrency.MainActor
final public func onAdditionalDetails(_ handler: @escaping Adyen.CheckoutAdditionalDetailsHandler) -> Self
/**
Changes:
- Modified parameter `_`: Changed type from `@escaping Adyen.AdditionalDetailsHandler` to `@escaping Adyen.CheckoutAdditionalDetailsHandler`
*/// From
@_Concurrency.MainActor
final public func onSubmit(_ handler: @escaping Adyen.SubmitHandler) -> Self
// To
@_Concurrency.MainActor
final public func onSubmit(_ handler: @escaping Adyen.CheckoutSubmitHandler) -> Self
/**
Changes:
- Modified parameter `_`: Changed type from `@escaping Adyen.SubmitHandler` to `@escaping Adyen.CheckoutSubmitHandler`
*/BaseCheckout
❇️ Added
@_Concurrency.MainActor
public func onAction(_ handler: @escaping Adyen.CheckoutActionHandler) -> SelfCheckout
🔀 Modified
// From
@_Concurrency.MainActor
public static func setup(
configuration: AdyenCheckout.CheckoutConfiguration,
presentationDelegate: (any Adyen.PresentationDelegate)? = nil
) async throws -> AdyenCheckout.ActionOnlyCheckout
// To
@_Concurrency.MainActor
public static func setup(configuration: AdyenCheckout.CheckoutConfiguration) async throws -> AdyenCheckout.ActionOnlyCheckout
/**
Changes:
- Removed parameter `presentationDelegate: (any Adyen.PresentationDelegate)? = nil`
*/// From
@_Concurrency.MainActor
public static func setup(
with paymentMethods: Adyen.PaymentMethods,
configuration: AdyenCheckout.CheckoutConfiguration,
presentationDelegate: (any Adyen.PresentationDelegate)? = nil
) async throws -> AdyenCheckout.AdvancedCheckout
// To
@_Concurrency.MainActor
public static func setup(
with paymentMethods: Adyen.PaymentMethods,
configuration: AdyenCheckout.CheckoutConfiguration
) async throws -> AdyenCheckout.AdvancedCheckout
/**
Changes:
- Removed parameter `presentationDelegate: (any Adyen.PresentationDelegate)? = nil`
*/// From
@_Concurrency.MainActor
public static func setup(
with sessionResponse: Adyen.SessionResponse,
configuration: AdyenCheckout.CheckoutConfiguration,
presentationDelegate: (any Adyen.PresentationDelegate)? = nil
) async throws -> AdyenCheckout.SessionCheckout
// To
@_Concurrency.MainActor
public static func setup(
with sessionResponse: Adyen.SessionResponse,
configuration: AdyenCheckout.CheckoutConfiguration
) async throws -> AdyenCheckout.SessionCheckout
/**
Changes:
- Removed parameter `presentationDelegate: (any Adyen.PresentationDelegate)? = nil`
*/SessionCheckout
🔀 Modified
// From
@_Concurrency.MainActor
final public func onBeforeSubmit(_ handler: @escaping Adyen.BeforeSubmitHandler) -> Self
// To
@_Concurrency.MainActor
final public func onBeforeSubmit(_ handler: @escaping Adyen.CheckoutBeforeSubmitHandler) -> Self
/**
Changes:
- Modified parameter `_`: Changed type from `@escaping Adyen.BeforeSubmitHandler` to `@escaping Adyen.CheckoutBeforeSubmitHandler`
*/Analyzed targets: Adyen, AdyenActions, AdyenCard, AdyenCardScanner, AdyenCashAppPay, AdyenCheckout, AdyenComponents, AdyenDelegatedAuthentication, AdyenDropIn, AdyenEncryption, AdyenSession, AdyenSwiftUI, AdyenTwint, AdyenUI, AdyenWeChatPay
Summary [Required]
Introduces
onAction(_ actionData: ActionData, actionViewController: UIViewController), which hands the integrator both the action's data and the view controller the SDK built for it, so they decide how the action is presented. It replaces thePresentationDelegateprotocol and thepresentationDelegate:parameter ofCheckout.setup(...). The callback lives onBaseCheckout, so the session, advanced and action-only flows all expose it from one declaration.Technical Information [Optional]
PresentationDelegatebecamepackage protocol ActionPresentationDelegatewithpresent(actionData:actionViewController:). All eleven presentation sites supply the matchingActionType.CheckoutCoreis now its own presentation delegate. With no handler set it falls back to presenting on the pending payment component; the action-only flow has none, so it asserts.onAction. Documented on the callback, inREADME.md,guides/v6/README.mdandMIGRATION.md.NavigationDelegate/DismissalDelegate,Session.presentationDelegate(stored, never read) andBACSDirectDebitComponent.presentationDelegate(ahead of COSDK-1284).Testing Instructions [Optional]
onAction, wrapped in a navigation controller with a cancel button.UnitTestsandIntegrationTestsschemes: 436 and 984 tests, no failures.Ticket [Optional]
COSDK-1557Checklist [Required]