@stripe/stripe-react-native 0.45.0 → 0.47.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 (80) hide show
  1. package/.env +19 -0
  2. package/CHANGELOG.md +12 -1
  3. package/README.md +1 -3
  4. package/android/build.gradle +1 -0
  5. package/android/gradle.properties +1 -1
  6. package/android/src/main/java/com/reactnativestripesdk/CollectBankAccountLauncherFragment.kt +31 -34
  7. package/android/src/main/java/com/reactnativestripesdk/EmbeddedPaymentElementView.kt +52 -10
  8. package/android/src/main/java/com/reactnativestripesdk/EmbeddedPaymentElementViewManager.kt +15 -8
  9. package/android/src/main/java/com/reactnativestripesdk/FinancialConnectionsSheetFragment.kt +3 -21
  10. package/android/src/main/java/com/reactnativestripesdk/GooglePayLauncherFragment.kt +3 -17
  11. package/android/src/main/java/com/reactnativestripesdk/GooglePayPaymentMethodLauncherFragment.kt +20 -6
  12. package/android/src/main/java/com/reactnativestripesdk/PaymentLauncherFragment.kt +63 -44
  13. package/android/src/main/java/com/reactnativestripesdk/PaymentSheetFragment.kt +17 -20
  14. package/android/src/main/java/com/reactnativestripesdk/StripeAbstractComposeView.kt +113 -0
  15. package/android/src/main/java/com/reactnativestripesdk/StripeSdkModule.kt +74 -6
  16. package/android/src/main/java/com/reactnativestripesdk/addresssheet/AddressLauncherFragment.kt +3 -17
  17. package/android/src/main/java/com/reactnativestripesdk/customersheet/CustomerSheetFragment.kt +3 -21
  18. package/android/src/main/java/com/reactnativestripesdk/utils/KeepJsAwakeTask.kt +2 -2
  19. package/android/src/main/java/com/reactnativestripesdk/utils/StripeFragment.kt +52 -0
  20. package/android/src/oldarch/java/com/facebook/react/viewmanagers/AddToWalletButtonManagerInterface.java +1 -2
  21. package/android/src/oldarch/java/com/facebook/react/viewmanagers/AddressSheetViewManagerInterface.java +1 -2
  22. package/android/src/oldarch/java/com/facebook/react/viewmanagers/ApplePayButtonManagerInterface.java +1 -2
  23. package/android/src/oldarch/java/com/facebook/react/viewmanagers/AuBECSDebitFormManagerInterface.java +1 -2
  24. package/android/src/oldarch/java/com/facebook/react/viewmanagers/CardFieldManagerInterface.java +1 -2
  25. package/android/src/oldarch/java/com/facebook/react/viewmanagers/CardFormManagerInterface.java +1 -2
  26. package/android/src/oldarch/java/com/facebook/react/viewmanagers/EmbeddedPaymentElementViewManagerInterface.java +1 -2
  27. package/android/src/oldarch/java/com/facebook/react/viewmanagers/GooglePayButtonManagerInterface.java +1 -2
  28. package/android/src/oldarch/java/com/facebook/react/viewmanagers/StripeContainerManagerInterface.java +1 -2
  29. package/android/src/oldarch/java/com/reactnativestripesdk/NativeStripeSdkModuleSpec.java +1 -2
  30. package/ios/EmbeddedPaymentElementView.swift +3 -2
  31. package/ios/NewArch/EmbeddedPaymentElementViewComponentView.h +10 -0
  32. package/ios/NewArch/EmbeddedPaymentElementViewComponentView.mm +81 -0
  33. package/ios/NewArch/GooglePayButtonComponentView.mm +9 -0
  34. package/ios/StripeSdk.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  35. package/ios/StripeSdk.xcodeproj/project.xcworkspace/xcuserdata/wooj.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  36. package/ios/StripeSdk.xcodeproj/xcuserdata/wooj.xcuserdatad/xcschemes/xcschememanagement.plist +19 -0
  37. package/lib/commonjs/components/AddToWalletButton.js +1 -1
  38. package/lib/commonjs/components/AddToWalletButton.js.map +1 -1
  39. package/lib/commonjs/components/AddressSheet.js +1 -1
  40. package/lib/commonjs/components/AddressSheet.js.map +1 -1
  41. package/lib/commonjs/components/AuBECSDebitForm.js +1 -1
  42. package/lib/commonjs/components/AuBECSDebitForm.js.map +1 -1
  43. package/lib/commonjs/components/CardField.js +1 -1
  44. package/lib/commonjs/components/CardField.js.map +1 -1
  45. package/lib/commonjs/components/CardForm.js +1 -1
  46. package/lib/commonjs/components/CardForm.js.map +1 -1
  47. package/lib/commonjs/components/PlatformPayButton.js +1 -1
  48. package/lib/commonjs/components/PlatformPayButton.js.map +1 -1
  49. package/lib/commonjs/components/StripeContainer.js +1 -1
  50. package/lib/commonjs/components/StripeContainer.js.map +1 -1
  51. package/lib/commonjs/specs/NativeEmbeddedPaymentElement.js +1 -1
  52. package/lib/commonjs/specs/NativeEmbeddedPaymentElement.js.map +1 -1
  53. package/lib/commonjs/types/EmbeddedPaymentElement.js +1 -1
  54. package/lib/commonjs/types/EmbeddedPaymentElement.js.map +1 -1
  55. package/lib/module/components/AddToWalletButton.js +1 -1
  56. package/lib/module/components/AddToWalletButton.js.map +1 -1
  57. package/lib/module/components/AddressSheet.js +1 -1
  58. package/lib/module/components/AddressSheet.js.map +1 -1
  59. package/lib/module/components/AuBECSDebitForm.js +1 -1
  60. package/lib/module/components/AuBECSDebitForm.js.map +1 -1
  61. package/lib/module/components/CardField.js +1 -1
  62. package/lib/module/components/CardField.js.map +1 -1
  63. package/lib/module/components/CardForm.js +1 -1
  64. package/lib/module/components/CardForm.js.map +1 -1
  65. package/lib/module/components/PlatformPayButton.js +1 -1
  66. package/lib/module/components/PlatformPayButton.js.map +1 -1
  67. package/lib/module/components/StripeContainer.js +1 -1
  68. package/lib/module/components/StripeContainer.js.map +1 -1
  69. package/lib/module/specs/NativeEmbeddedPaymentElement.js +1 -1
  70. package/lib/module/specs/NativeEmbeddedPaymentElement.js.map +1 -1
  71. package/lib/module/types/EmbeddedPaymentElement.js +1 -1
  72. package/lib/module/types/EmbeddedPaymentElement.js.map +1 -1
  73. package/lib/typescript/src/specs/NativeEmbeddedPaymentElement.d.ts +0 -5
  74. package/lib/typescript/src/specs/NativeEmbeddedPaymentElement.d.ts.map +1 -1
  75. package/lib/typescript/src/types/EmbeddedPaymentElement.d.ts +6 -0
  76. package/lib/typescript/src/types/EmbeddedPaymentElement.d.ts.map +1 -1
  77. package/package.json +3 -2
  78. package/src/specs/NativeEmbeddedPaymentElement.ts +1 -10
  79. package/src/types/EmbeddedPaymentElement.tsx +8 -2
  80. package/stripe-react-native.podspec +1 -1
