Skip to content

Commit 6aa4b97

Browse files
committed
[Android] Add advanced present builder callbacks and migrate sample flow
1 parent 08f6c9d commit 6aa4b97

13 files changed

Lines changed: 637 additions & 335 deletions

File tree

platforms/android/README.md

Lines changed: 83 additions & 181 deletions
Large diffs are not rendered by default.

platforms/android/lib/api/lib.api

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,17 @@ public final class com/shopify/checkoutkit/CheckoutLineItem$Companion {
756756
public final fun serializer ()Lkotlinx/serialization/KSerializer;
757757
}
758758

759+
public final class com/shopify/checkoutkit/CheckoutPresentation {
760+
public final fun connect (Lcom/shopify/checkoutkit/CheckoutCommunicationClient;)V
761+
public final fun onCancel (Lkotlin/jvm/functions/Function0;)V
762+
public final fun onComplete (Lkotlin/jvm/functions/Function1;)V
763+
public final fun onFail (Lkotlin/jvm/functions/Function1;)V
764+
public final fun onGeolocationPermissionsHidePrompt (Lkotlin/jvm/functions/Function0;)V
765+
public final fun onGeolocationPermissionsShowPrompt (Lkotlin/jvm/functions/Function2;)V
766+
public final fun onPermissionRequest (Lkotlin/jvm/functions/Function1;)V
767+
public final fun onShowFileChooser (Lkotlin/jvm/functions/Function3;)V
768+
}
769+
759770
public final class com/shopify/checkoutkit/CheckoutProtocol {
760771
public static final field INSTANCE Lcom/shopify/checkoutkit/CheckoutProtocol;
761772
public static final field specVersion Ljava/lang/String;
@@ -3927,6 +3938,7 @@ public final class com/shopify/checkoutkit/ShopifyCheckoutKit {
39273938
public static final fun preload (Ljava/lang/String;Landroidx/activity/ComponentActivity;)V
39283939
public static final fun present (Ljava/lang/String;Landroidx/activity/ComponentActivity;Lcom/shopify/checkoutkit/DefaultCheckoutEventProcessor;)Lcom/shopify/checkoutkit/CheckoutKitDialog;
39293940
public static final fun present (Ljava/lang/String;Landroidx/activity/ComponentActivity;Lcom/shopify/checkoutkit/DefaultCheckoutEventProcessor;Lcom/shopify/checkoutkit/CheckoutCommunicationClient;)Lcom/shopify/checkoutkit/CheckoutKitDialog;
3941+
public static final synthetic fun present (Ljava/lang/String;Landroidx/activity/ComponentActivity;Lkotlin/jvm/functions/Function1;)Lcom/shopify/checkoutkit/CheckoutKitDialog;
39303942
public static synthetic fun present$default (Ljava/lang/String;Landroidx/activity/ComponentActivity;Lcom/shopify/checkoutkit/DefaultCheckoutEventProcessor;Lcom/shopify/checkoutkit/CheckoutCommunicationClient;ILjava/lang/Object;)Lcom/shopify/checkoutkit/CheckoutKitDialog;
39313943
}
39323944

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
/*
2+
* MIT License
3+
*
4+
* Copyright 2023-present, Shopify Inc.
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22+
*/
23+
package com.shopify.checkoutkit
24+
25+
import android.net.Uri
26+
import android.webkit.GeolocationPermissions
27+
import android.webkit.PermissionRequest
28+
import android.webkit.ValueCallback
29+
import android.webkit.WebChromeClient
30+
import android.webkit.WebView
31+
import com.shopify.checkoutkit.lifecycleevents.CheckoutCompletedEvent
32+
33+
/**
34+
* Kotlin-first builder for per-presentation checkout callbacks.
35+
*
36+
* Use through [ShopifyCheckoutKit.present].
37+
*/
38+
public class CheckoutPresentation internal constructor() {
39+
internal var onComplete: ((CheckoutCompletedEvent) -> Unit)? = null
40+
internal var onFail: ((CheckoutException) -> Unit)? = null
41+
internal var onCancel: (() -> Unit)? = null
42+
internal var onPermissionRequest: ((PermissionRequest) -> Unit)? = null
43+
internal var onShowFileChooser:
44+
((WebView, ValueCallback<Array<Uri>>, WebChromeClient.FileChooserParams) -> Boolean)? = null
45+
internal var onGeolocationPermissionsShowPrompt:
46+
((String, GeolocationPermissions.Callback) -> Unit)? = null
47+
internal var onGeolocationPermissionsHidePrompt: (() -> Unit)? = null
48+
internal var communicationClient: CheckoutCommunicationClient? = null
49+
50+
/**
51+
* Called when checkout completes successfully.
52+
*/
53+
public fun onComplete(handler: (CheckoutCompletedEvent) -> Unit) {
54+
onComplete = handler
55+
}
56+
57+
/**
58+
* Called when checkout fails.
59+
*/
60+
public fun onFail(handler: (CheckoutException) -> Unit) {
61+
onFail = handler
62+
}
63+
64+
/**
65+
* Called when checkout is canceled by the buyer.
66+
*/
67+
public fun onCancel(handler: () -> Unit) {
68+
onCancel = handler
69+
}
70+
71+
/**
72+
* Called when checkout requests a web permission, such as camera access.
73+
*/
74+
public fun onPermissionRequest(handler: (PermissionRequest) -> Unit) {
75+
onPermissionRequest = handler
76+
}
77+
78+
/**
79+
* Called when checkout requests that the host app present a file chooser.
80+
*/
81+
public fun onShowFileChooser(
82+
handler: (
83+
webView: WebView,
84+
filePathCallback: ValueCallback<Array<Uri>>,
85+
fileChooserParams: WebChromeClient.FileChooserParams,
86+
) -> Boolean,
87+
) {
88+
onShowFileChooser = handler
89+
}
90+
91+
/**
92+
* Called when checkout requests that the host app present a geolocation prompt.
93+
*/
94+
public fun onGeolocationPermissionsShowPrompt(
95+
handler: (origin: String, callback: GeolocationPermissions.Callback) -> Unit,
96+
) {
97+
onGeolocationPermissionsShowPrompt = handler
98+
}
99+
100+
/**
101+
* Called when checkout requests that any visible geolocation prompt be dismissed.
102+
*/
103+
public fun onGeolocationPermissionsHidePrompt(handler: () -> Unit) {
104+
onGeolocationPermissionsHidePrompt = handler
105+
}
106+
107+
/**
108+
* Connects a communication client for Embedded Checkout Protocol messages.
109+
*/
110+
public fun connect(client: CheckoutCommunicationClient?) {
111+
communicationClient = client
112+
}
113+
114+
internal fun buildEventProcessor(): DefaultCheckoutEventProcessor =
115+
object : DefaultCheckoutEventProcessor() {
116+
override fun onCheckoutCompleted(checkoutCompletedEvent: CheckoutCompletedEvent) {
117+
onComplete?.invoke(checkoutCompletedEvent)
118+
}
119+
120+
override fun onCheckoutFailed(error: CheckoutException) {
121+
onFail?.invoke(error)
122+
}
123+
124+
override fun onCheckoutCanceled() {
125+
onCancel?.invoke()
126+
}
127+
128+
override fun onPermissionRequest(permissionRequest: PermissionRequest) {
129+
onPermissionRequest?.invoke(permissionRequest)
130+
}
131+
132+
override fun onShowFileChooser(
133+
webView: WebView,
134+
filePathCallback: ValueCallback<Array<Uri>>,
135+
fileChooserParams: WebChromeClient.FileChooserParams,
136+
): Boolean {
137+
return onShowFileChooser?.invoke(webView, filePathCallback, fileChooserParams) ?: false
138+
}
139+
140+
override fun onGeolocationPermissionsShowPrompt(origin: String, callback: GeolocationPermissions.Callback) {
141+
onGeolocationPermissionsShowPrompt?.invoke(origin, callback)
142+
}
143+
144+
override fun onGeolocationPermissionsHidePrompt() {
145+
onGeolocationPermissionsHidePrompt?.invoke()
146+
}
147+
}
148+
}

platforms/android/lib/src/main/java/com/shopify/checkoutkit/ShopifyCheckoutKit.kt

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,37 @@ public object ShopifyCheckoutKit {
118118
}
119119
}
120120

