Skip to content

Commit

Permalink
feat:new API replacing delegate pattern with closures.
Browse files Browse the repository at this point in the history
  • Loading branch information
daniela-trustly committed Mar 22, 2023
1 parent 22976fd commit 1862bc9
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 43 deletions.
38 changes: 9 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

The Trustly iOS SDK provides an easy way to implement the Trustly Checkout in your iOS app. The SDK handles communication with the Web View and exposes Checkout events that allows you to customize your Checkout flow.

**`Note: The latest version of the SDK does not support the older version of the Trustly Checkout. If you do use the older version of the Checkout, please use version 2.0.0 of the SDK. If you are not sure what version of the Trustly Checkout you are using, please contact our intergration support.`**

## Integration
Add the SDK as a Swift Package. [More detailed instructions can be found here.](https://eu.developers.trustly.com/doc/docs/ios)
Add the SDK as a Swift Package. [More detailed intructions can be found here.](https://www.trustly.net/site/developer-portal?part=iosandroid)
1. Navigate to File -> Swift Packages -> Add Package Dependency.
2. Paste the Trustly SDK URL: https://github.com/trustly/TrustlyIosSdk
3. Select Up to Next Major version and make sure you have the latest version
Expand All @@ -12,41 +14,19 @@ Add the SDK as a Swift Package. [More detailed instructions can be found here.](

## Usage
Pass your Checkout URL when initialising a new TrustlyWKWebView instance. The Checkout will be rendered within the TrustlyWKWebView.
Please note that you are responsible for presentation and dismissal of the TrustlyWKWebView object.

Example usage:
```swift
let webViewController = UIViewController.init(nibName: nil, bundle: nil)
let trustlyWebView = TrustlyWKWebView(checkoutUrl: trustlyCheckoutURLString, frame: rect)
webViewController.view = trustlyWebView
let mainView = TrustlyWKWebView(checkoutUrl: your_trustly_checkout_url.absoluteString, frame: self.view.bounds)
webViewController.view = mainView
show(webViewController, sender: nil)
```
### Receiving Checkout Events
If you want more control of your Checkout flow you can choose to provide custom handlers.

Provide `onSuccess`,`onError` and `onAbort` closures.
In case no custom functionality is provided, the webview will load the `SuccessURL`, in case of a success event, or the `FailURL` in case of a error or an abort event.
Read more https://eu.developers.trustly.com/doc/docs/order-initiation

If you want more control of your Checkout flow you can choose to opt-in to receiving and handling Checkout events.

```swift
let trustlyWebView = TrustlyWKWebView(checkoutUrl: trustlyCheckoutURLString, frame: rect)
guard let trustlyWebView = trustlyWebView {
// handle wrong initialisation.
}
trustlyWebView.onSuccess = {
// your custom implementation here.
}
trustlyWebView.onError = {
// your custom implementation here.
}
trustlyWebView.onAbort = {
// your custom implementation here.
}

```
You can opt-in by providing `onSuccess` and `onError` closures.


## Automatic re-directs back to your application
It can happen that during the order flow, the user needs to be redirected outside of your application, to a third party application or website (in external stand alone browser). This could be part of the authentication and authorisation process.
To enable automatic re-directs back to your native application, you can pass a [deep link](https://developer.apple.com/documentation/xcode/allowing-apps-and-websites-to-link-to-your-content) as an attribute to the order initiation request. You can pass your deep link (universal link or url scheme) value by including it in the "URLScheme" attribute when making an API call to Trustly. [You can read more about it here.](https://developers.trustly.com/emea/docs/ios)
## Notes about URLScheme
Please note that when rendering the Trustly Checkout from a native app you are required to pass your application’s [URLScheme](https://developer.apple.com/documentation/xcode/allowing_apps_and_websites_to_link_to_your_content/defining_a_custom_url_scheme_for_your_app) as an attribute to the order initiation request. By doing so, Trustly can redirect users back to your app after using external identification apps such as Mobile BankID. You can pass your URLScheme by including it in the "URLScheme" attribute when making an API call to Trustly. [You can read more about it here.](https://developers.trustly.com/emea/docs/ios)
21 changes: 16 additions & 5 deletions Sources/TrustlyIosSdk/TrustlyWKScriptHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,30 +40,33 @@ internal protocol TrustlyWKScriptHandlerDelegate: AnyObject {

internal class TrustlyWKScriptHandler: NSObject, WKScriptMessageHandler {

var webView: WKWebView
weak var delegate: TrustlyWKScriptHandlerDelegate?
/// Name of the "native bridge" that will be used to communicate with the web view.
static let NAME = "trustlySDKBridge"

init(delegate: TrustlyWKScriptHandlerDelegate) {
init(webView: WKWebView, delegate: TrustlyWKScriptHandlerDelegate) {
self.webView = webView
self.delegate = delegate
}

public func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {

guard let parsedCheckoutEventObject = getParsedJSON(object: message.body as AnyObject) else {
print("TRUSTLY SDK: Message posted from script handler has an invalid format")
return
}

guard let eventType = parsedCheckoutEventObject.object(forKey: "type") as? String else {
print("TRUSTLY SDK: Found no type property on checkout event")
return
}

guard let trustlyCheckoutEvent = TrustlyCheckoutEvent(rawValue: eventType) else {
print("TRUSTLY SDK: Checkout event type not recognized")
return
}

let urlString: String? = parsedCheckoutEventObject.object(forKey: "url") as? String ?? nil

handleCheckoutEvent(checkoutEvent: trustlyCheckoutEvent, URLString: urlString);
Expand All @@ -81,20 +84,28 @@ internal class TrustlyWKScriptHandler: NSObject, WKScriptMessageHandler {
if (!opened) {
print ("TRUSTLY SDK: Checkout event type .onTrustlyCheckoutRedirect - Unable to open URL: \(URL)")
}
}

} else {
UIApplication.shared.openURL(URL)
}
}

let js: String = String(format: "%@", ["", URLString])
webView.evaluateJavaScript(js, completionHandler: nil)
}

func handleCheckoutEvent(checkoutEvent: TrustlyCheckoutEvent, URLString: String?) {

switch checkoutEvent {
case .openURLScheme: handleOpenRedirectURL(URLString: URLString)
case .success: delegate?.trustlyWKScriptHandlerOnSuccess()
case .error: delegate?.trustlyWKScriptHandlerOnError()
case .abort: delegate?.trustlyWKScriptHandlerOnAbort()
}

}

}


Expand Down
19 changes: 10 additions & 9 deletions Sources/TrustlyIosSdk/TrustlyWKWebView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public typealias TrustlyWebViewOnAbort = () -> Void
/// or `FailURL` for error and abort events. The value of these parameters is passed by your backend API call to the
/// Trustly backend.
/// - See https://eu.developers.trustly.com/doc/docs/order-initiation
public class TrustlyWKWebView: UIView, TrustlyWKScriptHandlerDelegate {
public class TrustlyWKWebView: UIView, WKNavigationDelegate, WKUIDelegate, TrustlyWKScriptHandlerDelegate {

/// Custom closure that will be invoked when the Trustly checkout has successfully completed an order.
public var onSuccess: TrustlyWebViewOnSuccess?
Expand All @@ -62,19 +62,24 @@ public class TrustlyWKWebView: UIView, TrustlyWKScriptHandlerDelegate {

var webView: WKWebView?
var trustlyWKScriptHandler: TrustlyWKScriptHandler!
var configuration: WKWebViewConfiguration!

public init?(checkoutUrl: String, frame: CGRect) {
super.init(frame: frame)

configuration = WKWebViewConfiguration()
let userContentController: WKUserContentController = WKUserContentController()
let configuration: WKWebViewConfiguration = WKWebViewConfiguration()
configuration.userContentController = userContentController
configuration.preferences.javaScriptCanOpenWindowsAutomatically = true

webView = WKWebView(frame: frame, configuration: configuration)
guard let webView = webView else { return nil }

trustlyWKScriptHandler = TrustlyWKScriptHandler(delegate: self)
configuration.userContentController.add(trustlyWKScriptHandler, name: TrustlyWKScriptHandler.NAME)
webView.navigationDelegate = self
webView.uiDelegate = self

trustlyWKScriptHandler = TrustlyWKScriptHandler(webView: webView, delegate: self)
userContentController.add(trustlyWKScriptHandler, name: TrustlyWKScriptHandler.NAME)

if let url = URL(string: checkoutUrl) {
webView.load(URLRequest(url: url))
webView.allowsBackForwardNavigationGestures = true
Expand All @@ -87,10 +92,6 @@ public class TrustlyWKWebView: UIView, TrustlyWKScriptHandlerDelegate {
fatalError("init(coder:) has not been implemented")
}

deinit {
configuration.userContentController.removeScriptMessageHandler(forName: TrustlyWKScriptHandler.NAME)
}

internal func trustlyWKScriptHandlerOnSuccess() {
if let onSuccess = onSuccess {
onSuccess()
Expand Down

0 comments on commit 1862bc9

Please sign in to comment.