@stripe/stripe-react-native 0.70.0 → 0.72.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 (168) hide show
  1. package/android/gradle.properties +1 -1
  2. package/android/src/main/java/com/reactnativestripesdk/CurrencySelectorElementView.kt +7 -103
  3. package/android/src/main/java/com/reactnativestripesdk/CurrencySelectorElementViewManager.kt +1 -5
  4. package/android/src/main/java/com/reactnativestripesdk/EmbeddedPaymentElementView.kt +0 -26
  5. package/android/src/main/java/com/reactnativestripesdk/EmbeddedPaymentElementViewManager.kt +6 -21
  6. package/android/src/main/java/com/reactnativestripesdk/LinkControllerManager.kt +59 -18
  7. package/android/src/main/java/com/reactnativestripesdk/PaymentMethodCreateParamsFactory.kt +22 -0
  8. package/android/src/main/java/com/reactnativestripesdk/PaymentSheetManager.kt +6 -50
  9. package/android/src/main/java/com/reactnativestripesdk/StripeSdkModule.kt +38 -187
  10. package/android/src/main/java/com/reactnativestripesdk/utils/Mappers.kt +4 -0
  11. package/android/src/oldarch/java/com/reactnativestripesdk/NativeStripeSdkModuleSpec.java +4 -0
  12. package/android/src/onramp/java/com/reactnativestripesdk/OnrampMappers.kt +1 -0
  13. package/android/src/test/java/com/reactnativestripesdk/mappers/MappersTest.kt +10 -60
  14. package/ios/CurrencySelectorElementView.swift +18 -129
  15. package/ios/Mappers.swift +4 -0
  16. package/ios/PaymentMethodFactory.swift +22 -0
  17. package/ios/StripeSdk.mm +7 -0
  18. package/ios/StripeSdkImpl+Checkout.swift +35 -259
  19. package/ios/StripeSdkImpl+Embedded.swift +5 -28
  20. package/ios/StripeSdkImpl+LinkController.swift +40 -2
  21. package/ios/StripeSdkImpl+PaymentSheet.swift +2 -15
  22. package/ios/StripeSdkImpl.swift +2 -4
  23. package/lib/commonjs/components/AddToWalletButton.js +1 -1
  24. package/lib/commonjs/components/AddToWalletButton.js.map +1 -1
  25. package/lib/commonjs/components/AddressSheet.js +1 -1
  26. package/lib/commonjs/components/AddressSheet.js.map +1 -1
  27. package/lib/commonjs/components/AuBECSDebitForm.js +1 -1
  28. package/lib/commonjs/components/AuBECSDebitForm.js.map +1 -1
  29. package/lib/commonjs/components/CardField.js +1 -1
  30. package/lib/commonjs/components/CardField.js.map +1 -1
  31. package/lib/commonjs/components/CardForm.js +1 -1
  32. package/lib/commonjs/components/CardForm.js.map +1 -1
  33. package/lib/commonjs/components/CurrencySelectorElement.js +1 -1
  34. package/lib/commonjs/components/CurrencySelectorElement.js.map +1 -1
  35. package/lib/commonjs/components/PaymentMethodMessagingElement.js +1 -1
  36. package/lib/commonjs/components/PaymentMethodMessagingElement.js.map +1 -1
  37. package/lib/commonjs/components/PlatformPayButton.js +1 -1
  38. package/lib/commonjs/components/PlatformPayButton.js.map +1 -1
  39. package/lib/commonjs/components/StripeContainer.js +1 -1
  40. package/lib/commonjs/components/StripeContainer.js.map +1 -1
  41. package/lib/commonjs/connect/Components.js +1 -1
  42. package/lib/commonjs/connect/Components.js.map +1 -1
  43. package/lib/commonjs/connect/ConnectComponentsProvider.js +1 -1
  44. package/lib/commonjs/connect/ConnectComponentsProvider.js.map +1 -1
  45. package/lib/commonjs/connect/EmbeddedComponent.js +2 -2
  46. package/lib/commonjs/connect/EmbeddedComponent.js.map +1 -1
  47. package/lib/commonjs/connect/ModalCloseButton.js +1 -1
  48. package/lib/commonjs/connect/ModalCloseButton.js.map +1 -1
  49. package/lib/commonjs/connect/NavigationBar.js +1 -1
  50. package/lib/commonjs/connect/NavigationBar.js.map +1 -1
  51. package/lib/commonjs/functions.js +1 -1
  52. package/lib/commonjs/functions.js.map +1 -1
  53. package/lib/commonjs/helpers.js +1 -1
  54. package/lib/commonjs/hooks/useLinkController.js +1 -1
  55. package/lib/commonjs/hooks/useLinkController.js.map +1 -1
  56. package/lib/commonjs/specs/NativeAddToWalletButton.js +1 -1
  57. package/lib/commonjs/specs/NativeAddressSheet.js +1 -1
  58. package/lib/commonjs/specs/NativeApplePayButton.js +1 -1
  59. package/lib/commonjs/specs/NativeAuBECSDebitForm.js +1 -1
  60. package/lib/commonjs/specs/NativeCardField.js +1 -1
  61. package/lib/commonjs/specs/NativeCardField.js.map +1 -1
  62. package/lib/commonjs/specs/NativeCardForm.js +1 -1
  63. package/lib/commonjs/specs/NativeCardForm.js.map +1 -1
  64. package/lib/commonjs/specs/NativeConnectAccountOnboardingView.js +1 -1
  65. package/lib/commonjs/specs/NativeCurrencySelectorElement.js +1 -1
  66. package/lib/commonjs/specs/NativeEmbeddedPaymentElement.js +1 -1
  67. package/lib/commonjs/specs/NativeEmbeddedPaymentElement.js.map +1 -1
  68. package/lib/commonjs/specs/NativeGooglePayButton.js +1 -1
  69. package/lib/commonjs/specs/NativeNavigationBar.js +1 -1
  70. package/lib/commonjs/specs/NativePaymentMethodMessagingElement.js +1 -1
  71. package/lib/commonjs/specs/NativeStripeContainer.js +1 -1
  72. package/lib/commonjs/specs/NativeStripeSdkModule.js.map +1 -1
  73. package/lib/commonjs/types/EmbeddedPaymentElement.js +1 -1
  74. package/lib/commonjs/types/EmbeddedPaymentElement.js.map +1 -1
  75. package/lib/commonjs/types/PaymentIntent.js.map +1 -1
  76. package/lib/module/components/AddToWalletButton.js +1 -1
  77. package/lib/module/components/AddToWalletButton.js.map +1 -1
  78. package/lib/module/components/AddressSheet.js +1 -1
  79. package/lib/module/components/AddressSheet.js.map +1 -1
  80. package/lib/module/components/AuBECSDebitForm.js +1 -1
  81. package/lib/module/components/AuBECSDebitForm.js.map +1 -1
  82. package/lib/module/components/CardField.js +1 -1
  83. package/lib/module/components/CardField.js.map +1 -1
  84. package/lib/module/components/CardForm.js +1 -1
  85. package/lib/module/components/CardForm.js.map +1 -1
  86. package/lib/module/components/CurrencySelectorElement.js +1 -1
  87. package/lib/module/components/CurrencySelectorElement.js.map +1 -1
  88. package/lib/module/components/PaymentMethodMessagingElement.js +1 -1
  89. package/lib/module/components/PaymentMethodMessagingElement.js.map +1 -1
  90. package/lib/module/components/PlatformPayButton.js +1 -1
  91. package/lib/module/components/PlatformPayButton.js.map +1 -1
  92. package/lib/module/components/StripeContainer.js +1 -1
  93. package/lib/module/components/StripeContainer.js.map +1 -1
  94. package/lib/module/connect/Components.js +1 -1
  95. package/lib/module/connect/Components.js.map +1 -1
  96. package/lib/module/connect/ConnectComponentsProvider.js +1 -1
  97. package/lib/module/connect/ConnectComponentsProvider.js.map +1 -1
  98. package/lib/module/connect/EmbeddedComponent.js +2 -2
  99. package/lib/module/connect/EmbeddedComponent.js.map +1 -1
  100. package/lib/module/connect/ModalCloseButton.js +1 -1
  101. package/lib/module/connect/ModalCloseButton.js.map +1 -1
  102. package/lib/module/connect/NavigationBar.js +1 -1
  103. package/lib/module/connect/NavigationBar.js.map +1 -1
  104. package/lib/module/functions.js +1 -1
  105. package/lib/module/functions.js.map +1 -1
  106. package/lib/module/helpers.js +1 -1
  107. package/lib/module/hooks/useLinkController.js +1 -1
  108. package/lib/module/hooks/useLinkController.js.map +1 -1
  109. package/lib/module/specs/NativeAddToWalletButton.js +1 -1
  110. package/lib/module/specs/NativeAddressSheet.js +1 -1
  111. package/lib/module/specs/NativeApplePayButton.js +1 -1
  112. package/lib/module/specs/NativeAuBECSDebitForm.js +1 -1
  113. package/lib/module/specs/NativeCardField.js +1 -1
  114. package/lib/module/specs/NativeCardField.js.map +1 -1
  115. package/lib/module/specs/NativeCardForm.js +1 -1
  116. package/lib/module/specs/NativeCardForm.js.map +1 -1
  117. package/lib/module/specs/NativeConnectAccountOnboardingView.js +1 -1
  118. package/lib/module/specs/NativeCurrencySelectorElement.js +1 -1
  119. package/lib/module/specs/NativeEmbeddedPaymentElement.js +1 -1
  120. package/lib/module/specs/NativeEmbeddedPaymentElement.js.map +1 -1
  121. package/lib/module/specs/NativeGooglePayButton.js +1 -1
  122. package/lib/module/specs/NativeNavigationBar.js +1 -1
  123. package/lib/module/specs/NativePaymentMethodMessagingElement.js +1 -1
  124. package/lib/module/specs/NativeStripeContainer.js +1 -1
  125. package/lib/module/specs/NativeStripeSdkModule.js.map +1 -1
  126. package/lib/module/types/EmbeddedPaymentElement.js +1 -1
  127. package/lib/module/types/EmbeddedPaymentElement.js.map +1 -1
  128. package/lib/module/types/PaymentIntent.js.map +1 -1
  129. package/lib/typescript/src/connect/EmbeddedComponent.d.ts +1 -0
  130. package/lib/typescript/src/connect/EmbeddedComponent.d.ts.map +1 -1
  131. package/lib/typescript/src/functions.d.ts +11 -0
  132. package/lib/typescript/src/functions.d.ts.map +1 -1
  133. package/lib/typescript/src/hooks/useLinkController.d.ts +7 -0
  134. package/lib/typescript/src/hooks/useLinkController.d.ts.map +1 -1
  135. package/lib/typescript/src/specs/NativeStripeSdkModule.d.ts +4 -0
  136. package/lib/typescript/src/specs/NativeStripeSdkModule.d.ts.map +1 -1
  137. package/lib/typescript/src/types/LinkController.d.ts +10 -5
  138. package/lib/typescript/src/types/LinkController.d.ts.map +1 -1
  139. package/lib/typescript/src/types/PaymentIntent.d.ts +17 -1
  140. package/lib/typescript/src/types/PaymentIntent.d.ts.map +1 -1
  141. package/lib/typescript/src/types/PaymentMethod.d.ts +1 -1
  142. package/lib/typescript/src/types/PaymentMethod.d.ts.map +1 -1
  143. package/package.json +1 -1
  144. package/src/connect/EmbeddedComponent.tsx +14 -2
  145. package/src/functions.ts +26 -0
  146. package/src/hooks/useLinkController.tsx +24 -1
  147. package/src/specs/NativeStripeSdkModule.ts +5 -0
  148. package/src/types/LinkController.ts +9 -5
  149. package/src/types/PaymentIntent.ts +21 -1
  150. package/src/types/PaymentMethod.ts +1 -0
  151. package/stripe-react-native.podspec +1 -1
  152. package/android/.idea/AndroidProjectSystem.xml +0 -6
  153. package/android/.idea/caches/deviceStreaming.xml +0 -835
  154. package/android/.idea/compiler.xml +0 -6
  155. package/android/.idea/gradle.xml +0 -17
  156. package/android/.idea/migrations.xml +0 -10
  157. package/android/.idea/misc.xml +0 -10
  158. package/android/.idea/runConfigurations.xml +0 -17
  159. package/android/.idea/vcs.xml +0 -6
  160. package/android/local.properties +0 -8
  161. package/android/src/main/java/com/reactnativestripesdk/CurrencySelectorAppearance.kt +0 -229
  162. package/android/src/main/java/com/reactnativestripesdk/utils/CheckoutAddressUpdate.kt +0 -45
  163. package/android/src/main/java/com/reactnativestripesdk/utils/CheckoutMappers.kt +0 -127
  164. package/android/src/test/java/com/reactnativestripesdk/CurrencySelectorAppearanceTest.kt +0 -137
  165. package/android/src/test/java/com/reactnativestripesdk/utils/CheckoutMappersTest.kt +0 -98
  166. package/android/src/test/java/com/reactnativestripesdk/utils/CheckoutTestFixtures.java +0 -57
  167. package/ios/CurrencySelectorAppearance.swift +0 -120
  168. package/ios/Mappers+Checkout.swift +0 -337