121+
/**
122+
* Presents a Shopify checkout within a Dialog
123+
*
124+
* @param checkoutUrl The URL of the checkout to be presented, this can be obtained via the Storefront API
125+
* @param context The context the checkout is being presented from
126+
* @param configure a Kotlin-first builder for standard lifecycle callbacks and an optional communication client
127+
* @return An instance of [CheckoutKitDialog] if the dialog was successfully created and displayed.
128+
*/
129+
@JvmStatic
130+
@JvmSynthetic
131+
public fun present(
132+
checkoutUrl: String,
133+
context: ComponentActivity,
134+
configure: CheckoutPresentation.() -> Unit,
135+
): CheckoutKitDialog? {
136+
val presentation = CheckoutPresentation().apply(configure)
137+
return present(
138+
checkoutUrl = checkoutUrl,
139+
context = context,
140+
checkoutEventProcessor = presentation.buildEventProcessor(),
141+
communicationClient = presentation.communicationClient,
142+
)
143+
}
144+
121145
/**
122146
* Presents a Shopify checkout within a Dialog
123147
*
124148
* @param checkoutUrl The URL of the checkout to be presented, this can be obtained via the Storefront API
125149
* @param context The context the checkout is being presented from
126150
* @param checkoutEventProcessor provides callbacks to allow clients to listen for and respond to checkout lifecycle events such as
127-
* (failure, completion, cancellation, external link clicks).
151+
* (failure, completion, cancellation, and browser/system prompts).
128152
* @param communicationClient optional handler for Embedded Checkout Protocol (ECP) messages.
129153
* Implement [CheckoutCommunicationClient] to intercept arbitrary ECP messages from the checkout
130154
* web page. Built-in messages ([ec.ready][EmbeddedCheckoutProtocol.METHOD_READY] and

0 commit comments

Comments
 (0)