Skip to content

Commit

Permalink
Fire checkoutDidComplete with orderId if available on the URL
Browse files Browse the repository at this point in the history
  • Loading branch information
markmur committed Apr 18, 2024
1 parent 11e4bb4 commit e418b33
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 75 deletions.
2 changes: 1 addition & 1 deletion Sources/ShopifyCheckoutSheetKit/CheckoutBridge.swift
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ extension CheckoutBridge {
self = .checkoutComplete(event: checkoutCompletedEvent)
} catch {
logger.logError(error, "Error decoding CheckoutCompletedEvent")
self = .checkoutComplete(event: emptyCheckoutCompletedEvent)
self = .checkoutComplete(event: createEmptyCheckoutCompletedEvent())
}
case "error":
let errorDecoder = CheckoutErrorEventDecoder()
Expand Down
64 changes: 33 additions & 31 deletions Sources/ShopifyCheckoutSheetKit/CheckoutCompletedEvent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -117,36 +117,38 @@ extension CheckoutCompletedEvent {

// swiftlint:enable identifier_name

internal let emptyCheckoutCompletedEvent = CheckoutCompletedEvent(
orderDetails: CheckoutCompletedEvent.OrderDetails(
billingAddress: CheckoutCompletedEvent.Address(
address1: nil,
address2: nil,
city: nil,
countryCode: nil,
firstName: nil,
lastName: nil,
name: nil,
phone: nil,
postalCode: nil,
referenceId: nil,
zoneCode: nil
),
cart: CheckoutCompletedEvent.CartInfo(
lines: [],
price: CheckoutCompletedEvent.Price(
discounts: nil,
shipping: CheckoutCompletedEvent.Money(amount: nil, currencyCode: nil),
subtotal: CheckoutCompletedEvent.Money(amount: nil, currencyCode: nil),
taxes: CheckoutCompletedEvent.Money(amount: nil, currencyCode: nil),
total: CheckoutCompletedEvent.Money(amount: nil, currencyCode: nil)
internal func createEmptyCheckoutCompletedEvent(id: String? = "") -> CheckoutCompletedEvent {
return CheckoutCompletedEvent(
orderDetails: CheckoutCompletedEvent.OrderDetails(
billingAddress: CheckoutCompletedEvent.Address(
address1: nil,
address2: nil,
city: nil,
countryCode: nil,
firstName: nil,
lastName: nil,
name: nil,
phone: nil,
postalCode: nil,
referenceId: nil,
zoneCode: nil
),
token: ""
),
deliveries: nil,
email: nil,
id: "",
paymentMethods: nil,
phone: nil
cart: CheckoutCompletedEvent.CartInfo(
lines: [],
price: CheckoutCompletedEvent.Price(
discounts: nil,
shipping: CheckoutCompletedEvent.Money(amount: nil, currencyCode: nil),
subtotal: CheckoutCompletedEvent.Money(amount: nil, currencyCode: nil),
taxes: CheckoutCompletedEvent.Money(amount: nil, currencyCode: nil),
total: CheckoutCompletedEvent.Money(amount: nil, currencyCode: nil)
),
token: ""
),
deliveries: nil,
email: nil,
id: id ?? "",
paymentMethods: nil,
phone: nil
)
)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class CheckoutCompletedEventDecoder {
let messageBody = try container.decode(String.self, forKey: .body)

guard let data = messageBody.data(using: .utf8) else {
return emptyCheckoutCompletedEvent
return createEmptyCheckoutCompletedEvent()
}

return try JSONDecoder().decode(CheckoutCompletedEvent.self, from: data)
Expand Down
36 changes: 35 additions & 1 deletion Sources/ShopifyCheckoutSheetKit/CheckoutWebView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ protocol CheckoutWebViewDelegate: AnyObject {
func checkoutViewDidEmitWebPixelEvent(event: PixelEvent)
}

private let retryQueryParameter = "checkoutSheetRetry"
private let retryQueryParameter = "checkout_sheet_retry"
private let deprecatedReasonHeader = "X-Shopify-API-Deprecated-Reason"
private let checkoutLiquidNotSupportedReason = "checkout_liquid_not_supported"

Expand Down Expand Up @@ -295,6 +295,15 @@ extension CheckoutWebView: WKNavigationDelegate {
forStatusCode: statusCode
)

if let url = response.url {
let isRecoveryConfirmationPage = isRecovery && statusCode == 200 && isConfirmation(url: url)

if isRecoveryConfirmationPage {
let event = createEmptyCheckoutCompletedEvent(id: getOrderIdFromQuery(url: url))
viewDelegate?.checkoutViewDidCompleteCheckout(event: event)
}
}

guard isCheckout(url: response.url) else {
return .allow
}
Expand Down Expand Up @@ -405,6 +414,31 @@ extension CheckoutWebView: WKNavigationDelegate {
return self.url == url
}

private func isConfirmation(url: URL) -> Bool {
do {
let urlString = url.absoluteString
let regex = try NSRegularExpression(pattern: "thank[-_]you", options: .caseInsensitive)
let range = NSRange(urlString.startIndex..., in: urlString)
return regex.firstMatch(in: urlString, options: [], range: range) != nil
} catch {
return false
}
}

private func getOrderIdFromQuery(url: URL) -> String? {
guard let urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: true) else {
return nil
}

let queryItems = urlComponents.queryItems ?? []
for item in queryItems {
if item.name == "orderId" {

Check failure on line 435 in Sources/ShopifyCheckoutSheetKit/CheckoutWebView.swift

View workflow job for this annotation

GitHub Actions / SwiftLint

Prefer For-Where Violation: `where` clauses are preferred over a single `if` inside a `for` (for_where)
return item.value
}
}

return nil
}
}

extension CheckoutWebView {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ class CheckoutWebViewController: UIViewController, UIAdaptivePresentationControl
progressObserver?.invalidate()
checkoutView.removeFromSuperview()

let prod = URL(string: "https://checkout-sdk.myshopify.com/checkouts/cn/Z2NwLWV1cm9wZS13ZXN0MTowMUhWUDg0QkRKOUo5SkdWV0hFWDFHUzFNMw")
self.checkoutView = CheckoutWebView.for(checkout: prod!, recovery: true)
self.checkoutView = CheckoutWebView.for(checkout: url, recovery: true)
checkoutView.translatesAutoresizingMaskIntoConstraints = false
checkoutView.scrollView.contentInsetAdjustmentBehavior = .never
checkoutView.viewDelegate = self
Expand Down
40 changes: 1 addition & 39 deletions Sources/ShopifyCheckoutSheetKit/FallbackViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,43 +25,6 @@ import Foundation
import SafariServices
import WebKit

class FallbackViewController: NSObject {
private let checkoutURL: URL

var checkoutDelegate: CheckoutDelegate?

init(checkout url: URL, delegate: CheckoutDelegate?) {
self.checkoutURL = url
self.checkoutDelegate = delegate
}

func createSafariViewController() -> SFSafariViewController {
let config = SFSafariViewController.Configuration()
config.barCollapsingEnabled = true
config.entersReaderIfAvailable = false

let url = URL(string: "https://checkout-sdk.myshopify.com/checkouts/cn/Z2NwLWV1cm9wZS13ZXN0MTowMUhWUDg0QkRKOUo5SkdWV0hFWDFHUzFNMw")!
let fallback = SFSafariViewController(url: url, configuration: config)
fallback.delegate = self
fallback.presentationController?.delegate = self
return fallback
}
}

/// Safari delegate methods

extension FallbackViewController: SFSafariViewControllerDelegate, UIAdaptivePresentationControllerDelegate {
func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
checkoutDelegate?.checkoutDidCancel()
}

func safariViewController(_ controller: SFSafariViewController, didCompleteInitialLoad didLoadSuccessfully: Bool) {
if !didLoadSuccessfully {
checkoutDelegate?.checkoutDidFail(error: .checkoutUnavailable(message: "Checkout is unavailable", code: .httpError(statusCode: 500), recoverable: false))
}
}
}

class FallbackWebViewController: UIViewController {
internal let checkoutView: FallbackWebView
internal let checkoutURL: URL
Expand Down Expand Up @@ -131,8 +94,7 @@ class FallbackWebView: WKWebView {
}

func load(checkout url: URL) {
let prod = URL(string: "https://checkout-sdk.myshopify.com/checkouts/cn/Z2NwLWV1cm9wZS13ZXN0MTowMUhWUDg0QkRKOUo5SkdWV0hFWDFHUzFNMw")
load(URLRequest(url: prod!))
load(URLRequest(url: url))
}

required init?(coder: NSCoder) {
Expand Down

0 comments on commit e418b33

Please sign in to comment.