Skip to content

Commit c58840e

Browse files
Merge branch 'prototype/development' into prototype-development/issue-8681-checkout.paymentmethodchangestart2
2 parents bbda17d + 1c258ae commit c58840e

File tree

16 files changed

+426
-19
lines changed

16 files changed

+426
-19
lines changed

modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/RCTCheckoutWebView.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ of this software and associated documentation files (the "Software"), to deal
6262
import com.shopify.checkoutsheetkit.rpc.events.CheckoutPaymentMethodChangeStart;
6363

6464
import java.io.IOException;
65+
import com.shopify.checkoutsheetkit.rpc.events.CheckoutSubmitStart;
66+
import com.shopify.checkoutsheetkit.rpc.events.CheckoutSubmitStartEvent;
67+
68+
import com.fasterxml.jackson.core.type.TypeReference;
69+
import com.fasterxml.jackson.databind.ObjectMapper;
70+
6571
import java.util.HashMap;
6672
import java.util.Map;
6773
import java.util.Objects;
@@ -369,6 +375,25 @@ public void onPaymentMethodChangeStart(@NonNull CheckoutPaymentMethodChangeStart
369375
Log.e(TAG, "Error processing address change start event", e);
370376
}
371377
}
378+
379+
public void onSubmitStart(@NonNull CheckoutSubmitStart event) {
380+
try {
381+
CheckoutSubmitStartEvent params = event.getParams();
382+
Map<String, Object> eventData = new HashMap<>();
383+
384+
eventData.put("id", event.getId());
385+
eventData.put("type", "submitStart");
386+
eventData.put("cart", params.getCart());
387+
388+
Map<String, Object> checkoutData = new HashMap<>();
389+
checkoutData.put("id", params.getCheckout().getId());
390+
eventData.put("checkout", checkoutData);
391+
392+
sendEvent("onSubmitStart", serializeToWritableMap(eventData));
393+
} catch (Exception e) {
394+
Log.e(TAG, "Error processing submit start event", e);
395+
}
396+
}
372397

373398
@Override
374399
public void onLinkClick(@NonNull Uri uri) {

modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/RCTCheckoutWebViewManager.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
9191
events.put("onCancel", createEventMap("onCancel"));
9292
events.put("onLinkClick", createEventMap("onLinkClick"));
9393
events.put("onAddressChangeStart", createEventMap("onAddressChangeStart"));
94+
events.put("onSubmitStart", createEventMap("onSubmitStart"));
9495
return events;
9596
}
9697

modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/SheetCheckoutEventProcessor.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ of this software and associated documentation files (the "Software"), to deal
4747
import com.shopify.checkoutsheetkit.rpc.events.CheckoutAddressChangeStartEvent;
4848
import com.fasterxml.jackson.databind.ObjectMapper;
4949
import com.shopify.checkoutsheetkit.rpc.events.CheckoutPaymentMethodChangeStart;
50+
import com.shopify.checkoutsheetkit.rpc.events.CheckoutSubmitStart;
51+
import com.shopify.checkoutsheetkit.rpc.events.CheckoutSubmitStartEvent;
52+
import com.fasterxml.jackson.databind.ObjectMapper;
5053

5154
import java.io.IOException;
5255
import java.util.HashMap;
@@ -190,6 +193,30 @@ public void onPaymentMethodChangeStart(@NonNull CheckoutPaymentMethodChangeStart
190193
Log.e(TAG, "Error processing address change start event", e);
191194
}
192195
}
196+
197+
public void onSubmitStart(@NonNull CheckoutSubmitStart event) {
198+
try {
199+
CheckoutSubmitStartEvent params = event.getParams();
200+
if (params == null) {
201+
Log.e("ShopifyCheckoutSheetKit", "Submit start event has null params");
202+
return;
203+
}
204+
205+
Map<String, Object> eventData = new HashMap<>();
206+
eventData.put("id", event.getId());
207+
eventData.put("type", "submitStart");
208+
eventData.put("cart", params.getCart());
209+
210+
Map<String, Object> checkoutData = new HashMap<>();
211+
checkoutData.put("id", params.getCheckout().getId());
212+
eventData.put("checkout", checkoutData);
213+
214+
String data = mapper.writeValueAsString(eventData);
215+
sendEventWithStringData("submitStart", data);
216+
} catch (IOException e) {
217+
Log.e("ShopifyCheckoutSheetKit", "Error processing submit start event", e);
218+
}
219+
}
193220

