@stripe/stripe-react-native 0.59.1 → 0.60.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 (142) hide show
  1. package/README.md +6 -3
  2. package/android/gradle.properties +2 -2
  3. package/android/src/main/java/com/reactnativestripesdk/FakeOnrampSdkModule.kt +2 -7
  4. package/android/src/main/java/com/reactnativestripesdk/PaymentElementConfig.kt +20 -0
  5. package/android/src/main/java/com/reactnativestripesdk/PaymentMethodMessagingElementConfig.kt +1 -1
  6. package/android/src/main/java/com/reactnativestripesdk/PaymentSheetManager.kt +124 -88
  7. package/android/src/main/java/com/reactnativestripesdk/StripeSdkModule.kt +12 -9
  8. package/android/src/oldarch/java/com/reactnativestripesdk/NativeOnrampSdkModuleSpec.java +0 -4
  9. package/android/src/oldarch/java/com/reactnativestripesdk/NativeStripeSdkModuleSpec.java +6 -5
  10. package/android/src/onramp/java/com/reactnativestripesdk/OnrampMappers.kt +157 -0
  11. package/android/src/onramp/java/com/reactnativestripesdk/OnrampSdkModule.kt +130 -189
  12. package/android/src/test/java/com/reactnativestripesdk/PaymentElementConfigTest.kt +72 -0
  13. package/android/src/test/java/com/reactnativestripesdk/PaymentMethodMessagingElementConfigTest.kt +3 -3
  14. package/android/src/test/java/com/reactnativestripesdk/mappers/OnrampMappersTest.kt +219 -0
  15. package/ios/Mappers.swift +10 -0
  16. package/ios/PaymentMethodMessagingElementConfig.swift +1 -1
  17. package/ios/StripeOnrampSdk.mm +0 -6
  18. package/ios/StripeSdkImpl+PaymentSheet.swift +25 -0
  19. package/ios/StripeSdkImpl.swift +5 -37
  20. package/jest/mock.js +1 -1
  21. package/jest/setup.js +0 -1
  22. package/lib/commonjs/components/AddToWalletButton.js +1 -1
  23. package/lib/commonjs/components/AddToWalletButton.js.map +1 -1
  24. package/lib/commonjs/components/AddressSheet.js +1 -1
  25. package/lib/commonjs/components/AddressSheet.js.map +1 -1
  26. package/lib/commonjs/components/AuBECSDebitForm.js +1 -1
  27. package/lib/commonjs/components/AuBECSDebitForm.js.map +1 -1
  28. package/lib/commonjs/components/CardField.js +1 -1
  29. package/lib/commonjs/components/CardField.js.map +1 -1
  30. package/lib/commonjs/components/CardForm.js +1 -1
  31. package/lib/commonjs/components/CardForm.js.map +1 -1
  32. package/lib/commonjs/components/PlatformPayButton.js +1 -1
  33. package/lib/commonjs/components/PlatformPayButton.js.map +1 -1
  34. package/lib/commonjs/components/StripeContainer.js +1 -1
  35. package/lib/commonjs/components/StripeContainer.js.map +1 -1
  36. package/lib/commonjs/connect/Components.js +1 -1
  37. package/lib/commonjs/connect/Components.js.map +1 -1
  38. package/lib/commonjs/connect/ConnectComponentsProvider.js +1 -1
  39. package/lib/commonjs/connect/ConnectComponentsProvider.js.map +1 -1
  40. package/lib/commonjs/connect/EmbeddedComponent.js +1 -1
  41. package/lib/commonjs/connect/EmbeddedComponent.js.map +1 -1
  42. package/lib/commonjs/connect/ModalCloseButton.js +1 -1
  43. package/lib/commonjs/connect/ModalCloseButton.js.map +1 -1
  44. package/lib/commonjs/connect/NavigationBar.js +1 -1
  45. package/lib/commonjs/connect/NavigationBar.js.map +1 -1
  46. package/lib/commonjs/helpers.js +1 -1
  47. package/lib/commonjs/hooks/useOnramp.js +1 -1
  48. package/lib/commonjs/hooks/useOnramp.js.map +1 -1
  49. package/lib/commonjs/specs/NativeAddToWalletButton.js +1 -1
  50. package/lib/commonjs/specs/NativeAddressSheet.js +1 -1
  51. package/lib/commonjs/specs/NativeApplePayButton.js +1 -1
  52. package/lib/commonjs/specs/NativeAuBECSDebitForm.js +1 -1
  53. package/lib/commonjs/specs/NativeCardField.js +1 -1
  54. package/lib/commonjs/specs/NativeCardField.js.map +1 -1
  55. package/lib/commonjs/specs/NativeCardForm.js +1 -1
  56. package/lib/commonjs/specs/NativeCardForm.js.map +1 -1
  57. package/lib/commonjs/specs/NativeConnectAccountOnboardingView.js +1 -1
  58. package/lib/commonjs/specs/NativeEmbeddedPaymentElement.js +1 -1
  59. package/lib/commonjs/specs/NativeEmbeddedPaymentElement.js.map +1 -1
  60. package/lib/commonjs/specs/NativeGooglePayButton.js +1 -1
  61. package/lib/commonjs/specs/NativeNavigationBar.js +1 -1
  62. package/lib/commonjs/specs/NativeOnrampSdkModule.js.map +1 -1
  63. package/lib/commonjs/specs/NativePaymentMethodMessagingElement.js +1 -1
  64. package/lib/commonjs/specs/NativeStripeContainer.js +1 -1
  65. package/lib/commonjs/types/EmbeddedPaymentElement.js +1 -1
  66. package/lib/commonjs/types/EmbeddedPaymentElement.js.map +1 -1
  67. package/lib/commonjs/types/Onramp.js.map +1 -1
  68. package/lib/commonjs/types/PaymentSheet.js +1 -1
  69. package/lib/commonjs/types/PaymentSheet.js.map +1 -1
  70. package/lib/module/components/AddToWalletButton.js +1 -1
  71. package/lib/module/components/AddToWalletButton.js.map +1 -1
  72. package/lib/module/components/AddressSheet.js +1 -1
  73. package/lib/module/components/AddressSheet.js.map +1 -1
  74. package/lib/module/components/AuBECSDebitForm.js +1 -1
  75. package/lib/module/components/AuBECSDebitForm.js.map +1 -1
  76. package/lib/module/components/CardField.js +1 -1
  77. package/lib/module/components/CardField.js.map +1 -1
  78. package/lib/module/components/CardForm.js +1 -1
  79. package/lib/module/components/CardForm.js.map +1 -1
  80. package/lib/module/components/PlatformPayButton.js +1 -1
  81. package/lib/module/components/PlatformPayButton.js.map +1 -1
  82. package/lib/module/components/StripeContainer.js +1 -1
  83. package/lib/module/components/StripeContainer.js.map +1 -1
  84. package/lib/module/connect/Components.js +1 -1
  85. package/lib/module/connect/Components.js.map +1 -1
  86. package/lib/module/connect/ConnectComponentsProvider.js +1 -1
  87. package/lib/module/connect/ConnectComponentsProvider.js.map +1 -1
  88. package/lib/module/connect/EmbeddedComponent.js +1 -1
  89. package/lib/module/connect/EmbeddedComponent.js.map +1 -1
  90. package/lib/module/connect/ModalCloseButton.js +1 -1
  91. package/lib/module/connect/ModalCloseButton.js.map +1 -1
  92. package/lib/module/connect/NavigationBar.js +1 -1
  93. package/lib/module/connect/NavigationBar.js.map +1 -1
  94. package/lib/module/helpers.js +1 -1
  95. package/lib/module/hooks/useOnramp.js +1 -1
  96. package/lib/module/hooks/useOnramp.js.map +1 -1
  97. package/lib/module/specs/NativeAddToWalletButton.js +1 -1
  98. package/lib/module/specs/NativeAddressSheet.js +1 -1
  99. package/lib/module/specs/NativeApplePayButton.js +1 -1
  100. package/lib/module/specs/NativeAuBECSDebitForm.js +1 -1
  101. package/lib/module/specs/NativeCardField.js +1 -1
  102. package/lib/module/specs/NativeCardField.js.map +1 -1
  103. package/lib/module/specs/NativeCardForm.js +1 -1
  104. package/lib/module/specs/NativeCardForm.js.map +1 -1
  105. package/lib/module/specs/NativeConnectAccountOnboardingView.js +1 -1
  106. package/lib/module/specs/NativeEmbeddedPaymentElement.js +1 -1
  107. package/lib/module/specs/NativeEmbeddedPaymentElement.js.map +1 -1
  108. package/lib/module/specs/NativeGooglePayButton.js +1 -1
  109. package/lib/module/specs/NativeNavigationBar.js +1 -1
  110. package/lib/module/specs/NativeOnrampSdkModule.js.map +1 -1
  111. package/lib/module/specs/NativePaymentMethodMessagingElement.js +1 -1
  112. package/lib/module/specs/NativeStripeContainer.js +1 -1
  113. package/lib/module/types/EmbeddedPaymentElement.js +1 -1
  114. package/lib/module/types/EmbeddedPaymentElement.js.map +1 -1
  115. package/lib/module/types/Onramp.js.map +1 -1
  116. package/lib/module/types/PaymentSheet.js +1 -1
  117. package/lib/module/types/PaymentSheet.js.map +1 -1
  118. package/lib/typescript/src/hooks/useOnramp.d.ts +3 -9
  119. package/lib/typescript/src/hooks/useOnramp.d.ts.map +1 -1
  120. package/lib/typescript/src/specs/NativeOnrampSdkModule.d.ts +0 -1
  121. package/lib/typescript/src/specs/NativeOnrampSdkModule.d.ts.map +1 -1
  122. package/lib/typescript/src/types/Onramp.d.ts +30 -12
  123. package/lib/typescript/src/types/Onramp.d.ts.map +1 -1
  124. package/lib/typescript/src/types/PaymentSheet.d.ts +22 -0
  125. package/lib/typescript/src/types/PaymentSheet.d.ts.map +1 -1
  126. package/lib/typescript/src/types/index.d.ts +0 -5
  127. package/lib/typescript/src/types/index.d.ts.map +1 -1
  128. package/package.json +3 -2
  129. package/src/hooks/useOnramp.tsx +9 -17
  130. package/src/specs/NativeOnrampSdkModule.ts +0 -1
  131. package/src/types/Onramp.ts +32 -15
  132. package/src/types/PaymentSheet.ts +23 -0
  133. package/src/types/index.ts +0 -6
  134. package/stripe-react-native.podspec +1 -1
  135. package/android/.idea/AndroidProjectSystem.xml +0 -6
  136. package/android/.idea/compiler.xml +0 -6
  137. package/android/.idea/gradle.xml +0 -18
  138. package/android/.idea/migrations.xml +0 -10
  139. package/android/.idea/misc.xml +0 -10
  140. package/android/.idea/runConfigurations.xml +0 -17
  141. package/android/.idea/vcs.xml +0 -6
  142. package/android/local.properties +0 -8
