Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/rn-check-packed-files.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ on:
permissions:
contents: read

# TODO: remove once ShopifyCheckoutKit is published to CocoaPods trunk and
# Maven Central. Tracks the new pod/AAR name introduced by the
# ShopifyCheckoutSheetKit → ShopifyCheckoutKit rename.
env:
USE_LOCAL_SDK: "1"

jobs:
check-packed-files:
name: Check package files
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/rn-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ on:
permissions:
contents: read

# TODO: remove once ShopifyCheckoutKit is published to CocoaPods trunk and
# Maven Central. Tracks the new pod/AAR name introduced by the
# ShopifyCheckoutSheetKit → ShopifyCheckoutKit rename.
env:
USE_LOCAL_SDK: "1"

jobs:
swiftlint:
name: SwiftLint
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/rn-test-android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ permissions:

env:
JAVA_VERSION: '22'
# TODO: remove once ShopifyCheckoutKit is published to CocoaPods trunk and
# Maven Central. Tracks the new pod/AAR name introduced by the
# ShopifyCheckoutSheetKit → ShopifyCheckoutKit rename.
USE_LOCAL_SDK: "1"

jobs:
test-android:
Expand Down
9 changes: 9 additions & 0 deletions .github/workflows/rn-test-ios.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ on:
permissions:
contents: read

# TODO: remove once ShopifyCheckoutKit is published to CocoaPods trunk and
# Maven Central. Tracks the new pod/AAR name introduced by the
# ShopifyCheckoutSheetKit → ShopifyCheckoutKit rename.
env:
USE_LOCAL_SDK: "1"

jobs:
test-ios:
name: Run iOS Tests
Expand All @@ -18,6 +24,9 @@ jobs:
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Switch to Xcode 26.2
run: sudo xcode-select --switch /Applications/Xcode_26.2.app

- name: Display Xcode info
run: |
echo "Xcode Path: $(xcode-select -p)"
Expand Down
32 changes: 28 additions & 4 deletions dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -221,11 +221,35 @@ commands:
aliases: [s]
run: cd platforms/react-native && pnpm sample start --reset-cache
ios:
desc: Run the iOS sample app in the simulator
run: cd platforms/react-native && pnpm sample ios
desc: Run the iOS sample app in the simulator.
long_desc: |
Builds and runs the iOS sample app on a simulator.

--local
Build against in-repo Swift SDK sources (runs pod install first).
syntax:
optional: --local
run: cd platforms/react-native && pnpm sample ios "$@"
android:
desc: Run the Android sample app in the emulator
run: cd platforms/react-native && pnpm sample android
desc: Run the Android sample app in the emulator.
long_desc: |
Builds and runs the Android sample app on an emulator.

--local
Build against in-repo SDK sources (publishes a local Maven snapshot first).
syntax:
optional: --local
run: cd platforms/react-native && pnpm sample android "$@"
pod-install:
desc: Install CocoaPods for the iOS sample.
long_desc: |
Runs pod install for the iOS sample app.

--local
Wire the Podfile against in-repo Swift SDK sources.
syntax:
optional: --local
run: cd platforms/react-native && pnpm run pod-install -- "$@"
clean:
desc: Remove generated directories and stop sccache
run: |
Expand Down
6 changes: 4 additions & 2 deletions platforms/android/lib/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,10 @@ signing {
def signingKeyId = findProperty("signingKeyId")
def signingKey = findProperty("signingKey")
def signingPassword = findProperty("signingPassword")
useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword)
sign publishing.publications
if (signingKey) {
useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword)
sign publishing.publications
}
}

detekt {
Expand Down
34 changes: 34 additions & 0 deletions platforms/react-native/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,40 @@ an alias). The underlying `pnpm` commands below are run from
pnpm sample android
```

## Local SDK development (`--local`)

The RN module wraps the Shopify Swift and Android SDKs, which live in this same monorepo at `platforms/swift/` and `platforms/android/`. By default the sample app builds against the **published** artifacts on CocoaPods / Maven Central — the same path CI takes. To build against the in-repo SDK sources instead, pass `--local` to any sample command:

```sh
dev rn android --local # publishes lib to ~/.m2/ then builds the sample against it
dev rn ios --local # builds the sample against the local Swift SDK
dev rn pod-install --local # re-resolve iOS pods against the local Swift SDK
```

The flag is opt-in because the in-repo SDKs change as we develop. Default published mode is always safe; `--local` activates the in-progress API surface.

### How it works

- **Android**: every `--local` invocation runs `scripts/publish_android_snapshot`, which publishes `com.shopify:checkout-kit:1.0.0` to `~/.m2/` via the lib's own Gradle wrapper. The sample's `build.gradle` declares `mavenLocal()` first in the repository order, so the freshly-published AAR is picked up before falling through to Maven Central.
- **iOS**: with `--local`, the Podfile injects `pod "ShopifyCheckoutKit", :path => "../../../../"` (the repo root, where `ShopifyCheckoutKit.podspec` lives). CocoaPods reads Swift sources from `platforms/swift/` directly.

Internally `--local` exports `USE_LOCAL_SDK=1` before invoking the underlying tool. Setting the env var directly works too:

```sh
USE_LOCAL_SDK=1 dev rn android
```

### CI

CI uses the default (published) path naturally — no special flag handling. As defense-in-depth, the build wiring still ignores `USE_LOCAL_SDK=1` when the `CI` env var is set (GitHub Actions sets `CI=true` automatically).
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docs say CI naturally stays on the published path and ignores USE_LOCAL_SDK when CI=true, but the workflows added in this PR set USE_LOCAL_SDK=1 globally and the Podfile, podspec, Gradle files, and helper scripts do not check CI before honoring it. As written, this section gives reviewers and contributors the wrong model for how RN CI is currently working.

Suggestion:

Suggested change
CI uses the default (published) path naturally — no special flag handling. As defense-in-depth, the build wiring still ignores `USE_LOCAL_SDK=1` when the `CI` env var is set (GitHub Actions sets `CI=true` automatically).
CI currently sets `USE_LOCAL_SDK=1` so the sample and module build against the in-repo Swift and Android SDKs until the renamed `ShopifyCheckoutKit` artifacts are published to CocoaPods trunk and Maven Central.


### Gotchas

- **iOS**: re-run `dev rn pod-install --local` (or drop the flag) after switching modes — CocoaPods caches resolution.
- **Android (CLI)**: covered automatically by the publish script — every `--local` run re-publishes the AAR before building.
- **Android (Android Studio)**: when running the sample via Android Studio's Run button after editing `platforms/android/lib/src/**`, run `platforms/react-native/scripts/publish_android_snapshot` once manually (with `USE_LOCAL_SDK=1`) or run `dev rn android --local` from a terminal to refresh `~/.m2/`.
- The flag affects **only the RN build**. The standalone Swift and Android SDK builds (`dev android build`, `swift build`, etc.) are unaffected.

## Optional: Speed up builds with sccache

For faster native compilation (especially on incremental builds), you can install [sccache](https://github.com/mozilla/sccache), a shared compilation cache:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,16 @@ Pod::Spec.new do |s|
s.source_files = "ios/*.{h,m,mm,swift}"

s.dependency "React-Core"
s.dependency "ShopifyCheckoutSheetKit", "~> 3.8.0"
s.dependency "ShopifyCheckoutSheetKit/AcceleratedCheckouts", "~> 3.8.0"

use_local_sdk = ENV['USE_LOCAL_SDK'] == '1'

if use_local_sdk
s.dependency "ShopifyCheckoutKit"
s.dependency "ShopifyCheckoutKit/AcceleratedCheckouts"
else
s.dependency "ShopifyCheckoutKit", "~> 0.0.0"
s.dependency "ShopifyCheckoutKit/AcceleratedCheckouts", "~> 0.0.0"
end

install_modules_dependencies(s)
end
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,17 @@ android {
}

repositories {
mavenLocal()
mavenCentral()
google()
}


def useLocalSdk = (System.getenv("USE_LOCAL_SDK") ?: "0") == "1"
def shopifySdkArtifact = useLocalSdk
? "com.shopify:checkout-kit:1.0.0"
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this version doesn't matter as its just using local so it accepts anything

: "com.shopify:checkout-kit:0.0.0"

dependencies {
// For < 0.71, this will be from the local maven repo
// For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
Expand All @@ -89,8 +95,8 @@ dependencies {
// Uncomment to install dependencies for local development
// implementation("com.facebook.react:react-android:+")

implementation("com.shopify:checkout-sheet-kit:${SHOPIFY_CHECKOUT_SDK_VERSION}")
implementation(shopifySdkArtifact)
implementation("com.fasterxml.jackson.core:jackson-databind:2.12.5")
debugImplementation("com.shopify:checkout-sheet-kit:${SHOPIFY_CHECKOUT_SDK_VERSION}")
debugImplementation(shopifySdkArtifact)
}

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,3 @@ targetSdkVersion=35
compileSdkVersion=36
ndkVersion=23.1.7779620
buildToolsVersion = "35.0.0"

# Version of Shopify Checkout SDK to use with React Native
SHOPIFY_CHECKOUT_SDK_VERSION=3.5.3
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# Keep Checkout Sheet Kit classes
-keep class com.shopify.checkoutsheetkit.** { *; }
# Keep Checkout Kit classes
-keep class com.shopify.checkoutkit.** { *; }
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ of this software and associated documentation files (the "Software"), to deal
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.shopify.checkoutsheetkit.*;
import com.shopify.checkoutkit.*;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.facebook.react.bridge.WritableNativeMap;
import com.facebook.react.bridge.ReactApplicationContext;
import com.shopify.checkoutsheetkit.lifecycleevents.CheckoutCompletedEvent;
import com.shopify.checkoutkit.lifecycleevents.CheckoutCompletedEvent;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.HashMap;
Expand All @@ -50,7 +50,6 @@ public class CustomCheckoutEventProcessor extends DefaultCheckoutEventProcessor
private GeolocationPermissions.Callback geolocationCallback;

public CustomCheckoutEventProcessor(Context context, ReactApplicationContext reactContext) {
super(context);
this.reactContext = reactContext;
}

Expand Down Expand Up @@ -93,7 +92,7 @@ public void onGeolocationPermissionsShowPrompt(@NonNull String origin,
event.put("origin", origin);
sendEventWithStringData("geolocationRequest", mapper.writeValueAsString(event));
} catch (IOException e) {
Log.e("ShopifyCheckoutSheetKit", "Error emitting \"geolocationRequest\" event", e);
Log.e("ShopifyCheckoutKit", "Error emitting \"geolocationRequest\" event", e);
}
}

Expand All @@ -112,7 +111,7 @@ public void onCheckoutFailed(CheckoutException checkoutError) {
String data = mapper.writeValueAsString(populateErrorDetails(checkoutError));
sendEventWithStringData("error", data);
} catch (IOException e) {
Log.e("ShopifyCheckoutSheetKit", "Error processing checkout failed event", e);
Log.e("ShopifyCheckoutKit", "Error processing checkout failed event", e);
}
}

Expand All @@ -127,7 +126,7 @@ public void onCheckoutCompleted(@NonNull CheckoutCompletedEvent event) {
String data = mapper.writeValueAsString(event);
sendEventWithStringData("completed", data);
} catch (IOException e) {
Log.e("ShopifyCheckoutSheetKit", "Error processing completed event", e);
Log.e("ShopifyCheckoutKit", "Error processing completed event", e);
}
}

Expand Down Expand Up @@ -156,7 +155,7 @@ private String getErrorTypeName(CheckoutException error) {
return "CheckoutHTTPError";
} else if (error instanceof ConfigurationException) {
return "ConfigurationError";
} else if (error instanceof CheckoutSheetKitException) {
} else if (error instanceof CheckoutKitException) {
return "InternalError";
} else {
return "UnknownError";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ of this software and associated documentation files (the "Software"), to deal
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;
import com.shopify.checkoutkit.NativeShopifyCheckoutKitSpec;
import com.shopify.checkoutsheetkit.*;
import com.shopify.checkoutkit.*;

import java.util.HashMap;
import java.util.Map;
Expand All @@ -47,7 +47,7 @@ public class ShopifyCheckoutKitModule extends NativeShopifyCheckoutKitSpec {

private final ReactApplicationContext reactContext;

private CheckoutSheetKitDialog checkoutSheet;
private CheckoutKitDialog checkoutSheet;

private CustomCheckoutEventProcessor checkoutEventProcessor;

Expand All @@ -56,16 +56,16 @@ public ShopifyCheckoutKitModule(ReactApplicationContext reactContext) {

this.reactContext = reactContext;

ShopifyCheckoutSheetKit.configure(configuration -> {
configuration.setPlatform(Platform.REACT_NATIVE);
ShopifyCheckoutKit.configure(configuration -> {
configuration.setPlatform(new Platform.ReactNative());
checkoutConfig = configuration;
});
}

@Override
protected Map<String, Object> getTypedExportedConstants() {
final Map<String, Object> constants = new HashMap<>();
constants.put("version", ShopifyCheckoutSheetKit.version);
constants.put("version", ShopifyCheckoutKit.version);
return constants;
}

Expand All @@ -85,7 +85,7 @@ public void present(String checkoutURL) {
if (currentActivity instanceof ComponentActivity) {
checkoutEventProcessor = new CustomCheckoutEventProcessor(currentActivity, this.reactContext);
currentActivity.runOnUiThread(() -> {
checkoutSheet = ShopifyCheckoutSheetKit.present(checkoutURL, (ComponentActivity) currentActivity,
checkoutSheet = ShopifyCheckoutKit.present(checkoutURL, (ComponentActivity) currentActivity,
checkoutEventProcessor);
});
}
Expand All @@ -101,16 +101,12 @@ public void dismiss() {

@ReactMethod
public void preload(String checkoutURL) {
Activity currentActivity = getCurrentActivity();

if (currentActivity instanceof ComponentActivity) {
ShopifyCheckoutSheetKit.preload(checkoutURL, (ComponentActivity) currentActivity);
}
// Public native preload support is not exposed by the local Android SDK.
}

@ReactMethod
public void invalidateCache() {
ShopifyCheckoutSheetKit.invalidate();
ShopifyCheckoutKit.invalidate();
}

@ReactMethod(isBlockingSynchronousMethod = true)
Expand All @@ -128,7 +124,7 @@ public WritableMap getConfig() {
public void setConfig(ReadableMap config) {
Context context = getReactApplicationContext();

ShopifyCheckoutSheetKit.configure(configuration -> {
ShopifyCheckoutKit.configure(configuration -> {
if (config.hasKey("preloading")) {
configuration.setPreloading(new Preloading(config.getBoolean("preloading")));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import Foundation
import PassKit
import React
import ShopifyCheckoutSheetKit
import ShopifyCheckoutKit
import SwiftUI
import UIKit

Expand Down Expand Up @@ -127,7 +127,6 @@ class RCTAcceleratedCheckoutButtonsView: UIView {
}

@objc var onFail: RCTBubblingEventBlock?
@objc var onComplete: RCTBubblingEventBlock?
@objc var onCancel: RCTBubblingEventBlock?
@objc var onRenderStateChange: RCTBubblingEventBlock?
@objc var onShouldRecoverFromError: RCTDirectEventBlock?
Expand Down Expand Up @@ -253,9 +252,6 @@ class RCTAcceleratedCheckoutButtonsView: UIView {

private func attachEventListeners(to buttons: AcceleratedCheckoutButtons) -> AcceleratedCheckoutButtons {
return buttons
.onComplete { [weak self] event in
self?.handleCheckoutCompleted(event)
}
.onFail { [weak self] error in
self?.handleCheckoutFailed(error)
}
Expand All @@ -265,9 +261,6 @@ class RCTAcceleratedCheckoutButtonsView: UIView {
.onRenderStateChange { [weak self] state in
self?.handleRenderStateChange(state)
}
.onClickLink { [weak self] url in
self?.handleClickLink(url)
}
}

private func updateView() {
Expand Down Expand Up @@ -347,10 +340,6 @@ class RCTAcceleratedCheckoutButtonsView: UIView {

// MARK: - Event Handlers

private func handleCheckoutCompleted(_ event: CheckoutCompletedEvent) {
onComplete?(ShopifyEventSerialization.serialize(checkoutCompletedEvent: event))
}

private func handleCheckoutFailed(_ error: CheckoutError) {
onFail?(ShopifyEventSerialization.serialize(checkoutError: error))
}
Expand Down
Loading
Loading