194221
// Private
195222
private Map<String, Object> populateErrorDetails(CheckoutException error) {

modules/@shopify/checkout-sheet-kit/ios/RCTCheckoutWebView.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ class RCTCheckoutWebView: UIView {
8585
@objc var onLinkClick: RCTBubblingEventBlock?
8686
@objc var onAddressChangeStart: RCTBubblingEventBlock?
8787
@objc var onPaymentMethodChangeStart: RCTBubblingEventBlock?
88+
@objc var onSubmitStart: RCTBubblingEventBlock?
8889

8990
override init(frame: CGRect) {
9091
super.init(frame: frame)
@@ -329,4 +330,30 @@ extension RCTCheckoutWebView: CheckoutDelegate {
329330

330331
onPaymentMethodChangeStart?(eventData)
331332
}
333+
334+
/// Called when the buyer attempts to submit the checkout.
335+
///
336+
/// This event is only emitted when native payment delegation is configured
337+
/// for the authenticated app.
338+
///
339+
/// - Parameter event: The submit start event containing:
340+
/// - id: Unique identifier for responding to the event
341+
/// - cart: Current cart state
342+
/// - checkout: Checkout session information
343+
func checkoutDidStartSubmit(event: CheckoutSubmitStart) {
344+
guard let id = event.id else { return }
345+
346+
self.events.set(key: id, event: event)
347+
348+
let cartJSON = ShopifyEventSerialization.encodeToJSON(from: event.params.cart)
349+
350+
onSubmitStart?([
351+
"id": event.id,
352+
"type": "submitStart",
353+
"cart": cartJSON,
354+
"checkout": [
355+
"id": event.params.checkout.id
356+
],
357+
])
358+
}
332359
}

modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit+EventSerialization.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,20 @@ internal enum ShopifyEventSerialization {
8585
]
8686
}
8787

88+
/**
89+
* Converts a CheckoutSubmitStart to a React Native compatible dictionary.
90+
*/
91+
static func serialize(checkoutSubmitStart event: CheckoutSubmitStart) -> [String: Any] {
92+
return [
93+
"id": event.id as Any,
94+
"type": "submitStart",
95+
"cart": encodeToJSON(from: event.params.cart),
96+
"checkout": [
97+
"id": event.params.checkout.id
98+
]
99+
]
100+
}
101+
88102
static func serialize(clickEvent url: URL) -> [String: URL] {
89103
return ["url": url]
90104
}

modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.mm

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@ @interface RCT_EXTERN_MODULE (RCTCheckoutWebViewManager, RCTViewManager)
128128
*/
129129
RCT_EXPORT_VIEW_PROPERTY(onPaymentMethodChangeStart, RCTBubblingEventBlock)
130130

131+
/**
132+
* Emitted when the buyer attempts to submit the checkout
133+
*/
134+
RCT_EXPORT_VIEW_PROPERTY(onSubmitStart, RCTBubblingEventBlock)
135+
131136
/**
132137
* Emitted when a link is clicked
133138
*/

modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class RCTShopifyCheckoutSheetKit: RCTEventEmitter, CheckoutDelegate {
5353
}
5454

5555
override func supportedEvents() -> [String]! {
56-
return ["close", "complete", "start", "error", "addressChangeStart"]
56+
return ["close", "complete", "start", "error", "addressChangeStart", "submitStart"]
5757
}
5858

5959
override func startObserving() {
@@ -82,6 +82,12 @@ class RCTShopifyCheckoutSheetKit: RCTEventEmitter, CheckoutDelegate {
8282
}
8383
}
8484

85+
func checkoutDidStartSubmit(event: CheckoutSubmitStart) {
86+
if hasListeners {
87+
sendEvent(withName: "submitStart", body: ShopifyEventSerialization.serialize(checkoutSubmitStart: event))
88+
}
89+
}
90+
8591
func shouldRecoverFromError(error: CheckoutError) -> Bool {
8692
return error.isRecoverable
8793
}

modules/@shopify/checkout-sheet-kit/package.snapshot.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@
66
"android/proguard-rules.pro",
77
"android/src/main/AndroidManifest.xml",
88
"android/src/main/AndroidManifestNew.xml",
9-
"android/src/main/java/com/shopify/reactnative/checkoutsheetkit/CustomCheckoutEventProcessor.java",
9+
"android/src/main/java/com/shopify/reactnative/checkoutsheetkit/CheckoutEvent.java",
10+
"android/src/main/java/com/shopify/reactnative/checkoutsheetkit/RCTCheckoutWebView.java",
11+
"android/src/main/java/com/shopify/reactnative/checkoutsheetkit/RCTCheckoutWebViewManager.java",
12+
"android/src/main/java/com/shopify/reactnative/checkoutsheetkit/SheetCheckoutEventProcessor.java",
1013
"android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java",
1114
"android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitPackage.java",
15+
"android/src/test/java/com/shopify/reactnative/checkoutsheetkit/RCTCheckoutWebViewTest.java",
1216
"ios/AcceleratedCheckoutButtons.swift",
1317
"ios/AcceleratedCheckoutButtons+Extensions.swift",
1418
"ios/RCTCheckoutWebView.swift",

modules/@shopify/checkout-sheet-kit/src/components/Checkout.tsx

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,21 @@ import React, {
2626
} from 'react';
2727
import { requireNativeComponent, UIManager, findNodeHandle } from 'react-native';
2828
import type { ViewStyle } from 'react-native';
29+
import {
30+
requireNativeComponent,
31+
UIManager,
32+
findNodeHandle,
33+
} from 'react-native';
34+
import type {ViewStyle} from 'react-native';
35+
import {useCheckoutEvents} from '../CheckoutEventProvider';
2936
import type {
3037
CheckoutAddressChangeStart,
3138
CheckoutCompleteEvent,
3239
CheckoutException,
3340
CheckoutPaymentMethodChangeStart,
3441
CheckoutStartEvent,
35-
} from '..';
36-
import { useCheckoutEvents } from '../CheckoutEventProvider';
42+
CheckoutSubmitStart
43+
} from '../events';
3744

