@stripe/stripe-react-native 0.50.0 → 0.50.2

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 (61) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/CLAUDE.md +148 -0
  3. package/android/gradle.properties +1 -1
  4. package/android/src/main/java/com/reactnativestripesdk/EmbeddedPaymentElementViewManager.kt +10 -4
  5. package/android/src/main/java/com/reactnativestripesdk/PaymentSheetAppearance.kt +58 -29
  6. package/android/src/main/java/com/reactnativestripesdk/PaymentSheetFragment.kt +9 -11
  7. package/android/src/main/java/com/reactnativestripesdk/customersheet/CustomerSheetFragment.kt +1 -1
  8. package/android/src/main/java/com/reactnativestripesdk/pushprovisioning/AddToWalletButtonManager.kt +6 -2
  9. package/ios/PaymentSheetAppearance.swift +95 -77
  10. package/ios/StripeSdkImpl.swift +6 -0
  11. package/lib/commonjs/components/AddToWalletButton.js +1 -1
  12. package/lib/commonjs/components/AddToWalletButton.js.map +1 -1
  13. package/lib/commonjs/components/AddressSheet.js +1 -1
  14. package/lib/commonjs/components/AddressSheet.js.map +1 -1
  15. package/lib/commonjs/components/AuBECSDebitForm.js +1 -1
  16. package/lib/commonjs/components/AuBECSDebitForm.js.map +1 -1
  17. package/lib/commonjs/components/CardField.js +1 -1
  18. package/lib/commonjs/components/CardField.js.map +1 -1
  19. package/lib/commonjs/components/CardForm.js +1 -1
  20. package/lib/commonjs/components/CardForm.js.map +1 -1
  21. package/lib/commonjs/components/PlatformPayButton.js +1 -1
  22. package/lib/commonjs/components/PlatformPayButton.js.map +1 -1
  23. package/lib/commonjs/components/StripeContainer.js +1 -1
  24. package/lib/commonjs/components/StripeContainer.js.map +1 -1
  25. package/lib/commonjs/functions.js +1 -1
  26. package/lib/commonjs/functions.js.map +1 -1
  27. package/lib/commonjs/types/EmbeddedPaymentElement.js +1 -1
  28. package/lib/commonjs/types/EmbeddedPaymentElement.js.map +1 -1
  29. package/lib/commonjs/types/PaymentSheet.js +1 -1
  30. package/lib/commonjs/types/PaymentSheet.js.map +1 -1
  31. package/lib/module/components/AddToWalletButton.js +1 -1
  32. package/lib/module/components/AddToWalletButton.js.map +1 -1
  33. package/lib/module/components/AddressSheet.js +1 -1
  34. package/lib/module/components/AddressSheet.js.map +1 -1
  35. package/lib/module/components/AuBECSDebitForm.js +1 -1
  36. package/lib/module/components/AuBECSDebitForm.js.map +1 -1
  37. package/lib/module/components/CardField.js +1 -1
  38. package/lib/module/components/CardField.js.map +1 -1
  39. package/lib/module/components/CardForm.js +1 -1
  40. package/lib/module/components/CardForm.js.map +1 -1
  41. package/lib/module/components/PlatformPayButton.js +1 -1
  42. package/lib/module/components/PlatformPayButton.js.map +1 -1
  43. package/lib/module/components/StripeContainer.js +1 -1
  44. package/lib/module/components/StripeContainer.js.map +1 -1
  45. package/lib/module/functions.js +1 -1
  46. package/lib/module/functions.js.map +1 -1
  47. package/lib/module/types/EmbeddedPaymentElement.js +1 -1
  48. package/lib/module/types/EmbeddedPaymentElement.js.map +1 -1
  49. package/lib/module/types/PaymentSheet.js +1 -1
  50. package/lib/module/types/PaymentSheet.js.map +1 -1
  51. package/lib/typescript/src/functions.d.ts.map +1 -1
  52. package/lib/typescript/src/types/EmbeddedPaymentElement.d.ts +6 -9
  53. package/lib/typescript/src/types/EmbeddedPaymentElement.d.ts.map +1 -1
  54. package/lib/typescript/src/types/PaymentSheet.d.ts +17 -9
  55. package/lib/typescript/src/types/PaymentSheet.d.ts.map +1 -1
  56. package/package.json +1 -1
  57. package/patches/old-arch-codegen-fix.patch +6 -2
  58. package/src/functions.ts +8 -18
  59. package/src/types/EmbeddedPaymentElement.tsx +6 -19
  60. package/src/types/PaymentSheet.ts +17 -9
  61. package/stripe-react-native.podspec +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.50.2 - 2025-08-06
4
+
5
+ **Changes**
6
+ - Renamed `RowStyle.FlatWithChevron` to `RowStyle.FlatWithDisclosure` and updated related interfaces (`ChevronConfig` → `DisclosureConfig`).
7
+ - Updated `stripe-ios` to 24.19.0
8
+ - Updated `stripe-android` to 21.22.+
9
+ - Added `successBackgroundColor` and `successTextColor` properties to `PrimaryButtonColorConfig` for customizing the primary button appearance in success states.
10
+
11
+ **Fixes**
12
+ - Fixed missing `onCustomPaymentMethodConfirmHandlerCallback` in old architecture codegen patch. This resolves pod install failures when using React Native 0.74+ with old architecture and custom payment methods.
13
+ - Fixes an issue where saved payment methods weren't auto selected when using `EmbeddedPaymentElement` on Android.
14
+
15
+ ## 0.50.1 - 2025-07-22
16
+
17
+ **Fixes**
18
+ - Fixed embedded payment element color support to accept both single color strings and light/dark color objects for `ThemedColor` properties (separatorColor, selectedColor, unselectedColor, checkmark color, chevron color).
19
+ - Fixed Android crash when providing partial `billingDetailsCollectionConfiguration` objects. Now gracefully handles missing fields like `attachDefaultsToPaymentMethod` by using safe accessor methods with default values.
20
+ - Fixed Android Kotlin compilation errors where nullable `ReadableMap?` was passed to functions expecting non-nullable `ReadableMap`. Added null checks in `EmbeddedPaymentElementViewManager` and `AddToWalletButtonManager`. [#1988](https://github.com/stripe/stripe-react-native/issues/1988)
21
+
3
22
  ## 0.50.0 - 2025-07-17
4
23
 
5
24
  **Features**
package/CLAUDE.md ADDED
@@ -0,0 +1,148 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Development Commands
6
+
7
+ ### Building and Linting
8
+ - `yarn typescript` - Type-check TypeScript files
9
+ - `yarn lint` - Lint code with ESLint
10
+ - `yarn lint --fix` - Fix linting issues automatically
11
+ - `yarn test` - Run Jest unit tests
12
+ - `yarn prepare` - Build the library (runs `bob build && husky`)
13
+
14
+ ### Development Setup
15
+ - `yarn bootstrap` - Setup project by installing dependencies and CocoaPods
16
+ - `yarn bootstrap-no-pods` - Setup without installing CocoaPods
17
+ - `yarn pods` - Install CocoaPods for iOS (example app)
18
+ - `yarn update-pods` - Update specific Stripe pod dependencies
19
+
20
+ ### Example App Development Workflow
21
+ 1. **Setup**: `yarn bootstrap`
22
+ 2. **Run Example App** (requires 2 terminals):
23
+ - Terminal 1: `yarn example start`
24
+ - Terminal 2: `yarn example ios` OR `yarn example android`
25
+
26
+ The example app uses a pre-configured demo backend, so no server setup is required.
27
+
28
+ ### Example App Commands
29
+ - `yarn example start` - Start Metro server
30
+ - `yarn run-example-ios` - Run iOS example app on iPhone 16 simulator
31
+ - `yarn run-example-android` - Run Android example app
32
+ - `yarn run-example-ios:release` - Build and run iOS app in release mode
33
+ - `yarn run-example-android:release` - Build and run Android app in release mode
34
+
35
+ ### Testing
36
+ - `yarn test:e2e:ios` - Run all iOS E2E tests using Maestro
37
+ - `yarn test:e2e:android` - Run all Android E2E tests using Maestro
38
+ - `yarn test-ios ./path/to/test.yml` - Run single iOS E2E test
39
+ - `yarn test-android ./path/to/test.yml` - Run single Android E2E test
40
+ - `yarn test:unit:ios` - Run iOS native unit tests via Xcode
41
+ - `yarn test:unit:android` - Run Android unit tests
42
+
43
+ ### Documentation
44
+ - `yarn docs` - Generate API documentation using TypeDoc
45
+
46
+ ### Commit Convention
47
+ Follow [conventional commits](https://www.conventionalcommits.org/en):
48
+ - `fix:` - Bug fixes
49
+ - `feat:` - New features
50
+ - `refactor:` - Code refactoring
51
+ - `docs:` - Documentation changes
52
+ - `test:` - Test additions/updates
53
+ - `chore:` - Tooling changes
54
+
55
+ ## Architecture Overview
56
+
57
+ This is the official Stripe React Native SDK, providing payment processing capabilities for mobile apps.
58
+
59
+ ### Key Directories
60
+
61
+ - **`src/`** - Main TypeScript source code
62
+ - `components/` - React Native components (CardField, PaymentSheet, etc.)
63
+ - `hooks/` - React hooks for payment functionality
64
+ - `types/` - TypeScript type definitions
65
+ - `specs/` - Native module specifications for code generation
66
+ - `functions.ts` - Core payment functions
67
+ - `index.tsx` - Main exports
68
+
69
+ - **`ios/`** - Native iOS implementation in Swift/Objective-C
70
+ - Uses Stripe iOS SDK (~24.16.1)
71
+ - Supports both Old and New Architecture (Fabric)
72
+ - Test files in `ios/Tests/`
73
+
74
+ - **`android/`** - Native Android implementation in Kotlin/Java
75
+ - Uses Stripe Android SDK
76
+ - Gradle build configuration
77
+
78
+ - **`example/`** - Example React Native app demonstrating SDK usage
79
+ - Contains test server in `server/` directory
80
+ - Configured for both iOS and Android development
81
+
82
+ - **`e2e-tests/`** - End-to-end tests using Maestro framework
83
+ - Platform-specific tests in `ios-only/` and `android-only/`
84
+ - Tests payment flows, UI components, and integrations
85
+
86
+ ### Code Generation
87
+
88
+ The SDK uses React Native's TurboModules/Fabric for native communication:
89
+ - Specs defined in `src/specs/` generate native interfaces
90
+ - Both Old and New Architecture supported
91
+ - Special patch for Old Architecture compatibility in `patches/old-arch-codegen-fix.patch`
92
+
93
+ ### Build System
94
+
95
+ - **React Native Builder Bob** - Builds CommonJS, ES modules, and TypeScript declarations
96
+ - **CocoaPods** - iOS dependency management
97
+ - **Gradle** - Android build system
98
+ - **Expo Plugin** - `src/plugin/withStripe.ts` for Expo integration
99
+
100
+ ### Key Components
101
+
102
+ - **StripeProvider** - Context provider for SDK initialization
103
+ - **PaymentSheet** - Pre-built payment UI
104
+ - **CardField/CardForm** - Card input components
105
+ - **PlatformPayButton** - Apple Pay/Google Pay integration
106
+ - **CustomerSheet** - Customer payment method management
107
+ - **AddressSheet** - Address collection component
108
+
109
+ ### Testing Strategy
110
+
111
+ - **Jest** - Unit tests for TypeScript code
112
+ - **Maestro** - E2E testing framework for mobile flows
113
+ - **Native Tests** - iOS XCTest and Android instrumentation tests
114
+ - Mock implementation provided in `jest/mock.js`
115
+
116
+ ### Platform-Specific Notes
117
+
118
+ - **iOS**: Requires Xcode 14.1+, iOS 13+ deployment target
119
+ - **Android**: Requires API 21+, compileSdkVersion 34, Kotlin 2.x
120
+ - **React Native**: Compatible with 0.78+, TypeScript 5.7+
121
+ - **Expo**: Supported via plugin configuration
122
+
123
+ ### Development File Locations
124
+
125
+ - **iOS Native**: Open `example/ios/StripeSdkExample.xcworkspace` in Xcode
126
+ - Source files: `Pods > Development Pods > stripe-react-native`
127
+ - **Android Native**: Open `example/android` in Android Studio
128
+ - Source files: `reactnativestripesdk` under `Android`
129
+ - **TypeScript**: Edit files in `src/` and `example/`
130
+
131
+ ### GitHub Issue Management
132
+ - `GH_HOST=github.com gh issue list --repo stripe/stripe-react-native --limit 20` - List recent issues
133
+ - `GH_HOST=github.com gh issue view <issue_number> --repo stripe/stripe-react-native` - View specific issue
134
+ - `GH_HOST=github.com gh issue view <issue_number> --repo stripe/stripe-react-native --comments` - View issue with comments
135
+ - `GH_HOST=github.com gh issue list --repo stripe/stripe-react-native --state all --search "keyword" --limit 30` - Search ALL issues (open/closed) by keyword
136
+ - `GH_HOST=github.com gh issue create --repo stripe/stripe-react-native` - Create new issue
137
+ - `GH_HOST=github.com gh issue edit <issue_number> --repo stripe/stripe-react-native` - Edit issue
138
+ - `GH_HOST=github.com gh pr create --repo stripe/stripe-react-native` - Create pull request
139
+ - Always use `--state all` when searching to include closed/resolved issues
140
+ - Always check GitHub issues for similar problems before investigating user reports
141
+ - Use GitHub CLI to distinguish between SDK bugs vs integration issues
142
+
143
+ ### Filing PRs
144
+ When using the GitHub `gh` command, ALWAYS set `GH_HOST=github.com`. For example: `GH_HOST=github.com gh pr create --title [...]`
145
+
146
+ ### Old Architecture Compatibility
147
+
148
+ The SDK maintains compatibility with React Native's Old Architecture via `patches/old-arch-codegen-fix.patch`. This patch converts EventEmitter properties to callback functions for code generation compatibility with RN ≥ 0.74.
@@ -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.19.+
6
+ StripeSdk_stripeVersion=21.22.+
@@ -17,6 +17,7 @@ import com.reactnativestripesdk.PaymentSheetFragment.Companion.buildGooglePayCon
17
17
  import com.reactnativestripesdk.addresssheet.AddressSheetView
18
18
  import com.reactnativestripesdk.utils.PaymentSheetAppearanceException
19
19
  import com.reactnativestripesdk.utils.PaymentSheetException
20
+ import com.reactnativestripesdk.utils.getBooleanOr
20
21
  import com.reactnativestripesdk.utils.mapToPreferredNetworks
21
22
  import com.reactnativestripesdk.utils.parseCustomPaymentMethods
22
23
  import com.reactnativestripesdk.utils.toBundleObject
@@ -54,10 +55,13 @@ class EmbeddedPaymentElementViewManager :
54
55
  view: EmbeddedPaymentElementView,
55
56
  cfg: Dynamic,
56
57
  ) {
57
- val rowSelectionBehaviorType = parseRowSelectionBehavior(cfg.asMap())
58
+ val readableMap = cfg.asMap()
59
+ if (readableMap == null) return
60
+
61
+ val rowSelectionBehaviorType = parseRowSelectionBehavior(readableMap)
58
62
  view.rowSelectionBehaviorType.value = rowSelectionBehaviorType
59
63
 
60
- val elementConfig = parseElementConfiguration(cfg.asMap(), view.context)
64
+ val elementConfig = parseElementConfiguration(readableMap, view.context)
61
65
  view.latestElementConfig = elementConfig
62
66
  // if intentConfig is already set, configure immediately:
63
67
  view.latestIntentConfig?.let { intentCfg ->
@@ -74,7 +78,9 @@ class EmbeddedPaymentElementViewManager :
74
78
  view: EmbeddedPaymentElementView,
75
79
  cfg: Dynamic,
76
80
  ) {
77
- val intentConfig = parseIntentConfiguration(cfg.asMap())
81
+ val readableMap = cfg.asMap()
82
+ if (readableMap == null) return
83
+ val intentConfig = parseIntentConfiguration(readableMap)
78
84
  view.latestIntentConfig = intentConfig
79
85
  view.latestElementConfig?.let { elemCfg ->
80
86
  view.configure(elemCfg, intentConfig)
@@ -147,7 +153,7 @@ class EmbeddedPaymentElementViewManager :
147
153
  email = mapToCollectionMode(billingConfigParams?.getString("email")),
148
154
  address = mapToAddressCollectionMode(billingConfigParams?.getString("address")),
149
155
  attachDefaultsToPaymentMethod =
150
- billingConfigParams?.getBoolean("attachDefaultsToPaymentMethod") ?: false,
156
+ billingConfigParams?.getBooleanOr("attachDefaultsToPaymentMethod", false) ?: false,
151
157
  )
152
158
  val allowsRemovalOfLastSavedPaymentMethod =
153
159
  if (map.hasKey("allowsRemovalOfLastSavedPaymentMethod")) {
@@ -194,9 +194,9 @@ private fun buildPrimaryButton(
194
194
 
195
195
  return PaymentSheet.PrimaryButton(
196
196
  colorsLight =
197
- buildPrimaryButtonColors(lightColorParams, PaymentSheet.PrimaryButtonColors.defaultLight),
197
+ buildPrimaryButtonColors(lightColorParams, PaymentSheet.PrimaryButtonColors.defaultLight, context),
198
198
  colorsDark =
199
- buildPrimaryButtonColors(darkColorParams, PaymentSheet.PrimaryButtonColors.defaultDark),
199
+ buildPrimaryButtonColors(darkColorParams, PaymentSheet.PrimaryButtonColors.defaultDark, context),
200
200
  shape =
201
201
  PaymentSheet.PrimaryButtonShape(
202
202
  cornerRadiusDp =
@@ -217,6 +217,7 @@ private fun buildPrimaryButton(
217
217
  private fun buildPrimaryButtonColors(
218
218
  colorParams: Bundle,
219
219
  default: PaymentSheet.PrimaryButtonColors,
220
+ context: Context,
220
221
  ): PaymentSheet.PrimaryButtonColors =
221
222
  PaymentSheet.PrimaryButtonColors(
222
223
  background =
@@ -243,6 +244,20 @@ private fun buildPrimaryButtonColors(
243
244
  colorParams.getString(PaymentSheetAppearanceKeys.BORDER),
244
245
  default.border,
245
246
  ),
247
+ successBackgroundColor =
248
+ dynamicColorFromParams(
249
+ context,
250
+ colorParams,
251
+ PaymentSheetAppearanceKeys.SUCCESS_BACKGROUND,
252
+ default.successBackgroundColor,
253
+ ),
254
+ onSuccessBackgroundColor =
255
+ dynamicColorFromParams(
256
+ context,
257
+ colorParams,
258
+ PaymentSheetAppearanceKeys.SUCCESS_TEXT,
259
+ default.onSuccessBackgroundColor,
260
+ ),
246
261
  )
247
262
 
248
263
  @SuppressLint("RestrictedApi")
@@ -341,7 +356,7 @@ private fun buildEmbeddedAppearance(
341
356
  val checkmarkParams = getBundleOrNull(flatParams, PaymentSheetAppearanceKeys.CHECKMARK)
342
357
  val separatorInsetsParams = getBundleOrNull(flatParams, PaymentSheetAppearanceKeys.SEPARATOR_INSETS)
343
358
 
344
- // Default separator insets specific to FlatWithCheckmark and FlatWithChevron
359
+ // Default separator insets specific to FlatWithCheckmark and FlatWithDisclosure
345
360
  val defaultSeparatorStartInsetDp = 0.0f
346
361
  val defaultSeparatorEndInsetDp = 0.0f
347
362
 
@@ -392,12 +407,12 @@ private fun buildEmbeddedAppearance(
392
407
  colorsDark = flatCheckmarkColors,
393
408
  )
394
409
  }
395
- "flatWithChevron" -> {
410
+ "flatWithDisclosure" -> {
396
411
  val flatParams = getBundleOrNull(rowParams, PaymentSheetAppearanceKeys.FLAT)
397
- val chevronParams = getBundleOrNull(flatParams, PaymentSheetAppearanceKeys.CHEVRON)
412
+ val disclosureParams = getBundleOrNull(flatParams, PaymentSheetAppearanceKeys.DISCLOSURE)
398
413
  val separatorInsetsParams = getBundleOrNull(flatParams, PaymentSheetAppearanceKeys.SEPARATOR_INSETS)
399
414
 
400
- // Default separator insets specific to FlatWithCheckmark and FlatWithChevron
415
+ // Default separator insets specific to FlatWithCheckmark and FlatWithDisclosure
401
416
  val defaultSeparatorStartInsetDp = 0.0f
402
417
  val defaultSeparatorEndInsetDp = 0.0f
403
418
 
@@ -418,32 +433,33 @@ private fun buildEmbeddedAppearance(
418
433
  Color.GRAY,
419
434
  )
420
435
 
421
- val parsedChevronColor =
436
+ val parsedDisclosureColor =
422
437
  dynamicColorFromParams(
423
438
  context,
424
- chevronParams,
439
+ disclosureParams,
425
440
  PaymentSheetAppearanceKeys.COLOR,
426
441
  defaultColors.componentBorder, // Default to component border color like other elements
427
442
  )
428
443
 
429
444
  // Create the required Colors object
430
- val flatChevronColors =
431
- PaymentSheet.Appearance.Embedded.RowStyle.FlatWithChevron.Colors(
445
+ val flatDisclosureColors =
446
+ PaymentSheet.Appearance.Embedded.RowStyle.FlatWithDisclosure.Colors(
432
447
  separatorColor = parsedSeparatorColor,
433
- chevronColor = parsedChevronColor,
448
+ disclosureColor = parsedDisclosureColor,
434
449
  )
435
450
 
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
- )
451
+ PaymentSheet.Appearance.Embedded.RowStyle.FlatWithDisclosure
452
+ .Builder()
453
+ .separatorThicknessDp(separatorThickness)
454
+ .startSeparatorInsetDp(startSeparatorInset)
455
+ .endSeparatorInsetDp(endSeparatorInset)
456
+ .topSeparatorEnabled(topEnabled)
457
+ .bottomSeparatorEnabled(bottomEnabled)
458
+ .additionalVerticalInsetsDp(additionalInsets)
459
+ .horizontalInsetsDp(0.0F) // We do not have an iOS equal for this API so it's not configurable in React Native
460
+ .colorsLight(flatDisclosureColors)
461
+ .colorsDark(flatDisclosureColors)
462
+ .build()
447
463
  }
448
464
  "floatingButton" -> {
449
465
  val floatingParams = getBundleOrNull(rowParams, PaymentSheetAppearanceKeys.FLOATING)
@@ -478,9 +494,11 @@ private fun buildFormInsets(insetParams: Bundle?): PaymentSheet.Insets {
478
494
  }
479
495
 
480
496
  /**
481
- * Pulls a light/dark hex‑string map out of [params],
482
- * chooses the right one based on the current UI mode,
483
- * and parses it (falling back to [defaultColor]).
497
+ * Parses a ThemedColor from [params] at [key]. Supports both:
498
+ * - Single hex string: "#RRGGBB"
499
+ * - Light/dark object: { "light": "#RRGGBB", "dark": "#RRGGBB" }
500
+ * For light/dark objects, chooses the appropriate color based on current UI mode.
501
+ * Falls back to [defaultColor] if no color is provided.
484
502
  */
485
503
  private fun dynamicColorFromParams(
486
504
  context: Context,
@@ -488,8 +506,12 @@ private fun dynamicColorFromParams(
488
506
  key: String,
489
507
  defaultColor: Int,
490
508
  ): Int {
491
- // Expect a nested Bundle { "light": "#RRGGBB", "dark": "#RRGGBB" }
492
- val colorBundle = params?.getBundle(key)
509
+ if (params == null) {
510
+ return defaultColor
511
+ }
512
+
513
+ // First check if it's a nested Bundle { "light": "#RRGGBB", "dark": "#RRGGBB" }
514
+ val colorBundle = params.getBundle(key)
493
515
  if (colorBundle != null) {
494
516
  val isDark =
495
517
  (
@@ -508,7 +530,12 @@ private fun dynamicColorFromParams(
508
530
  return colorFromHexOrDefault(hex, defaultColor)
509
531
  }
510
532
 
511
- // no override bundle just use default
533
+ // Check if it's a single color string
534
+ params.getString(key)?.let { colorString ->
535
+ return colorFromHexOrDefault(colorString, defaultColor)
536
+ }
537
+
538
+ // no override → just use default
512
539
  return defaultColor
513
540
  }
514
541
 
@@ -643,6 +670,8 @@ private class PaymentSheetAppearanceKeys {
643
670
  const val PRIMARY_BUTTON = "primaryButton"
644
671
  const val TEXT = "text"
645
672
  const val BORDER = "border"
673
+ const val SUCCESS_BACKGROUND = "successBackgroundColor"
674
+ const val SUCCESS_TEXT = "successTextColor"
646
675
 
647
676
  const val EMBEDDED_PAYMENT_ELEMENT = "embeddedPaymentElement"
648
677
  const val ROW = "row"
@@ -659,7 +688,7 @@ private class PaymentSheetAppearanceKeys {
659
688
  const val SELECTED_COLOR = "selectedColor"
660
689
  const val UNSELECTED_COLOR = "unselectedColor"
661
690
  const val CHECKMARK = "checkmark"
662
- const val CHEVRON = "chevron"
691
+ const val DISCLOSURE = "disclosure"
663
692
  const val COLOR = "color"
664
693
  const val CHECKMARK_INSET = "inset"
665
694
 
@@ -218,7 +218,7 @@ class PaymentSheetFragment :
218
218
  email = mapToCollectionMode(billingConfigParams?.getString("email")),
219
219
  address = mapToAddressCollectionMode(billingConfigParams?.getString("address")),
220
220
  attachDefaultsToPaymentMethod =
221
- billingConfigParams?.getBoolean("attachDefaultsToPaymentMethod") ?: false,
221
+ billingConfigParams?.getBoolean("attachDefaultsToPaymentMethod", false) ?: false,
222
222
  )
223
223
 
224
224
  var defaultBillingDetails: PaymentSheet.BillingDetails? = null
@@ -617,14 +617,13 @@ class PaymentSheetFragment :
617
617
  }
618
618
 
619
619
  @OptIn(PaymentMethodOptionsSetupFutureUsagePreview::class)
620
- private fun buildIntentConfigurationMode(modeParams: Bundle): PaymentSheet.IntentConfiguration.Mode {
621
- val currencyCode =
622
- modeParams.getString("currencyCode")
623
- ?: throw PaymentSheetException(
624
- "You must provide a value to intentConfiguration.mode.currencyCode",
625
- )
626
-
627
- return if (modeParams.containsKey("amount")) {
620
+ private fun buildIntentConfigurationMode(modeParams: Bundle): PaymentSheet.IntentConfiguration.Mode =
621
+ if (modeParams.containsKey("amount")) {
622
+ val currencyCode =
623
+ modeParams.getString("currencyCode")
624
+ ?: throw PaymentSheetException(
625
+ "You must provide a value to intentConfiguration.mode.currencyCode",
626
+ )
628
627
  PaymentSheet.IntentConfiguration.Mode.Payment(
629
628
  amount = modeParams.getInt("amount").toLong(),
630
629
  currency = currencyCode,
@@ -639,11 +638,10 @@ class PaymentSheetFragment :
639
638
  "You must provide a value to intentConfiguration.mode.setupFutureUsage",
640
639
  )
641
640
  PaymentSheet.IntentConfiguration.Mode.Setup(
642
- currency = currencyCode,
641
+ currency = modeParams.getString("currencyCode"),
643
642
  setupFutureUse = setupFutureUsage,
644
643
  )
645
644
  }
646
- }
647
645
 
648
646
  @OptIn(ExperimentalCustomerSessionApi::class)
649
647
  @Throws(PaymentSheetException::class)
@@ -309,7 +309,7 @@ class CustomerSheetFragment : StripeFragment() {
309
309
  phone = mapToCollectionMode(bundle.getString("phone")),
310
310
  email = mapToCollectionMode(bundle.getString("email")),
311
311
  address = mapToAddressCollectionMode(bundle.getString("address")),
312
- attachDefaultsToPaymentMethod = bundle.getBoolean("attachDefaultsToPaymentMethod"),
312
+ attachDefaultsToPaymentMethod = bundle.getBoolean("attachDefaultsToPaymentMethod", false),
313
313
  )
314
314
 
315
315
  internal fun createCustomerAdapter(
@@ -64,7 +64,9 @@ class AddToWalletButtonManager(
64
64
  view: AddToWalletButtonView,
65
65
  ephemeralKey: Dynamic,
66
66
  ) {
67
- view.setEphemeralKey(ephemeralKey.asMap())
67
+ val map = ephemeralKey.asMap()
68
+ if (map == null) return
69
+ view.setEphemeralKey(map)
68
70
  }
69
71
 
70
72
  @ReactProp(name = "token")
@@ -72,7 +74,9 @@ class AddToWalletButtonManager(
72
74
  view: AddToWalletButtonView,
73
75
  token: Dynamic,
74
76
  ) {
75
- view.setToken(token.asMap())
77
+ val map = token.asMap()
78
+ if (map == null) return
79
+ view.setToken(map)
76
80
  }
77
81
 
78
82
  @ReactProp(name = "iOSButtonStyle")