package/README.md CHANGED
@@ -23,7 +23,10 @@ Get started with our [📚 integration guides](https://stripe.com/docs/payments/
23
23
 
24
24
  **Native UI**: We provide native screens and elements to securely collect payment details on Android and iOS.
25
25
 
26
- **PaymentSheet**: [Learn how to integrate](https://stripe.com/docs/payments/accept-a-payment) PaymentSheet, our new pre-built payments UI for mobile apps. PaymentSheet lets you accept cards, Apple Pay, Google Pay, and much more out of the box and also supports saving & reusing payment methods. PaymentSheet currently accepts the following payment methods: Card, Apple Pay, Google Pay, SEPA Debit, Bancontact, Billie, iDEAL, EPS, P24, Afterpay/Clearpay, Klarna, Giropay, and ACH.
26
+ **PaymentSheet**: [Learn how to integrate](https://stripe.com/docs/payments/accept-a-payment) PaymentSheet, our new pre-built payments UI for mobile apps.
27
+ - PaymentSheet lets you accept cards, Apple Pay, Google Pay, and much more out of the box and also supports saving & reusing payment methods.
28
+ - PaymentSheet currently accepts the following payment methods: Card, Apple Pay, Google Pay, SEPA Debit, Bancontact, Billie, iDEAL, EPS, P24, Afterpay/Clearpay, Klarna, Giropay, and ACH.
29
+ - PaymentSheet provides card scanning on iOS and Android, with the Android functionality provided by [Google Payment Card Recognition](https://developers.google.com/pay/payment-card-recognition/debit-credit-card-recognition). To enable card scanning in your app, follow [our guide](https://docs.corp.stripe.com/payments/accept-a-payment?payment-ui=mobile&platform=react-native#react-native-card-scanning).
27
30
 
28
31
  #### Recommended usage
29
32
 
@@ -97,7 +100,7 @@ implementation 'com.google.android.material:material:<version>'
97
100
 
98
101
  #### iOS
99
102
 
100
- The Stripe React Native SDK requires Xcode 14.1 or later and is compatible with apps targeting iOS 13 or above. For iOS 12 support, please use [`@stripe/stripe-react-native@0.19.0`](https://github.com/stripe/stripe-react-native/releases/tag/v0.19.0).
103
+ The Stripe React Native SDK supports all [Apple supported Xcode versions](https://developer.apple.com/news/upcoming-requirements/) and is compatible with apps targeting iOS 13 or above. For iOS 12 support, please use [`@stripe/stripe-react-native@0.19.0`](https://github.com/stripe/stripe-react-native/releases/tag/v0.19.0).
101
104
 
102
105
  The SDK uses TypeScript features available in Babel version `7.9.0` and above.
103
106
  Alternatively use the `plugin-transform-typescript` plugin in your project.
@@ -283,5 +286,5 @@ While installing pods in your iOS project using a Stripe React Native version be
283
286
  UnsupportedModulePropertyParserError: Module NativeStripeSdkModule: TypeScript interfaces extending TurboModule must only contain 'FunctionTypeAnnotation's. Property 'onConfirmHandlerCallback' refers to a 'TSTypeReference'.
284
287
  ```
285
288
 
286
- If possible, update to version 0.52 or above of the Stripe React Native SDK.
289
+ If possible, update to version 0.52 or above of the Stripe React Native SDK.
287
290
  If you are unable to do so, please follow our [guide to apply the fix patch](https://github.com/stripe/stripe-react-native/tree/master/patches).
@@ -1,6 +1,6 @@
1
- StripeSdk_kotlinVersion=1.8.0
1
+ StripeSdk_kotlinVersion=2.3.10
2
2
  StripeSdk_compileSdkVersion=30
3
3
  StripeSdk_targetSdkVersion=28
4
4
  StripeSdk_minSdkVersion=21
5
5
  # Keep StripeSdk_stripeVersion in sync with https://github.com/stripe/stripe-identity-react-native/blob/main/android/gradle.properties
6
- StripeSdk_stripeVersion=22.7.+
6
+ StripeSdk_stripeVersion=23.0.2
@@ -68,11 +68,6 @@ class FakeOnrampSdkModule(
68
68
  promise?.resolveNotImplemented()
69
69
  }
70
70
 
71
- @ReactMethod
72
- override fun authenticateUser(promise: Promise?) {
73
- promise?.resolveNotImplemented()
74
- }
75
-
76
71
  @ReactMethod
77
72
  override fun verifyIdentity(promise: Promise?) {
78
73
  promise?.resolveNotImplemented()
@@ -83,7 +78,7 @@ class FakeOnrampSdkModule(
83
78
  updatedAddress: ReadableMap?,
84
79
  promise: Promise,
85
80
  ) {
86
- promise?.resolveNotImplemented()
81
+ promise.resolveNotImplemented()
87
82
  }
88
83
 
89
84
  @ReactMethod
@@ -131,7 +126,7 @@ class FakeOnrampSdkModule(
131
126
  token: ReadableMap,
132
127
  promise: Promise,
133
128
  ) {
134
- promise?.resolveNotImplemented()
129
+ promise.resolveNotImplemented()
135
130
  }
136
131
 
137
132
  @ReactMethod
@@ -2,11 +2,13 @@ package com.reactnativestripesdk
2
2
 
3
3
  import com.facebook.react.bridge.ReadableMap
4
4
  import com.reactnativestripesdk.utils.PaymentSheetException
5
+ import com.reactnativestripesdk.utils.forEachKey
5
6
  import com.reactnativestripesdk.utils.getBooleanOr
6
7
  import com.reactnativestripesdk.utils.getIntOr
7
8
  import com.reactnativestripesdk.utils.getLongOr
8
9
  import com.reactnativestripesdk.utils.getStringList
9
10
  import com.reactnativestripesdk.utils.isEmpty
11
+ import com.stripe.android.model.PaymentMethod
10
12
  import com.stripe.android.paymentelement.PaymentMethodOptionsSetupFutureUsagePreview
11
13
  import com.stripe.android.paymentsheet.CardFundingFilteringPrivatePreview
12
14
  import com.stripe.android.paymentsheet.PaymentSheet
@@ -77,6 +79,24 @@ private fun mapStringToLinkDisplay(value: String?): PaymentSheet.LinkConfigurati
77
79
  else -> PaymentSheet.LinkConfiguration.Display.Automatic
78
80
  }
79
81
 
82
+ internal fun mapToTermsDisplay(params: ReadableMap?): Map<PaymentMethod.Type, PaymentSheet.TermsDisplay>? {
83
+ val termsDisplayMap = params?.getMap("termsDisplay") ?: return null
84
+ val result = mutableMapOf<PaymentMethod.Type, PaymentSheet.TermsDisplay>()
85
+ termsDisplayMap.forEachKey { code ->
86
+ val paymentMethodType = PaymentMethod.Type.fromCode(code)
87
+ val termsDisplay =
88
+ when (termsDisplayMap.getString(code)) {
89
+ "never" -> PaymentSheet.TermsDisplay.NEVER
90
+ "automatic" -> PaymentSheet.TermsDisplay.AUTOMATIC
91
+ else -> null
92
+ }
93
+ if (paymentMethodType != null && termsDisplay != null) {
94
+ result[paymentMethodType] = termsDisplay
95
+ }
96
+ }
97
+ return result.ifEmpty { null }
98
+ }
99
+
80
100
  private val mapIntToButtonType =
81
101
  mapOf(
82
102
  1 to PaymentSheet.GooglePayConfiguration.ButtonType.Buy,
@@ -61,7 +61,7 @@ fun parseAppearance(
61
61
  font?.let { appearance.font(font) }
62
62
  val colors = PaymentMethodMessagingElement.Appearance.Colors()
63
63
  textColor?.let { colors.textColor(it) }
64
- linkTextColor?.let { colors.infoIconColor(linkTextColor) }
64
+ linkTextColor?.let { colors.linkTextColor(linkTextColor) }
65
65
  appearance.colors(colors)
66
66
 
67
67
  return appearance
@@ -97,17 +97,6 @@ class PaymentSheetManager(
97
97
  )
98
98
  return
99
99
  }
100
- val primaryButtonLabel = arguments.getString("primaryButtonLabel")
101
- val googlePayConfig = buildGooglePayConfig(arguments.getMap("googlePay"))
102
- val linkConfig = buildLinkConfig(arguments.getMap("link"))
103
- val allowsDelayedPaymentMethods = arguments.getBooleanOr("allowsDelayedPaymentMethods", false)
104
- val billingDetailsMap = arguments.getMap("defaultBillingDetails")
105
- val billingConfigParams = arguments.getMap("billingDetailsCollectionConfiguration")
106
- val paymentMethodOrder = arguments.getStringList("paymentMethodOrder")
107
- val allowsRemovalOfLastSavedPaymentMethod =
108
- arguments.getBooleanOr("allowsRemovalOfLastSavedPaymentMethod", true)
109
- val opensCardScannerAutomatically =
110
- arguments.getBooleanOr("opensCardScannerAutomatically", false)
111
100
  paymentIntentClientSecret = arguments.getString("paymentIntentClientSecret").orEmpty()
112
101
  setupIntentClientSecret = arguments.getString("setupIntentClientSecret").orEmpty()
113
102
  intentConfiguration =
@@ -121,26 +110,6 @@ class PaymentSheetManager(
121
110
  // Determine which callback type to use based on what's provided
122
111
  val intentConfigMap = arguments.getMap("intentConfiguration")
123
112
  val useConfirmationTokenCallback = intentConfigMap?.hasKey("confirmationTokenConfirmHandler") == true
124
- val appearance =
125
- try {
126
- buildPaymentSheetAppearance(arguments.getMap("appearance"), context)
127
- } catch (error: PaymentSheetAppearanceException) {
128
- initPromise.resolve(createError(ErrorType.Failed.toString(), error))
129
- return
130
- }
131
-
132
- val customerConfiguration =
133
- try {
134
- buildCustomerConfiguration(arguments)
135
- } catch (error: PaymentSheetException) {
136
- initPromise.resolve(createError(ErrorType.Failed.toString(), error))
137
- return
138
- }
139
-
140
- val shippingDetails =
141
- arguments.getMap("defaultShippingDetails")?.let {
142
- AddressSheetView.buildAddressDetails(it)
143
- }
144
113
 
145
114
  val paymentOptionCallback =
146
115
  PaymentOptionResultCallback { paymentOptionResult ->
@@ -208,8 +177,6 @@ class PaymentSheetManager(
208
177
 
209
178
  is PaymentSheetResult.Completed -> {
210
179
  resolvePaymentResult(Arguments.createMap())
211
- paymentSheet = null
212
- flowController = null
213
180
  }
214
181
  }
215
182
  }
@@ -268,6 +235,117 @@ class PaymentSheetManager(
268
235
  }
269
236
  }
270
237
 
238
+ if (arguments.getBooleanOr("customFlow", false)) {
239
+ if (flowController == null) {
240
+ flowController =
241
+ if (intentConfiguration != null) {
242
+ val builder =
243
+ PaymentSheet.FlowController
244
+ .Builder(
245
+ resultCallback = paymentResultCallback,
246
+ paymentOptionResultCallback = paymentOptionCallback,
247
+ )
248
+ if (useConfirmationTokenCallback) {
249
+ builder.createIntentCallback(createConfirmationTokenCallback)
250
+ } else {
251
+ builder.createIntentCallback(createIntentCallback)
252
+ }
253
+ builder
254
+ .confirmCustomPaymentMethodCallback(this)
255
+ .build(activity)
256
+ } else {
257
+ PaymentSheet.FlowController
258
+ .Builder(
259
+ resultCallback = paymentResultCallback,
260
+ paymentOptionResultCallback = paymentOptionCallback,
261
+ ).confirmCustomPaymentMethodCallback(this)
262
+ .build(activity)
263
+ }
264
+ }
265
+ } else {
266
+ if (paymentSheet == null) {
267
+ paymentSheet =
268
+ if (intentConfiguration != null) {
269
+ val builder = PaymentSheet.Builder(paymentResultCallback)
270
+ if (useConfirmationTokenCallback) {
271
+ builder.createIntentCallback(createConfirmationTokenCallback)
272
+ } else {
273
+ builder.createIntentCallback(createIntentCallback)
274
+ }
275
+ @SuppressLint("RestrictedApi")
276
+ builder
277
+ .confirmCustomPaymentMethodCallback(this)
278
+ .build(activity, signal)
279
+ } else {
280
+ @SuppressLint("RestrictedApi")
281
+ PaymentSheet
282
+ .Builder(paymentResultCallback)
283
+ .confirmCustomPaymentMethodCallback(this)
284
+ .build(activity, signal)
285
+ }
286
+ }
287
+ }
288
+ configure(arguments, initPromise)
289
+ }
290
+
291
+ override fun onDestroy() {
292
+ flowController = null
293
+ paymentSheet = null
294
+ }
295
+
296
+ fun configure(
297
+ args: ReadableMap,
298
+ promise: Promise,
299
+ ) {
300
+ val merchantDisplayName = args.getString("merchantDisplayName").orEmpty()
301
+ if (merchantDisplayName.isEmpty()) {
302
+ promise.resolve(
303
+ createError(ErrorType.Failed.toString(), "merchantDisplayName cannot be empty or null."),
304
+ )
305
+ return
306
+ }
307
+ val primaryButtonLabel = args.getString("primaryButtonLabel")
308
+ val googlePayConfig = buildGooglePayConfig(args.getMap("googlePay"))
309
+ val linkConfig = buildLinkConfig(args.getMap("link"))
310
+ val allowsDelayedPaymentMethods = args.getBooleanOr("allowsDelayedPaymentMethods", false)
311
+ val billingDetailsMap = args.getMap("defaultBillingDetails")
312
+ val billingConfigParams = args.getMap("billingDetailsCollectionConfiguration")
313
+ val paymentMethodOrder = args.getStringList("paymentMethodOrder")
314
+ val allowsRemovalOfLastSavedPaymentMethod =
315
+ args.getBooleanOr("allowsRemovalOfLastSavedPaymentMethod", true)
316
+ val opensCardScannerAutomatically =
317
+ args.getBooleanOr("opensCardScannerAutomatically", false)
318
+ paymentIntentClientSecret = args.getString("paymentIntentClientSecret").orEmpty()
319
+ setupIntentClientSecret = args.getString("setupIntentClientSecret").orEmpty()
320
+ intentConfiguration =
321
+ try {
322
+ buildIntentConfiguration(args.getMap("intentConfiguration"))
323
+ } catch (error: PaymentSheetException) {
324
+ promise.resolve(createError(ErrorType.Failed.toString(), error))
325
+ return
326
+ }
327
+
328
+ val appearance =
329
+ try {
330
+ buildPaymentSheetAppearance(args.getMap("appearance"), context)
331
+ } catch (error: PaymentSheetAppearanceException) {
332
+ promise.resolve(createError(ErrorType.Failed.toString(), error))
333
+ return
334
+ }
335
+
336
+ val customerConfiguration =
337
+ try {
338
+ buildCustomerConfiguration(args)
339
+ } catch (error: PaymentSheetException) {
340
+ promise.resolve(createError(ErrorType.Failed.toString(), error))
341
+ return
342
+ }
343
+
344
+ val shippingDetails =
345
+ args.getMap("defaultShippingDetails")?.let {
346
+ AddressSheetView.buildAddressDetails(it)
347
+ }
348
+
271
349
  val billingDetailsConfig = buildBillingDetailsCollectionConfiguration(billingConfigParams)
272
350
 
273
351
  val defaultBillingDetails = buildBillingDetails(billingDetailsMap)
@@ -283,70 +361,28 @@ class PaymentSheetManager(
283
361
  .link(linkConfig)
284
362
  .billingDetailsCollectionConfiguration(billingDetailsConfig)
285
363
  .preferredNetworks(
286
- mapToPreferredNetworks(arguments.getIntegerList("preferredNetworks")),
364
+ mapToPreferredNetworks(args.getIntegerList("preferredNetworks")),
287
365
  ).allowsRemovalOfLastSavedPaymentMethod(allowsRemovalOfLastSavedPaymentMethod)
288
366
  .opensCardScannerAutomatically(opensCardScannerAutomatically)
289
- .cardBrandAcceptance(mapToCardBrandAcceptance(arguments))
367
+ .cardBrandAcceptance(mapToCardBrandAcceptance(args))
290
368
  .apply {
291
- mapToAllowedCardFundingTypes(arguments)?.let { allowedCardFundingTypes(it) }
292
- }.customPaymentMethods(parseCustomPaymentMethods(arguments.getMap("customPaymentMethodConfiguration")))
369
+ mapToAllowedCardFundingTypes(args)?.let { allowedCardFundingTypes(it) }
370
+ }.customPaymentMethods(parseCustomPaymentMethods(args.getMap("customPaymentMethodConfiguration")))
293
371
 
294
372
  primaryButtonLabel?.let { configurationBuilder.primaryButtonLabel(it) }
295
373
  paymentMethodOrder?.let { configurationBuilder.paymentMethodOrder(it) }
296
374
 
297
375
  configurationBuilder.paymentMethodLayout(
298
- mapToPaymentMethodLayout(arguments.getString("paymentMethodLayout")),
376
+ mapToPaymentMethodLayout(args.getString("paymentMethodLayout")),
299
377
  )
300
378
 
301
- paymentSheetConfiguration = configurationBuilder.build()
379
+ mapToTermsDisplay(args)?.let { configurationBuilder.termsDisplay(it) }
302
380
 
303
- if (arguments.getBooleanOr("customFlow", false)) {
304
- flowController =
305
- if (intentConfiguration != null) {
306
- val builder =
307
- PaymentSheet.FlowController
308
- .Builder(
309
- resultCallback = paymentResultCallback,
310
- paymentOptionResultCallback = paymentOptionCallback,
311
- )
312
- if (useConfirmationTokenCallback) {
313
- builder.createIntentCallback(createConfirmationTokenCallback)
314
- } else {
315
- builder.createIntentCallback(createIntentCallback)
316
- }
317
- builder
318
- .confirmCustomPaymentMethodCallback(this)
319
- .build(activity)
320
- } else {
321
- PaymentSheet.FlowController
322
- .Builder(
323
- resultCallback = paymentResultCallback,
324
- paymentOptionResultCallback = paymentOptionCallback,
325
- ).confirmCustomPaymentMethodCallback(this)
326
- .build(activity)
327
- }
328
- configureFlowController()
381
+ paymentSheetConfiguration = configurationBuilder.build()
382
+ if (args.getBooleanOr("customFlow", false)) {
383
+ configureFlowController(promise)
329
384
  } else {
330
- paymentSheet =
331
- if (intentConfiguration != null) {
332
- val builder = PaymentSheet.Builder(paymentResultCallback)
333
- if (useConfirmationTokenCallback) {
334
- builder.createIntentCallback(createConfirmationTokenCallback)
335
- } else {
336
- builder.createIntentCallback(createIntentCallback)
337
- }
338
- @SuppressLint("RestrictedApi")
339
- builder
340
- .confirmCustomPaymentMethodCallback(this)
341
- .build(activity, signal)
342
- } else {
343
- @SuppressLint("RestrictedApi")
344
- PaymentSheet
345
- .Builder(paymentResultCallback)
346
- .confirmCustomPaymentMethodCallback(this)
347
- .build(activity, signal)
348
- }
349
- initPromise.resolve(Arguments.createMap())
385
+ promise.resolve(Arguments.createMap())
350
386
  }
351
387
  }
352
388
 
@@ -431,10 +467,10 @@ class PaymentSheetManager(
431
467
  flowController?.confirm()
432
468
  }
433
469
 
434
- private fun configureFlowController() {
470
+ private fun configureFlowController(promise: Promise) {
435
471
  val onFlowControllerConfigure =
436
472
  PaymentSheet.FlowController.ConfigCallback { success, error ->
437
- handleFlowControllerConfigured(success, error, initPromise, flowController)
473
+ handleFlowControllerConfigured(success, error, promise, flowController)
438
474
  }
439
475
 
440
476
  if (!paymentIntentClientSecret.isNullOrEmpty()) {
@@ -456,7 +492,7 @@ class PaymentSheetManager(
456
492
  callback = onFlowControllerConfigure,
457
493
  )
458
494
  } else {
459
- initPromise.resolve(
495
+ promise.resolve(
460
496
  createError(
461
497
  ErrorType.Failed.toString(),
462
498
  "One of `paymentIntentClientSecret`, `setupIntentClientSecret`, or `intentConfiguration` is required",
@@ -257,11 +257,14 @@ class StripeSdkModule(
257
257
  params: ReadableMap,
258
258
  promise: Promise,
259
259
  ) {
260
- unregisterStripeUIManager(paymentSheetManager)
261
- paymentSheetManager =
262
- PaymentSheetManager(reactApplicationContext, params, promise).also {
263
- registerStripeUIManager(it)
264
- }
260
+ if (paymentSheetManager != null) {
261
+ paymentSheetManager?.configure(params, promise)
262
+ } else {
263
+ paymentSheetManager =
264
+ PaymentSheetManager(reactApplicationContext, params, promise).also {
265
+ registerStripeUIManager(it)
266
+ }
267
+ }
265
268
  }
266
269
 
267
270
  @ReactMethod
@@ -1340,10 +1343,10 @@ class StripeSdkModule(
1340
1343
  stripeAccountId = stripeAccountId,
1341
1344
  callback =
1342
1345
  object : com.stripe.android.ApiResultCallback<RadarSession> {
1343
- override fun onSuccess(session: RadarSession) {
1344
- val result = WritableNativeMap()
1345
- result.putString("id", session.id)
1346
- promise.resolve(result)
1346
+ override fun onSuccess(result: RadarSession) {
1347
+ val response = WritableNativeMap()
1348
+ response.putString("id", result.id)
1349
+ promise.resolve(response)
1347
1350
  }
1348
1351
 
1349
1352
  override fun onError(e: Exception) {
@@ -72,10 +72,6 @@ public abstract class NativeOnrampSdkModuleSpec extends ReactContextBaseJavaModu
72
72
  @DoNotStrip
73
73
  public abstract void updatePhoneNumber(String phone, Promise promise);
74
74
 
75
- @ReactMethod
76
- @DoNotStrip
77
- public abstract void authenticateUser(Promise promise);
78
-
79
75
  @ReactMethod
80
76
  @DoNotStrip
81
77
  public abstract void verifyIdentity(Promise promise);
@@ -142,7 +142,8 @@ public abstract class NativeStripeSdkModuleSpec extends ReactContextBaseJavaModu
142
142
  Map<String, Object> constants = getTypedExportedConstants();
143
143
  if (ReactBuildConfig.DEBUG || ReactBuildConfig.IS_INTERNAL_BUILD) {
144
144
  Set<String> obligatoryFlowConstants = new HashSet<>(Arrays.asList(
145
- "API_VERSIONS"
145
+ "API_VERSIONS",
146
+ "SYSTEM_INFO"
146
147
  ));
147
148
  Set<String> optionalFlowConstants = new HashSet<>();
148
149
  Set<String> undeclaredConstants = new HashSet<>(constants.keySet());
@@ -264,6 +265,10 @@ public abstract class NativeStripeSdkModuleSpec extends ReactContextBaseJavaModu
264
265
  @DoNotStrip
265
266
  public abstract void clearEmbeddedPaymentOption(double viewTag, Promise promise);
266
267
 
268
+ @ReactMethod
269
+ @DoNotStrip
270
+ public abstract void createRadarSession(Promise promise);
271
+
267
272
  @ReactMethod
268
273
  @DoNotStrip
269
274
  public abstract void setFinancialConnectionsForceNativeFlow(boolean enabled, Promise promise);
@@ -295,8 +300,4 @@ public abstract class NativeStripeSdkModuleSpec extends ReactContextBaseJavaModu
295
300
  @ReactMethod
296
301
  @DoNotStrip
297
302
  public abstract void removeListeners(double count);
298
-
299
- @ReactMethod
300
- @DoNotStrip
301
- public abstract void createRadarSession(Promise promise);
302
303
  }
@@ -0,0 +1,157 @@
1
+ package com.reactnativestripesdk
2
+
3
+ import android.annotation.SuppressLint
4
+ import androidx.compose.ui.graphics.Color
5
+ import com.facebook.react.bridge.ReadableMap
6
+ import com.stripe.android.crypto.onramp.model.OnrampConfiguration
7
+ import com.stripe.android.crypto.onramp.model.PaymentMethodDisplayData
8
+ import com.stripe.android.googlepaylauncher.GooglePayEnvironment
9
+ import com.stripe.android.googlepaylauncher.GooglePayPaymentMethodLauncher
10
+ import com.stripe.android.link.LinkAppearance
11
+ import com.stripe.android.link.LinkAppearance.Colors
12
+ import com.stripe.android.link.LinkAppearance.PrimaryButton
13
+ import com.stripe.android.link.LinkAppearance.Style
14
+
15
+ @SuppressLint("RestrictedApi")
16
+ internal fun mapConfig(
17
+ configMap: ReadableMap,
18
+ publishableKey: String,
19
+ ): OnrampConfiguration {
20
+ val appearanceMap = configMap.getMap("appearance")
21
+ val appearance =
22
+ if (appearanceMap != null) {
23
+ mapAppearance(appearanceMap)
24
+ } else {
25
+ LinkAppearance()
26
+ .style(Style.AUTOMATIC)
27
+ }
28
+
29
+ val displayName = configMap.getString("merchantDisplayName") ?: ""
30
+ val cryptoCustomerId = configMap.getString("cryptoCustomerId")
31
+ val googlePayConfig = mapGooglePayConfig(configMap.getMap("googlePay"))
32
+
33
+ return OnrampConfiguration()
34
+ .merchantDisplayName(displayName)
35
+ .publishableKey(publishableKey)
36
+ .appearance(appearance)
37
+ .cryptoCustomerId(cryptoCustomerId)
38
+ .apply { googlePayConfig?.let { googlePayConfig(it) } }
39
+ }
40
+
41
+ @SuppressLint("RestrictedApi")
42
+ internal fun mapGooglePayConfig(params: ReadableMap?): GooglePayPaymentMethodLauncher.Config? {
43
+ if (params == null) return null
44
+
45
+ val testEnv = params.hasKey("testEnv") && params.getBoolean("testEnv")
46
+ val merchantCountryCode = params.getString("merchantCountryCode") ?: return null
47
+ val merchantName = params.getString("merchantName") ?: return null
48
+ val existingPaymentMethodRequired =
49
+ params.hasKey("existingPaymentMethodRequired") && params.getBoolean("existingPaymentMethodRequired")
50
+
51
+ val billingAddressConfig =
52
+ mapGooglePayBillingAddressConfig(params.getMap("billingAddressConfig"))
53
+
54
+ return GooglePayPaymentMethodLauncher.Config(
55
+ environment = if (testEnv) GooglePayEnvironment.Test else GooglePayEnvironment.Production,
56
+ merchantCountryCode = merchantCountryCode,
57
+ merchantName = merchantName,
58
+ billingAddressConfig = billingAddressConfig,
59
+ existingPaymentMethodRequired = existingPaymentMethodRequired,
60
+ )
61
+ }
62
+
63
+ private fun mapGooglePayBillingAddressConfig(params: ReadableMap?): GooglePayPaymentMethodLauncher.BillingAddressConfig {
64
+ if (params == null) return GooglePayPaymentMethodLauncher.BillingAddressConfig()
65
+
66
+ val isRequired = params.hasKey("isRequired") && params.getBoolean("isRequired")
67
+ val format =
68
+ when (params.getString("format")) {
69
+ "Full" -> GooglePayPaymentMethodLauncher.BillingAddressConfig.Format.Full
70
+ else -> GooglePayPaymentMethodLauncher.BillingAddressConfig.Format.Min
71
+ }
72
+ val isPhoneNumberRequired =
73
+ params.hasKey("isPhoneNumberRequired") && params.getBoolean("isPhoneNumberRequired")
74
+
75
+ return GooglePayPaymentMethodLauncher.BillingAddressConfig(
76
+ isRequired = isRequired,
77
+ format = format,
78
+ isPhoneNumberRequired = isPhoneNumberRequired,
79
+ )
80
+ }
81
+
82
+ @SuppressLint("RestrictedApi")
83
+ internal fun mapAppearance(appearanceMap: ReadableMap): LinkAppearance {
84
+ val lightColorsMap = appearanceMap.getMap("lightColors")
85
+ val darkColorsMap = appearanceMap.getMap("darkColors")
86
+ val styleStr = appearanceMap.getString("style")
87
+ val primaryButtonMap = appearanceMap.getMap("primaryButton")
88
+
89
+ val lightColors =
90
+ if (lightColorsMap != null) {
91
+ val primaryColorStr = lightColorsMap.getString("primary")
92
+ val contentColorStr = lightColorsMap.getString("contentOnPrimary")
93
+ val borderSelectedColorStr = lightColorsMap.getString("borderSelected")
94
+
95
+ Colors()
96
+ .primary(Color(android.graphics.Color.parseColor(primaryColorStr)))
97
+ .contentOnPrimary(Color(android.graphics.Color.parseColor(contentColorStr)))
98
+ .borderSelected(Color(android.graphics.Color.parseColor(borderSelectedColorStr)))
99
+ } else {
100
+ Colors()
101
+ }
102
+
103
+ val darkColors =
104
+ if (darkColorsMap != null) {
105
+ val primaryColorStr = darkColorsMap.getString("primary")
106
+ val contentColorStr = darkColorsMap.getString("contentOnPrimary")
107
+ val borderSelectedColorStr = darkColorsMap.getString("borderSelected")
108
+
109
+ Colors()
110
+ .primary(Color(android.graphics.Color.parseColor(primaryColorStr)))
111
+ .contentOnPrimary(Color(android.graphics.Color.parseColor(contentColorStr)))
112
+ .borderSelected(Color(android.graphics.Color.parseColor(borderSelectedColorStr)))
113
+ } else {
114
+ Colors()
115
+ }
116
+
117
+ val style =
118
+ when (styleStr) {
119
+ "ALWAYS_LIGHT" -> Style.ALWAYS_LIGHT
120
+ "ALWAYS_DARK" -> Style.ALWAYS_DARK
121
+ else -> Style.AUTOMATIC
122
+ }
123
+
124
+ val primaryButton =
125
+ if (primaryButtonMap != null) {
126
+ PrimaryButton()
127
+ .cornerRadiusDp(
128
+ if (primaryButtonMap.hasKey("cornerRadius")) {
129
+ primaryButtonMap.getDouble("cornerRadius").toFloat()
130
+ } else {
131
+ null
132
+ },
133
+ ).heightDp(
134
+ if (primaryButtonMap.hasKey("height")) {
135
+ primaryButtonMap.getDouble("height").toFloat()
136
+ } else {
137
+ null
138
+ },
139
+ )
140
+ } else {
141
+ PrimaryButton()
142
+ }
143
+
144
+ return LinkAppearance()
145
+ .lightColors(lightColors)
146
+ .darkColors(darkColors)
147
+ .style(style)
148
+ .primaryButton(primaryButton)
149
+ }
150
+
151
+ @SuppressLint("RestrictedApi")
152
+ internal fun mapPaymentDetailsType(type: PaymentMethodDisplayData.Type): String =
153
+ when (type) {
154
+ PaymentMethodDisplayData.Type.Card -> "Card"
155
+ PaymentMethodDisplayData.Type.BankAccount -> "BankAccount"
156
+ PaymentMethodDisplayData.Type.GooglePay -> "GooglePay"
157
+ }