@stripe/stripe-react-native 0.49.0 → 0.50.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 (120) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +1 -1
  3. package/android/.gradle/8.11.1/checksums/checksums.lock +0 -0
  4. package/android/.gradle/8.11.1/checksums/md5-checksums.bin +0 -0
  5. package/android/.gradle/8.11.1/checksums/sha1-checksums.bin +0 -0
  6. package/android/.gradle/8.11.1/executionHistory/executionHistory.lock +0 -0
  7. package/android/.gradle/8.11.1/fileChanges/last-build.bin +0 -0
  8. package/android/.gradle/8.11.1/fileHashes/fileHashes.lock +0 -0
  9. package/android/.gradle/8.11.1/gc.properties +0 -0
  10. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  11. package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
  12. package/android/.gradle/vcs-1/gc.properties +0 -0
  13. package/android/src/main/AndroidManifest.xml +10 -0
  14. package/android/src/main/java/com/reactnativestripesdk/CustomPaymentMethodActivity.kt +81 -0
  15. package/android/src/main/java/com/reactnativestripesdk/EmbeddedPaymentElementView.kt +96 -1
  16. package/android/src/main/java/com/reactnativestripesdk/EmbeddedPaymentElementViewManager.kt +26 -5
  17. package/android/src/main/java/com/reactnativestripesdk/PaymentMethodCreateParamsFactory.kt +0 -17
  18. package/android/src/main/java/com/reactnativestripesdk/PaymentSheetAppearance.kt +17 -6
  19. package/android/src/main/java/com/reactnativestripesdk/PaymentSheetFragment.kt +116 -20
  20. package/android/src/main/java/com/reactnativestripesdk/StripeSdkModule.kt +22 -0
  21. package/android/src/main/java/com/reactnativestripesdk/customersheet/CustomerSheetFragment.kt +1 -1
  22. package/android/src/main/java/com/reactnativestripesdk/pushprovisioning/AddToWalletButtonManager.kt +6 -2
  23. package/android/src/main/java/com/reactnativestripesdk/utils/Mappers.kt +52 -6
  24. package/android/src/main/res/values/styles.xml +27 -0
  25. package/android/src/oldarch/java/com/reactnativestripesdk/NativeStripeSdkModuleSpec.java +8 -0
  26. package/ios/ApplePayButtonManager.m +4 -0
  27. package/ios/ApplePayButtonView.swift +11 -4
  28. package/ios/Mappers.swift +0 -5
  29. package/ios/NewArch/ApplePayButtonComponentView.mm +6 -0
  30. package/ios/OldArch/StripeSdkEventEmitterCompat.h +1 -1
  31. package/ios/OldArch/StripeSdkEventEmitterCompat.m +7 -1
  32. package/ios/PaymentMethodFactory.swift +0 -17
  33. package/ios/PaymentSheetAppearance.swift +81 -67
  34. package/ios/StripeSdk.mm +7 -0
  35. package/ios/StripeSdkEmitter.swift +1 -0
  36. package/ios/StripeSdkImpl+Embedded.swift +39 -17
  37. package/ios/StripeSdkImpl+PaymentSheet.swift +114 -1
  38. package/ios/StripeSdkImpl.swift +38 -9
  39. package/lib/commonjs/components/AddToWalletButton.js +1 -1
  40. package/lib/commonjs/components/AddToWalletButton.js.map +1 -1
  41. package/lib/commonjs/components/AddressSheet.js +1 -1
  42. package/lib/commonjs/components/AddressSheet.js.map +1 -1
  43. package/lib/commonjs/components/AuBECSDebitForm.js +1 -1
  44. package/lib/commonjs/components/AuBECSDebitForm.js.map +1 -1
  45. package/lib/commonjs/components/CardField.js +1 -1
  46. package/lib/commonjs/components/CardField.js.map +1 -1
  47. package/lib/commonjs/components/CardForm.js +1 -1
  48. package/lib/commonjs/components/CardForm.js.map +1 -1
  49. package/lib/commonjs/components/PlatformPayButton.js +1 -1
  50. package/lib/commonjs/components/PlatformPayButton.js.map +1 -1
  51. package/lib/commonjs/components/StripeContainer.js +1 -1
  52. package/lib/commonjs/components/StripeContainer.js.map +1 -1
  53. package/lib/commonjs/events.js.map +1 -1
  54. package/lib/commonjs/functions.js +1 -1
  55. package/lib/commonjs/functions.js.map +1 -1
  56. package/lib/commonjs/specs/NativeApplePayButton.js +1 -1
  57. package/lib/commonjs/specs/NativeApplePayButton.js.map +1 -1
  58. package/lib/commonjs/specs/NativeStripeSdkModule.js.map +1 -1
  59. package/lib/commonjs/types/EmbeddedPaymentElement.js +1 -1
  60. package/lib/commonjs/types/EmbeddedPaymentElement.js.map +1 -1
  61. package/lib/commonjs/types/PaymentIntent.js.map +1 -1
  62. package/lib/commonjs/types/PaymentSheet.js +1 -1
  63. package/lib/commonjs/types/PaymentSheet.js.map +1 -1
  64. package/lib/module/components/AddToWalletButton.js +1 -1
  65. package/lib/module/components/AddToWalletButton.js.map +1 -1
  66. package/lib/module/components/AddressSheet.js +1 -1
  67. package/lib/module/components/AddressSheet.js.map +1 -1
  68. package/lib/module/components/AuBECSDebitForm.js +1 -1
  69. package/lib/module/components/AuBECSDebitForm.js.map +1 -1
  70. package/lib/module/components/CardField.js +1 -1
  71. package/lib/module/components/CardField.js.map +1 -1
  72. package/lib/module/components/CardForm.js +1 -1
  73. package/lib/module/components/CardForm.js.map +1 -1
  74. package/lib/module/components/PlatformPayButton.js +1 -1
  75. package/lib/module/components/PlatformPayButton.js.map +1 -1
  76. package/lib/module/components/StripeContainer.js +1 -1
  77. package/lib/module/components/StripeContainer.js.map +1 -1
  78. package/lib/module/events.js.map +1 -1
  79. package/lib/module/functions.js +1 -1
  80. package/lib/module/functions.js.map +1 -1
  81. package/lib/module/specs/NativeApplePayButton.js +1 -1
  82. package/lib/module/specs/NativeApplePayButton.js.map +1 -1
  83. package/lib/module/specs/NativeStripeSdkModule.js.map +1 -1
  84. package/lib/module/types/EmbeddedPaymentElement.js +1 -1
  85. package/lib/module/types/EmbeddedPaymentElement.js.map +1 -1
  86. package/lib/module/types/PaymentIntent.js.map +1 -1
  87. package/lib/module/types/PaymentSheet.js +1 -1
  88. package/lib/module/types/PaymentSheet.js.map +1 -1
  89. package/lib/typescript/src/components/PlatformPayButton.d.ts.map +1 -1
  90. package/lib/typescript/src/events.d.ts +1 -1
  91. package/lib/typescript/src/events.d.ts.map +1 -1
  92. package/lib/typescript/src/functions.d.ts.map +1 -1
  93. package/lib/typescript/src/specs/NativeApplePayButton.d.ts +4 -0
  94. package/lib/typescript/src/specs/NativeApplePayButton.d.ts.map +1 -1
  95. package/lib/typescript/src/specs/NativeStripeSdkModule.d.ts +2 -0
  96. package/lib/typescript/src/specs/NativeStripeSdkModule.d.ts.map +1 -1
  97. package/lib/typescript/src/types/EmbeddedPaymentElement.d.ts +2 -0
  98. package/lib/typescript/src/types/EmbeddedPaymentElement.d.ts.map +1 -1
  99. package/lib/typescript/src/types/PaymentIntent.d.ts +1 -10
  100. package/lib/typescript/src/types/PaymentIntent.d.ts.map +1 -1
  101. package/lib/typescript/src/types/PaymentMethod.d.ts +2 -13
  102. package/lib/typescript/src/types/PaymentMethod.d.ts.map +1 -1
  103. package/lib/typescript/src/types/PaymentSheet.d.ts +55 -0
  104. package/lib/typescript/src/types/PaymentSheet.d.ts.map +1 -1
  105. package/package.json +1 -1
  106. package/patches/README.md +55 -0
  107. package/patches/old-arch-codegen-fix.patch +87 -0
  108. package/src/components/PlatformPayButton.tsx +12 -4
  109. package/src/events.ts +2 -1
  110. package/src/functions.ts +36 -1
  111. package/src/specs/NativeApplePayButton.ts +5 -0
  112. package/src/specs/NativeStripeSdkModule.ts +4 -0
  113. package/src/types/EmbeddedPaymentElement.tsx +33 -0
  114. package/src/types/PaymentIntent.ts +0 -10
  115. package/src/types/PaymentMethod.ts +0 -14
  116. package/src/types/PaymentSheet.ts +59 -0
  117. package/.env +0 -19
  118. package/ios/StripeSdk.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
  119. package/ios/StripeSdk.xcodeproj/project.xcworkspace/xcuserdata/wooj.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  120. package/ios/StripeSdk.xcodeproj/xcuserdata/wooj.xcuserdatad/xcschemes/xcschememanagement.plist +0 -19
