@stripe/stripe-react-native 0.48.0 → 0.49.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 (102) hide show
  1. package/.env +19 -0
  2. package/CHANGELOG.md +8 -0
  3. package/android/gradle.properties +1 -1
  4. package/android/src/main/java/com/reactnativestripesdk/EmbeddedPaymentElementView.kt +85 -65
  5. package/android/src/main/java/com/reactnativestripesdk/EmbeddedPaymentElementViewManager.kt +18 -2
  6. package/android/src/main/java/com/reactnativestripesdk/PaymentOptionDisplayDataMapper.kt +0 -2
  7. package/android/src/main/java/com/reactnativestripesdk/PaymentSheetAppearance.kt +57 -3
  8. package/android/src/main/java/com/reactnativestripesdk/PaymentSheetFragment.kt +25 -0
  9. package/ios/PaymentSheetAppearance.swift +22 -1
  10. package/ios/StripeSdk.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  11. package/ios/StripeSdk.xcodeproj/project.xcworkspace/xcuserdata/wooj.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  12. package/ios/StripeSdk.xcodeproj/xcuserdata/wooj.xcuserdatad/xcschemes/xcschememanagement.plist +19 -0
  13. package/ios/StripeSdkImpl+PaymentSheet.swift +43 -5
  14. package/ios/StripeSdkImpl.swift +5 -1
  15. package/lib/commonjs/components/AddToWalletButton.js +1 -1
  16. package/lib/commonjs/components/AddToWalletButton.js.map +1 -1
  17. package/lib/commonjs/components/AddressSheet.js +1 -1
  18. package/lib/commonjs/components/AddressSheet.js.map +1 -1
  19. package/lib/commonjs/components/AuBECSDebitForm.js +1 -1
  20. package/lib/commonjs/components/AuBECSDebitForm.js.map +1 -1
  21. package/lib/commonjs/components/CardField.js +1 -1
  22. package/lib/commonjs/components/CardField.js.map +1 -1
  23. package/lib/commonjs/components/CardForm.js +1 -1
  24. package/lib/commonjs/components/CardForm.js.map +1 -1
  25. package/lib/commonjs/components/CustomerSheet.js +1 -1
  26. package/lib/commonjs/components/CustomerSheet.js.map +1 -1
  27. package/lib/commonjs/components/PlatformPayButton.js +1 -1
  28. package/lib/commonjs/components/PlatformPayButton.js.map +1 -1
  29. package/lib/commonjs/components/StripeContainer.js +1 -1
  30. package/lib/commonjs/components/StripeContainer.js.map +1 -1
  31. package/lib/commonjs/events.js.map +1 -1
  32. package/lib/commonjs/functions.js +1 -1
  33. package/lib/commonjs/functions.js.map +1 -1
  34. package/lib/commonjs/hooks/useStripe.js +1 -1
  35. package/lib/commonjs/hooks/useStripe.js.map +1 -1
  36. package/lib/commonjs/types/EmbeddedPaymentElement.js +1 -1
  37. package/lib/commonjs/types/EmbeddedPaymentElement.js.map +1 -1
  38. package/lib/commonjs/types/PaymentSheet.js +1 -1
  39. package/lib/commonjs/types/PaymentSheet.js.map +1 -1
  40. package/lib/module/components/AddToWalletButton.js +1 -1
  41. package/lib/module/components/AddToWalletButton.js.map +1 -1
  42. package/lib/module/components/AddressSheet.js +1 -1
  43. package/lib/module/components/AddressSheet.js.map +1 -1
  44. package/lib/module/components/AuBECSDebitForm.js +1 -1
  45. package/lib/module/components/AuBECSDebitForm.js.map +1 -1
  46. package/lib/module/components/CardField.js +1 -1
  47. package/lib/module/components/CardField.js.map +1 -1
  48. package/lib/module/components/CardForm.js +1 -1
  49. package/lib/module/components/CardForm.js.map +1 -1
  50. package/lib/module/components/CustomerSheet.js +1 -1
  51. package/lib/module/components/CustomerSheet.js.map +1 -1
  52. package/lib/module/components/PlatformPayButton.js +1 -1
  53. package/lib/module/components/PlatformPayButton.js.map +1 -1
  54. package/lib/module/components/StripeContainer.js +1 -1
  55. package/lib/module/components/StripeContainer.js.map +1 -1
  56. package/lib/module/events.js.map +1 -1
  57. package/lib/module/functions.js +1 -1
  58. package/lib/module/functions.js.map +1 -1
  59. package/lib/module/hooks/useStripe.js +1 -1
  60. package/lib/module/hooks/useStripe.js.map +1 -1
  61. package/lib/module/types/EmbeddedPaymentElement.js +1 -1
  62. package/lib/module/types/EmbeddedPaymentElement.js.map +1 -1
  63. package/lib/module/types/PaymentSheet.js +1 -1
  64. package/lib/module/types/PaymentSheet.js.map +1 -1
  65. package/lib/typescript/src/events.d.ts +1 -1
  66. package/lib/typescript/src/events.d.ts.map +1 -1
  67. package/lib/typescript/src/types/EmbeddedPaymentElement.d.ts +27 -0
  68. package/lib/typescript/src/types/EmbeddedPaymentElement.d.ts.map +1 -1
  69. package/lib/typescript/src/types/PaymentIntent.d.ts +1 -1
  70. package/lib/typescript/src/types/PaymentIntent.d.ts.map +1 -1
  71. package/lib/typescript/src/types/PaymentSheet.d.ts +23 -2
  72. package/lib/typescript/src/types/PaymentSheet.d.ts.map +1 -1
  73. package/package-lock.json +14114 -0
  74. package/package.json +1 -1
  75. package/src/events.ts +1 -0
  76. package/src/types/EmbeddedPaymentElement.tsx +47 -2
  77. package/src/types/PaymentIntent.ts +1 -1
  78. package/src/types/PaymentSheet.ts +27 -1
  79. package/stripe-react-native.podspec +1 -1
  80. package/android/.gradle/8.11.1/checksums/checksums.lock +0 -0
  81. package/android/.gradle/8.11.1/checksums/md5-checksums.bin +0 -0
  82. package/android/.gradle/8.11.1/checksums/sha1-checksums.bin +0 -0
  83. package/android/.gradle/8.11.1/executionHistory/executionHistory.bin +0 -0
  84. package/android/.gradle/8.11.1/executionHistory/executionHistory.lock +0 -0
  85. package/android/.gradle/8.11.1/fileChanges/last-build.bin +0 -0
  86. package/android/.gradle/8.11.1/fileHashes/fileHashes.bin +0 -0
  87. package/android/.gradle/8.11.1/fileHashes/fileHashes.lock +0 -0
  88. package/android/.gradle/8.11.1/gc.properties +0 -0
  89. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  90. package/android/.gradle/buildOutputCleanup/cache.properties +0 -2
  91. package/android/.gradle/buildOutputCleanup/outputFiles.bin +0 -0
  92. package/android/.gradle/config.properties +0 -2
  93. package/android/.gradle/file-system.probe +0 -0
  94. package/android/.gradle/vcs-1/gc.properties +0 -0
  95. package/android/.idea/caches/deviceStreaming.xml +0 -619
  96. package/android/.idea/compiler.xml +0 -6
  97. package/android/.idea/gradle.xml +0 -19
  98. package/android/.idea/migrations.xml +0 -10
  99. package/android/.idea/misc.xml +0 -10
  100. package/android/.idea/runConfigurations.xml +0 -17
  101. package/android/.idea/vcs.xml +0 -6
  102. package/android/local.properties +0 -8
package/.env ADDED
@@ -0,0 +1,19 @@
1
+ # Stripe API keys - see https://stripe.com/docs/development/quickstart#api-keys
2
+ STRIPE_PUBLISHABLE_KEY=pk_test
3
+ STRIPE_SECRET_KEY=sk_test
4
+
5
+ STRIPE_PUBLISHABLE_KEY_MY=pk_test
6
+ STRIPE_SECRET_KEY_MY=sk_test
7
+
8
+ STRIPE_PUBLISHABLE_KEY_MX=pk_test
9
+ STRIPE_SECRET_KEY_MX=sk_test
10
+
11
+ STRIPE_PUBLISHABLE_KEY_AU=pk_test
12
+ STRIPE_SECRET_KEY_AU=sk_test
13
+
14
+ STRIPE_PUBLISHABLE_KEY_WECHAT=pk_test
15
+ STRIPE_SECRET_KEY_WECHAT=sk_test
16
+
17
+ # Required for webhook forwarding
18
+ # See the README on how to do this with the Stripe CLI
19
+ STRIPE_WEBHOOK_SECRET=whsec_
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.49.0 - 2025-07-02
4
+
5
+ **Features**
6
+ - Added rowSelectionBehavior to `EmbeddedPaymentElementConfiguration` with `immediateAction` option
7
+ - Added `flatWithChevron` to `AppearanceParams.embeddedPaymentElement.rowConfig.style`
8
+ - Added `PaymentMethodOptions` to `PaymentMode` to enable setting payment method level setup future usage value
9
+ - Added `None` to `FutureUsage`
10
+
3
11
  ## 0.48.0 - 2025-06-11
4
12
 
5
13
  **Feature**
@@ -3,4 +3,4 @@ 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=21.17.+
6
+ StripeSdk_stripeVersion=21.19.+
@@ -7,6 +7,7 @@ import androidx.compose.runtime.Composable
7
7
  import androidx.compose.runtime.LaunchedEffect
8
8
  import androidx.compose.runtime.getValue
9
9
  import androidx.compose.runtime.mutableIntStateOf
10
+ import androidx.compose.runtime.mutableStateOf
10
11
  import androidx.compose.runtime.remember
11
12
  import androidx.compose.runtime.setValue
12
13
  import androidx.compose.ui.Modifier
@@ -20,7 +21,6 @@ import com.facebook.react.uimanager.ThemedReactContext
20
21
  import com.reactnativestripesdk.utils.KeepJsAwakeTask
21
22
  import com.reactnativestripesdk.utils.mapFromPaymentMethod
22
23
  import com.stripe.android.paymentelement.EmbeddedPaymentElement
23
- import com.stripe.android.paymentelement.ExperimentalEmbeddedPaymentElementApi
24
24
  import com.stripe.android.paymentelement.rememberEmbeddedPaymentElement
25
25
  import com.stripe.android.paymentsheet.CreateIntentResult
26
26
  import com.stripe.android.paymentsheet.PaymentSheet
@@ -29,7 +29,11 @@ import kotlinx.coroutines.channels.Channel
29
29
  import kotlinx.coroutines.flow.consumeAsFlow
30
30
  import toWritableMap
31
31
 
32
- @OptIn(ExperimentalEmbeddedPaymentElementApi::class)
32
+ enum class RowSelectionBehaviorType {
33
+ Default,
34
+ ImmediateAction,
35
+ }
36
+
33
37
  class EmbeddedPaymentElementView(
34
38
  context: Context,
35
39
  ) : StripeAbstractComposeView(context) {
@@ -47,75 +51,91 @@ class EmbeddedPaymentElementView(
47
51
  var latestIntentConfig: PaymentSheet.IntentConfiguration? = null
48
52
  var latestElementConfig: EmbeddedPaymentElement.Configuration? = null
49
53
 
54
+ val rowSelectionBehaviorType = mutableStateOf<RowSelectionBehaviorType?>(null)
55
+
50
56
  private val reactContext get() = context as ThemedReactContext
51
57
  private val events = Channel<Event>(Channel.UNLIMITED)
52
58
 
53
- private val builder by lazy {
54
- EmbeddedPaymentElement.Builder(
55
- createIntentCallback = { paymentMethod, shouldSavePaymentMethod ->
56
- val stripeSdkModule =
57
- try {
58
- requireStripeSdkModule()
59
- } catch (ex: IllegalArgumentException) {
60
- return@Builder CreateIntentResult.Failure(
61
- cause =
62
- Exception(
63
- "Tried to call confirmHandler, but no callback was found. Please file an issue: https://github.com/stripe/stripe-react-native/issues",
64
- ),
65
- displayMessage = "An unexpected error occurred",
66
- )
67
- }
68
-
69
- // Make sure that JS is active since the activity will be paused when stripe ui is presented.
70
- val keepJsAwakeTask = KeepJsAwakeTask(reactContext.reactApplicationContext).apply { start() }
71
-
72
- val params =
73
- Arguments.createMap().apply {
74
- putMap("paymentMethod", mapFromPaymentMethod(paymentMethod))
75
- putBoolean("shouldSavePaymentMethod", shouldSavePaymentMethod)
76
- }
77
-
78
- stripeSdkModule.emitOnConfirmHandlerCallback(params)
79
-
80
- val resultFromJavascript = stripeSdkModule.embeddedIntentCreationCallback.await()
81
- // reset the completable
82
- stripeSdkModule.embeddedIntentCreationCallback = CompletableDeferred()
83
-
84
- keepJsAwakeTask.stop()
85
-
86
- resultFromJavascript.getString("clientSecret")?.let {
87
- CreateIntentResult.Success(clientSecret = it)
88
- } ?: run {
89
- val errorMap = resultFromJavascript.getMap("error")
90
- CreateIntentResult.Failure(
91
- cause = Exception(errorMap?.getString("message")),
92
- displayMessage = errorMap?.getString("localizedMessage"),
93
- )
94
- }
95
- },
96
- resultCallback = { result ->
97
- val map =
98
- Arguments.createMap().apply {
99
- when (result) {
100
- is EmbeddedPaymentElement.Result.Completed -> {
101
- putString("status", "completed")
102
- }
103
- is EmbeddedPaymentElement.Result.Canceled -> {
104
- putString("status", "canceled")
59
+ @Composable
60
+ override fun Content() {
61
+ val type by remember { rowSelectionBehaviorType }
62
+ val builder =
63
+ remember(type) {
64
+ EmbeddedPaymentElement
65
+ .Builder(
66
+ createIntentCallback = { paymentMethod, shouldSavePaymentMethod ->
67
+ val stripeSdkModule =
68
+ try {
69
+ requireStripeSdkModule()
70
+ } catch (ex: IllegalArgumentException) {
71
+ return@Builder CreateIntentResult.Failure(
72
+ cause =
73
+ Exception(
74
+ "Tried to call confirmHandler, but no callback was found. Please file an issue: https://github.com/stripe/stripe-react-native/issues",
75
+ ),
76
+ displayMessage = "An unexpected error occurred",
77
+ )
78
+ }
79
+
80
+ // Make sure that JS is active since the activity will be paused when stripe ui is presented.
81
+ val keepJsAwakeTask =
82
+ KeepJsAwakeTask(reactContext.reactApplicationContext).apply { start() }
83
+
84
+ val params =
85
+ Arguments.createMap().apply {
86
+ putMap("paymentMethod", mapFromPaymentMethod(paymentMethod))
87
+ putBoolean("shouldSavePaymentMethod", shouldSavePaymentMethod)
88
+ }
89
+
90
+ stripeSdkModule.emitOnConfirmHandlerCallback(params)
91
+
92
+ val resultFromJavascript = stripeSdkModule.embeddedIntentCreationCallback.await()
93
+ // reset the completable
94
+ stripeSdkModule.embeddedIntentCreationCallback = CompletableDeferred()
95
+
96
+ keepJsAwakeTask.stop()
97
+
98
+ resultFromJavascript.getString("clientSecret")?.let {
99
+ CreateIntentResult.Success(clientSecret = it)
100
+ } ?: run {
101
+ val errorMap = resultFromJavascript.getMap("error")
102
+ CreateIntentResult.Failure(
103
+ cause = Exception(errorMap?.getString("message")),
104
+ displayMessage = errorMap?.getString("localizedMessage"),
105
+ )
105
106
  }
106
- is EmbeddedPaymentElement.Result.Failed -> {
107
- putString("status", "failed")
108
- putString("error", result.error.message ?: "Unknown error")
107
+ },
108
+ resultCallback = { result ->
109
+ val map =
110
+ Arguments.createMap().apply {
111
+ when (result) {
112
+ is EmbeddedPaymentElement.Result.Completed -> {
113
+ putString("status", "completed")
114
+ }
115
+
116
+ is EmbeddedPaymentElement.Result.Canceled -> {
117
+ putString("status", "canceled")
118
+ }
119
+
120
+ is EmbeddedPaymentElement.Result.Failed -> {
121
+ putString("status", "failed")
122
+ putString("error", result.error.message ?: "Unknown error")
123
+ }
124
+ }
125
+ }
126
+ requireStripeSdkModule().emitEmbeddedPaymentElementFormSheetConfirmComplete(map)
127
+ },
128
+ ).rowSelectionBehavior(
129
+ if (type == RowSelectionBehaviorType.Default) {
130
+ EmbeddedPaymentElement.RowSelectionBehavior.default()
131
+ } else {
132
+ EmbeddedPaymentElement.RowSelectionBehavior.immediateAction {
133
+ requireStripeSdkModule().emitEmbeddedPaymentElementRowSelectionImmediateAction()
109
134
  }
110
- }
111
- }
112
- requireStripeSdkModule().emitEmbeddedPaymentElementFormSheetConfirmComplete(map)
113
- },
114
- )
115
- }
135
+ },
136
+ )
137
+ }
116
138
 
117
- @Composable
118
- override fun Content() {
119
139
  val embedded = rememberEmbeddedPaymentElement(builder)
120
140
  var height by remember {
121
141
  mutableIntStateOf(0)
@@ -21,10 +21,8 @@ import com.reactnativestripesdk.utils.mapToPreferredNetworks
21
21
  import com.reactnativestripesdk.utils.toBundleObject
22
22
  import com.stripe.android.ExperimentalAllowsRemovalOfLastSavedPaymentMethodApi
23
23
  import com.stripe.android.paymentelement.EmbeddedPaymentElement
24
- import com.stripe.android.paymentelement.ExperimentalEmbeddedPaymentElementApi
25
24
  import com.stripe.android.paymentsheet.PaymentSheet
26
25
 
27
- @OptIn(ExperimentalEmbeddedPaymentElementApi::class)
28
26
  @ReactModule(name = EmbeddedPaymentElementViewManager.NAME)
29
27
  class EmbeddedPaymentElementViewManager :
30
28
  ViewGroupManager<EmbeddedPaymentElementView>(),
@@ -54,6 +52,9 @@ class EmbeddedPaymentElementViewManager :
54
52
  view: EmbeddedPaymentElementView,
55
53
  cfg: Dynamic,
56
54
  ) {
55
+ val rowSelectionBehaviorType = parseRowSelectionBehavior(cfg.asMap())
56
+ view.rowSelectionBehaviorType.value = rowSelectionBehaviorType
57
+
57
58
  val elementConfig = parseElementConfiguration(cfg.asMap(), view.context)
58
59
  view.latestElementConfig = elementConfig
59
60
  // if intentConfig is already set, configure immediately:
@@ -190,6 +191,21 @@ class EmbeddedPaymentElementViewManager :
190
191
  return configurationBuilder.build()
191
192
  }
192
193
 
194
+ private fun parseRowSelectionBehavior(map: ReadableMap): RowSelectionBehaviorType {
195
+ val rowSelectionBehavior =
196
+ map
197
+ .getMap("rowSelectionBehavior")
198
+ ?.getString("type")
199
+ ?.let { type ->
200
+ when (type) {
201
+ "immediateAction" -> RowSelectionBehaviorType.ImmediateAction
202
+ else -> RowSelectionBehaviorType.Default
203
+ }
204
+ }
205
+ ?: RowSelectionBehaviorType.Default
206
+ return rowSelectionBehavior
207
+ }
208
+
193
209
  private fun parseIntentConfiguration(map: ReadableMap): PaymentSheet.IntentConfiguration {
194
210
  val intentConfig = PaymentSheetFragment.buildIntentConfiguration(toBundleObject(map))
195
211
  return intentConfig ?: throw IllegalArgumentException("IntentConfiguration is null")
@@ -2,13 +2,11 @@ import com.facebook.react.bridge.Arguments
2
2
  import com.facebook.react.bridge.WritableMap
3
3
  import com.reactnativestripesdk.utils.mapFromPaymentSheetBillingDetails
4
4
  import com.stripe.android.paymentelement.EmbeddedPaymentElement
5
- import com.stripe.android.paymentelement.ExperimentalEmbeddedPaymentElementApi
6
5
 
7
6
  /**
8
7
  * Serialize Stripe's PaymentOptionDisplayData into a WritableMap
9
8
  * that can be sent over the RN bridge.
10
9
  */
11
- @OptIn(ExperimentalEmbeddedPaymentElementApi::class)
12
10
  fun EmbeddedPaymentElement.PaymentOptionDisplayData.toWritableMap(): WritableMap =
13
11
  Arguments.createMap().apply {
14
12
  putString("label", label)
@@ -6,7 +6,7 @@ import android.content.res.Configuration
6
6
  import android.graphics.Color
7
7
  import android.os.Bundle
8
8
  import com.reactnativestripesdk.utils.PaymentSheetAppearanceException
9
- import com.stripe.android.paymentelement.ExperimentalEmbeddedPaymentElementApi
9
+ import com.stripe.android.paymentelement.AppearanceAPIAdditionsPreview
10
10
  import com.stripe.android.paymentsheet.PaymentSheet
11
11
  import com.stripe.android.uicore.StripeThemeDefaults
12
12
 
@@ -57,6 +57,7 @@ fun buildPaymentSheetAppearance(
57
57
  )
58
58
  }
59
59
 
60
+ @OptIn(AppearanceAPIAdditionsPreview::class)
60
61
  private fun buildTypography(
61
62
  fontParams: Bundle?,
62
63
  context: Context,
@@ -244,7 +245,6 @@ private fun buildPrimaryButtonColors(
244
245
  ),
245
246
  )
246
247
 
247
- @OptIn(ExperimentalEmbeddedPaymentElementApi::class)
248
248
  @SuppressLint("RestrictedApi")
249
249
  @Throws(PaymentSheetAppearanceException::class)
250
250
  private fun buildEmbeddedAppearance(
@@ -341,7 +341,7 @@ private fun buildEmbeddedAppearance(
341
341
  val checkmarkParams = getBundleOrNull(flatParams, PaymentSheetAppearanceKeys.CHECKMARK)
342
342
  val separatorInsetsParams = getBundleOrNull(flatParams, PaymentSheetAppearanceKeys.SEPARATOR_INSETS)
343
343
 
344
- // Default separator insets specific to FlatWithCheckmark
344
+ // Default separator insets specific to FlatWithCheckmark and FlatWithChevron
345
345
  val defaultSeparatorStartInsetDp = 0.0f
346
346
  val defaultSeparatorEndInsetDp = 0.0f
347
347
 
@@ -392,6 +392,59 @@ private fun buildEmbeddedAppearance(
392
392
  colorsDark = flatCheckmarkColors,
393
393
  )
394
394
  }
395
+ "flatWithChevron" -> {
396
+ val flatParams = getBundleOrNull(rowParams, PaymentSheetAppearanceKeys.FLAT)
397
+ val chevronParams = getBundleOrNull(flatParams, PaymentSheetAppearanceKeys.CHEVRON)
398
+ val separatorInsetsParams = getBundleOrNull(flatParams, PaymentSheetAppearanceKeys.SEPARATOR_INSETS)
399
+
400
+ // Default separator insets specific to FlatWithCheckmark and FlatWithChevron
401
+ val defaultSeparatorStartInsetDp = 0.0f
402
+ val defaultSeparatorEndInsetDp = 0.0f
403
+
404
+ // Parse dimensions as Floats
405
+ val separatorThickness = getFloatOr(flatParams, PaymentSheetAppearanceKeys.SEPARATOR_THICKNESS, defaultSeparatorThicknessDp)
406
+ val startSeparatorInset = getFloatOr(separatorInsetsParams, PaymentSheetAppearanceKeys.LEFT, defaultSeparatorStartInsetDp)
407
+ val endSeparatorInset = getFloatOr(separatorInsetsParams, PaymentSheetAppearanceKeys.RIGHT, defaultSeparatorEndInsetDp)
408
+
409
+ // Parse booleans
410
+ val topEnabled = getBooleanOr(flatParams, PaymentSheetAppearanceKeys.TOP_SEPARATOR_ENABLED, true)
411
+ val bottomEnabled = getBooleanOr(flatParams, PaymentSheetAppearanceKeys.BOTTOM_SEPARATOR_ENABLED, true)
412
+
413
+ val parsedSeparatorColor =
414
+ dynamicColorFromParams(
415
+ context,
416
+ flatParams,
417
+ PaymentSheetAppearanceKeys.SEPARATOR_COLOR,
418
+ Color.GRAY,
419
+ )
420
+
421
+ val parsedChevronColor =
422
+ dynamicColorFromParams(
423
+ context,
424
+ chevronParams,
425
+ PaymentSheetAppearanceKeys.COLOR,
426
+ defaultColors.componentBorder, // Default to component border color like other elements
427
+ )
428
+
429
+ // Create the required Colors object
430
+ val flatChevronColors =
431
+ PaymentSheet.Appearance.Embedded.RowStyle.FlatWithChevron.Colors(
432
+ separatorColor = parsedSeparatorColor,
433
+ chevronColor = parsedChevronColor,
434
+ )
435
+
436
+ PaymentSheet.Appearance.Embedded.RowStyle.FlatWithChevron(
437
+ separatorThicknessDp = separatorThickness,
438
+ startSeparatorInsetDp = startSeparatorInset,
439
+ endSeparatorInsetDp = endSeparatorInset,
440
+ topSeparatorEnabled = topEnabled,
441
+ bottomSeparatorEnabled = bottomEnabled,
442
+ additionalVerticalInsetsDp = additionalInsets,
443
+ horizontalInsetsDp = 0.0F, // We do not have an iOS equal for this API so it's not configurable in React Native
444
+ colorsLight = flatChevronColors,
445
+ colorsDark = flatChevronColors,
446
+ )
447
+ }
395
448
  "floatingButton" -> {
396
449
  val floatingParams = getBundleOrNull(rowParams, PaymentSheetAppearanceKeys.FLOATING)
397
450
  PaymentSheet.Appearance.Embedded.RowStyle.FloatingButton(
@@ -606,6 +659,7 @@ private class PaymentSheetAppearanceKeys {
606
659
  const val SELECTED_COLOR = "selectedColor"
607
660
  const val UNSELECTED_COLOR = "unselectedColor"
608
661
  const val CHECKMARK = "checkmark"
662
+ const val CHEVRON = "chevron"
609
663
  const val COLOR = "color"
610
664
  const val CHECKMARK_INSET = "inset"
611
665
 
@@ -32,6 +32,8 @@ import com.reactnativestripesdk.utils.mapFromPaymentMethod
32
32
  import com.reactnativestripesdk.utils.mapToPreferredNetworks
33
33
  import com.reactnativestripesdk.utils.removeFragment
34
34
  import com.stripe.android.ExperimentalAllowsRemovalOfLastSavedPaymentMethodApi
35
+ import com.stripe.android.model.PaymentMethod
36
+ import com.stripe.android.paymentelement.PaymentMethodOptionsSetupFutureUsagePreview
35
37
  import com.stripe.android.paymentsheet.CreateIntentCallback
36
38
  import com.stripe.android.paymentsheet.CreateIntentResult
37
39
  import com.stripe.android.paymentsheet.ExperimentalCustomerSessionApi
@@ -518,6 +520,7 @@ class PaymentSheetFragment : StripeFragment() {
518
520
  )
519
521
  }
520
522
 
523
+ @OptIn(PaymentMethodOptionsSetupFutureUsagePreview::class)
521
524
  private fun buildIntentConfigurationMode(modeParams: Bundle): PaymentSheet.IntentConfiguration.Mode {
522
525
  val currencyCode =
523
526
  modeParams.getString("currencyCode")
@@ -531,6 +534,7 @@ class PaymentSheetFragment : StripeFragment() {
531
534
  currency = currencyCode,
532
535
  setupFutureUse = mapToSetupFutureUse(modeParams.getString("setupFutureUsage")),
533
536
  captureMethod = mapToCaptureMethod(modeParams.getString("captureMethod")),
537
+ paymentMethodOptions = mapToPaymentMethodOptions(modeParams.getBundle("paymentMethodOptions")),
534
538
  )
535
539
  } else {
536
540
  val setupFutureUsage =
@@ -639,6 +643,7 @@ fun mapToSetupFutureUse(type: String?): PaymentSheet.IntentConfiguration.SetupFu
639
643
  when (type) {
640
644
  "OffSession" -> PaymentSheet.IntentConfiguration.SetupFutureUse.OffSession
641
645
  "OnSession" -> PaymentSheet.IntentConfiguration.SetupFutureUse.OnSession
646
+ "None" -> PaymentSheet.IntentConfiguration.SetupFutureUse.None
642
647
  else -> null
643
648
  }
644
649
 
@@ -650,6 +655,26 @@ fun mapToCaptureMethod(type: String?): PaymentSheet.IntentConfiguration.CaptureM
650
655
  else -> PaymentSheet.IntentConfiguration.CaptureMethod.Automatic
651
656
  }
652
657
 
658
+ @OptIn(PaymentMethodOptionsSetupFutureUsagePreview::class)
659
+ fun mapToPaymentMethodOptions(options: Bundle?): PaymentSheet.IntentConfiguration.Mode.Payment.PaymentMethodOptions? {
660
+ val sfuBundle = options?.getBundle("setupFutureUsageValues")
661
+ val paymentMethodToSfuMap = mutableMapOf<PaymentMethod.Type, PaymentSheet.IntentConfiguration.SetupFutureUse>()
662
+ sfuBundle?.keySet()?.forEach { code ->
663
+ val sfuValue = mapToSetupFutureUse(sfuBundle?.getString(code))
664
+ val paymentMethodType = PaymentMethod.Type.fromCode(code)
665
+ if (paymentMethodType != null && sfuValue != null) {
666
+ paymentMethodToSfuMap[paymentMethodType] = sfuValue
667
+ }
668
+ }
669
+ return if (paymentMethodToSfuMap.isNotEmpty()) {
670
+ PaymentSheet.IntentConfiguration.Mode.Payment.PaymentMethodOptions(
671
+ setupFutureUsageValues = paymentMethodToSfuMap,
672
+ )
673
+ } else {
674
+ null
675
+ }
676
+ }
677
+
653
678
  fun mapToCardBrandAcceptance(params: Bundle?): PaymentSheet.CardBrandAcceptance {
654
679
  val cardBrandAcceptanceParams = params?.getBundle("cardBrandAcceptance") ?: return PaymentSheet.CardBrandAcceptance.all()
655
680
  val filter = cardBrandAcceptanceParams.getString("filter") ?: return PaymentSheet.CardBrandAcceptance.all()
@@ -185,6 +185,8 @@ internal class PaymentSheetAppearance {
185
185
  row.style = .floatingButton
186
186
  case PaymentSheetAppearanceKeys.ROW_STYLE_FLAT_WITH_CHECKMARK:
187
187
  row.style = .flatWithCheckmark
188
+ case PaymentSheetAppearanceKeys.ROW_STYLE_FLAT_WITH_CHEVRON:
189
+ row.style = .flatWithChevron
188
190
  default:
189
191
  throw PaymentSheetAppearanceError.invalidRowStyle(styleString)
190
192
  }
@@ -239,6 +241,10 @@ internal class PaymentSheetAppearance {
239
241
  flat.checkmark = try buildEmbeddedCheckmark(params: checkmarkParams)
240
242
  }
241
243
 
244
+ if let chevronParams = params[PaymentSheetAppearanceKeys.CHEVRON] as? NSDictionary {
245
+ flat.chevron = try buildEmbeddedChevron(params: chevronParams)
246
+ }
247
+
242
248
  return flat
243
249
  }
244
250
 
@@ -277,6 +283,19 @@ internal class PaymentSheetAppearance {
277
283
  return checkmark
278
284
  }
279
285
 
286
+ private class func buildEmbeddedChevron(params: NSDictionary) throws -> PaymentSheet.Appearance.EmbeddedPaymentElement.Row.Flat.Chevron {
287
+ var chevron = PaymentSheet.Appearance.default.embeddedPaymentElement.row.flat.chevron
288
+
289
+ if let colorHexes = params[PaymentSheetAppearanceKeys.COLOR] as? [String: String] {
290
+ chevron.color = dynamicColor(
291
+ from: colorHexes,
292
+ default: UIColor.systemGray // Default iOS system gray color
293
+ )
294
+ }
295
+
296
+ return chevron
297
+ }
298
+
280
299
  private class func buildEmbeddedFloating(params: NSDictionary) throws -> PaymentSheet.Appearance.EmbeddedPaymentElement.Row.Floating {
281
300
  var floating = PaymentSheet.Appearance.default.embeddedPaymentElement.row.floating
282
301
 
@@ -354,7 +373,7 @@ extension PaymentSheetAppearanceError: LocalizedError {
354
373
  case .unexpectedHexStringLength(let hexString):
355
374
  return NSLocalizedString("Failed to set Payment Sheet appearance. Expected hex string of length 6 or 8, but received: \(hexString)", comment: "Failed to set color")
356
375
  case .invalidRowStyle(let styleString):
357
- return NSLocalizedString("Failed to set Embedded Payment Element appearance. Invalid row style '\(styleString)'. Expected one of: 'flatWithRadio', 'floatingButton', 'flatWithCheckmark'.", comment: "Invalid row style string")
376
+ return NSLocalizedString("Failed to set Embedded Payment Element appearance. Invalid row style '\(styleString)'. Expected one of: 'flatWithRadio', 'floatingButton', 'flatWithCheckmark', 'flatWithChevron'.", comment: "Invalid row style string")
358
377
  }
359
378
  }
360
379
  }
@@ -411,6 +430,7 @@ private struct PaymentSheetAppearanceKeys {
411
430
  static let SELECTED_COLOR = "selectedColor"
412
431
  static let UNSELECTED_COLOR = "unselectedColor"
413
432
  static let CHECKMARK = "checkmark"
433
+ static let CHEVRON = "chevron"
414
434
  static let SPACING = "spacing"
415
435
  static let TOP = "top"
416
436
  static let LEFT = "left"
@@ -422,6 +442,7 @@ private struct PaymentSheetAppearanceKeys {
422
442
  static let ROW_STYLE_FLAT_WITH_RADIO = "flatWithRadio"
423
443
  static let ROW_STYLE_FLOATING_BUTTON = "floatingButton"
424
444
  static let ROW_STYLE_FLAT_WITH_CHECKMARK = "flatWithCheckmark"
445
+ static let ROW_STYLE_FLAT_WITH_CHEVRON = "flatWithChevron"
425
446
 
426
447
  static let FORM_INSETS = "formInsetValues"
427
448
  }
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <Workspace
3
+ version = "1.0">
4
+ <FileRef
5
+ location = "self:">
6
+ </FileRef>
7
+ </Workspace>
@@ -0,0 +1,19 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>SchemeUserState</key>
6
+ <dict>
7
+ <key>StripeSdk.xcscheme_^#shared#^_</key>
8
+ <dict>
9
+ <key>orderHint</key>
10
+ <integer>1</integer>
11
+ </dict>
12
+ <key>Tests.xcscheme_^#shared#^_</key>
13
+ <dict>
14
+ <key>orderHint</key>
15
+ <integer>0</integer>
16
+ </dict>
17
+ </dict>
18
+ </dict>
19
+ </plist>
@@ -6,7 +6,7 @@
6
6
  //
7
7
 
8
8
  import Foundation
9
- @_spi(ExperimentalAllowsRemovalOfLastSavedPaymentMethodAPI) @_spi(CustomerSessionBetaAccess) @_spi(EmbeddedPaymentElementPrivateBeta) @_spi(STP) import StripePaymentSheet
9
+ @_spi(ExperimentalAllowsRemovalOfLastSavedPaymentMethodAPI) @_spi(CustomerSessionBetaAccess) @_spi(EmbeddedPaymentElementPrivateBeta) @_spi(STP) @_spi(PaymentMethodOptionsSetupFutureUsagePreview) import StripePaymentSheet
10
10
 
11
11
  extension StripeSdkImpl {
12
12
  internal func buildPaymentSheetConfiguration(
@@ -290,10 +290,9 @@ extension StripeSdkImpl {
290
290
  mode = PaymentSheet.IntentConfiguration.Mode.payment(
291
291
  amount: amount,
292
292
  currency: modeParams["currencyCode"] as? String ?? "",
293
- setupFutureUsage: modeParams["setupFutureUsage"] != nil
294
- ? (modeParams["setupFutureUsage"] as? String == "OffSession" ? .offSession : .onSession)
295
- : nil,
296
- captureMethod: captureMethod
293
+ setupFutureUsage: setupFutureUsageFromString(from: modeParams["setupFutureUsage"] as? String ?? ""),
294
+ captureMethod: captureMethod,
295
+ paymentMethodOptions: buildPaymentMethodOptions(paymentMethodOptionsParams: modeParams["paymentMethodOptions"] as? NSDictionary ?? [:])
297
296
  )
298
297
  } else {
299
298
  mode = PaymentSheet.IntentConfiguration.Mode.setup(
@@ -313,6 +312,45 @@ extension StripeSdkImpl {
313
312
  ])
314
313
  })
315
314
  }
315
+
316
+ func buildPaymentMethodOptions(paymentMethodOptionsParams: NSDictionary) -> PaymentSheet.IntentConfiguration.Mode.PaymentMethodOptions? {
317
+ if let sfuDictionary = paymentMethodOptionsParams["setupFutureUsageValues"] as? NSDictionary {
318
+ var setupFutureUsageValues: [STPPaymentMethodType: PaymentSheet.IntentConfiguration.SetupFutureUsage] = [:]
319
+
320
+ for (paymentMethodCode, sfuValue) in sfuDictionary {
321
+ if let paymentMethodCode = paymentMethodCode as? String,
322
+ let sfuString = sfuValue as? String {
323
+ let setupFutureUsage = setupFutureUsageFromString(from: sfuString)
324
+ let paymentMethodType = STPPaymentMethodType.fromIdentifier(paymentMethodCode)
325
+
326
+ if let setupFutureUsage = setupFutureUsage {
327
+ if paymentMethodType != .unknown {
328
+ setupFutureUsageValues[paymentMethodType] = setupFutureUsage
329
+ }
330
+ }
331
+ }
332
+ }
333
+
334
+ if !setupFutureUsageValues.isEmpty {
335
+ return PaymentSheet.IntentConfiguration.Mode.PaymentMethodOptions(setupFutureUsageValues: setupFutureUsageValues)
336
+ }
337
+ }
338
+
339
+ return nil
340
+ }
341
+
342
+ func setupFutureUsageFromString(from string: String) -> PaymentSheet.IntentConfiguration.SetupFutureUsage? {
343
+ switch string {
344
+ case "OnSession":
345
+ return PaymentSheet.IntentConfiguration.SetupFutureUsage.onSession
346
+ case "OffSession":
347
+ return PaymentSheet.IntentConfiguration.SetupFutureUsage.offSession
348
+ case "None":
349
+ return PaymentSheet.IntentConfiguration.SetupFutureUsage.none
350
+ default:
351
+ return nil
352
+ }
353
+ }
316
354
 
317
355
  func buildCustomerHandlersForPaymentSheet(applePayParams: NSDictionary) -> PaymentSheet.ApplePayConfiguration.Handlers? {
318
356
  if (applePayParams["request"] == nil) {
@@ -1,5 +1,5 @@
1
1
  import PassKit
2
- import Stripe
2
+ @_spi(DashboardOnly) @_spi(STP) import Stripe
3
3
  @_spi(EmbeddedPaymentElementPrivateBeta) import StripePaymentSheet
4
4
  import StripeFinancialConnections
5
5
  import Foundation
@@ -94,6 +94,10 @@ public class StripeSdkImpl: NSObject, UIAdaptivePresentationControllerDelegate {
94
94
  StripeAPI.defaultPublishableKey = publishableKey
95
95
  STPAPIClient.shared.stripeAccount = stripeAccountId
96
96
 
97
+ if STPAPIClient.shared.publishableKeyIsUserKey {
98
+ STPAPIClient.shared.userKeyLiveMode = UserDefaults.standard.object(forKey: "stripe_userKeyLiveMode") as? Bool ?? true
99
+ }
100
+
97
101
  let name = appInfo["name"] as? String ?? ""
98
102
  let partnerId = appInfo["partnerId"] as? String ?? ""
99
103
  let version = appInfo["version"] as? String ?? ""
@@ -1,2 +1,2 @@
1
- var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.AddToWalletButton=AddToWalletButton;var _objectWithoutProperties2=_interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));var _react=_interopRequireDefault(require("react"));var _NativeAddToWalletButton=_interopRequireDefault(require("../specs/NativeAddToWalletButton"));var _jsxRuntime=require("react/jsx-runtime");var _jsxFileName="/Users/porter/stripe/stripe-react-native/src/components/AddToWalletButton.tsx";var _excluded=["onComplete"];function AddToWalletButton(_ref){var onComplete=_ref.onComplete,props=(0,_objectWithoutProperties2.default)(_ref,_excluded);return(0,_jsxRuntime.jsx)(_NativeAddToWalletButton.default,Object.assign({},props,{onCompleteAction:function onCompleteAction(value){return onComplete(value.nativeEvent);}}));}
1
+ var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.AddToWalletButton=AddToWalletButton;var _objectWithoutProperties2=_interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));var _react=_interopRequireDefault(require("react"));var _NativeAddToWalletButton=_interopRequireDefault(require("../specs/NativeAddToWalletButton"));var _jsxRuntime=require("react/jsx-runtime");var _jsxFileName="/Users/wooj/stripe/stripe-react-native/src/components/AddToWalletButton.tsx";var _excluded=["onComplete"];function AddToWalletButton(_ref){var onComplete=_ref.onComplete,props=(0,_objectWithoutProperties2.default)(_ref,_excluded);return(0,_jsxRuntime.jsx)(_NativeAddToWalletButton.default,Object.assign({},props,{onCompleteAction:function onCompleteAction(value){return onComplete(value.nativeEvent);}}));}
2
2
  //# sourceMappingURL=AddToWalletButton.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["_react","_interopRequireDefault","require","_NativeAddToWalletButton","_jsxRuntime","_jsxFileName","_excluded","AddToWalletButton","_ref","onComplete","props","_objectWithoutProperties2","default","jsx","Object","assign","onCompleteAction","value","nativeEvent"],"sourceRoot":"../../../src","sources":["components/AddToWalletButton.tsx"],"mappings":"wSAAA,IAAAA,MAAA,CAAAC,sBAAA,CAAAC,OAAA,WAcA,IAAAC,wBAAA,CAAAF,sBAAA,CAAAC,OAAA,sCAAuE,IAAAE,WAAA,CAAAF,OAAA,0BAAAG,YAAA,qFAAAC,SAAA,gBAgEhE,QAAS,CAAAC,iBAAiBA,CAAAC,IAAA,CAAkC,IAA/B,CAAAC,UAAU,CAAAD,IAAA,CAAVC,UAAU,CAAKC,KAAK,IAAAC,yBAAA,CAAAC,OAAA,EAAAJ,IAAA,CAAAF,SAAA,EACtD,MACE,GAAAF,WAAA,CAAAS,GAAA,EAACV,wBAAA,CAAAS,OAAuB,CAAAE,MAAA,CAAAC,MAAA,IAClBL,KAAK,EACTM,gBAAgB,CAAE,QAAlB,CAAAA,gBAAgBA,CACdC,KAEE,QACC,CAAAR,UAAU,CAACQ,KAAK,CAACC,WAAW,CAAC,EAAC,EACpC,CAAC,CAEN","ignoreList":[]}
1
+ {"version":3,"names":["_react","_interopRequireDefault","require","_NativeAddToWalletButton","_jsxRuntime","_jsxFileName","_excluded","AddToWalletButton","_ref","onComplete","props","_objectWithoutProperties2","default","jsx","Object","assign","onCompleteAction","value","nativeEvent"],"sourceRoot":"../../../src","sources":["components/AddToWalletButton.tsx"],"mappings":"wSAAA,IAAAA,MAAA,CAAAC,sBAAA,CAAAC,OAAA,WAcA,IAAAC,wBAAA,CAAAF,sBAAA,CAAAC,OAAA,sCAAuE,IAAAE,WAAA,CAAAF,OAAA,0BAAAG,YAAA,mFAAAC,SAAA,gBAgEhE,QAAS,CAAAC,iBAAiBA,CAAAC,IAAA,CAAkC,IAA/B,CAAAC,UAAU,CAAAD,IAAA,CAAVC,UAAU,CAAKC,KAAK,IAAAC,yBAAA,CAAAC,OAAA,EAAAJ,IAAA,CAAAF,SAAA,EACtD,MACE,GAAAF,WAAA,CAAAS,GAAA,EAACV,wBAAA,CAAAS,OAAuB,CAAAE,MAAA,CAAAC,MAAA,IAClBL,KAAK,EACTM,gBAAgB,CAAE,QAAlB,CAAAA,gBAAgBA,CACdC,KAEE,QACC,CAAAR,UAAU,CAACQ,KAAK,CAACC,WAAW,CAAC,EAAC,EACpC,CAAC,CAEN","ignoreList":[]}
@@ -1,2 +1,2 @@
1
- var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.AddressSheet=AddressSheet;var _objectWithoutProperties2=_interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));var _react=_interopRequireDefault(require("react"));var _NativeAddressSheet=_interopRequireDefault(require("../specs/NativeAddressSheet"));var _jsxRuntime=require("react/jsx-runtime");var _jsxFileName="/Users/porter/stripe/stripe-react-native/src/components/AddressSheet.tsx";var _excluded=["onSubmit","onError"];function AddressSheet(_ref){var onSubmit=_ref.onSubmit,onError=_ref.onError,props=(0,_objectWithoutProperties2.default)(_ref,_excluded);return(0,_jsxRuntime.jsx)(_NativeAddressSheet.default,Object.assign({},props,{onSubmitAction:function onSubmitAction(event){return onSubmit(event.nativeEvent.result);},onErrorAction:function onErrorAction(event){return onError(event.nativeEvent.error);}}));}
1
+ var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.AddressSheet=AddressSheet;var _objectWithoutProperties2=_interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));var _react=_interopRequireDefault(require("react"));var _NativeAddressSheet=_interopRequireDefault(require("../specs/NativeAddressSheet"));var _jsxRuntime=require("react/jsx-runtime");var _jsxFileName="/Users/wooj/stripe/stripe-react-native/src/components/AddressSheet.tsx";var _excluded=["onSubmit","onError"];function AddressSheet(_ref){var onSubmit=_ref.onSubmit,onError=_ref.onError,props=(0,_objectWithoutProperties2.default)(_ref,_excluded);return(0,_jsxRuntime.jsx)(_NativeAddressSheet.default,Object.assign({},props,{onSubmitAction:function onSubmitAction(event){return onSubmit(event.nativeEvent.result);},onErrorAction:function onErrorAction(event){return onError(event.nativeEvent.error);}}));}
2
2
  //# sourceMappingURL=AddressSheet.js.map