@stripe/stripe-react-native 0.57.3 → 0.59.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 (233) hide show
  1. package/android/build.gradle +2 -0
  2. package/android/gradle.properties +1 -1
  3. package/android/src/main/AndroidManifest.xml +27 -1
  4. package/android/src/main/java/com/reactnativestripesdk/EmbeddedPaymentElementView.kt +0 -3
  5. package/android/src/main/java/com/reactnativestripesdk/EmbeddedPaymentElementViewManager.kt +7 -3
  6. package/android/src/main/java/com/reactnativestripesdk/EventEmitterCompat.kt +8 -0
  7. package/android/src/main/java/com/reactnativestripesdk/NavigationBarView.kt +12 -1
  8. package/android/src/main/java/com/reactnativestripesdk/PaymentElementConfig.kt +26 -0
  9. package/android/src/main/java/com/reactnativestripesdk/PaymentMethodMessagingElementConfig.kt +147 -0
  10. package/android/src/main/java/com/reactnativestripesdk/PaymentMethodMessagingElementView.kt +164 -0
  11. package/android/src/main/java/com/reactnativestripesdk/PaymentMethodMessagingElementViewManager.kt +65 -0
  12. package/android/src/main/java/com/reactnativestripesdk/PaymentSheetAppearance.kt +1 -1
  13. package/android/src/main/java/com/reactnativestripesdk/PaymentSheetManager.kt +60 -31
  14. package/android/src/main/java/com/reactnativestripesdk/StripeAbstractComposeView.kt +17 -5
  15. package/android/src/main/java/com/reactnativestripesdk/StripeConnectDeepLinkInterceptorActivity.kt +77 -0
  16. package/android/src/main/java/com/reactnativestripesdk/StripeSdkModule.kt +334 -24
  17. package/android/src/main/java/com/reactnativestripesdk/StripeSdkPackage.kt +1 -0
  18. package/android/src/main/java/com/reactnativestripesdk/customersheet/CustomerSheetManager.kt +3 -0
  19. package/android/src/main/java/com/reactnativestripesdk/utils/Errors.kt +8 -0
  20. package/android/src/main/java/com/reactnativestripesdk/utils/Mappers.kt +0 -2
  21. package/android/src/main/res/xml/file_paths.xml +4 -0
  22. package/android/src/oldarch/java/com/facebook/react/viewmanagers/PaymentMethodMessagingElementViewManagerDelegate.java +36 -0
  23. package/android/src/oldarch/java/com/facebook/react/viewmanagers/PaymentMethodMessagingElementViewManagerInterface.java +18 -0
  24. package/android/src/oldarch/java/com/reactnativestripesdk/NativeStripeSdkModuleSpec.java +20 -0
  25. package/android/src/test/java/com/reactnativestripesdk/PaymentElementConfigTest.kt +175 -1
  26. package/android/src/test/java/com/reactnativestripesdk/PaymentMethodMessagingElementConfigTest.kt +543 -0
  27. package/android/src/test/java/com/reactnativestripesdk/PaymentSheetManagerTest.kt +70 -0
  28. package/ios/ConnectAccountOnboarding/ConnectAccountOnboardingView.swift +13 -19
  29. package/ios/CustomerSheet/CustomerSheetUtils.swift +4 -0
  30. package/ios/OldArch/StripeSdkEventEmitterCompat.h +2 -0
  31. package/ios/OldArch/StripeSdkEventEmitterCompat.m +13 -1
  32. package/ios/PaymentMethodMessagingElementConfig.swift +116 -0
  33. package/ios/PaymentMethodMessagingElementHandler.m +9 -0
  34. package/ios/PaymentMethodMessagingElementView.swift +139 -0
  35. package/ios/StripeSdk.mm +40 -0
  36. package/ios/StripeSdkEmitter.swift +2 -0
  37. package/ios/StripeSdkImpl+CustomerSheet.swift +1 -0
  38. package/ios/StripeSdkImpl+Embedded.swift +8 -1
  39. package/ios/StripeSdkImpl+PaymentSheet.swift +44 -1
  40. package/ios/StripeSdkImpl.swift +158 -2
  41. package/jest/mock.js +26 -0
  42. package/jest/setup.js +30 -0
  43. package/lib/commonjs/components/AddToWalletButton.js +1 -1
  44. package/lib/commonjs/components/AddToWalletButton.js.map +1 -1
  45. package/lib/commonjs/components/AddressSheet.js +1 -1
  46. package/lib/commonjs/components/AddressSheet.js.map +1 -1
  47. package/lib/commonjs/components/AuBECSDebitForm.js +1 -1
  48. package/lib/commonjs/components/AuBECSDebitForm.js.map +1 -1
  49. package/lib/commonjs/components/CardField.js +1 -1
  50. package/lib/commonjs/components/CardField.js.map +1 -1
  51. package/lib/commonjs/components/CardForm.js +1 -1
  52. package/lib/commonjs/components/CardForm.js.map +1 -1
  53. package/lib/commonjs/components/PlatformPayButton.js +1 -1
  54. package/lib/commonjs/components/PlatformPayButton.js.map +1 -1
  55. package/lib/commonjs/components/StripeContainer.js +1 -1
  56. package/lib/commonjs/components/StripeContainer.js.map +1 -1
  57. package/lib/commonjs/connect/Components.js +1 -1
  58. package/lib/commonjs/connect/Components.js.map +1 -1
  59. package/lib/commonjs/connect/ConnectComponentsProvider.js +1 -1
  60. package/lib/commonjs/connect/ConnectComponentsProvider.js.map +1 -1
  61. package/lib/commonjs/connect/EmbeddedComponent.js +10 -5
  62. package/lib/commonjs/connect/EmbeddedComponent.js.map +1 -1
  63. package/lib/commonjs/connect/ModalCloseButton.js +1 -1
  64. package/lib/commonjs/connect/ModalCloseButton.js.map +1 -1
  65. package/lib/commonjs/connect/NavigationBar.js +1 -1
  66. package/lib/commonjs/connect/NavigationBar.js.map +1 -1
  67. package/lib/commonjs/connect/analytics/AnalyticsClient.js +2 -0
  68. package/lib/commonjs/connect/analytics/AnalyticsClient.js.map +1 -0
  69. package/lib/commonjs/connect/analytics/ComponentAnalyticsClient.js +2 -0
  70. package/lib/commonjs/connect/analytics/ComponentAnalyticsClient.js.map +1 -0
  71. package/lib/commonjs/connect/analytics/events.js +2 -0
  72. package/lib/commonjs/connect/analytics/events.js.map +1 -0
  73. package/lib/commonjs/connect/testUtils.js +2 -0
  74. package/lib/commonjs/connect/testUtils.js.map +1 -0
  75. package/lib/commonjs/events.js.map +1 -1
  76. package/lib/commonjs/functions.js +1 -1
  77. package/lib/commonjs/functions.js.map +1 -1
  78. package/lib/commonjs/helpers.js +1 -1
  79. package/lib/commonjs/hooks/useStripe.js +1 -1
  80. package/lib/commonjs/hooks/useStripe.js.map +1 -1
  81. package/lib/commonjs/specs/NativeAddToWalletButton.js +1 -1
  82. package/lib/commonjs/specs/NativeAddressSheet.js +1 -1
  83. package/lib/commonjs/specs/NativeApplePayButton.js +1 -1
  84. package/lib/commonjs/specs/NativeAuBECSDebitForm.js +1 -1
  85. package/lib/commonjs/specs/NativeCardField.js +1 -1
  86. package/lib/commonjs/specs/NativeCardField.js.map +1 -1
  87. package/lib/commonjs/specs/NativeCardForm.js +1 -1
  88. package/lib/commonjs/specs/NativeCardForm.js.map +1 -1
  89. package/lib/commonjs/specs/NativeConnectAccountOnboardingView.js +1 -1
  90. package/lib/commonjs/specs/NativeEmbeddedPaymentElement.js +1 -1
  91. package/lib/commonjs/specs/NativeEmbeddedPaymentElement.js.map +1 -1
  92. package/lib/commonjs/specs/NativeGooglePayButton.js +1 -1
  93. package/lib/commonjs/specs/NativeNavigationBar.js +1 -1
  94. package/lib/commonjs/specs/NativePaymentMethodMessagingElement.js +2 -0
  95. package/lib/commonjs/specs/NativePaymentMethodMessagingElement.js.map +1 -0
  96. package/lib/commonjs/specs/NativeStripeContainer.js +1 -1
  97. package/lib/commonjs/specs/NativeStripeSdkModule.js.map +1 -1
  98. package/lib/commonjs/types/EmbeddedPaymentElement.js +1 -1
  99. package/lib/commonjs/types/EmbeddedPaymentElement.js.map +1 -1
  100. package/lib/commonjs/types/Errors.js +1 -1
  101. package/lib/commonjs/types/Errors.js.map +1 -1
  102. package/lib/commonjs/types/FinancialConnections.js.map +1 -1
  103. package/lib/commonjs/types/PaymentSheet.js +1 -1
  104. package/lib/commonjs/types/PaymentSheet.js.map +1 -1
  105. package/lib/commonjs/types/components/PaymentMethodMessagingElementComponent.js +2 -0
  106. package/lib/commonjs/types/components/PaymentMethodMessagingElementComponent.js.map +1 -0
  107. package/lib/commonjs/types/index.js.map +1 -1
  108. package/lib/module/components/AddToWalletButton.js +1 -1
  109. package/lib/module/components/AddToWalletButton.js.map +1 -1
  110. package/lib/module/components/AddressSheet.js +1 -1
  111. package/lib/module/components/AddressSheet.js.map +1 -1
  112. package/lib/module/components/AuBECSDebitForm.js +1 -1
  113. package/lib/module/components/AuBECSDebitForm.js.map +1 -1
  114. package/lib/module/components/CardField.js +1 -1
  115. package/lib/module/components/CardField.js.map +1 -1
  116. package/lib/module/components/CardForm.js +1 -1
  117. package/lib/module/components/CardForm.js.map +1 -1
  118. package/lib/module/components/PlatformPayButton.js +1 -1
  119. package/lib/module/components/PlatformPayButton.js.map +1 -1
  120. package/lib/module/components/StripeContainer.js +1 -1
  121. package/lib/module/components/StripeContainer.js.map +1 -1
  122. package/lib/module/connect/Components.js +1 -1
  123. package/lib/module/connect/Components.js.map +1 -1
  124. package/lib/module/connect/ConnectComponentsProvider.js +1 -1
  125. package/lib/module/connect/ConnectComponentsProvider.js.map +1 -1
  126. package/lib/module/connect/EmbeddedComponent.js +10 -5
  127. package/lib/module/connect/EmbeddedComponent.js.map +1 -1
  128. package/lib/module/connect/ModalCloseButton.js +1 -1
  129. package/lib/module/connect/ModalCloseButton.js.map +1 -1
  130. package/lib/module/connect/NavigationBar.js +1 -1
  131. package/lib/module/connect/NavigationBar.js.map +1 -1
  132. package/lib/module/connect/analytics/AnalyticsClient.js +2 -0
  133. package/lib/module/connect/analytics/AnalyticsClient.js.map +1 -0
  134. package/lib/module/connect/analytics/ComponentAnalyticsClient.js +2 -0
  135. package/lib/module/connect/analytics/ComponentAnalyticsClient.js.map +1 -0
  136. package/lib/module/connect/analytics/events.js +2 -0
  137. package/lib/module/connect/analytics/events.js.map +1 -0
  138. package/lib/module/connect/testUtils.js +2 -0
  139. package/lib/module/connect/testUtils.js.map +1 -0
  140. package/lib/module/events.js.map +1 -1
  141. package/lib/module/functions.js +1 -1
  142. package/lib/module/functions.js.map +1 -1
  143. package/lib/module/helpers.js +1 -1
  144. package/lib/module/hooks/useStripe.js +1 -1
  145. package/lib/module/hooks/useStripe.js.map +1 -1
  146. package/lib/module/specs/NativeAddToWalletButton.js +1 -1
  147. package/lib/module/specs/NativeAddressSheet.js +1 -1
  148. package/lib/module/specs/NativeApplePayButton.js +1 -1
  149. package/lib/module/specs/NativeAuBECSDebitForm.js +1 -1
  150. package/lib/module/specs/NativeCardField.js +1 -1
  151. package/lib/module/specs/NativeCardField.js.map +1 -1
  152. package/lib/module/specs/NativeCardForm.js +1 -1
  153. package/lib/module/specs/NativeCardForm.js.map +1 -1
  154. package/lib/module/specs/NativeConnectAccountOnboardingView.js +1 -1
  155. package/lib/module/specs/NativeEmbeddedPaymentElement.js +1 -1
  156. package/lib/module/specs/NativeEmbeddedPaymentElement.js.map +1 -1
  157. package/lib/module/specs/NativeGooglePayButton.js +1 -1
  158. package/lib/module/specs/NativeNavigationBar.js +1 -1
  159. package/lib/module/specs/NativePaymentMethodMessagingElement.js +2 -0
  160. package/lib/module/specs/NativePaymentMethodMessagingElement.js.map +1 -0
  161. package/lib/module/specs/NativeStripeContainer.js +1 -1
  162. package/lib/module/specs/NativeStripeSdkModule.js.map +1 -1
  163. package/lib/module/types/EmbeddedPaymentElement.js +1 -1
  164. package/lib/module/types/EmbeddedPaymentElement.js.map +1 -1
  165. package/lib/module/types/Errors.js +1 -1
  166. package/lib/module/types/Errors.js.map +1 -1
  167. package/lib/module/types/FinancialConnections.js.map +1 -1
  168. package/lib/module/types/PaymentSheet.js +1 -1
  169. package/lib/module/types/PaymentSheet.js.map +1 -1
  170. package/lib/module/types/components/PaymentMethodMessagingElementComponent.js +2 -0
  171. package/lib/module/types/components/PaymentMethodMessagingElementComponent.js.map +1 -0
  172. package/lib/module/types/index.js.map +1 -1
  173. package/lib/typescript/src/connect/Components.d.ts +91 -0
  174. package/lib/typescript/src/connect/Components.d.ts.map +1 -1
  175. package/lib/typescript/src/connect/ConnectComponentsProvider.d.ts +61 -0
  176. package/lib/typescript/src/connect/ConnectComponentsProvider.d.ts.map +1 -1
  177. package/lib/typescript/src/connect/EmbeddedComponent.d.ts.map +1 -1
  178. package/lib/typescript/src/connect/analytics/AnalyticsClient.d.ts +32 -0
  179. package/lib/typescript/src/connect/analytics/AnalyticsClient.d.ts.map +1 -0
  180. package/lib/typescript/src/connect/analytics/ComponentAnalyticsClient.d.ts +94 -0
  181. package/lib/typescript/src/connect/analytics/ComponentAnalyticsClient.d.ts.map +1 -0
  182. package/lib/typescript/src/connect/analytics/events.d.ts +215 -0
  183. package/lib/typescript/src/connect/analytics/events.d.ts.map +1 -0
  184. package/lib/typescript/src/connect/connectTypes.d.ts +5 -1
  185. package/lib/typescript/src/connect/connectTypes.d.ts.map +1 -1
  186. package/lib/typescript/src/connect/testUtils.d.ts +45 -0
  187. package/lib/typescript/src/connect/testUtils.d.ts.map +1 -0
  188. package/lib/typescript/src/events.d.ts +2 -0
  189. package/lib/typescript/src/events.d.ts.map +1 -1
  190. package/lib/typescript/src/functions.d.ts +13 -1
  191. package/lib/typescript/src/functions.d.ts.map +1 -1
  192. package/lib/typescript/src/hooks/useStripe.d.ts +2 -1
  193. package/lib/typescript/src/hooks/useStripe.d.ts.map +1 -1
  194. package/lib/typescript/src/specs/NativePaymentMethodMessagingElement.d.ts +16 -0
  195. package/lib/typescript/src/specs/NativePaymentMethodMessagingElement.d.ts.map +1 -0
  196. package/lib/typescript/src/specs/NativeStripeSdkModule.d.ts +16 -1
  197. package/lib/typescript/src/specs/NativeStripeSdkModule.d.ts.map +1 -1
  198. package/lib/typescript/src/types/CustomerSheet.d.ts +5 -0
  199. package/lib/typescript/src/types/CustomerSheet.d.ts.map +1 -1
  200. package/lib/typescript/src/types/EmbeddedPaymentElement.d.ts +11 -1
  201. package/lib/typescript/src/types/EmbeddedPaymentElement.d.ts.map +1 -1
  202. package/lib/typescript/src/types/Errors.d.ts +4 -0
  203. package/lib/typescript/src/types/Errors.d.ts.map +1 -1
  204. package/lib/typescript/src/types/FinancialConnections.d.ts +2 -0
  205. package/lib/typescript/src/types/FinancialConnections.d.ts.map +1 -1
  206. package/lib/typescript/src/types/PaymentSheet.d.ts +35 -0
  207. package/lib/typescript/src/types/PaymentSheet.d.ts.map +1 -1
  208. package/lib/typescript/src/types/components/PaymentMethodMessagingElementComponent.d.ts +69 -0
  209. package/lib/typescript/src/types/components/PaymentMethodMessagingElementComponent.d.ts.map +1 -0
  210. package/lib/typescript/src/types/index.d.ts +8 -1
  211. package/lib/typescript/src/types/index.d.ts.map +1 -1
  212. package/package.json +4 -1
  213. package/src/connect/Components.tsx +109 -11
  214. package/src/connect/ConnectComponentsProvider.tsx +69 -2
  215. package/src/connect/EmbeddedComponent.tsx +458 -23
  216. package/src/connect/analytics/AnalyticsClient.ts +75 -0
  217. package/src/connect/analytics/ComponentAnalyticsClient.ts +315 -0
  218. package/src/connect/analytics/events.ts +253 -0
  219. package/src/connect/connectTypes.ts +5 -1
  220. package/src/connect/testUtils.ts +37 -0
  221. package/src/events.ts +2 -0
  222. package/src/functions.ts +10 -0
  223. package/src/hooks/useStripe.tsx +8 -0
  224. package/src/specs/NativePaymentMethodMessagingElement.ts +25 -0
  225. package/src/specs/NativeStripeSdkModule.ts +21 -1
  226. package/src/types/CustomerSheet.ts +5 -0
  227. package/src/types/EmbeddedPaymentElement.tsx +11 -1
  228. package/src/types/Errors.ts +5 -0
  229. package/src/types/FinancialConnections.ts +2 -0
  230. package/src/types/PaymentSheet.ts +38 -1
  231. package/src/types/components/PaymentMethodMessagingElementComponent.tsx +74 -0
  232. package/src/types/index.ts +11 -0
  233. package/stripe-react-native.podspec +1 -1
@@ -100,6 +100,7 @@ android {
100
100
  consumerProguardFiles "proguard-rules.txt"
101
101
  buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
102
102
  buildConfigField "boolean", "IS_ONRAMP_INCLUDED", isOnrampIncluded().toString()
103
+ buildConfigField "String", "STRIPE_ANDROID_SDK_VERSION", "\"${getExtOrDefault("stripeVersion")}\""
103
104
 
104
105
  ndk {
105
106
  abiFilters(*reactNativeArchitectures())
@@ -162,6 +163,7 @@ dependencies {
162
163
  implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.3.1"
163
164
  implementation("com.stripe:stripe-android:$stripeVersion")
164
165
  implementation("com.stripe:financial-connections:$stripeVersion")
166
+ implementation("com.stripe:payment-method-messaging:$stripeVersion")
165
167
 
166
168
  if (isOnrampIncluded()) {
167
169
  implementation("com.stripe:crypto-onramp:$stripeVersion")
@@ -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=22.2.+
6
+ StripeSdk_stripeVersion=22.7.+
@@ -2,12 +2,38 @@
2
2
  package="com.reactnativestripesdk">
3
3
 
4
4
  <application>
5
- <activity
5
+ <activity
6
6
  android:name=".CustomPaymentMethodActivity"
7
7
  android:theme="@style/Theme.StripeReactNative.Transparent"
8
8
  android:exported="false"
9
9
  android:launchMode="singleTop"
10
10
  android:excludeFromRecents="true"
11
11
  android:noHistory="true" />
12
+
13
+ <!-- Interceptor for stripe-connect:// deep links -->
14
+ <activity
15
+ android:name=".StripeConnectDeepLinkInterceptorActivity"
16
+ android:theme="@android:style/Theme.Translucent.NoTitleBar"
17
+ android:exported="true"
18
+ android:launchMode="singleTask"
19
+ android:excludeFromRecents="true"
20
+ android:noHistory="true">
21
+ <intent-filter>
22
+ <action android:name="android.intent.action.VIEW"/>
23
+ <category android:name="android.intent.category.DEFAULT"/>
24
+ <category android:name="android.intent.category.BROWSABLE"/>
25
+ <data android:scheme="stripe-connect"/>
26
+ </intent-filter>
27
+ </activity>
28
+
29
+ <provider
30
+ android:name="androidx.core.content.FileProvider"
31
+ android:authorities="${applicationId}.stripe.fileprovider"
32
+ android:exported="false"
33
+ android:grantUriPermissions="true">
34
+ <meta-data
35
+ android:name="android.support.FILE_PROVIDER_PATHS"
36
+ android:resource="@xml/file_paths" />
37
+ </provider>
12
38
  </application>
13
39
  </manifest>
@@ -29,7 +29,6 @@ import com.stripe.android.model.PaymentMethod
29
29
  import com.stripe.android.paymentelement.CustomPaymentMethodResult
30
30
  import com.stripe.android.paymentelement.CustomPaymentMethodResultHandler
31
31
  import com.stripe.android.paymentelement.EmbeddedPaymentElement
32
- import com.stripe.android.paymentelement.ExperimentalCustomPaymentMethodsApi
33
32
  import com.stripe.android.paymentelement.rememberEmbeddedPaymentElement
34
33
  import com.stripe.android.paymentsheet.CreateIntentResult
35
34
  import com.stripe.android.paymentsheet.PaymentSheet
@@ -44,7 +43,6 @@ enum class RowSelectionBehaviorType {
44
43
  ImmediateAction,
45
44
  }
46
45
 
47
- @OptIn(ExperimentalCustomPaymentMethodsApi::class)
48
46
  class EmbeddedPaymentElementView(
49
47
  context: Context,
50
48
  ) : StripeAbstractComposeView(context) {
@@ -77,7 +75,6 @@ class EmbeddedPaymentElementView(
77
75
  }
78
76
 
79
77
  @SuppressLint("RestrictedApi")
80
- @OptIn(ExperimentalCustomPaymentMethodsApi::class)
81
78
  @Composable
82
79
  override fun Content() {
83
80
  val type by remember { rowSelectionBehaviorType }
@@ -24,7 +24,7 @@ import com.reactnativestripesdk.utils.mapToPreferredNetworks
24
24
  import com.reactnativestripesdk.utils.parseCustomPaymentMethods
25
25
  import com.stripe.android.ExperimentalAllowsRemovalOfLastSavedPaymentMethodApi
26
26
  import com.stripe.android.paymentelement.EmbeddedPaymentElement
27
- import com.stripe.android.paymentelement.ExperimentalCustomPaymentMethodsApi
27
+ import com.stripe.android.paymentsheet.CardFundingFilteringPrivatePreview
28
28
  import com.stripe.android.paymentsheet.PaymentSheet
29
29
  import org.json.JSONArray
30
30
  import org.json.JSONObject
@@ -98,7 +98,7 @@ class EmbeddedPaymentElementViewManager :
98
98
  @SuppressLint("RestrictedApi")
99
99
  @OptIn(
100
100
  ExperimentalAllowsRemovalOfLastSavedPaymentMethodApi::class,
101
- ExperimentalCustomPaymentMethodsApi::class,
101
+ CardFundingFilteringPrivatePreview::class,
102
102
  )
103
103
  private fun parseElementConfiguration(
104
104
  map: ReadableMap,
@@ -132,6 +132,7 @@ class EmbeddedPaymentElementViewManager :
132
132
  map.getMap("billingDetailsCollectionConfiguration"),
133
133
  )
134
134
  val allowsRemovalOfLastSavedPaymentMethod = map.getBooleanOr("allowsRemovalOfLastSavedPaymentMethod", true)
135
+ val opensCardScannerAutomatically = map.getBooleanOr("opensCardScannerAutomatically", false)
135
136
  val primaryButtonLabel = map.getString("primaryButtonLabel")
136
137
  val paymentMethodOrder = map.getStringList("paymentMethodOrder")
137
138
 
@@ -156,8 +157,11 @@ class EmbeddedPaymentElementViewManager :
156
157
  ?.let { ArrayList(it) },
157
158
  ),
158
159
  ).allowsRemovalOfLastSavedPaymentMethod(allowsRemovalOfLastSavedPaymentMethod)
160
+ .opensCardScannerAutomatically(opensCardScannerAutomatically)
159
161
  .cardBrandAcceptance(mapToCardBrandAcceptance(map))
160
- .embeddedViewDisplaysMandateText(
162
+ .apply {
163
+ mapToAllowedCardFundingTypes(map)?.let { allowedCardFundingTypes(it) }
164
+ }.embeddedViewDisplaysMandateText(
161
165
  map.getBooleanOr("embeddedViewDisplaysMandateText", true),
162
166
  ).customPaymentMethods(
163
167
  parseCustomPaymentMethods(
@@ -91,4 +91,12 @@ class EventEmitterCompat(
91
91
  fun emitOnCustomPaymentMethodConfirmHandlerCallback(value: ReadableMap?) {
92
92
  invoke("onCustomPaymentMethodConfirmHandlerCallback", value)
93
93
  }
94
+
95
+ fun emitPaymentMethodMessagingElementDidUpdateHeight(value: ReadableMap?) {
96
+ invoke("paymentMethodMessagingElementDidUpdateHeight", value)
97
+ }
98
+
99
+ fun emitPaymentMethodMessagingElementConfigureResult(value: ReadableMap?) {
100
+ invoke("paymentMethodMessagingElementConfigureResult", value)
101
+ }
94
102
  }
@@ -2,7 +2,11 @@ package com.reactnativestripesdk
2
2
 
3
3
  import android.annotation.SuppressLint
4
4
  import android.graphics.Color
5
+ import android.graphics.PorterDuff
6
+ import android.graphics.PorterDuffColorFilter
7
+ import android.os.Build
5
8
  import android.view.Gravity
9
+ import android.view.View.MeasureSpec
6
10
  import android.widget.FrameLayout
7
11
  import android.widget.ImageButton
8
12
  import android.widget.TextView
@@ -18,6 +22,7 @@ class NavigationBarView(
18
22
  ) : FrameLayout(context) {
19
23
  private val toolbar: Toolbar
20
24
  private val titleTextView: TextView
25
+ private val closeButton: ImageButton
21
26
  private var titleText: String? = null
22
27
 
23
28
  init {
@@ -53,7 +58,7 @@ class NavigationBarView(
53
58
  toolbar.addView(titleTextView, titleParams)
54
59
 
55
60
  // Create close button
56
- val closeButton =
61
+ closeButton =
57
62
  ImageButton(context).apply {
58
63
  setImageDrawable(
59
64
  context.resources.getDrawable(
@@ -61,6 +66,12 @@ class NavigationBarView(
61
66
  null,
62
67
  ),
63
68
  )
69
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
70
+ drawable?.setColorFilter(android.graphics.BlendModeColorFilter(Color.BLACK, android.graphics.BlendMode.SRC_IN))
71
+ } else {
72
+ @Suppress("DEPRECATION")
73
+ drawable?.setColorFilter(PorterDuffColorFilter(Color.BLACK, PorterDuff.Mode.SRC_IN))
74
+ }
64
75
  setBackgroundColor(Color.TRANSPARENT)
65
76
  setOnClickListener {
66
77
  dispatchCloseButtonPress()
@@ -7,7 +7,9 @@ import com.reactnativestripesdk.utils.getIntOr
7
7
  import com.reactnativestripesdk.utils.getLongOr
8
8
  import com.reactnativestripesdk.utils.getStringList
9
9
  import com.reactnativestripesdk.utils.isEmpty
10
+ import com.stripe.android.model.PaymentMethod
10
11
  import com.stripe.android.paymentelement.PaymentMethodOptionsSetupFutureUsagePreview
12
+ import com.stripe.android.paymentsheet.CardFundingFilteringPrivatePreview
11
13
  import com.stripe.android.paymentsheet.PaymentSheet
12
14
 
13
15
  @Throws(PaymentSheetException::class)
@@ -76,6 +78,13 @@ private fun mapStringToLinkDisplay(value: String?): PaymentSheet.LinkConfigurati
76
78
  else -> PaymentSheet.LinkConfiguration.Display.Automatic
77
79
  }
78
80
 
81
+ internal fun computeTermsDisplayForUserKey(publishableKey: String): Map<PaymentMethod.Type, PaymentSheet.TermsDisplay> =
82
+ if (publishableKey.startsWith("uk_")) {
83
+ mapOf(PaymentMethod.Type.Card to PaymentSheet.TermsDisplay.NEVER)
84
+ } else {
85
+ emptyMap()
86
+ }
87
+
79
88
  private val mapIntToButtonType =
80
89
  mapOf(
81
90
  1 to PaymentSheet.GooglePayConfiguration.ButtonType.Buy,
@@ -226,3 +235,20 @@ internal fun mapToCardBrandCategory(brand: String): PaymentSheet.CardBrandAccept
226
235
  "discover" -> PaymentSheet.CardBrandAcceptance.BrandCategory.Discover
227
236
  else -> null
228
237
  }
238
+
239
+ @OptIn(CardFundingFilteringPrivatePreview::class)
240
+ internal fun mapToAllowedCardFundingTypes(params: ReadableMap?): List<PaymentSheet.CardFundingType>? {
241
+ val cardFundingFiltering = params?.getMap("cardFundingFiltering") ?: return null
242
+ val allowedTypes = cardFundingFiltering.getStringList("allowedCardFundingTypes") ?: return null
243
+
244
+ return allowedTypes
245
+ .mapNotNull { type ->
246
+ when (type) {
247
+ "debit" -> PaymentSheet.CardFundingType.Debit
248
+ "credit" -> PaymentSheet.CardFundingType.Credit
249
+ "prepaid" -> PaymentSheet.CardFundingType.Prepaid
250
+ "unknown" -> PaymentSheet.CardFundingType.Unknown
251
+ else -> null
252
+ }
253
+ }.ifEmpty { null }
254
+ }
@@ -0,0 +1,147 @@
1
+ @file:OptIn(PaymentMethodMessagingElementPreview::class)
2
+
3
+ package com.reactnativestripesdk
4
+
5
+ import android.content.Context
6
+ import androidx.core.graphics.toColorInt
7
+ import com.facebook.react.bridge.ReadableMap
8
+ import com.facebook.react.bridge.ReadableType
9
+ import com.reactnativestripesdk.utils.PaymentMethodMessagingElementAppearanceException
10
+ import com.reactnativestripesdk.utils.PaymentMethodMessagingElementConfigurationException
11
+ import com.reactnativestripesdk.utils.getDoubleOrNull
12
+ import com.reactnativestripesdk.utils.getStringList
13
+ import com.stripe.android.model.PaymentMethod
14
+ import com.stripe.android.paymentmethodmessaging.element.PaymentMethodMessagingElement
15
+ import com.stripe.android.paymentmethodmessaging.element.PaymentMethodMessagingElementPreview
16
+
17
+ @Throws(PaymentMethodMessagingElementConfigurationException::class)
18
+ fun parseElementConfiguration(map: ReadableMap): PaymentMethodMessagingElement.Configuration {
19
+ val amount =
20
+ map.getDoubleOrNull("amount")?.toLong()
21
+ ?: throw PaymentMethodMessagingElementConfigurationException("`amount` is required")
22
+ val currency =
23
+ map.getString("currency")
24
+ ?: throw PaymentMethodMessagingElementConfigurationException("`currency` is required")
25
+
26
+ val locale = map.getString("locale")
27
+ val countryCode = map.getString("country")
28
+ val stringPaymentMethodTypes = map.getStringList("paymentMethodTypes")
29
+ val paymentMethodTypes =
30
+ stringPaymentMethodTypes?.mapNotNull {
31
+ PaymentMethod.Type.fromCode(it)
32
+ }
33
+
34
+ val config = PaymentMethodMessagingElement.Configuration()
35
+ config.amount(amount)
36
+ config.currency(currency)
37
+ locale?.let { config.locale(it) }
38
+ countryCode?.let { config.countryCode(it) }
39
+ paymentMethodTypes?.let { config.paymentMethodTypes(it) }
40
+
41
+ return config
42
+ }
43
+
44
+ fun parseAppearance(
45
+ map: ReadableMap,
46
+ context: Context,
47
+ ): PaymentMethodMessagingElement.Appearance {
48
+ val font =
49
+ map.getMap("font")?.let {
50
+ parseFont(
51
+ it,
52
+ context,
53
+ )
54
+ }
55
+
56
+ val theme = getTheme(map)
57
+ val textColor = dynamicColorFromParams(map, "textColor", theme)
58
+ val linkTextColor = dynamicColorFromParams(map, "linkTextColor", theme)
59
+ val appearance = PaymentMethodMessagingElement.Appearance()
60
+ appearance.theme(theme)
61
+ font?.let { appearance.font(font) }
62
+ val colors = PaymentMethodMessagingElement.Appearance.Colors()
63
+ textColor?.let { colors.textColor(it) }
64
+ linkTextColor?.let { colors.infoIconColor(linkTextColor) }
65
+ appearance.colors(colors)
66
+
67
+ return appearance
68
+ }
69
+
70
+ private fun parseFont(
71
+ map: ReadableMap,
72
+ context: Context,
73
+ ): PaymentMethodMessagingElement.Appearance.Font {
74
+ val fontFamily =
75
+ getFontResId(
76
+ map,
77
+ "family",
78
+ context,
79
+ )
80
+ val scaleFactor = map.getDoubleOrNull("scale") ?: 1.0
81
+ val textSize: Double = 16 * scaleFactor
82
+
83
+ val font =
84
+ PaymentMethodMessagingElement.Appearance
85
+ .Font()
86
+ .fontFamily(fontFamily)
87
+ .fontSizeSp(textSize.toFloat())
88
+
89
+ return font
90
+ }
91
+
92
+ private fun getTheme(map: ReadableMap): PaymentMethodMessagingElement.Appearance.Theme {
93
+ val style = map.getString("style")
94
+ return when (style) {
95
+ "dark" -> PaymentMethodMessagingElement.Appearance.Theme.DARK
96
+ "flat" -> PaymentMethodMessagingElement.Appearance.Theme.FLAT
97
+ else -> PaymentMethodMessagingElement.Appearance.Theme.LIGHT
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Parses a ThemedColor from [params] at [key]. Supports both:
103
+ * - Single hex string: "#RRGGBB"
104
+ * - Light/dark object: { "light": "#RRGGBB", "dark": "#RRGGBB" }
105
+ * For light/dark objects, chooses the appropriate color based on current UI mode.
106
+ * Returns null if no color is provided.
107
+ */
108
+ private fun dynamicColorFromParams(
109
+ params: ReadableMap?,
110
+ key: String,
111
+ theme: PaymentMethodMessagingElement.Appearance.Theme,
112
+ ): Int? {
113
+ if (params == null) {
114
+ return null
115
+ }
116
+
117
+ // First check if it's a nested map { "light": "#RRGGBB", "dark": "#RRGGBB" }
118
+ if (params.hasKey(key) && params.getType(key) == ReadableType.Map) {
119
+ val colorMap = params.getMap(key)
120
+ val isDark = theme == PaymentMethodMessagingElement.Appearance.Theme.DARK
121
+
122
+ // Pick the hex for current mode, or null
123
+ val hex =
124
+ if (isDark) {
125
+ colorMap?.getString("dark")
126
+ } else {
127
+ colorMap?.getString("light")
128
+ }
129
+
130
+ return colorFromHex(hex)
131
+ }
132
+
133
+ // Check if it's a single color string
134
+ return colorFromHex(params.getString(key))
135
+ }
136
+
137
+ @Throws(PaymentMethodMessagingElementAppearanceException::class)
138
+ private fun colorFromHex(hexString: String?): Int? =
139
+ hexString?.trim()?.replace("#", "")?.let {
140
+ if (it.length == 6 || it.length == 8) {
141
+ "#$it".toColorInt()
142
+ } else {
143
+ throw PaymentMethodMessagingElementAppearanceException(
144
+ "Failed to set appearance. Expected hex string of length 6 or 8, but received: $it",
145
+ )
146
+ }
147
+ }
@@ -0,0 +1,164 @@
1
+ package com.reactnativestripesdk
2
+
3
+ import android.annotation.SuppressLint
4
+ import android.app.Application
5
+ import android.content.Context
6
+ import androidx.compose.foundation.layout.Box
7
+ import androidx.compose.runtime.Composable
8
+ import androidx.compose.runtime.LaunchedEffect
9
+ import androidx.compose.runtime.getValue
10
+ import androidx.compose.runtime.mutableStateOf
11
+ import androidx.compose.runtime.remember
12
+ import androidx.compose.runtime.setValue
13
+ import androidx.compose.ui.Modifier
14
+ import androidx.compose.ui.layout.layout
15
+ import androidx.compose.ui.layout.onSizeChanged
16
+ import androidx.compose.ui.platform.LocalDensity
17
+ import androidx.compose.ui.unit.IntOffset
18
+ import androidx.compose.ui.unit.dp
19
+ import com.facebook.react.bridge.Arguments
20
+ import com.facebook.react.uimanager.ThemedReactContext
21
+ import com.stripe.android.paymentmethodmessaging.element.PaymentMethodMessagingElement
22
+ import com.stripe.android.paymentmethodmessaging.element.PaymentMethodMessagingElementPreview
23
+ import kotlinx.coroutines.channels.Channel
24
+ import kotlinx.coroutines.flow.consumeAsFlow
25
+
26
+ @OptIn(PaymentMethodMessagingElementPreview::class)
27
+ class PaymentMethodMessagingElementView(
28
+ context: Context,
29
+ ) : StripeAbstractComposeView(context) {
30
+ private sealed interface Event {
31
+ data class Configure(
32
+ val configuration: PaymentMethodMessagingElement.Configuration,
33
+ ) : Event
34
+
35
+ data class Appearance(
36
+ val appearance: PaymentMethodMessagingElement.Appearance,
37
+ ) : Event
38
+ }
39
+
40
+ var latestElementConfig: PaymentMethodMessagingElement.Configuration? = null
41
+
42
+ private val reactContext get() = context as ThemedReactContext
43
+ private val events = Channel<Event>(Channel.UNLIMITED)
44
+
45
+ @SuppressLint("RestrictedApi")
46
+ @Composable
47
+ override fun Content() {
48
+ val messagingElement =
49
+ remember {
50
+ PaymentMethodMessagingElement.create(context.applicationContext as Application)
51
+ }
52
+ var appearance by remember { mutableStateOf(PaymentMethodMessagingElement.Appearance()) }
53
+
54
+ // collect events: configure, appearance
55
+ LaunchedEffect(Unit) {
56
+ events.consumeAsFlow().collect { ev ->
57
+ when (ev) {
58
+ is Event.Configure -> {
59
+ val loadingPayload = Arguments.createMap()
60
+ loadingPayload.putString("status", "loading")
61
+ requireStripeSdkModule().eventEmitter.emitPaymentMethodMessagingElementConfigureResult(loadingPayload)
62
+ val result =
63
+ messagingElement.configure(
64
+ configuration = ev.configuration,
65
+ )
66
+
67
+ val payload = Arguments.createMap()
68
+ when (result) {
69
+ is PaymentMethodMessagingElement.ConfigureResult.Succeeded -> {
70
+ payload.putString("status", "loaded")
71
+ }
72
+ is PaymentMethodMessagingElement.ConfigureResult.NoContent -> {
73
+ payload.putString("status", "no_content")
74
+ reportHeightChange(0f)
75
+ }
76
+ is PaymentMethodMessagingElement.ConfigureResult.Failed -> {
77
+ // send the error back to JS
78
+ val err = result.error
79
+ val msg = err.localizedMessage ?: err.toString()
80
+ // build a RN map
81
+ payload.putString("status", "failed")
82
+ payload.putString("message", msg)
83
+ reportHeightChange(0f)
84
+ }
85
+ }
86
+ requireStripeSdkModule().eventEmitter.emitPaymentMethodMessagingElementConfigureResult(payload)
87
+ }
88
+ is Event.Appearance -> {
89
+ appearance = ev.appearance
90
+ }
91
+ }
92
+ }
93
+ }
94
+
95
+ Box {
96
+ MeasureMessagingElement(
97
+ reportHeightChange = { h -> reportHeightChange(h) },
98
+ ) {
99
+ messagingElement.Content(appearance)
100
+ }
101
+ }
102
+ }
103
+
104
+ @Composable
105
+ private fun MeasureMessagingElement(
106
+ reportHeightChange: (Float) -> Unit,
107
+ content: @Composable () -> Unit,
108
+ ) {
109
+ val density = LocalDensity.current
110
+ var heightDp by remember { mutableStateOf(1.dp) } // non-zero sentinel
111
+
112
+ Box(
113
+ Modifier
114
+ // Post-layout: convert px -> dp, update RN & our dp state
115
+ .onSizeChanged { size ->
116
+ val h = with(density) { size.height.toDp() }
117
+ if (h != heightDp) {
118
+ heightDp = h
119
+ reportHeightChange(h.value) // send dp as Float to RN
120
+ }
121
+ }
122
+ // Custom measure path: force child to its min intrinsic height (in *px*)
123
+ .layout { measurable, constraints ->
124
+ val widthPx = constraints.maxWidth
125
+ val minHpx = measurable.minIntrinsicHeight(widthPx).coerceAtLeast(1)
126
+
127
+ // Measure the child with a tight height equal to min intrinsic
128
+ val placeable =
129
+ measurable.measure(
130
+ constraints.copy(
131
+ minHeight = minHpx,
132
+ maxHeight = minHpx,
133
+ ),
134
+ )
135
+
136
+ // Our own size: use the child’s measured size
137
+ layout(constraints.maxWidth, placeable.height) {
138
+ placeable.placeRelative(IntOffset.Zero)
139
+ }
140
+ },
141
+ ) {
142
+ content()
143
+ }
144
+ }
145
+
146
+ private fun reportHeightChange(height: Float) {
147
+ val params =
148
+ Arguments.createMap().apply {
149
+ putDouble("height", height.toDouble())
150
+ }
151
+ requireStripeSdkModule().eventEmitter.emitPaymentMethodMessagingElementDidUpdateHeight(params)
152
+ }
153
+
154
+ // APIs
155
+ fun configure(config: PaymentMethodMessagingElement.Configuration) {
156
+ events.trySend(Event.Configure(config))
157
+ }
158
+
159
+ fun appearance(appearance: PaymentMethodMessagingElement.Appearance) {
160
+ events.trySend(Event.Appearance(appearance))
161
+ }
162
+
163
+ private fun requireStripeSdkModule() = requireNotNull(reactContext.getNativeModule(StripeSdkModule::class.java))
164
+ }
@@ -0,0 +1,65 @@
1
+ package com.reactnativestripesdk
2
+
3
+ import com.facebook.react.bridge.Dynamic
4
+ import com.facebook.react.module.annotations.ReactModule
5
+ import com.facebook.react.uimanager.ThemedReactContext
6
+ import com.facebook.react.uimanager.ViewGroupManager
7
+ import com.facebook.react.uimanager.annotations.ReactProp
8
+ import com.facebook.react.viewmanagers.PaymentMethodMessagingElementViewManagerDelegate
9
+ import com.facebook.react.viewmanagers.PaymentMethodMessagingElementViewManagerInterface
10
+ import com.reactnativestripesdk.utils.asMapOrNull
11
+ import com.stripe.android.paymentmethodmessaging.element.PaymentMethodMessagingElementPreview
12
+
13
+ @OptIn(PaymentMethodMessagingElementPreview::class)
14
+ @ReactModule(name = PaymentMethodMessagingElementViewManager.NAME)
15
+ class PaymentMethodMessagingElementViewManager :
16
+ ViewGroupManager<PaymentMethodMessagingElementView>(),
17
+ PaymentMethodMessagingElementViewManagerInterface<PaymentMethodMessagingElementView> {
18
+ companion object {
19
+ const val NAME = "PaymentMethodMessagingElementView"
20
+ }
21
+
22
+ private val delegate = PaymentMethodMessagingElementViewManagerDelegate(this)
23
+
24
+ override fun getName() = NAME
25
+
26
+ override fun getDelegate() = delegate
27
+
28
+ override fun createViewInstance(ctx: ThemedReactContext): PaymentMethodMessagingElementView = PaymentMethodMessagingElementView(ctx)
29
+
30
+ override fun onDropViewInstance(view: PaymentMethodMessagingElementView) {
31
+ super.onDropViewInstance(view)
32
+
33
+ view.handleOnDropViewInstance()
34
+ }
35
+
36
+ override fun needsCustomLayoutForChildren(): Boolean = true
37
+
38
+ @ReactProp(name = "appearance")
39
+ override fun setAppearance(
40
+ view: PaymentMethodMessagingElementView?,
41
+ value: Dynamic?,
42
+ ) {
43
+ val readableMap = value?.asMapOrNull() ?: return
44
+ view?.let {
45
+ val appearance = parseAppearance(readableMap, view.context)
46
+ view.appearance(appearance)
47
+ }
48
+ }
49
+
50
+ @ReactProp(name = "configuration")
51
+ override fun setConfiguration(
52
+ view: PaymentMethodMessagingElementView,
53
+ cfg: Dynamic,
54
+ ) {
55
+ val readableMap = cfg.asMapOrNull() ?: return
56
+
57
+ val elementConfig = parseElementConfiguration(readableMap)
58
+ view.latestElementConfig = elementConfig
59
+ view.configure(elementConfig)
60
+ view.post {
61
+ view.requestLayout()
62
+ view.invalidate()
63
+ }
64
+ }
65
+ }
@@ -537,7 +537,7 @@ private fun dynamicColorFromParams(
537
537
  }
538
538
 
539
539
  @Throws(PaymentSheetAppearanceException::class)
540
- private fun getFontResId(
540
+ internal fun getFontResId(
541
541
  map: ReadableMap?,
542
542
  key: String,
543
543
  context: Context,