From 7d9fb79334c7636b44b4465e693d24e18f062835 Mon Sep 17 00:00:00 2001 From: Anatoly Pashias Date: Tue, 28 Jul 2026 12:01:30 +0300 Subject: [PATCH] fix(android): reject the promise on SDK errors instead of crashing the app MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `pairTerminal`, `charge` and `refund` each caught a launch failure, rejected the promise and then rethrew the same exception. The rethrow escapes the module's coroutine — on `refund` it escapes on the main queue (`.runOnQueue(Queues.MAIN)`) — so an error the JS side is fully equipped to handle takes the process down instead. Seen in production: on a device where `YocoSDK.initialise()` had failed, every subsequent call threw, and pressing Void in the POS killed the app rather than surfacing "could not start refund". A zero-amount charge did the same via `IllegalArgumentException: Amount provided needs to be a positive number`. Also null the stored promise on the failure path. It is only cleared in the `OnActivityResult` handlers, so a rejected-but-retained promise could later be resolved by an unrelated activity result — settling it twice. `configure` keeps its rethrow: it is a synchronous `Function`, where throwing is how the error reaches JS. Second, unrelated one-liner: `ReceiptInfo.transactionTime` was missing `@Field`, so it never serialised into the JS payment result on Android (iOS exposes it). Consumers reading `receiptInfo.transactionTime` silently got undefined. Co-Authored-By: Claude Opus 5 --- .../main/java/expo/modules/yoco/ReactNativeYocoModule.kt | 6 +++--- .../yoco/data/result/ReactNativeYocoPaymentResult.kt | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/android/src/main/java/expo/modules/yoco/ReactNativeYocoModule.kt b/android/src/main/java/expo/modules/yoco/ReactNativeYocoModule.kt index 8254060..f3eb7a4 100644 --- a/android/src/main/java/expo/modules/yoco/ReactNativeYocoModule.kt +++ b/android/src/main/java/expo/modules/yoco/ReactNativeYocoModule.kt @@ -72,8 +72,8 @@ class ReactNativeYocoModule : Module() { YocoSDK.pairTerminal(context = currentActivity) } catch (e: Exception) { + pairTerminalPromise = null promise.reject(e.toCodedException()) - throw e } } @@ -106,8 +106,8 @@ class ReactNativeYocoModule : Module() { null, ) } catch (e: Exception) { + chargePromise = null promise.reject(e.toCodedException()) - throw e } } @@ -188,8 +188,8 @@ class ReactNativeYocoModule : Module() { null, ) } catch (e: Exception) { + refundPromise = null promise.reject(e.toCodedException()) - throw e } }.runOnQueue(Queues.MAIN) diff --git a/android/src/main/java/expo/modules/yoco/data/result/ReactNativeYocoPaymentResult.kt b/android/src/main/java/expo/modules/yoco/data/result/ReactNativeYocoPaymentResult.kt index 28870cd..3caa50f 100644 --- a/android/src/main/java/expo/modules/yoco/data/result/ReactNativeYocoPaymentResult.kt +++ b/android/src/main/java/expo/modules/yoco/data/result/ReactNativeYocoPaymentResult.kt @@ -7,6 +7,8 @@ import expo.modules.yoco.enums.* class ReceiptInfo : Record { @Field var authorizationCode: String? = null + + @Field var transactionTime: String? = null fun injectValues(receiptInfo: com.yoco.payments.sdk.data.result.ReceiptInfo?): ReceiptInfo {