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
31 changes: 0 additions & 31 deletions platforms/android/lib/api/lib.api
Original file line number Diff line number Diff line change
Expand Up @@ -633,37 +633,6 @@ public abstract interface class com/shopify/checkoutkit/CheckoutCommunicationCli
public abstract fun process (Ljava/lang/String;)Ljava/lang/String;
}

public final class com/shopify/checkoutkit/CheckoutError {
public static final field Companion Lcom/shopify/checkoutkit/CheckoutError$Companion;
public fun <init> ()V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()Ljava/lang/String;
public final fun component3 ()Ljava/lang/String;
public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lcom/shopify/checkoutkit/CheckoutError;
public static synthetic fun copy$default (Lcom/shopify/checkoutkit/CheckoutError;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lcom/shopify/checkoutkit/CheckoutError;
public fun equals (Ljava/lang/Object;)Z
public final fun getCode ()Ljava/lang/String;
public final fun getContent ()Ljava/lang/String;
public final fun getSeverity ()Ljava/lang/String;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class com/shopify/checkoutkit/CheckoutError$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lcom/shopify/checkoutkit/CheckoutError$$serializer;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/shopify/checkoutkit/CheckoutError;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lcom/shopify/checkoutkit/CheckoutError;)V
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
}

public final class com/shopify/checkoutkit/CheckoutError$Companion {
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}

public abstract class com/shopify/checkoutkit/CheckoutException : java/lang/Exception {
public static final field Companion Lcom/shopify/checkoutkit/CheckoutException$Companion;
public synthetic fun <init> (ILjava/lang/String;Ljava/lang/String;ZLkotlinx/serialization/internal/SerializationConstructorMarker;)V
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,14 @@ public object CheckoutProtocol {
public val lineItemsChange: NotificationDescriptor<Checkout> = checkoutDescriptor("ec.line_items.change")
internal val buyerChange: NotificationDescriptor<Checkout> = checkoutDescriptor("ec.buyer.change")
public val totalsChange: NotificationDescriptor<Checkout> = checkoutDescriptor("ec.totals.change")
public val error: NotificationDescriptor<CheckoutError> = NotificationDescriptor(
public val error: NotificationDescriptor<ErrorResponse> = NotificationDescriptor(
method = "ec.error",
decode = { params ->
params?.jsonObject?.get("messages")?.let {
params?.jsonObject?.get("error")?.let {
try {
json.decodeFromJsonElement<List<CheckoutError>>(it).firstOrNull()
json.decodeFromJsonElement<ErrorResponse>(it)
} catch (e: Exception) {
log.d(BaseWebView.ECP_LOG_TAG, "Failed to decode ec.error messages: $e raw=$it")
log.d(BaseWebView.ECP_LOG_TAG, "Failed to decode ec.error params: $e raw=$it")
null
}
}
Expand Down Expand Up @@ -320,14 +320,6 @@ internal sealed class WindowOpenResult {
data class Rejected(val reason: String? = null) : WindowOpenResult()
}

/** Payload delivered with the [CheckoutProtocol.error] notification. */
@Serializable
public data class CheckoutError internal constructor(
public val code: String? = null,
public val content: String? = null,
public val severity: String? = null,
)

// UCP wire envelopes for delegation responses. Mirror Swift's UCPSuccess / UCPError /
// WindowOpenRejectedBody (origin/swift/window.open_request: ShopifyCheckoutProtocol/Codec.swift +
// WindowOpen.swift). UcpEnvelope / UcpMessage are intentionally generic so the next delegation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,18 +135,28 @@ class CheckoutProtocolTest {

@Test
fun `process dispatches ec error to registered handler with decoded payload`() {
var received: CheckoutError? = null
var received: ErrorResponse? = null
val client = CheckoutProtocol.Client()
.on(CheckoutProtocol.error) { received = it }

val errorMsg = """{"jsonrpc":"2.0","method":"ec.error","params":""" +
"""{"messages":[{"code":"unknown_error","content":"fail","severity":"unrecoverable"}]}}"""
"""{"error":{"ucp":{"version":"2026-04-08","status":"error"},"messages":[""" +
"""{"type":"error","code":"unknown_error","content":"fail","severity":"unrecoverable"},""" +
"""{"type":"error","code":"session_expired","content":"expired","severity":"recoverable"}""" +
"""],"continue_url":"https://example.com/retry"}}}"""
client.process(errorMsg)
shadowOf(Looper.getMainLooper()).runToEndOfTasks()

assertThat(received?.code).isEqualTo("unknown_error")
assertThat(received?.content).isEqualTo("fail")
assertThat(received?.severity).isEqualTo("unrecoverable")
assertThat(received?.ucp?.version).isEqualTo("2026-04-08")
assertThat(received?.ucp?.status).isEqualTo(StatusEnum.Error)
assertThat(received?.messages).hasSize(2)
assertThat(received?.messages?.get(0)?.type).isEqualTo(MessageType.Error)
assertThat(received?.messages?.get(0)?.code).isEqualTo("unknown_error")
assertThat(received?.messages?.get(0)?.content).isEqualTo("fail")
assertThat(received?.messages?.get(0)?.severity).isEqualTo(Severity.Unrecoverable)
assertThat(received?.messages?.get(1)?.code).isEqualTo("session_expired")
assertThat(received?.messages?.get(1)?.severity).isEqualTo(Severity.Recoverable)
assertThat(received?.continueURL).isEqualTo("https://example.com/retry")
}

@Test
Expand Down
Loading