@@ -3,6 +3,7 @@ package com.reactnativestripesdk
3
3
  import android.app.Activity
4
4
  import android.app.Application
5
5
  import android.content.Context
6
+ import android.content.Intent
6
7
  import android.graphics.Bitmap
7
8
  import android.graphics.Canvas
8
9
  import android.graphics.Color
@@ -11,6 +12,7 @@ import android.os.Bundle
11
12
  import android.os.Handler
12
13
  import android.os.Looper
13
14
  import android.util.Base64
15
+ import android.util.Log
14
16
  import androidx.appcompat.content.res.AppCompatResources
15
17
  import androidx.core.graphics.drawable.DrawableCompat
16
18
  import com.facebook.react.bridge.Arguments
@@ -28,11 +30,17 @@ import com.reactnativestripesdk.utils.PaymentSheetException
28
30
  import com.reactnativestripesdk.utils.StripeFragment
29
31
  import com.reactnativestripesdk.utils.createError
30
32
  import com.reactnativestripesdk.utils.createResult
33
+ import com.reactnativestripesdk.utils.mapFromCustomPaymentMethod
31
34
  import com.reactnativestripesdk.utils.mapFromPaymentMethod
32
35
  import com.reactnativestripesdk.utils.mapToPreferredNetworks
36
+ import com.reactnativestripesdk.utils.parseCustomPaymentMethods
33
37
  import com.reactnativestripesdk.utils.removeFragment