@@ -1,6 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="CompilerConfiguration">
4
- <bytecodeTargetLevel target="1.6" />
5
- </component>
6
- </project>
@@ -1,17 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="GradleSettings">
4
- <option name="linkedExternalProjectsSettings">
5
- <GradleProjectSettings>
6
- <option name="testRunner" value="CHOOSE_PER_TEST" />
7
- <option name="externalProjectPath" value="$PROJECT_DIR$" />
8
- <option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
9
- <option name="modules">
10
- <set>
11
- <option value="$PROJECT_DIR$" />
12
- </set>
13
- </option>
14
- </GradleProjectSettings>
15
- </option>
16
- </component>
17
- </project>
@@ -1,10 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="ProjectMigrations">
4
- <option name="MigrateToGradleLocalJavaHome">
5
- <set>
6
- <option value="$PROJECT_DIR$" />
7
- </set>
8
- </option>
9
- </component>
10
- </project>
@@ -1,10 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="ExternalStorageConfigurationManager" enabled="true" />
4
- <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
5
- <output url="file://$PROJECT_DIR$/build/classes" />
6
- </component>
7
- <component name="ProjectType">
8
- <option name="id" value="Android" />
9
- </component>
10
- </project>
@@ -1,17 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="RunConfigurationProducerService">
4
- <option name="ignoredProducers">
5
- <set>
6
- <option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
7
- <option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
8
- <option value="com.intellij.execution.junit.PatternConfigurationProducer" />
9
- <option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
10
- <option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
11
- <option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
12
- <option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
13
- <option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
14
- </set>
15
- </option>
16
- </component>
17
- </project>
@@ -1,6 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="VcsDirectoryMappings">
4
- <mapping directory="$PROJECT_DIR$/.." vcs="Git" />
5
- </component>
6
- </project>
@@ -1,8 +0,0 @@
1
- ## This file must *NOT* be checked into Version Control Systems,
2
- # as it contains information specific to your local configuration.
3
- #
4
- # Location of the SDK. This is only used by Gradle.
5
- # For customization when using a Version Control System, please read the
6
- # header note.
7
- #Tue Jul 29 21:50:46 PDT 2025
8
- sdk.dir=/Users/cttsai/Library/Android/sdk
@@ -1,229 +0,0 @@
1
- package com.reactnativestripesdk
2
-
3
- import android.annotation.SuppressLint
4
- import android.content.Context
5
- import android.content.res.Configuration
6
- import androidx.compose.ui.graphics.Color
7
- import androidx.core.graphics.toColorInt
8
- import com.facebook.react.bridge.ReadableMap
9
- import com.facebook.react.bridge.ReadableType
10
- import com.reactnativestripesdk.utils.PaymentSheetAppearanceException
11
- import com.stripe.android.checkout.Checkout
12
- import com.stripe.android.paymentelement.CheckoutSessionPreview
13
-
14
- @OptIn(CheckoutSessionPreview::class)
15
- @SuppressLint("RestrictedApi")
16
- fun buildCurrencySelectorAppearance(
17
- params: ReadableMap?,
18
- context: Context,
19
- ): Checkout.CurrencySelectorContentAppearance {
20
- val appearance = Checkout.CurrencySelectorContentAppearance()
21
-
22
- params ?: return appearance
23
-
24
- applyCurrencySelectorColors(appearance, params, context)
25
- applyCurrencySelectorDimensions(appearance, params)
26
- applyCurrencySelectorFont(appearance, params, context)
27
- applyCurrencySelectorLabelContent(appearance, params)
28
-
29
- return appearance
30
- }
31
-
32
- @OptIn(CheckoutSessionPreview::class)
33
- @SuppressLint("RestrictedApi")
34
- private fun applyCurrencySelectorColors(
35
- appearance: Checkout.CurrencySelectorContentAppearance,
36
- params: ReadableMap,
37
- context: Context,
38
- ) {
39
- dynamicColorFromParams(context, params, CurrencySelectorAppearanceKeys.BACKGROUND)?.let {
40
- appearance.background(it)
41
- }
42
- dynamicColorFromParams(context, params, CurrencySelectorAppearanceKeys.SELECTED_BACKGROUND)?.let {
43
- appearance.selectedBackground(it)
44
- }
45
- dynamicColorFromParams(context, params, CurrencySelectorAppearanceKeys.BORDER_COLOR)?.let {
46
- appearance.borderColor(it)
47
- }
48
- dynamicColorFromParams(context, params, CurrencySelectorAppearanceKeys.TEXT_COLOR)?.let {
49
- appearance.textColor(it)
50
- }
51
- dynamicColorFromParams(context, params, CurrencySelectorAppearanceKeys.SELECTED_TEXT_COLOR)?.let {
52
- appearance.selectedTextColor(it)
53
- }
54
- dynamicColorFromParams(context, params, CurrencySelectorAppearanceKeys.TEXT_SECONDARY_COLOR)?.let {
55
- appearance.textSecondaryColor(it)
56
- }
57
- dynamicColorFromParams(context, params, CurrencySelectorAppearanceKeys.DANGER_COLOR)?.let {
58
- appearance.dangerColor(it)
59
- }
60
- }
61
-
62
- @OptIn(CheckoutSessionPreview::class)
63
- @SuppressLint("RestrictedApi")
64
- private fun applyCurrencySelectorDimensions(
65
- appearance: Checkout.CurrencySelectorContentAppearance,
66
- params: ReadableMap,
67
- ) {
68
- getFloatOrNull(params, CurrencySelectorAppearanceKeys.CORNER_RADIUS)?.let {
69
- appearance.cornerRadiusDp(it)
70
- }
71
- getFloatOrNull(params, CurrencySelectorAppearanceKeys.BORDER_WIDTH)?.let {
72
- appearance.borderWidthDp(it)
73
- }
74
- getFloatOrNull(params, CurrencySelectorAppearanceKeys.CONTENT_VERTICAL_PADDING)?.let {
75
- appearance.contentVerticalPaddingDp(it)
76
- }
77
- }
78
-
79
- @OptIn(CheckoutSessionPreview::class)
80
- @SuppressLint("RestrictedApi")
81
- private fun applyCurrencySelectorFont(
82
- appearance: Checkout.CurrencySelectorContentAppearance,
83
- params: ReadableMap,
84
- context: Context,
85
- ) {
86
- params.getMap(CurrencySelectorAppearanceKeys.FONT)?.let { font ->
87
- getCurrencySelectorFontResId(font, CurrencySelectorAppearanceKeys.FAMILY, context)?.let {
88
- appearance.fontResId(it)
89
- }
90
- getFloatOrNull(font, CurrencySelectorAppearanceKeys.SCALE)?.let {
91
- appearance.sizeScaleFactor(it)
92
- }
93
- }
94
- }
95
-
96
- @OptIn(CheckoutSessionPreview::class)
97
- @SuppressLint("RestrictedApi")
98
- private fun applyCurrencySelectorLabelContent(
99
- appearance: Checkout.CurrencySelectorContentAppearance,
100
- params: ReadableMap,
101
- ) {
102
- when (params.getString(CurrencySelectorAppearanceKeys.LABEL_CONTENT)) {
103
- CurrencySelectorAppearanceKeys.AMOUNT -> {
104
- appearance.labelContent(Checkout.CurrencySelectorContentAppearance.LabelContent.AMOUNT)
105
- }
106
- CurrencySelectorAppearanceKeys.CURRENCY_CODE -> {
107
- appearance.labelContent(Checkout.CurrencySelectorContentAppearance.LabelContent.CURRENCY_CODE)
108
- }
109
- CurrencySelectorAppearanceKeys.AUTOMATIC -> {
110
- appearance.labelContent(Checkout.CurrencySelectorContentAppearance.LabelContent.AUTOMATIC)
111
- }
112
- }
113
- }
114
-
115
- private fun dynamicColorFromParams(
116
- context: Context,
117
- params: ReadableMap?,
118
- key: String,
119
- ): Color? {
120
- if (params == null) {
121
- return null
122
- }
123
-
124
- if (params.hasKey(key) && params.getType(key) == ReadableType.Map) {
125
- val colorMap = params.getMap(key)
126
- val isDark =
127
- (
128
- context.resources.configuration.uiMode
129
- and Configuration.UI_MODE_NIGHT_MASK
130
- ) == Configuration.UI_MODE_NIGHT_YES
131
-
132
- val hex =
133
- if (isDark) {
134
- colorMap?.getString(CurrencySelectorAppearanceKeys.DARK)
135
- } else {
136
- colorMap?.getString(CurrencySelectorAppearanceKeys.LIGHT)
137
- }
138
-
139
- return colorFromHex(hex)?.let { Color(it) }
140
- }
141
-
142
- return colorFromHex(params.getString(key))?.let { Color(it) }
143
- }
144
-
145
- private fun colorFromHex(hexString: String?): Int? =
146
- hexString?.trim()?.replace("#", "")?.let {
147
- if (it.length == HEX_COLOR_LENGTH_RGB || it.length == HEX_COLOR_LENGTH_ARGB) {
148
- "#$it".toColorInt()
149
- } else {
150
- android.util.Log.w(
151
- "StripeCurrencySelector",
152
- "Invalid hex color: expected length 6 or 8, but received: $it",
153
- )
154
- null
155
- }
156
- }
157
-
158
- private fun getFloatOrNull(
159
- map: ReadableMap?,
160
- key: String,
161
- ): Float? =
162
- if (map?.hasKey(key) == true && map.getType(key) == ReadableType.Number) {
163
- map.getDouble(key).toFloat()
164
- } else {
165
- null
166
- }
167
-
168
- @SuppressLint("DiscouragedApi")
169
- private fun getCurrencySelectorFontResId(
170
- map: ReadableMap?,
171
- key: String,
172
- context: Context,
173
- ): Int? {
174
- val fontErrorPrefix = "Encountered an error when setting a custom font:"
175
- if (map?.hasKey(key) != true) {
176
- return null
177
- }
178
-
179
- val fontFileName = map.getString(key)
180
- val validationError =
181
- when {
182
- fontFileName == null ->
183
- "$fontErrorPrefix expected String for font.$key, but received null."
184
- Regex("[^a-z0-9_]").containsMatchIn(fontFileName) ->
185
- "$fontErrorPrefix appearance.font.$key should only contain " +
186
- "lowercase alphanumeric characters and underscores on Android, " +
187
- "but received '$fontFileName'. " +
188
- "This value must match the filename in android/app/src/main/res/font"
189
- else -> null
190
- }
191
- if (validationError != null) {
192
- throw PaymentSheetAppearanceException(validationError)
193
- }
194
-
195
- val id = context.resources.getIdentifier(fontFileName, "font", context.packageName)
196
- if (id == 0) {
197
- throw PaymentSheetAppearanceException("$fontErrorPrefix Failed to find font: $fontFileName")
198
- }
199
- return id
200
- }
201
-
202
- private object CurrencySelectorAppearanceKeys {
203
- const val LIGHT = "light"
204
- const val DARK = "dark"
205
-
206
- const val BACKGROUND = "background"
207
- const val SELECTED_BACKGROUND = "selectedBackground"
208
- const val BORDER_COLOR = "borderColor"
209
- const val TEXT_COLOR = "textColor"
210
- const val SELECTED_TEXT_COLOR = "selectedTextColor"
211
- const val TEXT_SECONDARY_COLOR = "textSecondaryColor"
212
- const val DANGER_COLOR = "dangerColor"
213
-
214
- const val CORNER_RADIUS = "cornerRadius"
215
- const val BORDER_WIDTH = "borderWidth"
216
- const val CONTENT_VERTICAL_PADDING = "contentVerticalPadding"
217
-
218
- const val FONT = "font"
219
- const val FAMILY = "family"
220
- const val SCALE = "scale"
221
-
222
- const val LABEL_CONTENT = "labelContent"
223
- const val AUTOMATIC = "automatic"
224
- const val CURRENCY_CODE = "currencyCode"
225
- const val AMOUNT = "amount"
226
- }
227
-
228
- private const val HEX_COLOR_LENGTH_RGB = 6
229
- private const val HEX_COLOR_LENGTH_ARGB = 8
@@ -1,45 +0,0 @@
1
- package com.reactnativestripesdk.utils
2
-
3
- import com.facebook.react.bridge.ReadableMap
4
- import com.stripe.android.paymentelement.CheckoutSessionPreview
5
- import com.stripe.android.checkout.Address as CheckoutAddress
6
-
7
- @OptIn(CheckoutSessionPreview::class)
8
- internal data class CheckoutAddressUpdate(
9
- val name: String? = null,
10
- val phone: String? = null,
11
- val country: String,
12
- val line1: String? = null,
13
- val line2: String? = null,
14
- val city: String? = null,
15
- val state: String? = null,
16
- val postalCode: String? = null,
17
- )
18
-
19
- internal fun buildCheckoutAddressUpdate(
20
- name: String?,
21
- phone: String?,
22
- address: ReadableMap,
23
- ): CheckoutAddressUpdate? {
24
- val country = address.getString("country")?.trim()?.takeIf { it.isNotEmpty() } ?: return null
25
- return CheckoutAddressUpdate(
26
- name = name?.trim(),
27
- phone = phone?.trim(),
28
- country = country,
29
- line1 = address.getString("line1")?.trim(),
30
- line2 = address.getString("line2")?.trim(),
31
- city = address.getString("city")?.trim(),
32
- state = address.getString("state")?.trim(),
33
- postalCode = address.getString("postalCode")?.trim(),
34
- )
35
- }
36
-
37
- @OptIn(CheckoutSessionPreview::class)
38
- internal fun CheckoutAddressUpdate.toCheckoutAddress(): CheckoutAddress =
39
- CheckoutAddress()
40
- .country(country)
41
- .line1(line1)
42
- .line2(line2)
43
- .city(city)
44
- .state(state)
45
- .postalCode(postalCode)
@@ -1,127 +0,0 @@
1
- package com.reactnativestripesdk.utils
2
-
3
- import com.facebook.react.bridge.Arguments
4
- import com.facebook.react.bridge.WritableArray
5
- import com.facebook.react.bridge.WritableMap
6
- import com.stripe.android.checkout.Checkout
7
- import com.stripe.android.checkout.CheckoutSession
8
- import com.stripe.android.paymentelement.CheckoutSessionPreview
9
-
10
- @OptIn(CheckoutSessionPreview::class)
11
- internal fun mapFromCheckoutState(checkout: Checkout): WritableMap =
12
- mapFromCheckoutState(
13
- isLoading = checkout.isLoading.value,
14
- session = checkout.checkoutSession.value,
15
- )
16
-
17
- @OptIn(CheckoutSessionPreview::class)
18
- internal fun mapFromCheckoutState(
19
- isLoading: Boolean,
20
- session: CheckoutSession,
21
- ): WritableMap =
22
- Arguments.createMap().apply {
23
- putString("status", if (isLoading) "loading" else "loaded")
24
- putMap("session", mapFromCheckoutSession(session))
25
- }
26
-
27
- @OptIn(CheckoutSessionPreview::class)
28
- private fun mapFromCheckoutSession(session: CheckoutSession): WritableMap =
29
- Arguments.createMap().apply {
30
- putString("id", session.id)
31
- putBoolean("livemode", false)
32
-
33
- if (session.currency.isNotBlank()) {
34
- putString("currency", session.currency)
35
- }
36
-
37
- putMap("status", mapFromStatus(session.status))
38
- putMap("tax", mapFromTax(session.tax))
39
- session.totalSummary?.let { putMap("total", mapFromTotal(it)) }
40
-
41
- putArray("lineItems", mapFromLineItems(session))
42
- putArray("shippingOptions", mapFromShippingOptions(session))
43
- putArray("discountAmounts", Arguments.createArray())
44
- putArray("currencyOptions", Arguments.createArray())
45
- }
46
-
47
- @OptIn(CheckoutSessionPreview::class)
48
- private fun mapFromStatus(status: CheckoutSession.Status): WritableMap =
49
- Arguments.createMap().apply {
50
- putString(
51
- "type",
52
- when (status) {
53
- CheckoutSession.Status.Open -> "open"
54
- CheckoutSession.Status.Complete -> "complete"
55
- CheckoutSession.Status.Expired -> "expired"
56
- else -> "unknown"
57
- }
58
- )
59
- }
60
-
61
- @OptIn(CheckoutSessionPreview::class)
62
- private fun mapFromTax(tax: CheckoutSession.Tax): WritableMap =
63
- Arguments.createMap().apply {
64
- putString(
65
- "status",
66
- when (tax.status) {
67
- CheckoutSession.Tax.Status.Ready -> "ready"
68
- CheckoutSession.Tax.Status.RequiresShippingAddress -> "requiresShippingAddress"
69
- CheckoutSession.Tax.Status.RequiresBillingAddress -> "requiresBillingAddress"
70
- else -> "unknown"
71
- }
72
- )
73
- }
74
-
75
- @OptIn(CheckoutSessionPreview::class)
76
- private fun mapFromTotal(totals: CheckoutSession.TotalSummary): WritableMap =
77
- Arguments.createMap().apply {
78
- val taxTotal = totals.taxAmounts.sumOf { it.amount }
79
-
80
- putMap("subtotal", makeAmount(totals.subtotal))
81
- putMap("taxExclusive", makeAmount(taxTotal))
82
- putMap("taxInclusive", makeAmount(0L))
83
- putMap("shippingRate", makeAmount(totals.shippingRate?.amount ?: 0L))
84
- putMap("discount", makeAmount(0L))
85
- putMap("total", makeAmount(totals.totalAmountDue))
86
- putMap("appliedBalance", makeAmount(0L))
87
- putBoolean("balanceAppliedToNextInvoice", false)
88
- }
89
-
90
- @OptIn(CheckoutSessionPreview::class)
91
- private fun mapFromLineItems(session: CheckoutSession): WritableArray =
92
- Arguments.createArray().apply {
93
- session.lineItems.forEach { item ->
94
- pushMap(
95
- Arguments.createMap().apply {
96
- putString("id", item.id)
97
- putString("name", item.name)
98
- putInt("quantity", item.quantity)
99
- putArray("images", Arguments.createArray())
100
- putArray("discountAmounts", Arguments.createArray())
101
- putArray("taxAmounts", Arguments.createArray())
102
- item.unitAmount?.let { putMap("unitAmount", makeAmount(it)) }
103
- },
104
- )
105
- }
106
- }
107
-
108
- @OptIn(CheckoutSessionPreview::class)
109
- private fun mapFromShippingOptions(session: CheckoutSession): WritableArray =
110
- Arguments.createArray().apply {
111
- session.shippingOptions.forEach { option ->
112
- pushMap(
113
- Arguments.createMap().apply {
114
- putString("id", option.id)
115
- putString("displayName", option.displayName)
116
- putMap("amount", makeAmount(option.amount))
117
- putString("currency", session.currency)
118
- },
119
- )
120
- }
121
- }
122
-
123
- private fun makeAmount(minorUnits: Long): WritableMap =
124
- Arguments.createMap().apply {
125
- putString("amount", "")
126
- putDouble("minorUnitsAmount", minorUnits.toDouble())
127
- }
@@ -1,137 +0,0 @@
1
- package com.reactnativestripesdk
2
-
3
- import android.content.Context
4
- import androidx.test.core.app.ApplicationProvider
5
- import com.reactnativestripesdk.utils.readableMapOf
6
- import com.stripe.android.checkout.Checkout
7
- import com.stripe.android.paymentelement.CheckoutSessionPreview
8
- import org.junit.Assert.assertEquals
9
- import org.junit.Assert.assertNotNull
10
- import org.junit.Test
11
- import org.junit.runner.RunWith
12
- import org.robolectric.RobolectricTestRunner
13
-
14
- @OptIn(CheckoutSessionPreview::class)
15
- @RunWith(RobolectricTestRunner::class)
16
- class CurrencySelectorAppearanceTest {
17
- private val context: Context = ApplicationProvider.getApplicationContext()
18
-
19
- @Test
20
- fun buildCurrencySelectorAppearance_WithNullMap_ReturnsDefaultAppearance() {
21
- val appearance = buildCurrencySelectorAppearance(null, context)
22
-
23
- assertNotNull(appearance)
24
- }
25
-
26
- @Test
27
- fun buildCurrencySelectorAppearance_WithEmptyMap_ReturnsDefaultAppearance() {
28
- val appearance = buildCurrencySelectorAppearance(readableMapOf(), context)
29
-
30
- assertNotNull(appearance)
31
- }
32
-
33
- @Test
34
- fun buildCurrencySelectorAppearance_WithColorStrings_Success() {
35
- val appearance =
36
- buildCurrencySelectorAppearance(
37
- readableMapOf(
38
- "background" to "#111111",
39
- "selectedBackground" to "#222222",
40
- "borderColor" to "#333333",
41
- "textColor" to "#444444",
42
- "selectedTextColor" to "#555555",
43
- "textSecondaryColor" to "#666666",
44
- "dangerColor" to "#777777",
45
- ),
46
- context,
47
- )
48
-
49
- assertNotNull(getField(appearance, "background"))
50
- assertNotNull(getField(appearance, "selectedBackground"))
51
- assertNotNull(getField(appearance, "borderColor"))
52
- assertNotNull(getField(appearance, "textColor"))
53
- assertNotNull(getField(appearance, "selectedTextColor"))
54
- assertNotNull(getField(appearance, "textSecondaryColor"))
55
- assertNotNull(getField(appearance, "dangerColor"))
56
- }
57
-
58
- @Test
59
- fun buildCurrencySelectorAppearance_WithThemedColor_UsesLightColor() {
60
- val appearance =
61
- buildCurrencySelectorAppearance(
62
- readableMapOf(
63
- "textColor" to
64
- readableMapOf(
65
- "light" to "#000000",
66
- "dark" to "#FFFFFF",
67
- ),
68
- ),
69
- context,
70
- )
71
-
72
- assertNotNull(getField(appearance, "textColor"))
73
- }
74
-
75
- @Test
76
- fun buildCurrencySelectorAppearance_WithInvalidColor_IgnoresValue() {
77
- val appearance =
78
- buildCurrencySelectorAppearance(
79
- readableMapOf(
80
- "textColor" to "#FF",
81
- ),
82
- context,
83
- )
84
-
85
- // Invalid hex is silently ignored (logged as warning), color remains null/default
86
- val field = appearance.javaClass.getDeclaredField("textColor")
87
- field.isAccessible = true
88
- val textColor = field.get(appearance)
89
- assertEquals(null, textColor)
90
- }
91
-
92
- @Test
93
- fun buildCurrencySelectorAppearance_WithDimensionsAndFont_Success() {
94
- val appearance =
95
- buildCurrencySelectorAppearance(
96
- readableMapOf(
97
- "cornerRadius" to 12.0,
98
- "borderWidth" to 2.0,
99
- "contentVerticalPadding" to 6.0,
100
- "font" to
101
- readableMapOf(
102
- "scale" to 1.2,
103
- ),
104
- ),
105
- context,
106
- )
107
-
108
- assertEquals(12f, getField(appearance, "cornerRadiusDp"))
109
- assertEquals(2f, getField(appearance, "borderWidthDp"))
110
- assertEquals(6f, getField(appearance, "contentVerticalPaddingDp"))
111
- assertEquals(1.2f, getField(appearance, "sizeScaleFactor"))
112
- }
113
-
114
- @Test
115
- fun buildCurrencySelectorAppearance_WithLabelContentValues_Success() {
116
- listOf("automatic", "currencyCode", "amount").forEach { labelContent ->
117
- val appearance =
118
- buildCurrencySelectorAppearance(
119
- readableMapOf(
120
- "labelContent" to labelContent,
121
- ),
122
- context,
123
- )
124
-
125
- assertNotNull(getField(appearance, "labelContent"))
126
- }
127
- }
128
-
129
- private fun getField(
130
- appearance: Checkout.CurrencySelectorContentAppearance,
131
- fieldName: String,
132
- ): Any? {
133
- val field = appearance.javaClass.getDeclaredField(fieldName)
134
- field.isAccessible = true
135
- return field.get(appearance)
136
- }
137
- }