Skip to content

Commit 21ca044

Browse files
committed
Add embedded checkout support to CheckoutWebViewController and CheckoutDelegate
This commit integrates embedded checkout functionality into the view controller layer and delegate protocol while maintaining backward compatibility. CheckoutWebViewController changes: - Added CheckoutOptions parameter to initializer for embedded checkout configuration - Implemented embedded checkout delegate methods: - checkoutViewDidChangeState() for state change events - checkoutViewDidComplete() for completion with embedded payload - checkoutViewDidFail() for error handling with embedded error payloads - checkoutViewDidEmitWebPixelEvent() for embedded web pixel events - Enhanced error recovery logic for embedded checkout error types CheckoutDelegate changes: - Extended protocol with embedded checkout event methods - Added default implementations for all new methods to maintain compatibility - Documented embedded checkout methods with Schema 2025-04 specification All changes are backward compatible - existing implementations continue to work unchanged while new embedded checkout functionality is available for apps that need it.
1 parent 9340a74 commit 21ca044

File tree

2 files changed

+69
-1
lines changed

2 files changed

+69
-1
lines changed

Sources/ShopifyCheckoutSheetKit/CheckoutDelegate.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,20 @@ public protocol CheckoutDelegate: AnyObject {
4444

4545
/// Tells te delegate that a Web Pixel event was emitted
4646
func checkoutDidEmitWebPixelEvent(event: PixelEvent)
47+
48+
// MARK: - Embedded Checkout Events (Schema 2025-04)
49+
50+
/// Tells the delegate that the embedded checkout state has changed
51+
func checkoutDidChangeState(state: CheckoutStatePayload)
52+
53+
/// Tells the delegate that the embedded checkout successfully completed with order details
54+
func checkoutDidComplete(payload: CheckoutCompletePayload)
55+
56+
/// Tells the delegate that the embedded checkout encountered one or more errors
57+
func checkoutDidFail(errors: [ErrorPayload])
58+
59+
/// Tells the delegate that an embedded checkout web pixel event was emitted
60+
func checkoutDidEmitWebPixelEvent(payload: WebPixelsPayload)
4761
}
4862

4963
extension CheckoutDelegate {
@@ -68,4 +82,22 @@ extension CheckoutDelegate {
6882
UIApplication.shared.open(url)
6983
}
7084
}
85+
86+
// MARK: - Embedded Checkout Default Implementations
87+
88+
public func checkoutDidChangeState(state: CheckoutStatePayload) {
89+
/// No-op by default
90+
}
91+
92+
public func checkoutDidComplete(payload: CheckoutCompletePayload) {
93+
/// No-op by default
94+
}
95+
96+
public func checkoutDidFail(errors: [ErrorPayload]) {
97+
/// No-op by default
98+
}
99+
100+
public func checkoutDidEmitWebPixelEvent(payload: WebPixelsPayload) {
101+
/// No-op by default
102+
}
71103
}

Sources/ShopifyCheckoutSheetKit/CheckoutWebViewController.swift

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class CheckoutWebViewController: UIViewController, UIAdaptivePresentationControl
6262

6363
// MARK: Initializers
6464

65-
public init(checkoutURL url: URL, delegate: CheckoutDelegate? = nil, entryPoint: MetaData.EntryPoint? = nil) {
65+
public init(checkoutURL url: URL, delegate: CheckoutDelegate? = nil, entryPoint: MetaData.EntryPoint? = nil, options: CheckoutOptions? = nil) {
6666
checkoutURL = url
6767
self.delegate = delegate
6868

@@ -71,6 +71,9 @@ class CheckoutWebViewController: UIViewController, UIAdaptivePresentationControl
7171
checkoutView.scrollView.contentInsetAdjustmentBehavior = .never
7272
self.checkoutView = checkoutView
7373

74+
// Set checkout options for embedded checkout support
75+
checkoutView.checkoutOptions = options
76+
7477
super.init(nibName: nil, bundle: nil)
7578

7679
title = ShopifyCheckoutSheetKit.configuration.title
@@ -246,6 +249,39 @@ extension CheckoutWebViewController: CheckoutWebViewDelegate {
246249
func checkoutViewDidEmitWebPixelEvent(event: PixelEvent) {
247250
delegate?.checkoutDidEmitWebPixelEvent(event: event)
248251
}
252+
253+
// MARK: - Embedded Checkout Delegate Methods
254+
255+
func checkoutViewDidChangeState(state: CheckoutStatePayload) {
256+
delegate?.checkoutDidChangeState(state: state)
257+
}
258+
259+
func checkoutViewDidComplete(payload: CheckoutCompletePayload) {
260+
ConfettiCannon.fire(in: view)
261+
CheckoutWebView.invalidate(disconnect: false)
262+
delegate?.checkoutDidComplete(payload: payload)
263+
}
264+
265+
func checkoutViewDidFail(errors: [ErrorPayload]) {
266+
CheckoutWebView.invalidate()
267+
delegate?.checkoutDidFail(errors: errors)
268+
269+
// For embedded checkout errors, attempt recovery based on error group and URL type
270+
let shouldAttemptRecovery = errors.contains { error in
271+
// Only recover from specific recoverable network errors (5xx server errors)
272+
return error.group == "network" && error.type == "server_error" && (error.code?.hasPrefix("5") == true)
273+
} && !CheckoutURL(from: checkoutURL).isMultipassURL()
274+
275+
if shouldAttemptRecovery {
276+
presentFallbackViewController(url: checkoutURL)
277+
} else {
278+
dismiss(animated: true)
279+
}
280+
}
281+
282+
func checkoutViewDidEmitWebPixelEvent(payload: WebPixelsPayload) {
283+
delegate?.checkoutDidEmitWebPixelEvent(payload: payload)
284+
}
249285

250286
private func canRecoverFromError(_: CheckoutError) -> Bool {
251287
/// Reuse of multipass tokens will cause 422 errors. A new token must be generated

0 commit comments

Comments
 (0)