package/.env ADDED
@@ -0,0 +1,19 @@
1
+ # Stripe API keys - see https://stripe.com/docs/development/quickstart#api-keys
2
+ STRIPE_PUBLISHABLE_KEY=pk_test
3
+ STRIPE_SECRET_KEY=sk_test
4
+
5
+ STRIPE_PUBLISHABLE_KEY_MY=pk_test
6
+ STRIPE_SECRET_KEY_MY=sk_test
7
+
8
+ STRIPE_PUBLISHABLE_KEY_MX=pk_test
9
+ STRIPE_SECRET_KEY_MX=sk_test
10
+
11
+ STRIPE_PUBLISHABLE_KEY_AU=pk_test
12
+ STRIPE_SECRET_KEY_AU=sk_test
13
+
14
+ STRIPE_PUBLISHABLE_KEY_WECHAT=pk_test
15
+ STRIPE_SECRET_KEY_WECHAT=sk_test
16
+
17
+ # Required for webhook forwarding
18
+ # See the README on how to do this with the Stripe CLI
19
+ STRIPE_WEBHOOK_SECRET=whsec_
package/CHANGELOG.md CHANGED
@@ -1,7 +1,18 @@
1
1
  # CHANGELOG
2
- ## Unreleased
2
+ ## 0.47.0 - 2025-05-21
3
+
4
+ **Features**
5
+ - Added `customerEphemeralKeySecret` and `customerSessionClientSecret` to EmbeddedPaymentElement
6
+
7
+ ## 0.46.0 - 2025-05-08
8
+
9
+ **Features**
10
+ - Added support for the Embedded Payment Element. Learn more by visiting the [docs](https://docs.stripe.com/payments/mobile/embedded).
11
+
12
+ ## 0.45.0 - 2025-04-29
3
13
 
4
14
  ** Features **
15
+ - Support for the New Architecture in React Native v0.68 or later.
5
16
  - Ability to update saved cards when using CustomerSessions (private preview)
6
17
 
7
18
  **Fixes**
package/README.md CHANGED
@@ -5,9 +5,6 @@
5
5
 
6
6
  The Stripe React Native SDK allows you to build delightful payment experiences in your native Android and iOS apps using React Native. We provide powerful and customizable UI screens and elements that can be used out-of-the-box to collect your users' payment details.
7
7
 
8
- > [!WARNING]
9
- > Until we support React Native's [New Architecture](https://reactnative.dev/blog/2024/10/23/the-new-architecture-is-here), if you are using React Native 0.76 or higher, we recommend [opting out](https://reactnative.dev/blog/2024/10/23/the-new-architecture-is-here#opt-out) of it.
10
-
11
8
  ## Getting started
12
9
 
13
10
  Get started with our [📚 integration guides](https://stripe.com/docs/payments/accept-a-payment?platform=react-native) and [example project](./CONTRIBUTING.md#running-the-example-app), or [📘 browse the SDK reference](https://stripe.dev/stripe-react-native).
@@ -78,6 +75,7 @@ to your `app.json` file, where `merchantIdentifier` is the Apple merchant ID obt
78
75
  - Android 5.0 (API level 21) and above
79
76
  - Your `compileSdkVersion` must be `34`. See [this issue](https://github.com/stripe/stripe-react-native/issues/812) for potential workarounds.
80
77
  - Android gradle plugin 4.x and above
78
+ - Kotlin 2.x and above. See [this issue](https://github.com/stripe/stripe-react-native/issues/1924#issuecomment-2867227374) for how to update the Kotlin version when using react-native 0.77 and below or Expo SDK 52.
81
79
 
82
80
  _Components_
83
81
 
@@ -235,4 +235,5 @@ dependencies {
235
235
  androidTestImplementation "org.mockito:mockito-core:3.+"
236
236
 
237
237
  implementation "androidx.compose.ui:ui:1.7.8"
238
+ implementation "androidx.compose.foundation:foundation-layout:1.7.8"
238
239
  }
@@ -3,4 +3,4 @@ StripeSdk_compileSdkVersion=30
3
3
  StripeSdk_targetSdkVersion=28
4
4
  StripeSdk_minSdkVersion=21
5
5
  # Keep StripeSdk_stripeVersion in sync with https://github.com/stripe/stripe-identity-react-native/blob/main/android/gradle.properties
6
- StripeSdk_stripeVersion=21.12.+
6
+ StripeSdk_stripeVersion=21.14.+
@@ -1,14 +1,9 @@
1
1
  package com.reactnativestripesdk
2
2
 
3
- import android.os.Bundle
4
- import android.view.LayoutInflater
5
- import android.view.View
6
- import android.view.ViewGroup
7
- import android.widget.FrameLayout
8
- import androidx.fragment.app.Fragment
9
3
  import com.facebook.react.bridge.Promise
10
4
  import com.facebook.react.bridge.ReactApplicationContext
11
5
  import com.reactnativestripesdk.utils.ErrorType
6
+ import com.reactnativestripesdk.utils.StripeFragment
12
7
  import com.reactnativestripesdk.utils.createError
13
8
  import com.reactnativestripesdk.utils.createResult
14
9
  import com.reactnativestripesdk.utils.mapFromFinancialConnectionsEvent
@@ -23,19 +18,18 @@ import com.stripe.android.payments.bankaccount.CollectBankAccountConfiguration
23
18
  import com.stripe.android.payments.bankaccount.CollectBankAccountLauncher
24
19
  import com.stripe.android.payments.bankaccount.navigation.CollectBankAccountResult
25
20
 
26
- class CollectBankAccountLauncherFragment(
27
- private val context: ReactApplicationContext,
28
- private val publishableKey: String,
29
- private val stripeAccountId: String?,
30
- private val clientSecret: String,
31
- private val isPaymentIntent: Boolean,
32
- private val collectParams: CollectBankAccountConfiguration.USBankAccount,
33
- private val promise: Promise,
34
- ) : Fragment() {
21
+ class CollectBankAccountLauncherFragment : StripeFragment() {
22
+ private lateinit var context: ReactApplicationContext
23
+ private lateinit var publishableKey: String
24
+ private var stripeAccountId: String? = null
25
+ private lateinit var clientSecret: String
26
+ private var isPaymentIntent: Boolean = false
27
+ private lateinit var collectParams: CollectBankAccountConfiguration.USBankAccount
28
+ private lateinit var promise: Promise
35
29
  private lateinit var collectBankAccountLauncher: CollectBankAccountLauncher
36
30
 
37
- override fun onCreate(savedInstanceState: Bundle?) {
38
- super.onCreate(savedInstanceState)
31
+ override fun prepare() {
32
+ collectBankAccountLauncher = createBankAccountLauncher()
39
33
 
40
34
  val stripeSdkModule: StripeSdkModule? = context.getNativeModule(StripeSdkModule::class.java)
41
35
  if (stripeSdkModule != null) {
@@ -44,23 +38,6 @@ class CollectBankAccountLauncherFragment(
44
38
  stripeSdkModule.emitOnFinancialConnectionsEvent(params)
45
39
  }
46
40
  }
47
- }
48
-
49
- override fun onCreateView(
50
- inflater: LayoutInflater,
51
- container: ViewGroup?,
52
- savedInstanceState: Bundle?,
53
- ): View {
54
- collectBankAccountLauncher = createBankAccountLauncher()
55
-
56
- return FrameLayout(requireActivity()).also { it.visibility = View.GONE }
57
- }
58
-
59
- override fun onViewCreated(
60
- view: View,
61
- savedInstanceState: Bundle?,
62
- ) {
63
- super.onViewCreated(view, savedInstanceState)
64
41
 
65
42
  if (isPaymentIntent) {
66
43
  collectBankAccountLauncher.presentWithPaymentIntent(
@@ -124,5 +101,25 @@ class CollectBankAccountLauncherFragment(
124
101
 
125
102
  companion object {
126
103
  internal const val TAG = "collect_bank_account_launcher_fragment"
104
+
105
+ fun create(
106
+ context: ReactApplicationContext,
107
+ publishableKey: String,
108
+ stripeAccountId: String? = null,
109
+ clientSecret: String,
110
+ isPaymentIntent: Boolean,
111
+ collectParams: CollectBankAccountConfiguration.USBankAccount,
112
+ promise: Promise,
113
+ ): CollectBankAccountLauncherFragment {
114
+ val instance = CollectBankAccountLauncherFragment()
115
+ instance.context = context
116
+ instance.publishableKey = publishableKey
117
+ instance.stripeAccountId = stripeAccountId
118
+ instance.clientSecret = clientSecret
119
+ instance.isPaymentIntent = isPaymentIntent
120
+ instance.collectParams = collectParams
121
+ instance.promise = promise
122
+ return instance
123
+ }
127
124
  }
128
125
  }
@@ -1,11 +1,23 @@
1
1
  package com.reactnativestripesdk
2
2
 
3
3
  import android.content.Context
4
+ import androidx.compose.foundation.layout.Box
5
+ import androidx.compose.foundation.layout.requiredHeight
4
6
  import androidx.compose.runtime.Composable
5
7
  import androidx.compose.runtime.LaunchedEffect
6
- import androidx.compose.ui.platform.AbstractComposeView
8
+ import androidx.compose.runtime.getValue
9
+ import androidx.compose.runtime.mutableIntStateOf
10
+ import androidx.compose.runtime.remember
11
+ import androidx.compose.runtime.setValue
12
+ import androidx.compose.ui.Modifier
13
+ import androidx.compose.ui.layout.layout
14
+ import androidx.compose.ui.layout.onPlaced
15
+ import androidx.compose.ui.platform.LocalDensity
16
+ import androidx.compose.ui.unit.IntOffset
17
+ import androidx.compose.ui.unit.dp
7
18
  import com.facebook.react.bridge.Arguments
8
- import com.facebook.react.bridge.ReactContext
19
+ import com.facebook.react.uimanager.ThemedReactContext
20
+ import com.reactnativestripesdk.utils.KeepJsAwakeTask
9
21
  import com.reactnativestripesdk.utils.mapFromPaymentMethod
10
22
  import com.stripe.android.paymentelement.EmbeddedPaymentElement
11
23
  import com.stripe.android.paymentelement.ExperimentalEmbeddedPaymentElementApi
@@ -20,7 +32,7 @@ import toWritableMap
20
32
  @OptIn(ExperimentalEmbeddedPaymentElementApi::class)
21
33
  class EmbeddedPaymentElementView(
22
34
  context: Context,
23
- ) : AbstractComposeView(context) {
35
+ ) : StripeAbstractComposeView(context) {
24
36
  private sealed interface Event {
25
37
  data class Configure(
26
38
  val configuration: EmbeddedPaymentElement.Configuration,
@@ -35,7 +47,7 @@ class EmbeddedPaymentElementView(
35
47
  var latestIntentConfig: PaymentSheet.IntentConfiguration? = null
36
48
  var latestElementConfig: EmbeddedPaymentElement.Configuration? = null
37
49
 
38
- private val reactContext get() = context as ReactContext
50
+ private val reactContext get() = context as ThemedReactContext
39
51
  private val events = Channel<Event>(Channel.UNLIMITED)
40
52
 
41
53
  private val builder by lazy {
@@ -53,6 +65,10 @@ class EmbeddedPaymentElementView(
53
65
  displayMessage = "An unexpected error occurred",
54
66
  )
55
67
  }
68
+
69
+ // Make sure that JS is active since the activity will be paused when stripe ui is presented.
70
+ val keepJsAwakeTask = KeepJsAwakeTask(reactContext.reactApplicationContext).apply { start() }
71
+
56
72
  val params =
57
73
  Arguments.createMap().apply {
58
74
  putMap("paymentMethod", mapFromPaymentMethod(paymentMethod))
@@ -65,6 +81,8 @@ class EmbeddedPaymentElementView(
65
81
  // reset the completable
66
82
  stripeSdkModule.embeddedIntentCreationCallback = CompletableDeferred()
67
83
 
84
+ keepJsAwakeTask.stop()
85
+
68
86
  resultFromJavascript.getString("clientSecret")?.let {
69
87
  CreateIntentResult.Success(clientSecret = it)
70
88
  } ?: run {
@@ -99,6 +117,9 @@ class EmbeddedPaymentElementView(
99
117
  @Composable
100
118
  override fun Content() {
101
119
  val embedded = rememberEmbeddedPaymentElement(builder)
120
+ var height by remember {
121
+ mutableIntStateOf(0)
122
+ }
102
123
 
103
124
  // collect events: configure, confirm, clear
104
125
  LaunchedEffect(Unit) {
@@ -113,9 +134,7 @@ class EmbeddedPaymentElementView(
113
134
  )
114
135
 
115
136
  when (result) {
116
- is EmbeddedPaymentElement.ConfigureResult.Succeeded -> {
117
- reportHeightChange(450)
118
- }
137
+ is EmbeddedPaymentElement.ConfigureResult.Succeeded -> reportHeightChange(1f)
119
138
  is EmbeddedPaymentElement.ConfigureResult.Failed -> {
120
139
  // send the error back to JS
121
140
  val err = result.error
@@ -151,13 +170,36 @@ class EmbeddedPaymentElementView(
151
170
  }
152
171
  }
153
172
 
154
- embedded.Content()
173
+ val density = LocalDensity.current
174
+
175
+ Box(
176
+ modifier =
177
+ Modifier
178
+ .requiredHeight(height.dp)
179
+ .layout { measurable, constraints ->
180
+ val minIntrinsicHeight = measurable.minIntrinsicHeight(constraints.maxWidth)
181
+
182
+ height = minIntrinsicHeight
183
+
184
+ layout(constraints.maxWidth, minIntrinsicHeight) {
185
+ measurable.measure(constraints).placeRelative(IntOffset.Zero)
186
+ }
187
+ }.onPlaced {
188
+ reportHeightChange(
189
+ with(density) {
190
+ height.toDp().value
191
+ },
192
+ )
193
+ },
194
+ ) {
195
+ embedded.Content()
196
+ }
155
197
  }
156
198
 
157
- private fun reportHeightChange(height: Int) {
199
+ private fun reportHeightChange(height: Float) {
158
200
  val params =
159
201
  Arguments.createMap().apply {
160
- putInt("height", height)
202
+ putDouble("height", height.toDouble())
161
203
  }
162
204
  requireStripeSdkModule().emitEmbeddedPaymentElementDidUpdateHeight(params)
163
205
  }
@@ -2,7 +2,6 @@ package com.reactnativestripesdk
2
2
 
3
3
  import android.annotation.SuppressLint
4
4
  import android.content.Context
5
- import androidx.compose.ui.platform.ViewCompositionStrategy
6
5
  import com.facebook.react.bridge.Dynamic
7
6
  import com.facebook.react.bridge.ReadableArray
8
7
  import com.facebook.react.bridge.ReadableMap
@@ -40,12 +39,13 @@ class EmbeddedPaymentElementViewManager :
40
39
 
41
40
  override fun getDelegate() = delegate
42
41
 
43
- override fun createViewInstance(ctx: ThemedReactContext): EmbeddedPaymentElementView =
44
- EmbeddedPaymentElementView(ctx).apply {
45
- setViewCompositionStrategy(
46
- ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed,
47
- )
48
- }
42
+ override fun createViewInstance(ctx: ThemedReactContext): EmbeddedPaymentElementView = EmbeddedPaymentElementView(ctx)
43
+
44
+ override fun onDropViewInstance(view: EmbeddedPaymentElementView) {
45
+ super.onDropViewInstance(view)
46
+
47
+ view.handleOnDropViewInstance()
48
+ }
49
49
 
50
50
  override fun needsCustomLayoutForChildren(): Boolean = true
51
51
 
@@ -85,7 +85,14 @@ class EmbeddedPaymentElementViewManager :
85
85
  context: Context,
86
86
  ): EmbeddedPaymentElement.Configuration {
87
87
  val merchantDisplayName = map.getString("merchantDisplayName").orEmpty()
88
- val allowsDelayedPaymentMethods = map.getBoolean("allowsDelayedPaymentMethods")
88
+ val allowsDelayedPaymentMethods: Boolean =
89
+ if (map.hasKey("allowsDelayedPaymentMethods") &&
90
+ map.getType("allowsDelayedPaymentMethods") == ReadableType.Boolean
91
+ ) {
92
+ map.getBoolean("allowsDelayedPaymentMethods")
93
+ } else {
94
+ false // default
95
+ }
89
96
  var defaultBillingDetails: PaymentSheet.BillingDetails? = null
90
97
  val billingDetailsMap = map.getMap("defaultBillingDetails")
91
98
  if (billingDetailsMap != null) {
@@ -1,11 +1,5 @@
1
1
  package com.reactnativestripesdk
2
2
 
3
- import android.os.Bundle
4
- import android.view.LayoutInflater
5
- import android.view.View
6
- import android.view.ViewGroup
7
- import android.widget.FrameLayout
8
- import androidx.fragment.app.Fragment
9
3
  import androidx.fragment.app.FragmentActivity
10
4
  import com.facebook.react.bridge.Arguments
11
5
  import com.facebook.react.bridge.Promise
@@ -15,6 +9,7 @@ import com.facebook.react.bridge.WritableArray
15
9
  import com.facebook.react.bridge.WritableMap
16
10
  import com.facebook.react.bridge.WritableNativeMap
17
11
  import com.reactnativestripesdk.utils.ErrorType
12
+ import com.reactnativestripesdk.utils.StripeFragment
18
13
  import com.reactnativestripesdk.utils.createError
19
14
  import com.reactnativestripesdk.utils.createMissingActivityError
20
15
  import com.reactnativestripesdk.utils.mapFromFinancialConnectionsEvent
@@ -29,7 +24,7 @@ import com.stripe.android.financialconnections.model.FinancialConnectionsAccount
29
24
  import com.stripe.android.financialconnections.model.FinancialConnectionsAccountList
30
25
  import com.stripe.android.financialconnections.model.FinancialConnectionsSession
31
26
 
32
- class FinancialConnectionsSheetFragment : Fragment() {
27
+ class FinancialConnectionsSheetFragment : StripeFragment() {
33
28
  enum class Mode {
34
29
  ForToken,
35
30
  ForSession,
@@ -40,26 +35,13 @@ class FinancialConnectionsSheetFragment : Fragment() {
40
35
  private lateinit var configuration: FinancialConnectionsSheet.Configuration
41
36
  private lateinit var mode: Mode
42
37
 
43
- override fun onCreate(savedInstanceState: Bundle?) {
44
- super.onCreate(savedInstanceState)
45
-
38
+ override fun prepare() {
46
39
  val stripeSdkModule: StripeSdkModule? = context.getNativeModule(StripeSdkModule::class.java)
47
40
  FinancialConnections.setEventListener { event ->
48
41
  val params = mapFromFinancialConnectionsEvent(event)
49
42
  stripeSdkModule?.emitOnFinancialConnectionsEvent(params)
50
43
  }
51
- }
52
44
 
53
- override fun onCreateView(
54
- inflater: LayoutInflater,
55
- container: ViewGroup?,
56
- savedInstanceState: Bundle?,
57
- ): View = FrameLayout(requireActivity()).also { it.visibility = View.GONE }
58
-
59
- override fun onViewCreated(
60
- view: View,
61
- savedInstanceState: Bundle?,
62
- ) {
63
45
  when (mode) {
64
46
  Mode.ForToken -> {
65
47
  FinancialConnectionsSheet
@@ -1,17 +1,12 @@
1
1
  package com.reactnativestripesdk
2
2
 
3
- import android.os.Bundle
4
- import android.view.LayoutInflater
5
- import android.view.View
6
- import android.view.ViewGroup
7
- import android.widget.FrameLayout
8
- import androidx.fragment.app.Fragment
9
3
  import androidx.fragment.app.FragmentActivity
10
4
  import com.facebook.react.bridge.ReactApplicationContext
11
5
  import com.facebook.react.bridge.ReadableMap
12
6
  import com.facebook.react.bridge.WritableMap
13
7
  import com.reactnativestripesdk.utils.ErrorType
14
8
  import com.reactnativestripesdk.utils.GooglePayErrorType
9
+ import com.reactnativestripesdk.utils.StripeFragment
15
10
  import com.reactnativestripesdk.utils.createError
16
11
  import com.reactnativestripesdk.utils.createMissingActivityError
17
12
  import com.reactnativestripesdk.utils.getBooleanOr
@@ -19,7 +14,7 @@ import com.reactnativestripesdk.utils.getIntOrNull
19
14
  import com.stripe.android.googlepaylauncher.GooglePayEnvironment
20
15
  import com.stripe.android.googlepaylauncher.GooglePayLauncher
21
16
 
22
- class GooglePayLauncherFragment : Fragment() {
17
+ class GooglePayLauncherFragment : StripeFragment() {
23
18
  enum class Mode {
24
19
  ForSetup,
25
20
  ForPayment,
@@ -34,16 +29,7 @@ class GooglePayLauncherFragment : Fragment() {
34
29
  private var label: String? = null
35
30
  private lateinit var callback: (result: GooglePayLauncher.Result?, error: WritableMap?) -> Unit
36
31
 
37
- override fun onCreateView(
38
- inflater: LayoutInflater,
39
- container: ViewGroup?,
40
- savedInstanceState: Bundle?,
41
- ): View = FrameLayout(requireActivity()).also { it.visibility = View.GONE }
42
-
43
- override fun onViewCreated(
44
- view: View,
45
- savedInstanceState: Bundle?,
46
- ) {
32
+ override fun prepare() {
47
33
  launcher =
48
34
  GooglePayLauncher(
49
35
  fragment = this,
@@ -12,12 +12,12 @@ import com.reactnativestripesdk.utils.removeFragment
12
12
  import com.stripe.android.googlepaylauncher.GooglePayEnvironment
13
13
  import com.stripe.android.googlepaylauncher.GooglePayPaymentMethodLauncher
14
14
 
15
- class GooglePayPaymentMethodLauncherFragment(
16
- private val context: ReactApplicationContext,
17
- private val isTestEnv: Boolean,
18
- private val paymentMethodRequired: Boolean,
19
- private val promise: Promise,
20
- ) : Fragment() {
15
+ class GooglePayPaymentMethodLauncherFragment : Fragment() {
16
+ private lateinit var context: ReactApplicationContext
17
+ private var isTestEnv = false
18
+ private var paymentMethodRequired = false
19
+ private lateinit var promise: Promise
20
+
21
21
  override fun onCreateView(
22
22
  inflater: LayoutInflater,
23
23
  container: ViewGroup?,
@@ -50,5 +50,19 @@ class GooglePayPaymentMethodLauncherFragment(
50
50
 
51
51
  companion object {
52
52
  const val TAG = "google_pay_support_fragment"
53
+
54
+ fun create(
55
+ context: ReactApplicationContext,
56
+ isTestEnv: Boolean,
57
+ paymentMethodRequired: Boolean,
58
+ promise: Promise,
59
+ ): GooglePayPaymentMethodLauncherFragment {
60
+ val instance = GooglePayPaymentMethodLauncherFragment()
61
+ instance.context = context
62
+ instance.isTestEnv = isTestEnv
63
+ instance.paymentMethodRequired = paymentMethodRequired
64
+ instance.promise = promise
65
+ return instance
66
+ }
53
67
  }
54
68
  }
@@ -1,17 +1,12 @@
1
1
  package com.reactnativestripesdk
2
2
 
3
- import android.os.Bundle
4
- import android.view.LayoutInflater
5
- import android.view.View
6
- import android.view.ViewGroup
7
- import android.widget.FrameLayout
8
- import androidx.fragment.app.Fragment
9
3
  import androidx.fragment.app.FragmentActivity
10
4
  import com.facebook.react.bridge.Promise
11
5
  import com.facebook.react.bridge.ReactApplicationContext
12
6
  import com.reactnativestripesdk.utils.ConfirmPaymentErrorType
13
7
  import com.reactnativestripesdk.utils.ConfirmSetupIntentErrorType
14
8
  import com.reactnativestripesdk.utils.ErrorType
9
+ import com.reactnativestripesdk.utils.StripeFragment
15
10
  import com.reactnativestripesdk.utils.createError
16
11
  import com.reactnativestripesdk.utils.createMissingActivityError
17
12
  import com.reactnativestripesdk.utils.createResult
@@ -29,26 +24,57 @@ import com.stripe.android.payments.paymentlauncher.PaymentLauncher
29
24
  import com.stripe.android.payments.paymentlauncher.PaymentResult
30
25
 
31
26
  /** Instances of this class should only be initialized with the companion's helper methods. */
32
- class PaymentLauncherFragment(
33
- private val context: ReactApplicationContext,
34
- private val stripe: Stripe,
35
- private val publishableKey: String,
36
- private val stripeAccountId: String?,
37
- private val promise: Promise,
27
+ class PaymentLauncherFragment : StripeFragment() {
28
+ private lateinit var context: ReactApplicationContext
29
+ private lateinit var stripe: Stripe
30
+ private lateinit var publishableKey: String
31
+ private var stripeAccountId: String? = null
32
+ private lateinit var promise: Promise
33
+
38
34
  // Used when confirming a payment intent
39
- private val paymentIntentClientSecret: String? = null,
40
- private val confirmPaymentParams: ConfirmPaymentIntentParams? = null,
35
+ private var paymentIntentClientSecret: String? = null
36
+ private var confirmPaymentParams: ConfirmPaymentIntentParams? = null
37
+
41
38
  // Used when confirming a setup intent
42
- private val setupIntentClientSecret: String? = null,
43
- private val confirmSetupParams: ConfirmSetupIntentParams? = null,
39
+ private var setupIntentClientSecret: String? = null
40
+ private var confirmSetupParams: ConfirmSetupIntentParams? = null
41
+
44
42
  // Used when handling the next action on a payment intent
45
- private val handleNextActionPaymentIntentClientSecret: String? = null,
43
+ private var handleNextActionPaymentIntentClientSecret: String? = null
44
+
46
45
  // Used when handling the next action on a setup intent
47
- private val handleNextActionSetupIntentClientSecret: String? = null,
48
- ) : Fragment() {
46
+ private var handleNextActionSetupIntentClientSecret: String? = null
49
47
  private lateinit var paymentLauncher: PaymentLauncher
50
48
 
51
49
  companion object {
50
+ private fun create(
51
+ context: ReactApplicationContext,
52
+ stripe: Stripe,
53
+ publishableKey: String,
54
+ stripeAccountId: String?,
55
+ promise: Promise,
56
+ paymentIntentClientSecret: String? = null,
57
+ confirmPaymentParams: ConfirmPaymentIntentParams? = null,
58
+ setupIntentClientSecret: String? = null,
59
+ confirmSetupParams: ConfirmSetupIntentParams? = null,
60
+ handleNextActionPaymentIntentClientSecret: String? = null,
61
+ handleNextActionSetupIntentClientSecret: String? = null,
62
+ ): PaymentLauncherFragment {
63
+ val instance = PaymentLauncherFragment()
64
+ instance.context = context
65
+ instance.stripe = stripe
66
+ instance.publishableKey = publishableKey
67
+ instance.stripeAccountId = stripeAccountId
68
+ instance.promise = promise
69
+ instance.paymentIntentClientSecret = paymentIntentClientSecret
70
+ instance.confirmPaymentParams = confirmPaymentParams
71
+ instance.setupIntentClientSecret = setupIntentClientSecret
72
+ instance.confirmSetupParams = confirmSetupParams
73
+ instance.handleNextActionPaymentIntentClientSecret = handleNextActionPaymentIntentClientSecret
74
+ instance.handleNextActionSetupIntentClientSecret = handleNextActionSetupIntentClientSecret
75
+ return instance
76
+ }
77
+
52
78
  /** Helper-constructor used for confirming payment intents */
53
79
  fun forPayment(
54
80
  context: ReactApplicationContext,
@@ -60,7 +86,7 @@ class PaymentLauncherFragment(
60
86
  confirmPaymentParams: ConfirmPaymentIntentParams,
61
87
  ): PaymentLauncherFragment {
62
88
  val paymentLauncherFragment =
63
- PaymentLauncherFragment(
89
+ create(
64
90
  context,
65
91
  stripe,
66
92
  publishableKey,
@@ -84,7 +110,7 @@ class PaymentLauncherFragment(
84
110
  confirmSetupParams: ConfirmSetupIntentParams,
85
111
  ): PaymentLauncherFragment {
86
112
  val paymentLauncherFragment =
87
- PaymentLauncherFragment(
113
+ create(
88
114
  context,
89
115
  stripe,
90
116
  publishableKey,
@@ -107,7 +133,7 @@ class PaymentLauncherFragment(
107
133
  handleNextActionPaymentIntentClientSecret: String,
108
134
  ): PaymentLauncherFragment {
109
135
  val paymentLauncherFragment =
110
- PaymentLauncherFragment(
136
+ create(
111
137
  context,
112
138
  stripe,
113
139
  publishableKey,
@@ -129,7 +155,7 @@ class PaymentLauncherFragment(
129
155
  handleNextActionSetupIntentClientSecret: String,
130
156
  ): PaymentLauncherFragment {
131
157
  val paymentLauncherFragment =
132
- PaymentLauncherFragment(
158
+ create(
133
159
  context,
134
160
  stripe,
135
161
  publishableKey,
@@ -161,43 +187,36 @@ class PaymentLauncherFragment(
161
187
  internal const val TAG = "payment_launcher_fragment"
162
188
  }
163
189
 
164
- override fun onCreateView(
165
- inflater: LayoutInflater,
166
- container: ViewGroup?,
167
- savedInstanceState: Bundle?,
168
- ): View {
190
+ override fun prepare() {
169
191
  paymentLauncher = createPaymentLauncher()
170
192
  if (paymentIntentClientSecret != null && confirmPaymentParams != null) {
171
- paymentLauncher.confirm(confirmPaymentParams)
193
+ paymentLauncher.confirm(confirmPaymentParams!!)
172
194
  } else if (setupIntentClientSecret != null && confirmSetupParams != null) {
173
- paymentLauncher.confirm(confirmSetupParams)
195
+ paymentLauncher.confirm(confirmSetupParams!!)
174
196
  } else if (handleNextActionPaymentIntentClientSecret != null) {
175
- paymentLauncher.handleNextActionForPaymentIntent(handleNextActionPaymentIntentClientSecret)
197
+ paymentLauncher.handleNextActionForPaymentIntent(handleNextActionPaymentIntentClientSecret!!)
176
198
  } else if (handleNextActionSetupIntentClientSecret != null) {
177
- paymentLauncher.handleNextActionForSetupIntent(handleNextActionSetupIntentClientSecret)
199
+ paymentLauncher.handleNextActionForSetupIntent(handleNextActionSetupIntentClientSecret!!)
178
200
  } else {
179
201
  throw Exception(
180
202
  "Invalid parameters provided to PaymentLauncher. Ensure that you are providing the correct client secret and setup params (if necessary).",
181
203
  )
182
204
  }
183
- return FrameLayout(requireActivity()).also { it.visibility = View.GONE }
184
205
  }
185
206
 
186
207
  private fun createPaymentLauncher(): PaymentLauncher =
187
208
  PaymentLauncher.create(this, publishableKey, stripeAccountId) { paymentResult ->
188
209
  when (paymentResult) {
189
210
  is PaymentResult.Completed -> {
190
- if (paymentIntentClientSecret != null) {
191
- retrievePaymentIntent(paymentIntentClientSecret, stripeAccountId)
192
- } else if (handleNextActionPaymentIntentClientSecret != null) {
193
- retrievePaymentIntent(handleNextActionPaymentIntentClientSecret, stripeAccountId)
194
- } else if (setupIntentClientSecret != null) {
195
- retrieveSetupIntent(setupIntentClientSecret, stripeAccountId)
196
- } else if (handleNextActionSetupIntentClientSecret != null) {
197
- retrieveSetupIntent(handleNextActionSetupIntentClientSecret, stripeAccountId)
198
- } else {
199
- throw Exception("Failed to create Payment Launcher. No client secret provided.")
200
- }
211
+ paymentIntentClientSecret?.let {
212
+ retrievePaymentIntent(it, stripeAccountId)
213
+ } ?: handleNextActionPaymentIntentClientSecret?.let {
214
+ retrievePaymentIntent(it, stripeAccountId)
215
+ } ?: setupIntentClientSecret?.let {
216
+ retrieveSetupIntent(it, stripeAccountId)
217
+ } ?: handleNextActionSetupIntentClientSecret?.let {
218
+ retrieveSetupIntent(it, stripeAccountId)
219
+ } ?: throw Exception("Failed to create Payment Launcher. No client secret provided.")
201
220
  }
202
221
  is PaymentResult.Canceled -> {
203
222
  promise.resolve(createError(ConfirmPaymentErrorType.Canceled.toString(), message = null))