@stripe/stripe-react-native 0.65.1 → 0.67.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/android/detekt/detekt-baseline.xml +0 -10
  2. package/android/gradle.properties +1 -1
  3. package/android/src/main/java/com/reactnativestripesdk/CardFieldView.kt +51 -57
  4. package/android/src/main/java/com/reactnativestripesdk/CurrencySelectorElementEvent.kt +26 -0
  5. package/android/src/main/java/com/reactnativestripesdk/CurrencySelectorElementView.kt +129 -16
  6. package/android/src/main/java/com/reactnativestripesdk/CurrencySelectorElementViewManager.kt +17 -0
  7. package/android/src/main/java/com/reactnativestripesdk/EventEmitterCompat.kt +4 -0
  8. package/android/src/main/java/com/reactnativestripesdk/PaymentSheetManager.kt +8 -19
  9. package/android/src/main/java/com/reactnativestripesdk/StripeAbstractComposeView.kt +1 -0
  10. package/android/src/main/java/com/reactnativestripesdk/StripeSdkModule.kt +89 -31
  11. package/android/src/main/java/com/reactnativestripesdk/StripeSdkPackage.kt +1 -0
  12. package/android/src/main/java/com/reactnativestripesdk/customersheet/CustomerSheetManager.kt +2 -16
  13. package/android/src/main/java/com/reactnativestripesdk/utils/CheckoutMappers.kt +59 -33
  14. package/android/src/main/java/com/reactnativestripesdk/utils/DefaultActivityLifecycleCallbacks.kt +41 -0
  15. package/android/src/main/java/com/reactnativestripesdk/utils/Errors.kt +11 -6
  16. package/android/src/oldarch/java/com/reactnativestripesdk/NativeOnrampSdkModuleSpec.java +17 -3
  17. package/android/src/oldarch/java/com/reactnativestripesdk/NativeStripeSdkModuleSpec.java +2 -2
  18. package/android/src/onramp/java/com/reactnativestripesdk/OnrampErrors.kt +145 -0
  19. package/android/src/onramp/java/com/reactnativestripesdk/OnrampMappers.kt +125 -0
  20. package/android/src/onramp/java/com/reactnativestripesdk/OnrampSdkModule.kt +144 -22
  21. package/android/src/test/java/com/reactnativestripesdk/DrawableLoadingTest.kt +6 -2
  22. package/android/src/test/java/com/reactnativestripesdk/OnrampErrorsTest.kt +168 -0
  23. package/android/src/test/java/com/reactnativestripesdk/mappers/OnrampMappersTest.kt +107 -0
  24. package/android/src/test/java/com/reactnativestripesdk/utils/CheckoutMappersTest.kt +39 -30
  25. package/android/src/test/java/com/reactnativestripesdk/utils/CheckoutTestFixtures.java +8 -0
  26. package/ios/CurrencySelectorElementManager.m +7 -0
  27. package/ios/CurrencySelectorElementView.swift +142 -7
  28. package/ios/EmbeddedPaymentElementView.swift +1 -1
  29. package/ios/Mappers+Checkout.swift +251 -107
  30. package/ios/Mappers.swift +97 -7
  31. package/ios/NewArch/StripeCurrencySelectorElementComponentView.mm +14 -0
  32. package/ios/OldArch/StripeSdkEventEmitterCompat.h +1 -0
  33. package/ios/OldArch/StripeSdkEventEmitterCompat.m +6 -0
  34. package/ios/OnrampErrors.swift +132 -0
  35. package/ios/PaymentOptionDisplayData+ReactNative.swift +1 -1
  36. package/ios/PaymentSheetAppearance.swift +1 -1
  37. package/ios/StripeOnrampSdk.mm +19 -0
  38. package/ios/StripeSdk.mm +14 -14
  39. package/ios/StripeSdkEmitter.swift +1 -0
  40. package/ios/StripeSdkImpl+Checkout.swift +66 -31
  41. package/ios/StripeSdkImpl+CustomerSheet.swift +1 -1
  42. package/ios/StripeSdkImpl+Embedded.swift +1 -1
  43. package/ios/StripeSdkImpl+PaymentSheet.swift +1 -1
  44. package/ios/StripeSdkImpl.swift +116 -24
  45. package/lib/commonjs/components/PaymentMethodMessagingElement.js +1 -1
  46. package/lib/commonjs/components/PaymentMethodMessagingElement.js.map +1 -1
  47. package/lib/commonjs/components/StripeProvider.js +1 -1
  48. package/lib/commonjs/components/StripeProvider.js.map +1 -1
  49. package/lib/commonjs/hooks/useCheckout.js +1 -1
  50. package/lib/commonjs/hooks/useCheckout.js.map +1 -1
  51. package/lib/commonjs/hooks/useOnramp.js +1 -1
  52. package/lib/commonjs/hooks/useOnramp.js.map +1 -1
  53. package/lib/commonjs/internal/stripeConfig.js +2 -0
  54. package/lib/commonjs/internal/stripeConfig.js.map +1 -0
  55. package/lib/commonjs/specs/NativeOnrampSdkModule.js.map +1 -1
  56. package/lib/commonjs/specs/NativeStripeSdkModule.js.map +1 -1
  57. package/lib/commonjs/types/Errors.js +1 -1
  58. package/lib/commonjs/types/Errors.js.map +1 -1
  59. package/lib/commonjs/types/Onramp.js +1 -1
  60. package/lib/commonjs/types/Onramp.js.map +1 -1
  61. package/lib/module/components/PaymentMethodMessagingElement.js +1 -1
  62. package/lib/module/components/PaymentMethodMessagingElement.js.map +1 -1
  63. package/lib/module/components/StripeProvider.js +1 -1
  64. package/lib/module/components/StripeProvider.js.map +1 -1
  65. package/lib/module/hooks/useCheckout.js +1 -1
  66. package/lib/module/hooks/useCheckout.js.map +1 -1
  67. package/lib/module/hooks/useOnramp.js +1 -1
  68. package/lib/module/hooks/useOnramp.js.map +1 -1
  69. package/lib/module/internal/stripeConfig.js +2 -0
  70. package/lib/module/internal/stripeConfig.js.map +1 -0
  71. package/lib/module/specs/NativeOnrampSdkModule.js.map +1 -1
  72. package/lib/module/specs/NativeStripeSdkModule.js.map +1 -1
  73. package/lib/module/types/Errors.js +1 -1
  74. package/lib/module/types/Errors.js.map +1 -1
  75. package/lib/module/types/Onramp.js +1 -1
  76. package/lib/module/types/Onramp.js.map +1 -1
  77. package/lib/typescript/src/components/PaymentMethodMessagingElement.d.ts +1 -1
  78. package/lib/typescript/src/components/PaymentMethodMessagingElement.d.ts.map +1 -1
  79. package/lib/typescript/src/components/StripeProvider.d.ts.map +1 -1
  80. package/lib/typescript/src/hooks/useCheckout.d.ts.map +1 -1
  81. package/lib/typescript/src/hooks/useOnramp.d.ts +32 -10
  82. package/lib/typescript/src/hooks/useOnramp.d.ts.map +1 -1
  83. package/lib/typescript/src/internal/stripeConfig.d.ts +3 -0
  84. package/lib/typescript/src/internal/stripeConfig.d.ts.map +1 -0
  85. package/lib/typescript/src/specs/NativeOnrampSdkModule.d.ts +3 -0
  86. package/lib/typescript/src/specs/NativeOnrampSdkModule.d.ts.map +1 -1
  87. package/lib/typescript/src/specs/NativeStripeSdkModule.d.ts +2 -2
  88. package/lib/typescript/src/specs/NativeStripeSdkModule.d.ts.map +1 -1
  89. package/lib/typescript/src/types/Checkout.d.ts +266 -92
  90. package/lib/typescript/src/types/Checkout.d.ts.map +1 -1
  91. package/lib/typescript/src/types/Errors.d.ts +0 -5
  92. package/lib/typescript/src/types/Errors.d.ts.map +1 -1
  93. package/lib/typescript/src/types/Onramp.d.ts +168 -9
  94. package/lib/typescript/src/types/Onramp.d.ts.map +1 -1
  95. package/package.json +3 -2
  96. package/src/components/PaymentMethodMessagingElement.tsx +54 -52
  97. package/src/components/StripeProvider.tsx +2 -0
  98. package/src/hooks/useCheckout.tsx +20 -13
  99. package/src/hooks/useOnramp.tsx +139 -12
  100. package/src/internal/stripeConfig.ts +9 -0
  101. package/src/specs/NativeOnrampSdkModule.ts +5 -0
  102. package/src/specs/NativeStripeSdkModule.ts +6 -5
  103. package/src/types/Checkout.ts +289 -93
  104. package/src/types/Errors.ts +0 -6
  105. package/src/types/Onramp.ts +192 -9
  106. package/stripe-react-native.podspec +3 -3
  107. package/ios/CurrencySelectorElementManager.swift +0 -12
@@ -2,7 +2,6 @@ package com.reactnativestripesdk
2
2
 
3
3
  import android.annotation.SuppressLint
4
4
  import android.app.Activity
5
- import android.app.Application
6
5
  import android.content.Intent
7
6
  import android.os.Bundle
8
7
  import android.os.Handler
@@ -10,7 +9,6 @@ import android.os.Looper
10
9
  import android.util.Log
11
10
  import android.view.ViewGroup
12
11
  import androidx.appcompat.app.AppCompatActivity
13
- import androidx.browser.customtabs.CustomTabsIntent
14
12
  import androidx.core.net.toUri
15
13
  import androidx.fragment.app.FragmentActivity
16
14
  import com.facebook.react.ReactActivity
@@ -31,6 +29,7 @@ import com.reactnativestripesdk.customersheet.CustomerSheetManager
31
29
  import com.reactnativestripesdk.pushprovisioning.PushProvisioningProxy
32
30
  import com.reactnativestripesdk.utils.ConfirmPaymentErrorType
33
31
  import com.reactnativestripesdk.utils.CreateTokenErrorType
32
+ import com.reactnativestripesdk.utils.DefaultActivityLifecycleCallbacks
34
33
  import com.reactnativestripesdk.utils.ErrorType
35
34
  import com.reactnativestripesdk.utils.GooglePayErrorType
36
35
  import com.reactnativestripesdk.utils.RetrievePaymentIntentErrorType
@@ -82,10 +81,15 @@ import com.stripe.android.model.Token
82
81
  import com.stripe.android.paymentelement.CheckoutSessionPreview
83
82
  import com.stripe.android.payments.bankaccount.CollectBankAccountConfiguration
84
83
  import com.stripe.android.paymentsheet.PaymentSheet
84
+ import kotlinx.coroutines.CancellableContinuation
85
85
  import kotlinx.coroutines.CompletableDeferred
86
86
  import kotlinx.coroutines.CoroutineScope
87
87
  import kotlinx.coroutines.Dispatchers
88
+ import kotlinx.coroutines.Job
89
+ import kotlinx.coroutines.flow.combine
90
+ import kotlinx.coroutines.flow.distinctUntilChanged
88
91
  import kotlinx.coroutines.launch
92
+ import kotlinx.coroutines.suspendCancellableCoroutine
89
93
  import org.json.JSONObject
90
94
  import java.util.UUID
91
95
 
@@ -113,6 +117,13 @@ class StripeSdkModule(
113
117
  private var googlePayLauncherManager: GooglePayLauncherManager? = null
114
118
  private var googlePayPaymentMethodLauncherManager: GooglePayPaymentMethodLauncherManager? = null
115
119
  internal val checkoutInstances = mutableMapOf<String, Checkout>()
120
+ private val serverUpdateContinuations =
121
+ mutableMapOf<String, CancellableContinuation<Result<Unit>>>()
122
+
123
+ // / Tracks the long-running coroutine that observes each Checkout's
124
+ // / `checkoutSession` + `isLoading` flows and forwards transitions to JS as
125
+ // / `checkoutSessionDidChangeState` events.
126
+ private val checkoutStateObservers = mutableMapOf<String, Job>()
116
127
 
117
128
  private var customerSheetManager: CustomerSheetManager? = null
118
129
 
@@ -165,6 +176,8 @@ class StripeSdkModule(
165
176
 
166
177
  stripeUIManagers.forEach { it.destroy() }
167
178
  stripeUIManagers.clear()
179
+ checkoutStateObservers.values.forEach { it.cancel() }
180
+ checkoutStateObservers.clear()
168
181
  checkoutInstances.clear()
169
182
  }
170
183
 
@@ -1743,6 +1756,7 @@ class StripeSdkModule(
1743
1756
  onSuccess = { checkout ->
1744
1757
  val sessionKey = UUID.randomUUID().toString()
1745
1758
  checkoutInstances[sessionKey] = checkout
1759
+ observeCheckoutState(sessionKey, checkout)
1746
1760
 
1747
1761
  promise.resolve(
1748
1762
  Arguments.createMap().apply {
@@ -1855,24 +1869,48 @@ class StripeSdkModule(
1855
1869
  }
1856
1870
  }
1857
1871
 
1858
- override fun checkoutUpdateTaxId(
1872
+ override fun checkoutRunServerUpdateStart(
1859
1873
  sessionKey: String,
1860
- type: String,
1861
- value: String,
1862
1874
  promise: Promise,
1863
1875
  ) {
1864
- performCheckoutMutation(sessionKey, promise) { checkout ->
1865
- checkout.updateTaxId(type = type, value = value)
1876
+ val checkout = checkoutInstances[sessionKey] ?: run {
1877
+ promise.reject(ErrorType.Failed.toString(), "Checkout session not found.")
1878
+ return
1879
+ }
1880
+
1881
+ if (serverUpdateContinuations.containsKey(sessionKey)) {
1882
+ promise.reject(ErrorType.Failed.toString(), "A server update is already in progress for this session.")
1883
+ return
1884
+ }
1885
+
1886
+ CoroutineScope(Dispatchers.Main).launch {
1887
+ checkout.runServerUpdate {
1888
+ suspendCancellableCoroutine { continuation ->
1889
+ serverUpdateContinuations[sessionKey] = continuation
1890
+ }
1891
+ }.fold(
1892
+ onSuccess = { promise.resolve(mapFromCheckoutState(checkout)) },
1893
+ onFailure = { promise.reject(ErrorType.Failed.toString(), it.message, it) },
1894
+ )
1866
1895
  }
1867
1896
  }
1868
1897
 
1869
- override fun checkoutRefresh(
1898
+ override fun checkoutRunServerUpdateComplete(
1870
1899
  sessionKey: String,
1900
+ error: String?,
1871
1901
  promise: Promise,
1872
1902
  ) {
1873
- performCheckoutMutation(sessionKey, promise) { checkout ->
1874
- checkout.refresh()
1903
+ val continuation = serverUpdateContinuations.remove(sessionKey) ?: run {
1904
+ promise.reject(ErrorType.Failed.toString(), "No pending server update for this session.")
1905
+ return
1875
1906
  }
1907
+
1908
+ if (error != null) {
1909
+ continuation.resume(Result.failure(Exception(error))) {}
1910
+ } else {
1911
+ continuation.resume(Result.success(Unit)) {}
1912
+ }
1913
+ promise.resolve(null)
1876
1914
  }
1877
1915
 
1878
1916
  private fun buildCheckoutConfiguration(configuration: ReadableMap): Checkout.Configuration {
@@ -1884,6 +1922,41 @@ class StripeSdkModule(
1884
1922
  return checkoutConfiguration
1885
1923
  }
1886
1924
 
1925
+ /**
1926
+ * Forwards the checkout's `(checkoutSession, isLoading)` flow to JS as
1927
+ * `checkoutSessionDidChangeState` events. Equivalent to the iOS
1928
+ * `CheckoutDelegate` bridge — every native-side mutation (currency selection,
1929
+ * promo code, refresh, etc.) goes through one canonical channel that
1930
+ * `useCheckout` listens to.
1931
+ */
1932
+ private fun observeCheckoutState(
1933
+ sessionKey: String,
1934
+ checkout: Checkout,
1935
+ ) {
1936
+ checkoutStateObservers[sessionKey]?.cancel()
1937
+
1938
+ val job = CoroutineScope(Dispatchers.Main).launch {
1939
+ // `combine` re-emits on every upstream tick. `distinctUntilChanged`
1940
+ // collapses runs where neither field actually moved — both flows are
1941
+ // StateFlows so we'd otherwise see a redundant initial replay when
1942
+ // wiring up.
1943
+ combine(
1944
+ checkout.checkoutSession,
1945
+ checkout.isLoading,
1946
+ ) { session, isLoading -> session to isLoading }
1947
+ .distinctUntilChanged()
1948
+ .collect {
1949
+ eventEmitter.emitCheckoutSessionDidChangeState(
1950
+ Arguments.createMap().apply {
1951
+ putString("sessionKey", sessionKey)
1952
+ putMap("state", mapFromCheckoutState(checkout))
1953
+ },
1954
+ )
1955
+ }
1956
+ }
1957
+ checkoutStateObservers[sessionKey] = job
1958
+ }
1959
+
1887
1960
  private fun performCheckoutMutation(
1888
1961
  sessionKey: String,
1889
1962
  promise: Promise,
@@ -1925,14 +1998,14 @@ class StripeSdkModule(
1925
1998
  private var isRecreatingReactActivity = false
1926
1999
  private var isAuthWebViewActive = false
1927
2000
  private val activityLifecycleCallbacks =
1928
- object : Application.ActivityLifecycleCallbacks {
2001
+ object : DefaultActivityLifecycleCallbacks() {
1929
2002
  override fun onActivityCreated(
1930
2003
  activity: Activity,
1931
- bundle: Bundle?,
2004
+ savedInstanceState: Bundle?,
1932
2005
  ) {
1933
- // Only set flag when ReactActivity is actually being recreated (bundle != null)
1934
- // bundle != null means this is a recreation, not first creation
1935
- if (activity is ReactActivity && bundle != null) {
2006
+ // Only set flag when ReactActivity is actually being recreated (savedInstanceState != null)
2007
+ // savedInstanceState != null means this is a recreation, not first creation
2008
+ if (activity is ReactActivity && savedInstanceState != null) {
1936
2009
  isRecreatingReactActivity = true
1937
2010
  }
1938
2011
 
@@ -1951,21 +2024,6 @@ class StripeSdkModule(
1951
2024
  }
1952
2025
  }
1953
2026
  }
1954
-
1955
- override fun onActivityStarted(activity: Activity) {}
1956
-
1957
- override fun onActivityResumed(activity: Activity) {}
1958
-
1959
- override fun onActivityPaused(activity: Activity) {}
1960
-
1961
- override fun onActivityStopped(activity: Activity) {}
1962
-
1963
- override fun onActivitySaveInstanceState(
1964
- activity: Activity,
1965
- bundle: Bundle,
1966
- ) {}
1967
-
1968
- override fun onActivityDestroyed(activity: Activity) {}
1969
2027
  }
1970
2028
 
1971
2029
  /**
@@ -2006,7 +2064,7 @@ class StripeSdkModule(
2006
2064
  // Timeout for auth webview fallback (if JavaScript doesn't call authWebViewDeepLinkHandled)
2007
2065
  private const val AUTH_WEBVIEW_FALLBACK_TIMEOUT_MS = 60_000L
2008
2066
 
2009
- private const val FILE_CLEANUP_DELAY_MS = 3000L
2067
+ private const val FILE_CLEANUP_DELAY_MS = 3_000L
2010
2068
 
2011
2069
  // SDK-managed storage for pending stripe-connect:// URLs
2012
2070
  // This is static because deep links can arrive before ReactContext is available
@@ -62,6 +62,7 @@ class StripeSdkPackage : BaseReactPackage() {
62
62
  EmbeddedPaymentElementViewManager(),
63
63
  NavigationBarManager(),
64
64
  PaymentMethodMessagingElementViewManager(),
65
+ CurrencySelectorElementViewManager(),
65
66
  )
66
67
 
67
68
  private fun getOnrampModuleClass(): Class<out NativeModule?>? {
@@ -1,7 +1,6 @@
1
1
  package com.reactnativestripesdk.customersheet
2
2
 
3
3
  import android.app.Activity
4
- import android.app.Application
5
4
  import android.graphics.drawable.Drawable
6
5
  import android.os.Bundle
7
6
  import android.os.Handler
@@ -20,6 +19,7 @@ import com.reactnativestripesdk.buildPaymentSheetAppearance
20
19
  import com.reactnativestripesdk.convertDrawableToBase64
21
20
  import com.reactnativestripesdk.mapToCardBrandAcceptance
22
21
  import com.reactnativestripesdk.utils.CreateTokenErrorType
22
+ import com.reactnativestripesdk.utils.DefaultActivityLifecycleCallbacks
23
23
  import com.reactnativestripesdk.utils.ErrorType
24
24
  import com.reactnativestripesdk.utils.KeepJsAwakeTask
25
25
  import com.reactnativestripesdk.utils.PaymentSheetAppearanceException
@@ -224,7 +224,7 @@ class CustomerSheetManager(
224
224
  private fun presentWithTimeout(timeout: Long) {
225
225
  var activities: MutableList<Activity> = mutableListOf()
226
226
  val activityLifecycleCallbacks =
227
- object : Application.ActivityLifecycleCallbacks {
227
+ object : DefaultActivityLifecycleCallbacks() {
228
228
  override fun onActivityCreated(
229
229
  activity: Activity,
230
230
  savedInstanceState: Bundle?,
@@ -232,20 +232,6 @@ class CustomerSheetManager(
232
232
  activities.add(activity)
233
233
  }
234
234
 
235
- override fun onActivityStarted(activity: Activity) {}
236
-
237
- override fun onActivityResumed(activity: Activity) {}
238
-
239
- override fun onActivityPaused(activity: Activity) {}
240
-
241
- override fun onActivityStopped(activity: Activity) {}
242
-
243
- override fun onActivitySaveInstanceState(
244
- activity: Activity,
245
- outState: Bundle,
246
- ) {
247
- }
248
-
249
235
  override fun onActivityDestroyed(activity: Activity) {
250
236
  activities = mutableListOf()
251
237
  context.currentActivity?.application?.unregisterActivityLifecycleCallbacks(this)
@@ -25,51 +25,70 @@ internal fun mapFromCheckoutState(
25
25
  }
26
26
 
27
27
  @OptIn(CheckoutSessionPreview::class)
28
- private fun mapFromCheckoutSession(
29
- session: CheckoutSession,
30
- ): WritableMap =
28
+ private fun mapFromCheckoutSession(session: CheckoutSession): WritableMap =
31
29
  Arguments.createMap().apply {
32
30
  putString("id", session.id)
33
- // TODO(CheckoutSessionsPreview): Populate from public Android checkout fields once
34
- // stripe-android exposes status, paymentStatus, and livemode on CheckoutSession.
35
- putString("status", "unknown")
36
- putString("paymentStatus", "unknown")
37
31
  putBoolean("livemode", false)
38
32
 
39
33
  if (session.currency.isNotBlank()) {
40
34
  putString("currency", session.currency)
41
35
  }
42
36
 
43
- session.totalSummary?.let { putMap("totals", mapFromCheckoutTotals(it)) }
44
- putArray("lineItems", mapFromCheckoutLineItems(session))
45
- putArray("shippingOptions", mapFromCheckoutShippingOptions(session))
37
+ putMap("status", mapFromStatus(session.status))
38
+ putMap("tax", mapFromTax(session.tax))
39
+ session.totalSummary?.let { putMap("total", mapFromTotal(it)) }
40
+
41
+ putArray("lineItems", mapFromLineItems(session))
42
+ putArray("shippingOptions", mapFromShippingOptions(session))
43
+ putArray("discountAmounts", Arguments.createArray())
44
+ putArray("currencyOptions", Arguments.createArray())
45
+ }
46
46
 
47
- // TODO(CheckoutSessionsPreview): Populate top-level discounts once stripe-android
48
- // exposes them directly instead of only exposing TotalSummary.discountAmounts.
49
- putArray("discounts", Arguments.createArray())
47
+ @OptIn(CheckoutSessionPreview::class)
48
+ private fun mapFromStatus(status: CheckoutSession.Status): WritableMap =
49
+ Arguments.createMap().apply {
50
+ putString(
51
+ "type",
52
+ when (status) {
53
+ CheckoutSession.Status.Open -> "open"
54
+ CheckoutSession.Status.Complete -> "complete"
55
+ CheckoutSession.Status.Expired -> "expired"
56
+ else -> "unknown"
57
+ }
58
+ )
59
+ }
50
60
 
51
- // TODO(CheckoutSessionsPreview): Populate customerId, customerEmail, billingAddress,
52
- // and shippingAddress once stripe-android exposes them on public checkout models.
61
+ @OptIn(CheckoutSessionPreview::class)
62
+ private fun mapFromTax(tax: CheckoutSession.Tax): WritableMap =
63
+ Arguments.createMap().apply {
64
+ putString(
65
+ "status",
66
+ when (tax.status) {
67
+ CheckoutSession.Tax.Status.Ready -> "ready"
68
+ CheckoutSession.Tax.Status.RequiresShippingAddress -> "requiresShippingAddress"
69
+ CheckoutSession.Tax.Status.RequiresBillingAddress -> "requiresBillingAddress"
70
+ else -> "unknown"
71
+ }
72
+ )
53
73
  }
54
74
 
55
75
  @OptIn(CheckoutSessionPreview::class)
56
- private fun mapFromCheckoutTotals(totals: CheckoutSession.TotalSummary): WritableMap {
57
- val taxTotal = totals.taxAmounts.sumOf { it.amount }
76
+ private fun mapFromTotal(totals: CheckoutSession.TotalSummary): WritableMap =
77
+ Arguments.createMap().apply {
78
+ val taxTotal = totals.taxAmounts.sumOf { it.amount }
58
79
 
59
- return Arguments.createMap().apply {
60
- putDouble("subtotal", totals.subtotal.toDouble())
61
- putDouble("total", totals.totalAmountDue.toDouble())
62
- putDouble("due", totals.totalDueToday.toDouble())
63
- // TODO(CheckoutSessionsPreview): Populate the top-level discount total once the
64
- // Android TotalSummary model exposes it directly.
65
- putDouble("discount", 0.0)
66
- putDouble("shipping", (totals.shippingRate?.amount ?: 0L).toDouble())
67
- putDouble("tax", taxTotal.toDouble())
80
+ putMap("subtotal", makeAmount(totals.subtotal))
81
+ putMap("taxExclusive", makeAmount(taxTotal))
82
+ putMap("taxInclusive", makeAmount(0L))
83
+ putMap("shippingRate", makeAmount(totals.shippingRate?.amount ?: 0L))
84
+ putMap("discount", makeAmount(0L))
85
+ putMap("total", makeAmount(totals.totalAmountDue))
86
+ putMap("appliedBalance", makeAmount(0L))
87
+ putBoolean("balanceAppliedToNextInvoice", false)
68
88
  }
69
- }
70
89
 
71
90
  @OptIn(CheckoutSessionPreview::class)
72
- private fun mapFromCheckoutLineItems(session: CheckoutSession): WritableArray =
91
+ private fun mapFromLineItems(session: CheckoutSession): WritableArray =
73
92
  Arguments.createArray().apply {
74
93
  session.lineItems.forEach { item ->
75
94
  pushMap(
@@ -77,25 +96,32 @@ private fun mapFromCheckoutLineItems(session: CheckoutSession): WritableArray =
77
96
  putString("id", item.id)
78
97
  putString("name", item.name)
79
98
  putInt("quantity", item.quantity)
80
- putDouble("unitAmount", (item.unitAmount ?: 0L).toDouble())
81
- putString("currency", session.currency)
99
+ putArray("images", Arguments.createArray())
100
+ putArray("discountAmounts", Arguments.createArray())
101
+ putArray("taxAmounts", Arguments.createArray())
102
+ item.unitAmount?.let { putMap("unitAmount", makeAmount(it)) }
82
103
  },
83
104
  )
84
105
  }
85
106
  }
86
107
 
87
108
  @OptIn(CheckoutSessionPreview::class)
88
- private fun mapFromCheckoutShippingOptions(session: CheckoutSession): WritableArray =
109
+ private fun mapFromShippingOptions(session: CheckoutSession): WritableArray =
89
110
  Arguments.createArray().apply {
90
111
  session.shippingOptions.forEach { option ->
91
112
  pushMap(
92
113
  Arguments.createMap().apply {
93
114
  putString("id", option.id)
94
115
  putString("displayName", option.displayName)
95
- putDouble("amount", option.amount.toDouble())
116
+ putMap("amount", makeAmount(option.amount))
96
117
  putString("currency", session.currency)
97
- option.deliveryEstimate?.let { putString("deliveryEstimate", it) }
98
118
  },
99
119
  )
100
120
  }
101
121
  }
122
+
123
+ private fun makeAmount(minorUnits: Long): WritableMap =
124
+ Arguments.createMap().apply {
125
+ putString("amount", "")
126
+ putDouble("minorUnitsAmount", minorUnits.toDouble())
127
+ }
@@ -0,0 +1,41 @@
1
+ package com.reactnativestripesdk.utils
2
+
3
+ import android.app.Activity
4
+ import android.app.Application
5
+ import android.os.Bundle
6
+
7
+ internal open class DefaultActivityLifecycleCallbacks : Application.ActivityLifecycleCallbacks {
8
+ override fun onActivityCreated(
9
+ activity: Activity,
10
+ savedInstanceState: Bundle?,
11
+ ) {
12
+ // NO-OP
13
+ }
14
+
15
+ override fun onActivityStarted(activity: Activity) {
16
+ // NO-OP
17
+ }
18
+
19
+ override fun onActivityResumed(activity: Activity) {
20
+ // NO-OP
21
+ }
22
+
23
+ override fun onActivityPaused(activity: Activity) {
24
+ // NO-OP
25
+ }
26
+
27
+ override fun onActivityStopped(activity: Activity) {
28
+ // NO-OP
29
+ }
30
+
31
+ override fun onActivitySaveInstanceState(
32
+ activity: Activity,
33
+ outState: Bundle,
34
+ ) {
35
+ // NO-OP
36
+ }
37
+
38
+ override fun onActivityDestroyed(activity: Activity) {
39
+ // NO-OP
40
+ }
41
+ }
@@ -5,6 +5,7 @@ import com.facebook.react.bridge.WritableMap
5
5
  import com.stripe.android.core.exception.APIException
6
6
  import com.stripe.android.core.exception.AuthenticationException
7
7
  import com.stripe.android.core.exception.InvalidRequestException
8
+ import com.stripe.android.core.exception.StripeException
8
9
  import com.stripe.android.exception.CardException
9
10
  import com.stripe.android.model.PaymentIntent
10
11
  import com.stripe.android.model.SetupIntent
@@ -173,6 +174,16 @@ internal fun createError(
173
174
  error.stripeError?.code,
174
175
  )
175
176
  }
177
+ is StripeException -> {
178
+ mapError(
179
+ code,
180
+ error.message,
181
+ error.localizedMessage,
182
+ error.stripeError?.declineCode,
183
+ error.stripeError?.type,
184
+ error.stripeError?.code
185
+ )
186
+ }
176
187
  else -> mapError(code, error.message, error.localizedMessage.orEmpty(), null, null, null)
177
188
  }
178
189
 
@@ -197,9 +208,3 @@ internal fun createMissingInitError(): WritableMap =
197
208
  "Stripe has not been initialized. Initialize Stripe in your app with the StripeProvider component " +
198
209
  "or the initStripe method.",
199
210
  )
200
-
201
- internal fun createOnrampNotConfiguredError(): WritableMap =
202
- createError(
203
- ErrorType.Failed.toString(),
204
- "Onramp is not configured.",
205
- )
@@ -17,9 +17,11 @@ import com.facebook.react.bridge.Promise;
17
17
  import com.facebook.react.bridge.ReactApplicationContext;
18
18
  import com.facebook.react.bridge.ReactContextBaseJavaModule;
19
19
  import com.facebook.react.bridge.ReactMethod;
20
+ import com.facebook.react.bridge.ReadableArray;
20
21
  import com.facebook.react.bridge.ReadableMap;
21
22
  import com.facebook.react.turbomodule.core.interfaces.TurboModule;
22
23
  import javax.annotation.Nonnull;
24
+ import javax.annotation.Nullable;
23
25
 
24
26
  public abstract class NativeOnrampSdkModuleSpec extends ReactContextBaseJavaModule implements TurboModule {
25
27
  public static final String NAME = "OnrampSdk";
@@ -57,6 +59,18 @@ public abstract class NativeOnrampSdkModuleSpec extends ReactContextBaseJavaModu
57
59
  @DoNotStrip
58
60
  public abstract void attachKycInfo(ReadableMap kycInfo, Promise promise);
59
61
 
62
+ @ReactMethod
63
+ @DoNotStrip
64
+ public abstract void retrieveMissingIdentifiers(Promise promise);
65
+
66
+ @ReactMethod
67
+ @DoNotStrip
68
+ public abstract void submitIdentifiers(ReadableArray identifiers, Promise promise);
69
+
70
+ @ReactMethod
71
+ @DoNotStrip
72
+ public abstract void presentUserAttestation(Promise promise);
73
+
60
74
  @ReactMethod
61
75
  @DoNotStrip
62
76
  public abstract void updatePhoneNumber(String phone, Promise promise);
@@ -71,7 +85,7 @@ public abstract class NativeOnrampSdkModuleSpec extends ReactContextBaseJavaModu
71
85
 
72
86
  @ReactMethod
73
87
  @DoNotStrip
74
- public abstract void provideCheckoutClientSecret(String clientSecret);
88
+ public abstract void provideCheckoutClientSecret(@Nullable String clientSecret);
75
89
 
76
90
  @ReactMethod
77
91
  @DoNotStrip
@@ -91,11 +105,11 @@ public abstract class NativeOnrampSdkModuleSpec extends ReactContextBaseJavaModu
91
105
 
92
106
  @ReactMethod
93
107
  @DoNotStrip
94
- public abstract void authenticateUserWithToken(String token, Promise promise);
108
+ public abstract void authenticateUserWithToken(String linkAuthTokenClientSecret, Promise promise);
95
109
 
96
110
  @ReactMethod
97
111
  @DoNotStrip
98
- public abstract void presentKycInfoVerification(ReadableMap updatedAddress, Promise promise);
112
+ public abstract void presentKycInfoVerification(@Nullable ReadableMap updatedAddress, Promise promise);
99
113
 
100
114
  @ReactMethod
101
115
  @DoNotStrip
@@ -331,11 +331,11 @@ public abstract class NativeStripeSdkModuleSpec extends ReactContextBaseJavaModu
331
331
 
332
332
  @ReactMethod
333
333
  @DoNotStrip
334
- public abstract void checkoutUpdateTaxId(String sessionKey, String type, String value, Promise promise);
334
+ public abstract void checkoutRunServerUpdateStart(String sessionKey, Promise promise);
335
335
 
336
336
  @ReactMethod
337
337
  @DoNotStrip
338
- public abstract void checkoutRefresh(String sessionKey, Promise promise);
338
+ public abstract void checkoutRunServerUpdateComplete(String sessionKey, @Nullable String error, Promise promise);
339
339
 
340
340
  @ReactMethod
341
341
  @DoNotStrip