3845
export interface CheckoutProps {
3946
/**
@@ -80,12 +87,22 @@ export interface CheckoutProps {
8087
onAddressChangeStart?: (event: CheckoutAddressChangeStart) => void;
8188

8289
/**
83-
* Called when checkout requests a payment method change (e.g., for native payment selector)
90+
* Called when the buyer attempts to submit the checkout.
91+
*
92+
* Note: This callback is only invoked when native payment delegation is configured
93+
* for the authenticated app.
94+
*/
95+
onSubmitStart?: (event: CheckoutSubmitStart) => void;
96+
97+
/**
98+
* Called when checkout starts a payment method change flow (e.g., for native picker).
99+
*
100+
* Note: This callback is only invoked when native address selection is enabled
101+
* for the authenticated app.
84102
*/
85103
onPaymentMethodChangeStart?: (
86104
event: CheckoutPaymentMethodChangeStart,
87105
) => void;
88-
89106
/**
90107
* Style for the webview container
91108
*/
@@ -114,9 +131,8 @@ interface NativeCheckoutWebViewProps {
114131
onComplete?: (event: { nativeEvent: CheckoutCompleteEvent }) => void;
115132
onCancel?: () => void;
116133
onLinkClick?: (event: { nativeEvent: { url: string } }) => void;
117-
onAddressChangeStart?: (event: {
118-
nativeEvent: CheckoutAddressChangeStart;
119-
}) => void;
134+
onAddressChangeStart?: (event: { nativeEvent: CheckoutAddressChangeStart; }) => void;
135+
onSubmitStart?: (event: {nativeEvent: CheckoutSubmitStart}) => void;
120136
onPaymentMethodChangeStart?: (event: { nativeEvent: CheckoutPaymentMethodChangeStart; }) => void;
121137
}
122138

@@ -176,6 +192,7 @@ export const Checkout = forwardRef<CheckoutRef, CheckoutProps>(
176192
onLinkClick,
177193
onAddressChangeStart,
178194
onPaymentMethodChangeStart,
195+
onSubmitStart,
179196
style,
180197
testID,
181198
},
@@ -195,7 +212,7 @@ export const Checkout = forwardRef<CheckoutRef, CheckoutProps>(
195212
}, [eventContext]);
196213

197214
const handleStart = useCallback<Required<NativeCheckoutWebViewProps>['onStart']>(
198-
(event) => {
215+
(event: {nativeEvent: CheckoutStartEvent}) => {
199216
onStart?.(event.nativeEvent);
200217
},
201218
[onStart],
@@ -242,11 +259,22 @@ export const Checkout = forwardRef<CheckoutRef, CheckoutProps>(
242259
},
243260
[onPaymentMethodChangeStart],
244261
);
262+
263+
const handleSubmitStart = useCallback<
264+
Required<NativeCheckoutWebViewProps>['onSubmitStart']
265+
>(
266+
(event: {nativeEvent: CheckoutSubmitStart}) => {
267+
if (!event.nativeEvent) return;
268+
onSubmitStart?.(event.nativeEvent);
269+
},
270+
[onSubmitStart],
271+
);
245272

246273
const reload = useCallback(() => {
247274
if (!webViewRef.current) {
248275
return;
249276
}
277+
250278
const handle = findNodeHandle(webViewRef.current);
251279
if (!handle) {
252280
return;
@@ -255,6 +283,13 @@ export const Checkout = forwardRef<CheckoutRef, CheckoutProps>(
255283
const viewConfig = UIManager.getViewManagerConfig('RCTCheckoutWebView');
256284
const commandId = viewConfig?.Commands?.reload ?? 'reload';
257285

286+
UIManager.dispatchViewManagerCommand(
287+
handle,
288+
commandId,
289+
[],
290+
);
291+
}, []);
292+
258293
UIManager.dispatchViewManagerCommand(handle, commandId, []);
259294
}, []);
260295

@@ -274,6 +309,7 @@ export const Checkout = forwardRef<CheckoutRef, CheckoutProps>(
274309
onLinkClick={handleLinkClick}
275310
onAddressChangeStart={handleAddressChangeStart}
276311
onPaymentMethodChangeStart={handlePaymentMethodChangeStart}
312+
onSubmitStart={handleSubmitStart}
277313
/>
278314
);
279315
},

0 commit comments

Comments
 (0)