34
38
  import com.stripe.android.ExperimentalAllowsRemovalOfLastSavedPaymentMethodApi
35
39
  import com.stripe.android.model.PaymentMethod
40
+ import com.stripe.android.paymentelement.ConfirmCustomPaymentMethodCallback
41
+ import com.stripe.android.paymentelement.CustomPaymentMethodResult
42
+ import com.stripe.android.paymentelement.CustomPaymentMethodResultHandler
43
+ import com.stripe.android.paymentelement.ExperimentalCustomPaymentMethodsApi
36
44
  import com.stripe.android.paymentelement.PaymentMethodOptionsSetupFutureUsagePreview
37
45
  import com.stripe.android.paymentsheet.CreateIntentCallback
38
46
  import com.stripe.android.paymentsheet.CreateIntentResult
@@ -42,11 +50,17 @@ import com.stripe.android.paymentsheet.PaymentSheet
42
50
  import com.stripe.android.paymentsheet.PaymentSheetResult
43
51
  import com.stripe.android.paymentsheet.PaymentSheetResultCallback
44
52
  import kotlinx.coroutines.CompletableDeferred
53
+ import kotlinx.coroutines.CoroutineScope
54
+ import kotlinx.coroutines.Dispatchers
55
+ import kotlinx.coroutines.delay
56
+ import kotlinx.coroutines.launch
45
57
  import java.io.ByteArrayOutputStream
46
58
  import kotlin.Exception
47
59
 
