Skip to content

[Kotlin] Move Client to protocol#438

Merged
markmur merged 2 commits into
mainfrom
kotlin-decode-error-parity
Jul 14, 2026
Merged

[Kotlin] Move Client to protocol#438
markmur merged 2 commits into
mainfrom
kotlin-decode-error-parity

Conversation

@markmur

@markmur markmur commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

What changes are you making?

Kotlin was the odd platform out: TS (client.ts) and Swift (EmbeddedCheckoutProtocol+Client.swift) ship a generic dispatch Client — with onDecodeError — inside their protocol packages, but Kotlin had no Client in the embedded-checkout-protocol artifact. The dispatch loop lived entirely in the kit's CheckoutProtocol.Client, which decoded, routed, and encoded inline. This PR closes that structural gap and exposes onDecodeError publicly, matching the parity #437 established for TS + Swift.

Stacked on #437.

Protocol (embedded-checkout-protocol)

  • New generic Client: on(NotificationDescriptor), on(RequestDescriptor), chainable onDecodeError, and process(message). It is thread-agnostic and synchronous — handlers run on the calling thread, so hosts wrap them for threading before registering.
  • onDecodeError is public (Kotlin lands at TS's public level; it has no package visibility and internal in the artifact is invisible to the kit). A SerializationException while decoding a notification skips dispatch and fires the callback; a request with undecodable params fires the callback and answers with an invalid-params error; envelope-level failures stay silent (matching the .unknown path on the other platforms).
  • hasValidJsonRpcRequestId moved into the artifact codec (now shared/public) since both the generic client and the kit need it.

Kit (checkout-kit)

  • CheckoutProtocol.Client is now a thin wrapper over the generic client: it keeps Checkout Kit curation (only supported descriptors register), main-thread delivery of consumer handlers, and wires onDecodeError to log.e once. The duplicated decode/route/encode/catch code is gone. Public kit API is unchanged (lib.api untouched).

The embedded-checkout-protocol.api baseline gains Client and hasValidJsonRpcRequestId; that diff is intended.

Usage

Directly against the protocol artifact (com.shopify:embedded-checkout-protocol) — for a custom transport/WebView integration:

import com.shopify.ucp.embedded.checkout.Client
import com.shopify.ucp.embedded.checkout.EmbeddedCheckoutProtocol

val client = Client()
    .onDecodeError { method, error ->
        Log.e("MyApp", "Failed to decode $method", error)   // you wire your own logging
    }
    .on(EmbeddedCheckoutProtocol.start) { params ->
        // raw protocol payload — you unwrap it yourself; runs on the calling thread
        println("started: ${params.checkout.id}")
    }
    .on(EmbeddedCheckoutProtocol.windowOpen) { request ->
        WindowOpenResult(/**/)                            // request handler returns the response
    }

// you drive it from your own message pump; response is the JSON-RPC reply (or null)
val response: String? = client.process(rawJsonRpcMessage)

Through Checkout Kit (com.shopify:checkout-kit) — the managed path, wired into the kit's WebView automatically:

import com.shopify.checkoutkit.CheckoutProtocol

val client = CheckoutProtocol.Client()
    .on(CheckoutProtocol.start) { checkout ->
        // payload already unwrapped to `Checkout`, delivered on the main thread
        println("started: ${checkout.id}")
    }
    .on(CheckoutProtocol.windowOpen) { request ->
        WindowOpenResult(/**/)
    }
// no onDecodeError needed — the kit wires it to its logger; no process() — the WebView bridge drives it

The kit adds, on top of the generic client: payload unwrapping (Checkout vs raw CheckoutParams), descriptor curation (only supported events register), main-thread handler delivery, decode-error logging, and WebView wiring. The protocol client is the unopinionated primitive underneath.


Before you merge

Important

  • I've added tests to support my implementation
  • I have read and agree with the Contribution Guidelines
  • I have read and agree with the Code of Conduct
  • I've updated the relevant platform README (platforms/swift/README.md and/or platforms/android/README.md)

Releasing a new Swift version?
  • I have bumped the version in ShopifyCheckoutKit.podspec
  • I have bumped the version in platforms/swift/Sources/ShopifyCheckoutKit/ShopifyCheckoutKit.swift
  • I have updated the SwiftPM/CocoaPods version snippets in platforms/swift/README.md (major version only)
Releasing a new Embedded Checkout Protocol version?
  • I have bumped embeddedCheckoutProtocolAndroid in platforms/android/gradle/libs.versions.toml
  • I have updated protocol/languages/kotlin/embedded-checkout-protocol/api/embedded-checkout-protocol.api if the public API changed
Releasing a new Android version?
  • I have bumped checkoutKitAndroid in platforms/android/gradle/libs.versions.toml
  • I have updated the Gradle/Maven version snippets in platforms/android/README.md

Tip

See the Contributing documentation for the full release process per platform.

@github-actions github-actions Bot added the #gsd:50662 Rebase Checkout Kit on UCP label Jul 13, 2026

markmur commented Jul 13, 2026

Copy link
Copy Markdown
Contributor Author

@markmur markmur changed the title Move Client to protocol [Kotlin] Move Client to protocol Jul 13, 2026
@markmur
markmur requested a review from kiftio July 13, 2026 15:35
@markmur markmur self-assigned this Jul 13, 2026
@markmur
markmur marked this pull request as ready for review July 13, 2026 15:39
@markmur
markmur requested a review from a team as a code owner July 13, 2026 15:39
@github-actions

github-actions Bot commented Jul 13, 2026

Copy link
Copy Markdown

React Native — Coverage Report

Lines Statements Branches Functions
Coverage: 92%
91.85% (327/356) 87.98% (183/208) 100% (86/86)

@github-actions

github-actions Bot commented Jul 13, 2026

Copy link
Copy Markdown

Package Size

Platform Artifact Base Head Delta
Android release AAR 222.8 KiB 216.7 KiB -6.1 KiB
Android file breakdown
File Base Head Delta
classes.jar 235.8 KiB 229.1 KiB -6.6 KiB
res/layout/checkout_sheet_content.xml 4.0 KiB 4.0 KiB 0 B
res/values/values.xml 1.2 KiB 1.2 KiB 0 B
R.txt 1.0 KiB 1.0 KiB 0 B
proguard.txt 798 B 798 B 0 B
AndroidManifest.xml 578 B 578 B 0 B
res/drawable/close.xml 431 B 431 B 0 B
res/menu/checkout_menu.xml 354 B 354 B 0 B
META-INF/com/android/build/gradle/aar-metadata.properties 157 B 157 B 0 B

Measured from the PR base SHA and PR head SHA. The file breakdown shows uncompressed sizes within each package artifact, so individual files do not sum to the compressed artifact total. This comment reports package artifact sizes only; it is not a final app binary-size report.

@markmur
markmur force-pushed the kotlin-decode-error-parity branch from 4775200 to 3b8b1e8 Compare July 14, 2026 08:22
@markmur
markmur force-pushed the decode-error-logging-parity branch from 296e415 to 0070c87 Compare July 14, 2026 08:22
@markmur
markmur force-pushed the kotlin-decode-error-parity branch 2 times, most recently from acda492 to d0e4451 Compare July 14, 2026 08:59
Base automatically changed from decode-error-logging-parity to main July 14, 2026 10:02
@markmur
markmur force-pushed the kotlin-decode-error-parity branch from d0e4451 to 1e6dca2 Compare July 14, 2026 10:03

markmur commented Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

Merge activity

  • Jul 14, 11:14 AM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Jul 14, 11:14 AM UTC: @markmur merged this pull request with Graphite.

@markmur
markmur merged commit fbb495c into main Jul 14, 2026
57 of 59 checks passed
@markmur
markmur deleted the kotlin-decode-error-parity branch July 14, 2026 11:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

#gsd:50662 Rebase Checkout Kit on UCP

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants