@stripe/stripe-react-native 0.65.0 → 0.65.1

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 (203) hide show
  1. package/README.md +2 -2
  2. package/android/detekt/detekt-baseline.xml +1 -66
  3. package/android/gradle.properties +3 -3
  4. package/android/src/main/java/com/reactnativestripesdk/AuBECSDebitFormView.kt +3 -1
  5. package/android/src/main/java/com/reactnativestripesdk/AuBECSDebitFormViewManager.kt +2 -1
  6. package/android/src/main/java/com/reactnativestripesdk/CardFieldView.kt +5 -1
  7. package/android/src/main/java/com/reactnativestripesdk/CurrencySelectorElementView.kt +26 -0
  8. package/android/src/main/java/com/reactnativestripesdk/CurrencySelectorElementViewManager.kt +42 -0
  9. package/android/src/main/java/com/reactnativestripesdk/EmbeddedPaymentElementView.kt +105 -49
  10. package/android/src/main/java/com/reactnativestripesdk/EmbeddedPaymentElementViewManager.kt +72 -12
  11. package/android/src/main/java/com/reactnativestripesdk/FinancialConnectionsSheetManager.kt +8 -4
  12. package/android/src/main/java/com/reactnativestripesdk/GooglePayButtonManager.kt +2 -1
  13. package/android/src/main/java/com/reactnativestripesdk/GooglePayButtonView.kt +26 -11
  14. package/android/src/main/java/com/reactnativestripesdk/GooglePayLauncherManager.kt +2 -1
  15. package/android/src/main/java/com/reactnativestripesdk/NavigationBarView.kt +14 -5
  16. package/android/src/main/java/com/reactnativestripesdk/PaymentElementConfig.kt +6 -2
  17. package/android/src/main/java/com/reactnativestripesdk/PaymentLauncherManager.kt +2 -1
  18. package/android/src/main/java/com/reactnativestripesdk/PaymentMethodCreateParamsFactory.kt +2 -1
  19. package/android/src/main/java/com/reactnativestripesdk/PaymentMethodMessagingElementConfig.kt +6 -2
  20. package/android/src/main/java/com/reactnativestripesdk/PaymentMethodMessagingElementViewManager.kt +2 -1
  21. package/android/src/main/java/com/reactnativestripesdk/PaymentOptionDisplayDataMapper.kt +8 -4
  22. package/android/src/main/java/com/reactnativestripesdk/PaymentSheetAppearance.kt +9 -3
  23. package/android/src/main/java/com/reactnativestripesdk/PaymentSheetManager.kt +110 -29
  24. package/android/src/main/java/com/reactnativestripesdk/StripeSdkModule.kt +190 -24
  25. package/android/src/main/java/com/reactnativestripesdk/StripeSdkPackage.kt +1 -0
  26. package/android/src/main/java/com/reactnativestripesdk/addresssheet/AddressLauncherManager.kt +2 -1
  27. package/android/src/main/java/com/reactnativestripesdk/addresssheet/AddressSheetView.kt +3 -1
  28. package/android/src/main/java/com/reactnativestripesdk/customersheet/CustomerSheetManager.kt +6 -2
  29. package/android/src/main/java/com/reactnativestripesdk/customersheet/ReactNativeCustomerAdapter.kt +3 -1
  30. package/android/src/main/java/com/reactnativestripesdk/customersheet/ReactNativeCustomerSessionProvider.kt +2 -1
  31. package/android/src/main/java/com/reactnativestripesdk/pushprovisioning/AddToWalletButtonManager.kt +2 -1
  32. package/android/src/main/java/com/reactnativestripesdk/utils/CheckoutAddressUpdate.kt +45 -0
  33. package/android/src/main/java/com/reactnativestripesdk/utils/CheckoutMappers.kt +101 -0
  34. package/android/src/main/java/com/reactnativestripesdk/utils/Errors.kt +4 -2
  35. package/android/src/main/java/com/reactnativestripesdk/utils/Extensions.kt +5 -1
  36. package/android/src/main/java/com/reactnativestripesdk/utils/Mappers.kt +29 -13
  37. package/android/src/main/java/com/reactnativestripesdk/utils/PostalCodeUtilities.kt +2 -1
  38. package/android/src/oldarch/java/com/facebook/react/viewmanagers/EmbeddedPaymentElementViewManagerDelegate.java +6 -0
  39. package/android/src/oldarch/java/com/facebook/react/viewmanagers/EmbeddedPaymentElementViewManagerInterface.java +2 -0
  40. package/android/src/oldarch/java/com/facebook/react/viewmanagers/StripeCurrencySelectorElementManagerDelegate.java +35 -0
  41. package/android/src/oldarch/java/com/facebook/react/viewmanagers/StripeCurrencySelectorElementManagerInterface.java +18 -0
  42. package/android/src/oldarch/java/com/reactnativestripesdk/NativeStripeSdkModuleSpec.java +8 -0
  43. package/android/src/test/java/com/reactnativestripesdk/mappers/MappersTest.kt +60 -0
  44. package/android/src/test/java/com/reactnativestripesdk/mappers/OnrampMappersTest.kt +38 -0
  45. package/android/src/test/java/com/reactnativestripesdk/mappers/PaymentOptionDisplayDataMapperTest.kt +9 -4
  46. package/android/src/test/java/com/reactnativestripesdk/utils/CheckoutMappersTest.kt +89 -0
  47. package/android/src/test/java/com/reactnativestripesdk/utils/CheckoutTestFixtures.java +49 -0
  48. package/ios/ConnectAccountOnboarding/ConnectAccountOnboardingViewController.swift +6 -8
  49. package/ios/CurrencySelectorElementManager.m +9 -0
  50. package/ios/CurrencySelectorElementManager.swift +12 -0
  51. package/ios/CurrencySelectorElementView.swift +24 -0
  52. package/ios/Mappers+Checkout.swift +193 -0
  53. package/ios/NewArch/EmbeddedPaymentElementViewComponentView.mm +16 -2
  54. package/ios/NewArch/StripeCurrencySelectorElementComponentView.h +10 -0
  55. package/ios/NewArch/StripeCurrencySelectorElementComponentView.mm +75 -0
  56. package/ios/StripeSdk.mm +123 -0
  57. package/ios/StripeSdkImpl+Checkout.swift +308 -0
  58. package/ios/StripeSdkImpl+Embedded.swift +108 -27
  59. package/ios/StripeSdkImpl+PaymentSheet.swift +18 -2
  60. package/ios/StripeSdkImpl.swift +3 -1
  61. package/jest/mock.js +13 -1
  62. package/lib/commonjs/components/AddToWalletButton.js +1 -1
  63. package/lib/commonjs/components/AddToWalletButton.js.map +1 -1
  64. package/lib/commonjs/components/AddressSheet.js +1 -1
  65. package/lib/commonjs/components/AddressSheet.js.map +1 -1
  66. package/lib/commonjs/components/AuBECSDebitForm.js +1 -1
  67. package/lib/commonjs/components/AuBECSDebitForm.js.map +1 -1
  68. package/lib/commonjs/components/CardField.js +1 -1
  69. package/lib/commonjs/components/CardField.js.map +1 -1
  70. package/lib/commonjs/components/CardForm.js +1 -1
  71. package/lib/commonjs/components/CardForm.js.map +1 -1
  72. package/lib/commonjs/components/CurrencySelectorElement.js +2 -0
  73. package/lib/commonjs/components/CurrencySelectorElement.js.map +1 -0
  74. package/lib/commonjs/components/PaymentMethodMessagingElement.js +1 -1
  75. package/lib/commonjs/components/PaymentMethodMessagingElement.js.map +1 -1
  76. package/lib/commonjs/components/PlatformPayButton.js +1 -1
  77. package/lib/commonjs/components/PlatformPayButton.js.map +1 -1
  78. package/lib/commonjs/components/StripeContainer.js +1 -1
  79. package/lib/commonjs/components/StripeContainer.js.map +1 -1
  80. package/lib/commonjs/connect/Components.js +1 -1
  81. package/lib/commonjs/connect/Components.js.map +1 -1
  82. package/lib/commonjs/connect/ConnectComponentsProvider.js +1 -1
  83. package/lib/commonjs/connect/ConnectComponentsProvider.js.map +1 -1
  84. package/lib/commonjs/connect/EmbeddedComponent.js +1 -1
  85. package/lib/commonjs/connect/EmbeddedComponent.js.map +1 -1
  86. package/lib/commonjs/connect/ModalCloseButton.js +1 -1
  87. package/lib/commonjs/connect/ModalCloseButton.js.map +1 -1
  88. package/lib/commonjs/connect/NavigationBar.js +1 -1
  89. package/lib/commonjs/connect/NavigationBar.js.map +1 -1
  90. package/lib/commonjs/events.js.map +1 -1
  91. package/lib/commonjs/functions.js +1 -1
  92. package/lib/commonjs/functions.js.map +1 -1
  93. package/lib/commonjs/helpers.js +1 -1
  94. package/lib/commonjs/hooks/useCheckout.js +1 -1
  95. package/lib/commonjs/hooks/useCheckout.js.map +1 -1
  96. package/lib/commonjs/specs/NativeAddToWalletButton.js +1 -1
  97. package/lib/commonjs/specs/NativeAddressSheet.js +1 -1
  98. package/lib/commonjs/specs/NativeApplePayButton.js +1 -1
  99. package/lib/commonjs/specs/NativeAuBECSDebitForm.js +1 -1
  100. package/lib/commonjs/specs/NativeCardField.js +1 -1
  101. package/lib/commonjs/specs/NativeCardField.js.map +1 -1
  102. package/lib/commonjs/specs/NativeCardForm.js +1 -1
  103. package/lib/commonjs/specs/NativeCardForm.js.map +1 -1
  104. package/lib/commonjs/specs/NativeConnectAccountOnboardingView.js +1 -1
  105. package/lib/commonjs/specs/NativeCurrencySelectorElement.js +2 -0
  106. package/lib/commonjs/specs/NativeCurrencySelectorElement.js.map +1 -0
  107. package/lib/commonjs/specs/NativeEmbeddedPaymentElement.js +1 -1
  108. package/lib/commonjs/specs/NativeEmbeddedPaymentElement.js.map +1 -1
  109. package/lib/commonjs/specs/NativeGooglePayButton.js +1 -1
  110. package/lib/commonjs/specs/NativeNavigationBar.js +1 -1
  111. package/lib/commonjs/specs/NativePaymentMethodMessagingElement.js +1 -1
  112. package/lib/commonjs/specs/NativeStripeContainer.js +1 -1
  113. package/lib/commonjs/specs/NativeStripeSdkModule.js.map +1 -1
  114. package/lib/commonjs/types/EmbeddedPaymentElement.js +1 -1
  115. package/lib/commonjs/types/EmbeddedPaymentElement.js.map +1 -1
  116. package/lib/module/components/AddToWalletButton.js +1 -1
  117. package/lib/module/components/AddToWalletButton.js.map +1 -1
  118. package/lib/module/components/AddressSheet.js +1 -1
  119. package/lib/module/components/AddressSheet.js.map +1 -1
  120. package/lib/module/components/AuBECSDebitForm.js +1 -1
  121. package/lib/module/components/AuBECSDebitForm.js.map +1 -1
  122. package/lib/module/components/CardField.js +1 -1
  123. package/lib/module/components/CardField.js.map +1 -1
  124. package/lib/module/components/CardForm.js +1 -1
  125. package/lib/module/components/CardForm.js.map +1 -1
  126. package/lib/module/components/CurrencySelectorElement.js +2 -0
  127. package/lib/module/components/CurrencySelectorElement.js.map +1 -0
  128. package/lib/module/components/PaymentMethodMessagingElement.js +1 -1
  129. package/lib/module/components/PaymentMethodMessagingElement.js.map +1 -1
  130. package/lib/module/components/PlatformPayButton.js +1 -1
  131. package/lib/module/components/PlatformPayButton.js.map +1 -1
  132. package/lib/module/components/StripeContainer.js +1 -1
  133. package/lib/module/components/StripeContainer.js.map +1 -1
  134. package/lib/module/connect/Components.js +1 -1
  135. package/lib/module/connect/Components.js.map +1 -1
  136. package/lib/module/connect/ConnectComponentsProvider.js +1 -1
  137. package/lib/module/connect/ConnectComponentsProvider.js.map +1 -1
  138. package/lib/module/connect/EmbeddedComponent.js +1 -1
  139. package/lib/module/connect/EmbeddedComponent.js.map +1 -1
  140. package/lib/module/connect/ModalCloseButton.js +1 -1
  141. package/lib/module/connect/ModalCloseButton.js.map +1 -1
  142. package/lib/module/connect/NavigationBar.js +1 -1
  143. package/lib/module/connect/NavigationBar.js.map +1 -1
  144. package/lib/module/events.js.map +1 -1
  145. package/lib/module/functions.js +1 -1
  146. package/lib/module/functions.js.map +1 -1
  147. package/lib/module/helpers.js +1 -1
  148. package/lib/module/hooks/useCheckout.js +1 -1
  149. package/lib/module/hooks/useCheckout.js.map +1 -1
  150. package/lib/module/specs/NativeAddToWalletButton.js +1 -1
  151. package/lib/module/specs/NativeAddressSheet.js +1 -1
  152. package/lib/module/specs/NativeApplePayButton.js +1 -1
  153. package/lib/module/specs/NativeAuBECSDebitForm.js +1 -1
  154. package/lib/module/specs/NativeCardField.js +1 -1
  155. package/lib/module/specs/NativeCardField.js.map +1 -1
  156. package/lib/module/specs/NativeCardForm.js +1 -1
  157. package/lib/module/specs/NativeCardForm.js.map +1 -1
  158. package/lib/module/specs/NativeConnectAccountOnboardingView.js +1 -1
  159. package/lib/module/specs/NativeCurrencySelectorElement.js +2 -0
  160. package/lib/module/specs/NativeCurrencySelectorElement.js.map +1 -0
  161. package/lib/module/specs/NativeEmbeddedPaymentElement.js +1 -1
  162. package/lib/module/specs/NativeEmbeddedPaymentElement.js.map +1 -1
  163. package/lib/module/specs/NativeGooglePayButton.js +1 -1
  164. package/lib/module/specs/NativeNavigationBar.js +1 -1
  165. package/lib/module/specs/NativePaymentMethodMessagingElement.js +1 -1
  166. package/lib/module/specs/NativeStripeContainer.js +1 -1
  167. package/lib/module/specs/NativeStripeSdkModule.js.map +1 -1
  168. package/lib/module/types/EmbeddedPaymentElement.js +1 -1
  169. package/lib/module/types/EmbeddedPaymentElement.js.map +1 -1
  170. package/lib/typescript/src/components/CurrencySelectorElement.d.ts +62 -0
  171. package/lib/typescript/src/components/CurrencySelectorElement.d.ts.map +1 -0
  172. package/lib/typescript/src/events.d.ts +11 -0
  173. package/lib/typescript/src/events.d.ts.map +1 -1
  174. package/lib/typescript/src/functions.d.ts.map +1 -1
  175. package/lib/typescript/src/hooks/useCheckout.d.ts.map +1 -1
  176. package/lib/typescript/src/specs/NativeCurrencySelectorElement.d.ts +25 -0
  177. package/lib/typescript/src/specs/NativeCurrencySelectorElement.d.ts.map +1 -0
  178. package/lib/typescript/src/specs/NativeEmbeddedPaymentElement.d.ts +5 -1
  179. package/lib/typescript/src/specs/NativeEmbeddedPaymentElement.d.ts.map +1 -1
  180. package/lib/typescript/src/specs/NativeStripeSdkModule.d.ts +3 -1
  181. package/lib/typescript/src/specs/NativeStripeSdkModule.d.ts.map +1 -1
  182. package/lib/typescript/src/types/Checkout.d.ts +2 -2
  183. package/lib/typescript/src/types/EmbeddedPaymentElement.d.ts +36 -1
  184. package/lib/typescript/src/types/EmbeddedPaymentElement.d.ts.map +1 -1
  185. package/package.json +14 -3
  186. package/src/components/CurrencySelectorElement.tsx +95 -0
  187. package/src/events.ts +11 -0
  188. package/src/functions.ts +30 -1
  189. package/src/hooks/useCheckout.tsx +114 -75
  190. package/src/specs/NativeCurrencySelectorElement.ts +35 -0
  191. package/src/specs/NativeEmbeddedPaymentElement.ts +12 -2
  192. package/src/specs/NativeStripeSdkModule.ts +8 -1
  193. package/src/types/Checkout.ts +2 -2
  194. package/src/types/EmbeddedPaymentElement.tsx +117 -26
  195. package/android/.idea/AndroidProjectSystem.xml +0 -6
  196. package/android/.idea/caches/deviceStreaming.xml +0 -835
  197. package/android/.idea/compiler.xml +0 -6
  198. package/android/.idea/gradle.xml +0 -17
  199. package/android/.idea/migrations.xml +0 -10
  200. package/android/.idea/misc.xml +0 -10
  201. package/android/.idea/runConfigurations.xml +0 -17
  202. package/android/.idea/vcs.xml +0 -6
  203. package/android/local.properties +0 -8
@@ -205,7 +205,9 @@ internal fun mapFromBillingDetails(billingDatails: PaymentMethod.BillingDetails?
205
205
  return details
206
206
  }
207
207
 
208
- internal fun mapFromPaymentSheetBillingDetails(billing: com.stripe.android.paymentsheet.PaymentSheet.BillingDetails?): WritableMap {
208
+ internal fun mapFromPaymentSheetBillingDetails(
209
+ billing: com.stripe.android.paymentsheet.PaymentSheet.BillingDetails?
210
+ ): WritableMap {
209
211
  val details = Arguments.createMap()
210
212
  details.putString("name", billing?.name)
211
213
  details.putString("email", billing?.email)
@@ -712,7 +714,7 @@ internal fun mapToShippingDetails(shippingDetails: ReadableMap?): ConfirmPayment
712
714
  )
713
715
  }
714
716
 
715
- private fun convertToUnixTimestamp(timestamp: Long): String = (timestamp * 1000).toString()
717
+ private fun convertToUnixTimestamp(timestamp: Long): String = (timestamp * SECONDS_TO_MILLIS).toString()
716
718
 
717
719
  fun mapToUICustomization(params: ReadableMap): PaymentAuthConfig.Stripe3ds2UiCustomization {
718
720
  val labelCustomization = params.getMap("label")
@@ -964,15 +966,15 @@ internal fun mapToPreferredNetworks(networksAsInts: List<Int>?): List<CardBrand>
964
966
 
965
967
  val intToCardBrand =
966
968
  mapOf(
967
- 0 to CardBrand.JCB,
968
- 1 to CardBrand.AmericanExpress,
969
- 2 to CardBrand.CartesBancaires,
970
- 3 to CardBrand.DinersClub,
971
- 4 to CardBrand.Discover,
972
- 5 to CardBrand.MasterCard,
973
- 6 to CardBrand.UnionPay,
974
- 7 to CardBrand.Visa,
975
- 8 to CardBrand.Unknown,
969
+ CARD_BRAND_JCB to CardBrand.JCB,
970
+ CARD_BRAND_AMEX to CardBrand.AmericanExpress,
971
+ CARD_BRAND_CARTES_BANCAIRES to CardBrand.CartesBancaires,
972
+ CARD_BRAND_DINERS_CLUB to CardBrand.DinersClub,
973
+ CARD_BRAND_DISCOVER to CardBrand.Discover,
974
+ CARD_BRAND_MASTERCARD to CardBrand.MasterCard,
975
+ CARD_BRAND_UNION_PAY to CardBrand.UnionPay,
976
+ CARD_BRAND_VISA to CardBrand.Visa,
977
+ CARD_BRAND_UNKNOWN to CardBrand.Unknown,
976
978
  )
977
979
 
978
980
  return networksAsInts.mapNotNull { intToCardBrand[it] }
@@ -1034,7 +1036,9 @@ private fun Map<String, Any?>.toReadableMap(): ReadableMap {
1034
1036
  }
1035
1037
 
1036
1038
  @SuppressLint("RestrictedApi")
1037
- internal fun parseCustomPaymentMethods(customPaymentMethodConfig: ReadableMap?): List<PaymentSheet.CustomPaymentMethod> {
1039
+ internal fun parseCustomPaymentMethods(
1040
+ customPaymentMethodConfig: ReadableMap?
1041
+ ): List<PaymentSheet.CustomPaymentMethod> {
1038
1042
  if (customPaymentMethodConfig == null) {
1039
1043
  return emptyList()
1040
1044
  }
@@ -1047,7 +1051,8 @@ internal fun parseCustomPaymentMethods(customPaymentMethodConfig: ReadableMap?):
1047
1051
  val id = customPaymentMethodMap.getString("id")
1048
1052
  if (id != null) {
1049
1053
  val subtitle = customPaymentMethodMap.getString("subtitle")
1050
- val disableBillingDetailCollection = customPaymentMethodMap.getBooleanOr("disableBillingDetailCollection", false)
1054
+ val disableBillingDetailCollection = customPaymentMethodMap
1055
+ .getBooleanOr("disableBillingDetailCollection", false)
1051
1056
  result.add(
1052
1057
  PaymentSheet.CustomPaymentMethod(
1053
1058
  id = id,
@@ -1190,3 +1195,14 @@ fun readableArrayOf(vararg elements: Any?): ReadableArray =
1190
1195
  }
1191
1196
  }
1192
1197
  }
1198
+
1199
+ private const val SECONDS_TO_MILLIS = 1000
1200
+ private const val CARD_BRAND_JCB = 0
1201
+ private const val CARD_BRAND_AMEX = 1
1202
+ private const val CARD_BRAND_CARTES_BANCAIRES = 2
1203
+ private const val CARD_BRAND_DINERS_CLUB = 3
1204
+ private const val CARD_BRAND_DISCOVER = 4
1205
+ private const val CARD_BRAND_MASTERCARD = 5
1206
+ private const val CARD_BRAND_UNION_PAY = 6
1207
+ private const val CARD_BRAND_VISA = 7
1208
+ private const val CARD_BRAND_UNKNOWN = 8
@@ -2,7 +2,8 @@ package com.reactnativestripesdk.utils
2
2
 
3
3
  class PostalCodeUtilities {
4
4
  companion object {
5
- internal fun isValidGlobalPostalCodeCharacter(c: Char): Boolean = Character.isLetterOrDigit(c) || c.isWhitespace() || c == '-'
5
+ internal fun isValidGlobalPostalCodeCharacter(c: Char): Boolean =
6
+ Character.isLetterOrDigit(c) || c.isWhitespace() || c == '-'
6
7
 
7
8
  internal fun isValidUsPostalCodeCharacter(c: Char): Boolean = Character.isDigit(c) || c.isWhitespace() || c == '-'
8
9
  }
@@ -30,6 +30,9 @@ public class EmbeddedPaymentElementViewManagerDelegate<T extends View, U extends
30
30
  case "intentConfiguration":
31
31
  mViewManager.setIntentConfiguration(view, new DynamicFromObject(value));
32
32
  break;
33
+ case "checkout":
34
+ mViewManager.setCheckout(view, new DynamicFromObject(value));
35
+ break;
33
36
  default:
34
37
  super.setProperty(view, propName, value);
35
38
  }
@@ -47,6 +50,9 @@ public class EmbeddedPaymentElementViewManagerDelegate<T extends View, U extends
47
50
  case "update":
48
51
  mViewManager.update(view, args != null ? args.getString(0) : null);
49
52
  break;
53
+ case "updateWithCheckout":
54
+ mViewManager.updateWithCheckout(view, args != null ? args.getString(0) : null);
55
+ break;
50
56
  }
51
57
  }
52
58
  }
@@ -16,7 +16,9 @@ import com.facebook.react.bridge.Dynamic;
16
16
  public interface EmbeddedPaymentElementViewManagerInterface<T extends View> {
17
17
  void setConfiguration(T view, Dynamic value);
18
18
  void setIntentConfiguration(T view, Dynamic value);
19
+ void setCheckout(T view, Dynamic value);
19
20
  void confirm(T view);
20
21
  void clearPaymentOption(T view);
21
22
  void update(T view, @Nullable String intentConfigurationJson);
23
+ void updateWithCheckout(T view, @Nullable String sessionKey);
22
24
  }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
3
+ *
4
+ * Do not edit this file as changes may cause incorrect behavior and will be lost
5
+ * once the code is regenerated.
6
+ *
7
+ * @generated by codegen project: GeneratePropsJavaDelegate.js
8
+ */
9
+
10
+ package com.facebook.react.viewmanagers;
11
+
12
+ import android.view.View;
13
+ import androidx.annotation.Nullable;
14
+ import com.facebook.react.uimanager.BaseViewManager;
15
+ import com.facebook.react.uimanager.BaseViewManagerDelegate;
16
+ import com.facebook.react.uimanager.LayoutShadowNode;
17
+
18
+ public class StripeCurrencySelectorElementManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & StripeCurrencySelectorElementManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
19
+ public StripeCurrencySelectorElementManagerDelegate(U viewManager) {
20
+ super(viewManager);
21
+ }
22
+ @Override
23
+ public void setProperty(T view, String propName, @Nullable Object value) {
24
+ switch (propName) {
25
+ case "sessionKey":
26
+ mViewManager.setSessionKey(view, value == null ? null : (String) value);
27
+ break;
28
+ case "disabled":
29
+ mViewManager.setDisabled(view, value == null ? false : (boolean) value);
30
+ break;
31
+ default:
32
+ super.setProperty(view, propName, value);
33
+ }
34
+ }
35
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
3
+ *
4
+ * Do not edit this file as changes may cause incorrect behavior and will be lost
5
+ * once the code is regenerated.
6
+ *
7
+ * @generated by codegen project: GeneratePropsJavaInterface.js
8
+ */
9
+
10
+ package com.facebook.react.viewmanagers;
11
+
12
+ import android.view.View;
13
+ import androidx.annotation.Nullable;
14
+
15
+ public interface StripeCurrencySelectorElementManagerInterface<T extends View> {
16
+ void setSessionKey(T view, @Nullable String value);
17
+ void setDisabled(T view, boolean value);
18
+ }
@@ -253,6 +253,10 @@ public abstract class NativeStripeSdkModuleSpec extends ReactContextBaseJavaModu
253
253
  @DoNotStrip
254
254
  public abstract void createEmbeddedPaymentElement(ReadableMap intentConfig, ReadableMap configuration, Promise promise);
255
255
 
256
+ @ReactMethod
257
+ @DoNotStrip
258
+ public abstract void createEmbeddedPaymentElementWithCheckout(String sessionKey, ReadableMap configuration, Promise promise);
259
+
256
260
  @ReactMethod
257
261
  @DoNotStrip
258
262
  public abstract void confirmEmbeddedPaymentElement(double viewTag, Promise promise);
@@ -261,6 +265,10 @@ public abstract class NativeStripeSdkModuleSpec extends ReactContextBaseJavaModu
261
265
  @DoNotStrip
262
266
  public abstract void updateEmbeddedPaymentElement(ReadableMap intentConfig, Promise promise);
263
267
 
268
+ @ReactMethod
269
+ @DoNotStrip
270
+ public abstract void updateEmbeddedPaymentElementWithCheckout(String sessionKey, Promise promise);
271
+
264
272
  @ReactMethod
265
273
  @DoNotStrip
266
274
  public abstract void clearEmbeddedPaymentOption(double viewTag, Promise promise);
@@ -2,6 +2,7 @@ package com.reactnativestripesdk.mappers
2
2
 
3
3
  import android.annotation.SuppressLint
4
4
  import com.facebook.react.bridge.WritableMap
5
+ import com.reactnativestripesdk.utils.buildCheckoutAddressUpdate
5
6
  import com.reactnativestripesdk.utils.createCanAddCardResult
6
7
  import com.reactnativestripesdk.utils.mapNextAction
7
8
  import com.reactnativestripesdk.utils.mapPaymentMethodType
@@ -348,6 +349,65 @@ class MappersTest {
348
349
  assertEquals("cpmt_valid", result[0].id)
349
350
  }
350
351
 
352
+ // ============================================
353
+ // buildCheckoutAddressUpdate Tests
354
+ // ============================================
355
+
356
+ @Test
357
+ fun buildCheckoutAddressUpdate_TrimsFields() {
358
+ val update =
359
+ buildCheckoutAddressUpdate(
360
+ name = " Jane Doe ",
361
+ phone = " 5551234567 ",
362
+ address =
363
+ readableMapOf(
364
+ "country" to " US ",
365
+ "line1" to " 123 Main St ",
366
+ "line2" to " Apt 4 ",
367
+ "city" to " San Francisco ",
368
+ "state" to " CA ",
369
+ "postalCode" to " 94111 ",
370
+ ),
371
+ )
372
+
373
+ assertNotNull(update)
374
+ assertEquals("Jane Doe", update!!.name)
375
+ assertEquals("5551234567", update.phone)
376
+ assertEquals("US", update.country)
377
+ assertEquals("123 Main St", update.line1)
378
+ assertEquals("Apt 4", update.line2)
379
+ assertEquals("San Francisco", update.city)
380
+ assertEquals("CA", update.state)
381
+ assertEquals("94111", update.postalCode)
382
+ }
383
+
384
+ @Test
385
+ fun buildCheckoutAddressUpdate_RequiresCountry() {
386
+ val withoutCountry =
387
+ buildCheckoutAddressUpdate(
388
+ name = "Jane Doe",
389
+ phone = "5551234567",
390
+ address =
391
+ readableMapOf(
392
+ "line1" to "123 Main St",
393
+ "city" to "San Francisco",
394
+ ),
395
+ )
396
+
397
+ val blankCountry =
398
+ buildCheckoutAddressUpdate(
399
+ name = "Jane Doe",
400
+ phone = "5551234567",
401
+ address =
402
+ readableMapOf(
403
+ "country" to " ",
404
+ ),
405
+ )
406
+
407
+ assertNull(withoutCountry)
408
+ assertNull(blankCountry)
409
+ }
410
+
351
411
  // ============================================
352
412
  // mapToAddress Tests
353
413
  // ============================================
@@ -8,9 +8,11 @@ import com.reactnativestripesdk.mapAppearance
8
8
  import com.reactnativestripesdk.mapConfig
9
9
  import com.reactnativestripesdk.mapFromKycInfo
10
10
  import com.reactnativestripesdk.mapGooglePayConfig
11
+ import com.reactnativestripesdk.mapPaymentDetailsType
11
12
  import com.reactnativestripesdk.utils.readableMapOf
12
13
  import com.stripe.android.crypto.onramp.ExperimentalCryptoOnramp
13
14
  import com.stripe.android.crypto.onramp.model.KycInfo
15
+ import com.stripe.android.crypto.onramp.model.PaymentMethodDisplayData
14
16
  import com.stripe.android.googlepaylauncher.GooglePayEnvironment
15
17
  import com.stripe.android.googlepaylauncher.GooglePayPaymentMethodLauncher
16
18
  import com.stripe.android.link.LinkAppearance.Style
@@ -363,6 +365,35 @@ class OnrampMappersTest {
363
365
  assertNull(state.primaryButton.heightDp)
364
366
  }
365
367
 
368
+ @Test
369
+ fun mapAppearance_WithPrimaryButton_HeightOnly() {
370
+ val primaryButton =
371
+ readableMapOf(
372
+ "height" to 48.0,
373
+ )
374
+ val appearanceMap =
375
+ readableMapOf(
376
+ "primaryButton" to primaryButton,
377
+ )
378
+ val state = mapAppearance(appearanceMap).build()
379
+
380
+ assertNull(state.primaryButton.cornerRadiusDp)
381
+ assertEquals(48f, state.primaryButton.heightDp)
382
+ }
383
+
384
+ @Test
385
+ fun mapAppearance_WithPrimaryButton_EmptyMap() {
386
+ val primaryButton = readableMapOf()
387
+ val appearanceMap =
388
+ readableMapOf(
389
+ "primaryButton" to primaryButton,
390
+ )
391
+ val state = mapAppearance(appearanceMap).build()
392
+
393
+ assertNull(state.primaryButton.cornerRadiusDp)
394
+ assertNull(state.primaryButton.heightDp)
395
+ }
396
+
366
397
  @Test
367
398
  fun mapAppearance_FullConfig() {
368
399
  val lightColors =
@@ -405,6 +436,13 @@ class OnrampMappersTest {
405
436
  assertEquals(48f, state.primaryButton.heightDp)
406
437
  }
407
438
 
439
+ @Test
440
+ fun mapPaymentDetailsType_MapsAllSupportedTypes() {
441
+ assertEquals("Card", mapPaymentDetailsType(PaymentMethodDisplayData.Type.Card))
442
+ assertEquals("BankAccount", mapPaymentDetailsType(PaymentMethodDisplayData.Type.BankAccount))
443
+ assertEquals("GooglePay", mapPaymentDetailsType(PaymentMethodDisplayData.Type.GooglePay))
444
+ }
445
+
408
446
  @Test
409
447
  fun mapFromKycInfo_AllFields() {
410
448
  val kycInfo =
@@ -52,7 +52,8 @@ class PaymentOptionDisplayDataMapperTest {
52
52
  val result = annotatedString.toHtmlString()
53
53
 
54
54
  Assert.assertEquals(
55
- "By continuing, you agree to our <a href=\"https://stripe.com/privacy\">Privacy Policy</a> and <a href=\"https://stripe.com/terms\">Terms of Service</a>.",
55
+ "By continuing, you agree to our <a href=\"https://stripe.com/privacy\">Privacy Policy</a>" +
56
+ " and <a href=\"https://stripe.com/terms\">Terms of Service</a>.",
56
57
  result,
57
58
  )
58
59
  }
@@ -193,7 +194,8 @@ class PaymentOptionDisplayDataMapperTest {
193
194
  val result = annotatedString.toHtmlString()
194
195
 
195
196
  Assert.assertEquals(
196
- "Visit our <b><font color=\"#0000FF\"><a href=\"https://stripe.com/privacy\">Privacy Policy</a></font></b> for details",
197
+ "Visit our <b><font color=\"#0000FF\"><a href=\"https://stripe.com/privacy\">" +
198
+ "Privacy Policy</a></font></b> for details",
197
199
  result,
198
200
  )
199
201
  }
@@ -293,7 +295,8 @@ class PaymentOptionDisplayDataMapperTest {
293
295
  val result = annotatedString.toHtmlString()
294
296
 
295
297
  Assert.assertEquals(
296
- "Check <b><a href=\"https://stripe.com\">Stripe</a></b> and <i><font color=\"#00FF00\"><a href=\"https://github.com\">GitHub</a></font></i>",
298
+ "Check <b><a href=\"https://stripe.com\">Stripe</a></b> and <i><font color=\"#00FF00\">" +
299
+ "<a href=\"https://github.com\">GitHub</a></font></i>",
297
300
  result,
298
301
  )
299
302
  }
@@ -449,7 +452,9 @@ class PaymentOptionDisplayDataMapperTest {
449
452
  val result = annotatedString.toHtmlString()
450
453
 
451
454
  Assert.assertEquals(
452
- "By continuing, you agree to <b><font color=\"#0000FF\"><u><a href=\"https://stripe.com/terms\">Terms</a></u></font></b> and <i><font color=\"#FF0000\"><a href=\"https://stripe.com/privacy\">Privacy</a></font></i>. Important details are <span style=\"background-color: #FFFF00;\">highlighted</span>.",
455
+ "By continuing, you agree to <b><font color=\"#0000FF\"><u><a href=\"https://stripe.com/terms\">" +
456
+ "Terms</a></u></font></b> and <i><font color=\"#FF0000\"><a href=\"https://stripe.com/privacy\">" +
457
+ "Privacy</a></font></i>. Important details are <span style=\"background-color: #FFFF00;\">highlighted</span>.",
453
458
  result,
454
459
  )
455
460
  }
@@ -0,0 +1,89 @@
1
+ package com.reactnativestripesdk.utils
2
+
3
+ import com.stripe.android.paymentelement.CheckoutSessionPreview
4
+ import org.junit.Assert.assertEquals
5
+ import org.junit.Assert.assertFalse
6
+ import org.junit.Assert.assertNotNull
7
+ import org.junit.Test
8
+ import org.junit.runner.RunWith
9
+ import org.robolectric.RobolectricTestRunner
10
+
11
+ @RunWith(RobolectricTestRunner::class)
12
+ @OptIn(CheckoutSessionPreview::class)
13
+ class CheckoutMappersTest {
14
+ @Test
15
+ fun mapFromCheckoutState_mapsLoadedSessionAndCurrentAndroidPlaceholders() {
16
+ val mapped =
17
+ mapFromCheckoutState(
18
+ isLoading = false,
19
+ session = CheckoutTestFixtures.fullSession(),
20
+ )
21
+
22
+ assertEquals("loaded", mapped.getString("status"))
23
+
24
+ val session = mapped.getMap("session")
25
+ assertNotNull(session)
26
+ assertEquals("cs_test_123", session!!.getString("id"))
27
+ assertEquals("unknown", session.getString("status"))
28
+ assertEquals("unknown", session.getString("paymentStatus"))
29
+ assertFalse(session.getBoolean("livemode"))
30
+ assertEquals("usd", session.getString("currency"))
31
+ assertFalse(session.hasKey("customerId"))
32
+ assertFalse(session.hasKey("customerEmail"))
33
+ assertFalse(session.hasKey("billingAddress"))
34
+ assertFalse(session.hasKey("shippingAddress"))
35
+
36
+ val totals = session.getMap("totals")
37
+ assertNotNull(totals)
38
+ assertEquals(5000.0, totals!!.getDouble("subtotal"), 0.0)
39
+ assertEquals(4044.0, totals.getDouble("total"), 0.0)
40
+ assertEquals(4044.0, totals.getDouble("due"), 0.0)
41
+ assertEquals(0.0, totals.getDouble("discount"), 0.0)
42
+ assertEquals(500.0, totals.getDouble("shipping"), 0.0)
43
+ assertEquals(294.0, totals.getDouble("tax"), 0.0)
44
+
45
+ val discounts = session.getArray("discounts")
46
+ assertNotNull(discounts)
47
+ assertEquals(0, discounts!!.size())
48
+
49
+ val lineItems = session.getArray("lineItems")
50
+ assertNotNull(lineItems)
51
+ assertEquals(2, lineItems!!.size())
52
+ assertEquals("li_item1", lineItems.getMap(0)?.getString("id"))
53
+ assertEquals("Llama Figure", lineItems.getMap(0)?.getString("name"))
54
+ assertEquals(2, lineItems.getMap(0)?.getInt("quantity"))
55
+ assertEquals(0.0, lineItems.getMap(0)?.getDouble("unitAmount") ?: -1.0, 0.0)
56
+ assertEquals("usd", lineItems.getMap(0)?.getString("currency"))
57
+ assertEquals(2499.0, lineItems.getMap(1)?.getDouble("unitAmount") ?: -1.0, 0.0)
58
+
59
+ val shippingOptions = session.getArray("shippingOptions")
60
+ assertNotNull(shippingOptions)
61
+ assertEquals(2, shippingOptions!!.size())
62
+ assertEquals("shr_standard", shippingOptions.getMap(0)?.getString("id"))
63
+ assertEquals("Standard Shipping", shippingOptions.getMap(0)?.getString("displayName"))
64
+ assertEquals(500.0, shippingOptions.getMap(0)?.getDouble("amount") ?: -1.0, 0.0)
65
+ assertEquals("usd", shippingOptions.getMap(0)?.getString("currency"))
66
+ assertFalse(shippingOptions.getMap(0)?.hasKey("deliveryEstimate") ?: true)
67
+ assertEquals("1-2 business days", shippingOptions.getMap(1)?.getString("deliveryEstimate"))
68
+ }
69
+
70
+ @Test
71
+ fun mapFromCheckoutState_mapsLoadingStateAndOmitsBlankCurrency() {
72
+ val mapped =
73
+ mapFromCheckoutState(
74
+ isLoading = true,
75
+ session = CheckoutTestFixtures.blankCurrencySession(),
76
+ )
77
+
78
+ assertEquals("loading", mapped.getString("status"))
79
+
80
+ val session = mapped.getMap("session")
81
+ assertNotNull(session)
82
+ assertEquals("cs_test_blank_currency", session!!.getString("id"))
83
+ assertFalse(session.hasKey("currency"))
84
+ assertFalse(session.hasKey("totals"))
85
+ assertEquals(0, session.getArray("lineItems")!!.size())
86
+ assertEquals(0, session.getArray("shippingOptions")!!.size())
87
+ assertEquals(0, session.getArray("discounts")!!.size())
88
+ }
89
+ }
@@ -0,0 +1,49 @@
1
+ package com.reactnativestripesdk.utils;
2
+
3
+ import com.stripe.android.checkout.CheckoutSession;
4
+ import com.stripe.android.paymentsheet.verticalmode.CurrencySelectorOptions;
5
+ import java.util.Arrays;
6
+ import java.util.Collections;
7
+
8
+ public final class CheckoutTestFixtures {
9
+ private CheckoutTestFixtures() {}
10
+
11
+ public static CheckoutSession fullSession() {
12
+ CheckoutSession.TotalSummary totals =
13
+ new CheckoutSession.TotalSummary(
14
+ 5000L,
15
+ 4044L,
16
+ 4044L,
17
+ Arrays.asList(
18
+ new CheckoutSession.DiscountAmount(500L, "SUMMER10"),
19
+ new CheckoutSession.DiscountAmount(250L, "LOYALTY5")),
20
+ Collections.singletonList(
21
+ new CheckoutSession.TaxAmount(294L, false, "Sales Tax", 6.875d)),
22
+ new CheckoutSession.ShippingRate(
23
+ "shr_standard", 500L, "Standard Shipping", "5-7 business days"),
24
+ null);
25
+
26
+ return new CheckoutSession(
27
+ "cs_test_123",
28
+ "usd",
29
+ totals,
30
+ Arrays.asList(
31
+ new CheckoutSession.LineItem("li_item1", "Llama Figure", 2, null, 1998L, 1998L),
32
+ new CheckoutSession.LineItem("li_item2", "Alpaca Plushie", 1, 2499L, 2499L, 2499L)),
33
+ Arrays.asList(
34
+ new CheckoutSession.ShippingRate("shr_standard", 500L, "Standard Shipping", null),
35
+ new CheckoutSession.ShippingRate(
36
+ "shr_express", 1500L, "Express Shipping", "1-2 business days")),
37
+ (CurrencySelectorOptions) null);
38
+ }
39
+
40
+ public static CheckoutSession blankCurrencySession() {
41
+ return new CheckoutSession(
42
+ "cs_test_blank_currency",
43
+ "",
44
+ null,
45
+ Collections.<CheckoutSession.LineItem>emptyList(),
46
+ Collections.<CheckoutSession.ShippingRate>emptyList(),
47
+ (CurrencySelectorOptions) null);
48
+ }
49
+ }
@@ -122,12 +122,10 @@ class ConnectAccountOnboardingViewController: UIViewController {
122
122
  reactContentView?.layoutIfNeeded()
123
123
  }
124
124
 
125
- override func viewWillDisappear(_ animated: Bool) {
126
- super.viewWillDisappear(animated)
127
-
128
- // If being dismissed (not just going to background), notify
129
- if isBeingDismissed {
130
- onClose?()
131
- }
132
- }
125
+ // No viewWillDisappear/isBeingDismissed handler here. The modal uses .fullScreen
126
+ // presentation which prevents swipe-to-dismiss, so the only user-initiated exit path
127
+ // is the close button (handleCloseButtonPressed). Adding isBeingDismissed here would
128
+ // cause spurious onExit events when iOS presents a child VC (e.g. ASWebAuthenticationSession
129
+ // for identity verification) over this modal — UIKit calls viewWillDisappear and reports
130
+ // isBeingDismissed = true even though the user didn't close the modal.
133
131
  }
@@ -0,0 +1,9 @@
1
+ #import <Foundation/Foundation.h>
2
+ #import <React/RCTBridgeModule.h>
3
+ #import <React/RCTViewManager.h>
4
+
5
+ @interface RCT_EXTERN_MODULE(StripeCurrencySelectorElementManager, RCTViewManager)
6
+ RCT_EXPORT_VIEW_PROPERTY(sessionKey, NSString)
7
+ RCT_EXPORT_VIEW_PROPERTY(disabled, BOOL)
8
+ RCT_EXPORT_VIEW_PROPERTY(onHeightChange, RCTDirectEventBlock)
9
+ @end
@@ -0,0 +1,12 @@
1
+ import Foundation
2
+
3
+ @objc(StripeCurrencySelectorElementManager)
4
+ class StripeCurrencySelectorElementManager: RCTViewManager {
5
+ override static func requiresMainQueueSetup() -> Bool {
6
+ return true
7
+ }
8
+
9
+ override func view() -> UIView! {
10
+ return StripeCurrencySelectorElementContainerView(frame: .zero)
11
+ }
12
+ }
@@ -0,0 +1,24 @@
1
+ import Foundation
2
+ import UIKit
3
+
4
+ /// Minimal stub so the JS-side `CurrencySelectorElement` codegen mapping
5
+ /// resolves at app launch. The real implementation (hosting
6
+ /// `Checkout.CurrencySelectorView`, height reporting, session observation)
7
+ /// lives on the full-feature branch and will replace this once that lands.
8
+ @objc(StripeCurrencySelectorElementContainerView)
9
+ public class StripeCurrencySelectorElementContainerView: UIView {
10
+ @objc public var sessionKey: String?
11
+
12
+ @objc public var disabled: Bool = false
13
+
14
+ @objc public var onHeightChange: RCTDirectEventBlock?
15
+
16
+ public override init(frame: CGRect) {
17
+ super.init(frame: frame)
18
+ }
19
+
20
+ @available(*, unavailable)
21
+ required init?(coder _: NSCoder) {
22
+ fatalError("init(coder:) has not been implemented")
23
+ }
24
+ }