48
- @OptIn(ExperimentalAllowsRemovalOfLastSavedPaymentMethodApi::class)
49
- class PaymentSheetFragment : StripeFragment() {
60
+ @OptIn(ExperimentalAllowsRemovalOfLastSavedPaymentMethodApi::class, ExperimentalCustomPaymentMethodsApi::class)
61
+ class PaymentSheetFragment :
62
+ StripeFragment(),
63
+ ConfirmCustomPaymentMethodCallback {
50
64
  private lateinit var context: ReactApplicationContext
51
65
  private lateinit var initPromise: Promise
52
66
  private var paymentSheet: PaymentSheet? = null
@@ -61,6 +75,7 @@ class PaymentSheetFragment : StripeFragment() {
61
75
  internal var paymentSheetIntentCreationCallback = CompletableDeferred<ReadableMap>()
62
76
  private var keepJsAwake: KeepJsAwakeTask? = null
63
77
 
78
+ @OptIn(ExperimentalCustomPaymentMethodsApi::class)
64
79
  override fun prepare() {
65
80
  val merchantDisplayName = arguments?.getString("merchantDisplayName").orEmpty()
66
81
  if (merchantDisplayName.isEmpty()) {
@@ -203,7 +218,7 @@ class PaymentSheetFragment : StripeFragment() {
203
218
  email = mapToCollectionMode(billingConfigParams?.getString("email")),
204
219
  address = mapToAddressCollectionMode(billingConfigParams?.getString("address")),
205
220
  attachDefaultsToPaymentMethod =
206
- billingConfigParams?.getBoolean("attachDefaultsToPaymentMethod") ?: false,
221
+ billingConfigParams?.getBoolean("attachDefaultsToPaymentMethod", false) ?: false,
207
222
  )
208
223
 
209
224
  var defaultBillingDetails: PaymentSheet.BillingDetails? = null
@@ -240,6 +255,7 @@ class PaymentSheetFragment : StripeFragment() {
240
255
  mapToPreferredNetworks(arguments?.getIntegerArrayList("preferredNetworks")),
241
256
  ).allowsRemovalOfLastSavedPaymentMethod(allowsRemovalOfLastSavedPaymentMethod)
242
257
  .cardBrandAcceptance(mapToCardBrandAcceptance(arguments))
258
+ .customPaymentMethods(parseCustomPaymentMethods(arguments))
243
259
 
244
260
  primaryButtonLabel?.let { configurationBuilder.primaryButtonLabel(it) }
245
261
  paymentMethodOrder?.let { configurationBuilder.paymentMethodOrder(it) }
@@ -253,30 +269,35 @@ class PaymentSheetFragment : StripeFragment() {
253
269
  if (arguments?.getBoolean("customFlow") == true) {
254
270
  flowController =
255
271
  if (intentConfiguration != null) {
256
- PaymentSheet.FlowController.create(
257
- this,
258
- paymentOptionCallback = paymentOptionCallback,
259
- createIntentCallback = createIntentCallback,
260
- paymentResultCallback = paymentResultCallback,
261
- )
272
+ PaymentSheet.FlowController
273
+ .Builder(
274
+ resultCallback = paymentResultCallback,
275
+ paymentOptionCallback = paymentOptionCallback,
276
+ ).createIntentCallback(createIntentCallback)
277
+ .confirmCustomPaymentMethodCallback(this)
278
+ .build(this)
262
279
  } else {
263
- PaymentSheet.FlowController.create(
264
- this,
265
- paymentOptionCallback = paymentOptionCallback,
266
- paymentResultCallback = paymentResultCallback,
267
- )
280
+ PaymentSheet.FlowController
281
+ .Builder(
282
+ resultCallback = paymentResultCallback,
283
+ paymentOptionCallback = paymentOptionCallback,
284
+ ).confirmCustomPaymentMethodCallback(this)
285
+ .build(this)
268
286
  }
269
287
  configureFlowController()
270
288
  } else {
271
289
  paymentSheet =
272
290
  if (intentConfiguration != null) {
273
- PaymentSheet(
274
- this,
275
- createIntentCallback = createIntentCallback,
276
- paymentResultCallback = paymentResultCallback,
277
- )
291
+ PaymentSheet
292
+ .Builder(paymentResultCallback)
293
+ .createIntentCallback(createIntentCallback)
294
+ .confirmCustomPaymentMethodCallback(this)
295
+ .build(this)
278
296
  } else {
279
- PaymentSheet(this, callback = paymentResultCallback)
297
+ PaymentSheet
298
+ .Builder(paymentResultCallback)
299
+ .confirmCustomPaymentMethodCallback(this)
300
+ .build(this)
280
301
  }
281
302
  initPromise.resolve(WritableNativeMap())
282
303
  }
@@ -420,6 +441,81 @@ class PaymentSheetFragment : StripeFragment() {
420
441
  } ?: run { resolvePresentPromise(map) }
421
442
  }
422
443
 
444
+ @OptIn(ExperimentalCustomPaymentMethodsApi::class)
445
+ override fun onConfirmCustomPaymentMethod(
446
+ customPaymentMethod: PaymentSheet.CustomPaymentMethod,
447
+ billingDetails: PaymentMethod.BillingDetails,
448
+ ) {
449
+ // Launch a transparent Activity to ensure React Native UI can appear on top of the Stripe proxy activity.
450
+ try {
451
+ val intent =
452
+ Intent(context, CustomPaymentMethodActivity::class.java).apply {
453
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
454
+ addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)
455
+ }
456
+ context.startActivity(intent)
457
+ } catch (e: Exception) {
458
+ Log.e("StripeReactNative", "Failed to start CustomPaymentMethodActivity", e)
459
+ }
460
+
461
+ val stripeSdkModule =
462
+ try {
463
+ context.getNativeModule(StripeSdkModule::class.java)
464
+ ?: throw IllegalArgumentException("StripeSdkModule not found")
465
+ } catch (ex: IllegalArgumentException) {
466
+ Log.e("StripeReactNative", "StripeSdkModule not found for CPM callback", ex)
467
+ CustomPaymentMethodActivity.finishCurrent()
468
+ return
469
+ }
470
+
471
+ // Keep JS awake while React Native is backgrounded by Stripe SDK.
472
+ val keepJsAwakeTask =
473
+ KeepJsAwakeTask(context).apply { start() }
474
+
475
+ // Run on main coroutine scope.
476
+ CoroutineScope(Dispatchers.Main).launch {
477
+ try {
478
+ // Give the CustomPaymentMethodActivity a moment to fully initialize
479
+ delay(100)
480
+
481
+ // Emit event so JS can show the Alert and eventually respond via `customPaymentMethodResultCallback`.
482
+ stripeSdkModule.emitOnCustomPaymentMethodConfirmHandlerCallback(
483
+ mapFromCustomPaymentMethod(customPaymentMethod, billingDetails),
484
+ )
485
+
486
+ // Await JS result.
487
+ val resultFromJs = stripeSdkModule.customPaymentMethodResultCallback.await()
488
+
489
+ keepJsAwakeTask.stop()
490
+
491
+ val status = resultFromJs.getString("status")
492
+
493
+ val nativeResult =
494
+ when (status) {
495
+ "completed" ->
496
+ CustomPaymentMethodResult.completed()
497
+ "canceled" ->
498
+ CustomPaymentMethodResult.canceled()
499
+ "failed" -> {
500
+ val errMsg = resultFromJs.getString("error") ?: "Custom payment failed"
501
+ CustomPaymentMethodResult.failed(displayMessage = errMsg)
502
+ }
503
+ else ->
504
+ CustomPaymentMethodResult.failed(displayMessage = "Unknown status")
505
+ }
506
+
507
+ // Return result to Stripe SDK.
508
+ CustomPaymentMethodResultHandler.handleCustomPaymentMethodResult(
509
+ context,
510
+ nativeResult,
511
+ )
512
+ } finally {
513
+ // Clean up the transparent activity
514
+ CustomPaymentMethodActivity.finishCurrent()
515
+ }
516
+ }
517
+ }
518
+
423
519
  companion object {
424
520
  internal const val TAG = "payment_sheet_launch_fragment"
425
521
 
@@ -8,6 +8,7 @@ import android.os.Bundle
8
8
  import android.util.Log
9
9
  import android.view.ViewGroup
10
10
  import androidx.fragment.app.FragmentActivity
11
+ import com.facebook.react.bridge.Arguments
11
12
  import com.facebook.react.bridge.BaseActivityEventListener
12
13
  import com.facebook.react.bridge.Promise
13
14
  import com.facebook.react.bridge.ReactApplicationContext
@@ -92,6 +93,7 @@ class StripeSdkModule(
92
93
  private var customerSheetFragment: CustomerSheetFragment? = null
93
94
 
94
95
  internal var embeddedIntentCreationCallback = CompletableDeferred<ReadableMap>()
96
+ internal var customPaymentMethodResultCallback = CompletableDeferred<ReadableMap>()
95
97
 
96
98
  internal var composeCompatView: StripeAbstractComposeView.CompatView? = null
97
99
 
@@ -233,6 +235,14 @@ class StripeSdkModule(
233
235
  getCurrentActivityOrResolveWithError(promise)?.let { activity ->
234
236
  paymentSheetFragment?.removeFragment(reactApplicationContext)
235
237
  val bundle = toBundleObject(params)
238
+
239
+ // Handle custom payment methods separately since toBundleObject cannot handle arrays of objects
240
+ val customPaymentMethodConfig = params.getMap("customPaymentMethodConfiguration")
241
+ if (customPaymentMethodConfig != null) {
242
+ // Store the original ReadableMap for custom payment methods
243
+ bundle.putSerializable("customPaymentMethodConfigurationReadableMap", customPaymentMethodConfig.toHashMap())
244
+ }
245
+
236
246
  paymentSheetFragment =
237
247
  PaymentSheetFragment.create(reactApplicationContext, bundle, promise)
238
248
  try {
@@ -298,6 +308,18 @@ class StripeSdkModule(
298
308
  paymentSheetFragment?.paymentSheetIntentCreationCallback?.complete(params)
299
309
  }
300
310
 
311
+ @ReactMethod
312
+ override fun customPaymentMethodResultCallback(
313
+ result: ReadableMap?,
314
+ promise: Promise?,
315
+ ) {
316
+ // Complete the deferred with the result from JavaScript
317
+ customPaymentMethodResultCallback.complete(result ?: Arguments.createMap())
318
+ // Reset for next use
319
+ customPaymentMethodResultCallback = CompletableDeferred()
320
+ promise?.resolve(null)
321
+ }
322
+
301
323
  @ReactMethod
302
324
  override fun createPaymentMethod(
303
325
  data: ReadableMap,
@@ -309,7 +309,7 @@ class CustomerSheetFragment : StripeFragment() {
309
309
  phone = mapToCollectionMode(bundle.getString("phone")),
310
310
  email = mapToCollectionMode(bundle.getString("email")),
311
311
  address = mapToAddressCollectionMode(bundle.getString("address")),
312
- attachDefaultsToPaymentMethod = bundle.getBoolean("attachDefaultsToPaymentMethod"),
312
+ attachDefaultsToPaymentMethod = bundle.getBoolean("attachDefaultsToPaymentMethod", false),
313
313
  )
314
314
 
315
315
  internal fun createCustomerAdapter(
@@ -64,7 +64,9 @@ class AddToWalletButtonManager(
64
64
  view: AddToWalletButtonView,
65
65
  ephemeralKey: Dynamic,
66
66
  ) {
67
- view.setEphemeralKey(ephemeralKey.asMap())
67
+ val map = ephemeralKey.asMap()
68
+ if (map == null) return
69
+ view.setEphemeralKey(map)
68
70
  }
69
71
 
70
72
  @ReactProp(name = "token")
@@ -72,7 +74,9 @@ class AddToWalletButtonManager(
72
74
  view: AddToWalletButtonView,
73
75
  token: Dynamic,
74
76
  ) {
75
- view.setToken(token.asMap())
77
+ val map = token.asMap()
78
+ if (map == null) return
79
+ view.setToken(map)
76
80
  }
77
81
 
78
82
  @ReactProp(name = "iOSButtonStyle")
@@ -27,6 +27,8 @@ import com.stripe.android.model.StripeIntent
27
27
  import com.stripe.android.model.StripeIntent.NextActionData
28
28
  import com.stripe.android.model.StripeIntent.NextActionType
29
29
  import com.stripe.android.model.Token
30
+ import com.stripe.android.paymentelement.ExperimentalCustomPaymentMethodsApi
31
+ import com.stripe.android.paymentsheet.PaymentSheet
30
32
 
31
33
  internal fun createResult(
32
34
  key: String,
@@ -138,7 +140,6 @@ internal fun mapPaymentMethodType(type: PaymentMethod.Type?): String =
138
140
  PaymentMethod.Type.Oxxo -> "Oxxo"
139
141
  PaymentMethod.Type.P24 -> "P24"
140
142
  PaymentMethod.Type.SepaDebit -> "SepaDebit"
141
- PaymentMethod.Type.Sofort -> "Sofort"
142
143
  PaymentMethod.Type.Upi -> "Upi"
143
144
  PaymentMethod.Type.WeChatPay -> "WeChatPay"
144
145
  PaymentMethod.Type.Klarna -> "Klarna"
@@ -168,7 +169,6 @@ internal fun mapToPaymentMethodType(type: String?): PaymentMethod.Type? =
168
169
  "Oxxo" -> PaymentMethod.Type.Oxxo
169
170
  "P24" -> PaymentMethod.Type.P24
170
171
  "SepaDebit" -> PaymentMethod.Type.SepaDebit
171
- "Sofort" -> PaymentMethod.Type.Sofort
172
172
  "Upi" -> PaymentMethod.Type.Upi
173
173
  "WeChatPay" -> PaymentMethod.Type.WeChatPay
174
174
  "Klarna" -> PaymentMethod.Type.Klarna
@@ -415,10 +415,6 @@ internal fun mapFromPaymentMethod(paymentMethod: PaymentMethod): WritableMap {
415
415
  it.putString("last4", paymentMethod.bacsDebit?.last4)
416
416
  },
417
417
  )
418
- pm.putMap(
419
- "Sofort",
420
- WritableNativeMap().also { it.putString("country", paymentMethod.sofort?.country) },
421
- )
422
418
  pm.putMap(
423
419
  "Ideal",
424
420
  WritableNativeMap().also {
@@ -1065,3 +1061,53 @@ private fun Map<String, Any?>.toReadableMap(): ReadableMap {
1065
1061
 
1066
1062
  return writableMap
1067
1063
  }
1064
+
1065
+ @OptIn(ExperimentalCustomPaymentMethodsApi::class)
1066
+ @SuppressLint("RestrictedApi")
1067
+ internal fun parseCustomPaymentMethods(customPaymentMethodConfig: Bundle?): List<PaymentSheet.CustomPaymentMethod> {
1068
+ if (customPaymentMethodConfig == null) {
1069
+ return emptyList()
1070
+ }
1071
+
1072
+ val configHashMap = customPaymentMethodConfig.getSerializable("customPaymentMethodConfigurationReadableMap") as? HashMap<String, Any>
1073
+ if (configHashMap != null) {
1074
+ val customPaymentMethods = configHashMap["customPaymentMethods"] as? List<HashMap<String, Any>>
1075
+ if (customPaymentMethods != null) {
1076
+ val result = mutableListOf<PaymentSheet.CustomPaymentMethod>()
1077
+
1078
+ for (customPaymentMethodMap in customPaymentMethods) {
1079
+ val id = customPaymentMethodMap["id"] as? String
1080
+ if (id != null) {
1081
+ val subtitle = customPaymentMethodMap["subtitle"] as? String
1082
+ val disableBillingDetailCollection = customPaymentMethodMap["disableBillingDetailCollection"] as? Boolean ?: false
1083
+ result.add(
1084
+ PaymentSheet.CustomPaymentMethod(
1085
+ id = id,
1086
+ subtitle = subtitle,
1087
+ disableBillingDetailCollection = disableBillingDetailCollection,
1088
+ ),
1089
+ )
1090
+ }
1091
+ }
1092
+
1093
+ return result
1094
+ }
1095
+ }
1096
+
1097
+ return emptyList()
1098
+ }
1099
+
1100
+ @SuppressLint("RestrictedApi")
1101
+ internal fun mapFromCustomPaymentMethod(
1102
+ customPaymentMethod: PaymentSheet.CustomPaymentMethod,
1103
+ billingDetails: PaymentMethod.BillingDetails,
1104
+ ): WritableMap =
1105
+ WritableNativeMap().apply {
1106
+ putMap(
1107
+ "customPaymentMethod",
1108
+ WritableNativeMap().apply {
1109
+ putString("id", customPaymentMethod.id)
1110
+ },
1111
+ )
1112
+ putMap("billingDetails", mapFromBillingDetails(billingDetails))
1113
+ }
@@ -0,0 +1,27 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <resources>
3
+ <style name="Theme.StripeReactNative.Transparent" parent="Theme.AppCompat.Light.NoActionBar">
4
+ <!-- Core transparency settings -->
5
+ <item name="android:windowIsTranslucent">true</item>
6
+ <item name="android:windowBackground">@android:color/transparent</item>
7
+ <item name="android:windowContentOverlay">@null</item>
8
+ <item name="android:windowNoTitle">true</item>
9
+ <item name="android:windowIsFloating">false</item>
10
+ <item name="android:backgroundDimEnabled">false</item>
11
+ <item name="android:windowAnimationStyle">@null</item>
12
+
13
+ <!-- Enhanced transparency and touch handling -->
14
+ <item name="android:windowCloseOnTouchOutside">false</item>
15
+ <item name="android:windowEnableSplitTouch">false</item>
16
+ <item name="android:windowDrawsSystemBarBackgrounds">false</item>
17
+ <item name="android:statusBarColor">@android:color/transparent</item>
18
+ <item name="android:navigationBarColor">@android:color/transparent</item>
19
+
20
+ <!-- Performance optimizations -->
21
+ <item name="android:windowDisablePreview">true</item>
22
+
23
+ <!-- Prevent visual artifacts -->
24
+ <item name="android:windowShowWallpaper">false</item>
25
+ <item name="android:windowFullscreen">false</item>
26
+ </style>
27
+ </resources>
@@ -114,6 +114,10 @@ public abstract class NativeStripeSdkModuleSpec extends ReactContextBaseJavaModu
114
114
  invoke("embeddedPaymentElementLoadingFailed", value);
115
115
  }
116
116
 
117
+ protected final void emitOnCustomPaymentMethodConfirmHandlerCallback(ReadableMap value) {
118
+ invoke("onCustomPaymentMethodConfirmHandlerCallback", value);
119
+ }
120
+
117
121
  @ReactMethod
118
122
  @DoNotStrip
119
123
  public abstract void initialise(ReadableMap params, Promise promise);
@@ -154,6 +158,10 @@ public abstract class NativeStripeSdkModuleSpec extends ReactContextBaseJavaModu
154
158
  @DoNotStrip
155
159
  public abstract void intentCreationCallback(ReadableMap result, Promise promise);
156
160
 
161
+ @ReactMethod
162
+ @DoNotStrip
163
+ public abstract void customPaymentMethodResultCallback(ReadableMap result, Promise promise);
164
+
157
165
  @ReactMethod
158
166
  @DoNotStrip
159
167
  public abstract void presentPaymentSheet(ReadableMap options, Promise promise);
@@ -11,5 +11,9 @@ RCT_EXPORT_VIEW_PROPERTY(onShippingMethodSelectedAction, RCTDirectEventBlock)
11
11
  RCT_EXPORT_VIEW_PROPERTY(onShippingContactSelectedAction, RCTDirectEventBlock)
12
12
  RCT_EXPORT_VIEW_PROPERTY(onCouponCodeEnteredAction, RCTDirectEventBlock)
13
13
  RCT_EXPORT_VIEW_PROPERTY(onOrderTrackingAction, RCTDirectEventBlock)
14
+ RCT_EXPORT_VIEW_PROPERTY(hasShippingMethodCallback, BOOL)
15
+ RCT_EXPORT_VIEW_PROPERTY(hasShippingContactCallback, BOOL)
16
+ RCT_EXPORT_VIEW_PROPERTY(hasCouponCodeCallback, BOOL)
17
+ RCT_EXPORT_VIEW_PROPERTY(hasOrderTrackingCallback, BOOL)
14
18
 
15
19
  @end
@@ -10,16 +10,23 @@ public class ApplePayButtonView: UIView {
10
10
  @objc public var onCouponCodeEnteredAction: RCTDirectEventBlock?
11
11
  @objc public var onOrderTrackingAction: RCTDirectEventBlock?
12
12
 
13
+ // Boolean flags to track which callbacks were provided as props
14
+ @objc public var hasShippingMethodCallback = false
15
+ @objc public var hasShippingContactCallback = false
16
+ @objc public var hasCouponCodeCallback = false
17
+ @objc public var hasOrderTrackingCallback = false
18
+
13
19
  @objc public var type: NSNumber?
14
20
  @objc public var buttonStyle: NSNumber?
15
21
  @objc public var borderRadius: NSNumber?
16
22
  @objc public var disabled = false
17
23
 
18
24
  @objc func handleApplePayButtonTapped() {
19
- StripeSdkImpl.shared.shippingMethodUpdateJSCallback = onShippingMethodSelectedAction
20
- StripeSdkImpl.shared.shippingContactUpdateJSCallback = onShippingContactSelectedAction
21
- StripeSdkImpl.shared.couponCodeEnteredJSCallback = onCouponCodeEnteredAction
22
- StripeSdkImpl.shared.platformPayOrderTrackingJSCallback = onOrderTrackingAction
25
+ // Only set callbacks that were actually provided as props
26
+ StripeSdkImpl.shared.shippingMethodUpdateJSCallback = hasShippingMethodCallback ? onShippingMethodSelectedAction : nil
27
+ StripeSdkImpl.shared.shippingContactUpdateJSCallback = hasShippingContactCallback ? onShippingContactSelectedAction : nil
28
+ StripeSdkImpl.shared.couponCodeEnteredJSCallback = hasCouponCodeCallback ? onCouponCodeEnteredAction : nil
29
+ StripeSdkImpl.shared.platformPayOrderTrackingJSCallback = hasOrderTrackingCallback ? onOrderTrackingAction : nil
23
30
  }
24
31
 
25
32
  @objc public func didSetProps() {
package/ios/Mappers.swift CHANGED
@@ -285,7 +285,6 @@ class Mappers {
285
285
  case STPPaymentMethodType.EPS: return "Eps"
286
286
  case STPPaymentMethodType.bancontact: return "Bancontact"
287
287
  case STPPaymentMethodType.OXXO: return "Oxxo"
288
- case STPPaymentMethodType.sofort: return "Sofort"
289
288
  case STPPaymentMethodType.UPI: return "Upi"
290
289
  case STPPaymentMethodType.afterpayClearpay: return "AfterpayClearpay"
291
290
  case STPPaymentMethodType.klarna: return "Klarna"
@@ -316,7 +315,6 @@ class Mappers {
316
315
  case "Eps": return STPPaymentMethodType.EPS
317
316
  case "Bancontact": return STPPaymentMethodType.bancontact
318
317
  case "Oxxo": return STPPaymentMethodType.OXXO
319
- case "Sofort": return STPPaymentMethodType.sofort
320
318
  case "Upi": return STPPaymentMethodType.UPI
321
319
  case "AfterpayClearpay": return STPPaymentMethodType.afterpayClearpay
322
320
  case "Klarna": return STPPaymentMethodType.klarna
@@ -666,9 +664,6 @@ class Mappers {
666
664
  "SepaDebit": sepaDebit,
667
665
  "BacsDebit": bacsDebit,
668
666
  "AuBecsDebit": auBECSDebit,
669
- "Sofort": [
670
- "country": paymentMethod.sofort?.country
671
- ],
672
667
  "Upi": [
673
668
  "vpa": paymentMethod.upi?.vpa
674
669
  ],
@@ -98,6 +98,12 @@ using namespace facebook::react;
98
98
  _view.disabled = newViewProps.disabled;
99
99
  _view.borderRadius = @(newViewProps.borderRadius);
100
100
 
101
+ // Set the boolean flags from props
102
+ _view.hasShippingMethodCallback = newViewProps.hasShippingMethodCallback;
103
+ _view.hasShippingContactCallback = newViewProps.hasShippingContactCallback;
104
+ _view.hasCouponCodeCallback = newViewProps.hasCouponCodeCallback;
105
+ _view.hasOrderTrackingCallback = newViewProps.hasOrderTrackingCallback;
106
+
101
107
  [super updateProps:props oldProps:oldProps];
102
108
 
103
109
  [_view didSetProps];
@@ -21,7 +21,7 @@
21
21
  - (void)emitEmbeddedPaymentElementFormSheetConfirmComplete:(NSDictionary *)value;
22
22
  - (void)emitEmbeddedPaymentElementRowSelectionImmediateAction;
23
23
  - (void)emitEmbeddedPaymentElementLoadingFailed:(NSDictionary *)value;
24
-
24
+ - (void)emitOnCustomPaymentMethodConfirmHandlerCallback:(NSDictionary *)value;
25
25
  @end
26
26
 
27
27
  #endif
@@ -21,7 +21,8 @@
21
21
  @"embeddedPaymentElementDidUpdatePaymentOption",
22
22
  @"embeddedPaymentElementFormSheetConfirmComplete",
23
23
  @"embeddedPaymentElementRowSelectionImmediateAction",
24
- @"embeddedPaymentElementLoadingFailed"
24
+ @"embeddedPaymentElementLoadingFailed",
25
+ @"onCustomPaymentMethodConfirmHandlerCallback"
25
26
  ];
26
27
  }
27
28
 
@@ -100,6 +101,11 @@
100
101
  [self sendEventWithName:@"embeddedPaymentElementLoadingFailed" body:value];
101
102
  }
102
103
 
104
+ - (void)emitOnCustomPaymentMethodConfirmHandlerCallback:(NSDictionary *)value
105
+ {
106
+ [self sendEventWithName:@"onCustomPaymentMethodConfirmHandlerCallback" body:value];
107
+ }
108
+
103
109
  @end
104
110
 
105
111
  #endif
@@ -31,8 +31,6 @@ class PaymentMethodFactory {
31
31
  return try createFPXPaymentMethodParams()
32
32
  case STPPaymentMethodType.alipay:
33
33
  return try createAlipayPaymentMethodParams()
34
- case STPPaymentMethodType.sofort:
35
- return try createSofortPaymentMethodParams()
36
34
  case STPPaymentMethodType.bancontact:
37
35
  return try createBancontactPaymentMethodParams()
38
36
  case STPPaymentMethodType.SEPADebit:
@@ -82,8 +80,6 @@ class PaymentMethodFactory {
82
80
  return createCardPaymentMethodOptions()
83
81
  case STPPaymentMethodType.FPX:
84
82
  return nil
85
- case STPPaymentMethodType.sofort:
86
- return nil
87
83
  case STPPaymentMethodType.alipay:
88
84
  return try createAlipayPaymentMethodOptions()
89
85
  case STPPaymentMethodType.bancontact:
@@ -250,16 +246,6 @@ class PaymentMethodFactory {
250
246
  return options
251
247
  }
252
248
 
253
- private func createSofortPaymentMethodParams() throws -> STPPaymentMethodParams {
254
- guard let country = self.paymentMethodData?["country"] as? String else {
255
- throw PaymentMethodError.sofortPaymentMissingParams
256
- }
257
- let params = STPPaymentMethodSofortParams()
258
- params.country = country
259
-
260
- return STPPaymentMethodParams(sofort: params, billingDetails: billingDetailsParams, metadata: metadata)
261
- }
262
-
263
249
  private func createBancontactPaymentMethodParams() throws -> STPPaymentMethodParams {
264
250
  let params = STPPaymentMethodBancontactParams()
265
251
 
@@ -411,7 +397,6 @@ enum PaymentMethodError: Error {
411
397
  case epsPaymentMissingParams
412
398
  case idealPaymentMissingParams
413
399
  case paymentNotSupported
414
- case sofortPaymentMissingParams
415
400
  case cardPaymentOptionsMissingParams
416
401
  case bancontactPaymentMissingParams
417
402
  case sepaPaymentMissingParams
@@ -434,8 +419,6 @@ extension PaymentMethodError: LocalizedError {
434
419
  return NSLocalizedString("You must provide billing details", comment: "Create payment error")
435
420
  case .idealPaymentMissingParams:
436
421
  return NSLocalizedString("You must provide bank name", comment: "Create payment error")
437
- case .sofortPaymentMissingParams:
438
- return NSLocalizedString("You must provide bank account country", comment: "Create payment error")
439
422
  case .p24PaymentMissingParams:
440
423
  return NSLocalizedString("You must provide billing details", comment: "Create payment error")
441
424
  case .bancontactPaymentMissingParams: