Skip to content

Commit 9abcc99

Browse files
Merge branch 'master' into porter/image-po-embedded
2 parents 084811b + acbf4a6 commit 9abcc99

89 files changed

Lines changed: 766 additions & 256 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/e2e-tests.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
name: RN Stripe
22

3+
concurrency:
4+
group: ${{ github.workflow }}-${{ github.ref }}
5+
cancel-in-progress: true
6+
37
on:
48
push:
59
branches: [master]
610
pull_request:
711
branches: ['**']
12+
paths-ignore:
13+
- '**/*.md'
14+
- '**/*.MD'
815
schedule:
916
- cron: '0 7 * * *' # run at 7 AM UTC, 12 AM PST
1017
workflow_dispatch: # manually trigger the e2e tests
@@ -188,6 +195,9 @@ jobs:
188195
- name: checkout
189196
uses: actions/checkout@v4
190197

198+
- name: Setup Xcode
199+
run: sudo xcode-select -s /Applications/Xcode_16.3.app/Contents/Developer
200+
191201
- name: Get yarn cache directory path
192202
id: yarn-cache-dir-path
193203
run: echo "::set-output name=dir::$(yarn cache dir)"

.github/workflows/js-tests.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@ on:
55
branches: [master]
66
pull_request:
77
branches: ['**']
8+
paths-ignore:
9+
- '**/*.md'
10+
- '**/*.MD'
11+
12+
concurrency:
13+
group: ${{ github.workflow }}-${{ github.ref }}
14+
cancel-in-progress: true
815

916
jobs:
1017
js-tests:

.github/workflows/unit-tests.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@ on:
55
branches: [master]
66
pull_request:
77
branches: ['**']
8+
paths-ignore:
9+
- '**/*.md'
10+
- '**/*.MD'
11+
12+
concurrency:
13+
group: ${{ github.workflow }}-${{ github.ref }}
14+
cancel-in-progress: true
815

916
jobs:
1017
test-ios:
@@ -14,6 +21,9 @@ jobs:
1421
- name: checkout
1522
uses: actions/checkout@v4
1623

24+
- name: Setup Xcode
25+
run: sudo xcode-select -s /Applications/Xcode_16.3.app/Contents/Developer
26+
1727
- name: Get yarn cache directory path
1828
id: yarn-cache-dir-path
1929
run: echo "::set-output name=dir::$(yarn cache dir)"

CHANGELOG.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,31 @@
22

33
## x.x.x - x-x-x
44

5+
**Features**
6+
- [#1956](https://github.com/stripe/stripe-react-native/pull/1956) Added support for the Billie payment method
7+
8+
**Changes**
9+
- Klarna: Made `billingDetails.email` and `billingDetails.address.country` optional when creating Klarna payment methods. See Stripe docs: [Migrate Klarna from Sources – Field mapping reference](https://docs.stripe.com/payments/klarna/migrate) ("Not required when using the Payment Element. It’s collected automatically.").
10+
11+
**Fixes**
12+
- Fixed iOS crash "Stripe SDK confirmPayment must not be null" when calling `confirmPayment` with optional parameters. Updated native bridge to properly handle nullable params argument. [#2048](https://github.com/stripe/stripe-react-native/issues/2048)
13+
14+
## 0.50.3 - 2025-08-07
15+
16+
**Fixed**
17+
- Fixed Android crash when using `RowSelectionBehavior.ImmediateAction` with `FormSheetAction.Confirm` in EmbeddedPaymentElement.
18+
19+
## 0.50.2 - 2025-08-06
20+
21+
**Changes**
22+
- Renamed `RowStyle.FlatWithChevron` to `RowStyle.FlatWithDisclosure` and updated related interfaces (`ChevronConfig``DisclosureConfig`).
23+
- Updated `stripe-ios` to 24.19.0
24+
- Updated `stripe-android` to 21.22.+
25+
- Added `successBackgroundColor` and `successTextColor` properties to `PrimaryButtonColorConfig` for customizing the primary button appearance in success states.
26+
527
**Fixes**
628
- Fixed missing `onCustomPaymentMethodConfirmHandlerCallback` in old architecture codegen patch. This resolves pod install failures when using React Native 0.74+ with old architecture and custom payment methods.
29+
- Fixes an issue where saved payment methods weren't auto selected when using `EmbeddedPaymentElement` on Android.
730

831
## 0.50.1 - 2025-07-22
932

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Get started with our [📚 integration guides](https://stripe.com/docs/payments/
2323

2424
**Native UI**: We provide native screens and elements to securely collect payment details on Android and iOS.
2525

26-
**PaymentSheet**: [Learn how to integrate](https://stripe.com/docs/payments/accept-a-payment) PaymentSheet, our new pre-built payments UI for mobile apps. PaymentSheet lets you accept cards, Apple Pay, Google Pay, and much more out of the box and also supports saving & reusing payment methods. PaymentSheet currently accepts the following payment methods: Card, Apple Pay, Google Pay, SEPA Debit, Bancontact, iDEAL, EPS, P24, Afterpay/Clearpay, Klarna, Giropay, and ACH.
26+
**PaymentSheet**: [Learn how to integrate](https://stripe.com/docs/payments/accept-a-payment) PaymentSheet, our new pre-built payments UI for mobile apps. PaymentSheet lets you accept cards, Apple Pay, Google Pay, and much more out of the box and also supports saving & reusing payment methods. PaymentSheet currently accepts the following payment methods: Card, Apple Pay, Google Pay, SEPA Debit, Bancontact, Billie, iDEAL, EPS, P24, Afterpay/Clearpay, Klarna, Giropay, and ACH.
2727

2828
#### Recommended usage
2929

android/gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ StripeSdk_compileSdkVersion=30
33
StripeSdk_targetSdkVersion=28
44
StripeSdk_minSdkVersion=21
55
# Keep StripeSdk_stripeVersion in sync with https://github.com/stripe/stripe-identity-react-native/blob/main/android/gradle.properties
6-
StripeSdk_stripeVersion=21.19.+
6+
StripeSdk_stripeVersion=21.23.+

android/src/androidTest/java/com/reactnativestripesdk/PaymentSheetFragmentTest.kt

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,8 @@ class PaymentSheetFragmentTest {
4444
}
4545

4646
@Test
47-
fun buildGooglePayConfig_defaultsToCorrectValues() {
47+
fun buildGooglePayConfig_returnsNullForEmptyBundle() {
4848
val config = PaymentSheetFragment.buildGooglePayConfig(Bundle.EMPTY)
49-
Assert.assertEquals(
50-
config,
51-
PaymentSheet.GooglePayConfiguration(
52-
environment = PaymentSheet.GooglePayConfiguration.Environment.Production,
53-
countryCode = "",
54-
currencyCode = "",
55-
buttonType = PaymentSheet.GooglePayConfiguration.ButtonType.Pay,
56-
),
57-
)
49+
Assert.assertNull(config)
5850
}
5951
}

android/src/main/java/com/reactnativestripesdk/PaymentMethodCreateParamsFactory.kt

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class PaymentMethodCreateParamsFactory(
3939
PaymentMethod.Type.Ideal -> createIDEALParams()
4040
PaymentMethod.Type.Alipay -> createAlipayParams()
4141
PaymentMethod.Type.Bancontact -> createBancontactParams()
42+
PaymentMethod.Type.Billie -> createBillieParams()
4243
PaymentMethod.Type.SepaDebit -> createSepaParams()
4344
PaymentMethod.Type.Oxxo -> createOXXOParams()
4445
PaymentMethod.Type.Giropay -> createGiropayParams()
@@ -90,6 +91,13 @@ class PaymentMethodCreateParamsFactory(
9091
throw PaymentMethodCreateParamsException("You must provide billing details")
9192
}
9293

94+
@Throws(PaymentMethodCreateParamsException::class)
95+
private fun createBillieParams(): PaymentMethodCreateParams =
96+
PaymentMethodCreateParams.createBillie(
97+
billingDetails = billingDetailsParams,
98+
metadata = metadataParams,
99+
)
100+
93101
@Throws(PaymentMethodCreateParamsException::class)
94102
private fun createSepaParams(): PaymentMethodCreateParams {
95103
billingDetailsParams?.let {
@@ -200,21 +208,11 @@ class PaymentMethodCreateParamsFactory(
200208
}
201209

202210
@Throws(PaymentMethodCreateParamsException::class)
203-
private fun createKlarnaParams(): PaymentMethodCreateParams {
204-
if (billingDetailsParams == null ||
205-
billingDetailsParams.address?.country.isNullOrBlank() ||
206-
billingDetailsParams.email.isNullOrBlank()
207-
) {
208-
throw PaymentMethodCreateParamsException(
209-
"Klarna requires that you provide the following billing details: email, country",
210-
)
211-
}
212-
213-
return PaymentMethodCreateParams.createKlarna(
211+
private fun createKlarnaParams(): PaymentMethodCreateParams =
212+
PaymentMethodCreateParams.createKlarna(
214213
billingDetails = billingDetailsParams,
215214
metadata = metadataParams,
216215
)
217-
}
218216

219217
@Throws(PaymentMethodCreateParamsException::class)
220218
private fun createPayPalParams(): PaymentMethodCreateParams = PaymentMethodCreateParams.createPayPal(metadata = metadataParams)
@@ -256,6 +254,7 @@ class PaymentMethodCreateParamsFactory(
256254
PaymentMethod.Type.Ideal,
257255
PaymentMethod.Type.Alipay,
258256
PaymentMethod.Type.Bancontact,
257+
PaymentMethod.Type.Billie,
259258
PaymentMethod.Type.SepaDebit,
260259
PaymentMethod.Type.Oxxo,
261260
PaymentMethod.Type.Giropay,

android/src/main/java/com/reactnativestripesdk/PaymentSheetAppearance.kt

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -194,9 +194,9 @@ private fun buildPrimaryButton(
194194

195195
return PaymentSheet.PrimaryButton(
196196
colorsLight =
197-
buildPrimaryButtonColors(lightColorParams, PaymentSheet.PrimaryButtonColors.defaultLight),
197+
buildPrimaryButtonColors(lightColorParams, PaymentSheet.PrimaryButtonColors.defaultLight, context),
198198
colorsDark =
199-
buildPrimaryButtonColors(darkColorParams, PaymentSheet.PrimaryButtonColors.defaultDark),
199+
buildPrimaryButtonColors(darkColorParams, PaymentSheet.PrimaryButtonColors.defaultDark, context),
200200
shape =
201201
PaymentSheet.PrimaryButtonShape(
202202
cornerRadiusDp =
@@ -217,6 +217,7 @@ private fun buildPrimaryButton(
217217
private fun buildPrimaryButtonColors(
218218
colorParams: Bundle,
219219
default: PaymentSheet.PrimaryButtonColors,
220+
context: Context,
220221
): PaymentSheet.PrimaryButtonColors =
221222
PaymentSheet.PrimaryButtonColors(
222223
background =
@@ -243,6 +244,20 @@ private fun buildPrimaryButtonColors(
243244
colorParams.getString(PaymentSheetAppearanceKeys.BORDER),
244245
default.border,
245246
),
247+
successBackgroundColor =
248+
dynamicColorFromParams(
249+
context,
250+
colorParams,
251+
PaymentSheetAppearanceKeys.SUCCESS_BACKGROUND,
252+
default.successBackgroundColor,
253+
),
254+
onSuccessBackgroundColor =
255+
dynamicColorFromParams(
256+
context,
257+
colorParams,
258+
PaymentSheetAppearanceKeys.SUCCESS_TEXT,
259+
default.onSuccessBackgroundColor,
260+
),
246261
)
247262

248263
@SuppressLint("RestrictedApi")
@@ -341,7 +356,7 @@ private fun buildEmbeddedAppearance(
341356
val checkmarkParams = getBundleOrNull(flatParams, PaymentSheetAppearanceKeys.CHECKMARK)
342357
val separatorInsetsParams = getBundleOrNull(flatParams, PaymentSheetAppearanceKeys.SEPARATOR_INSETS)
343358

344-
// Default separator insets specific to FlatWithCheckmark and FlatWithChevron
359+
// Default separator insets specific to FlatWithCheckmark and FlatWithDisclosure
345360
val defaultSeparatorStartInsetDp = 0.0f
346361
val defaultSeparatorEndInsetDp = 0.0f
347362

@@ -392,12 +407,12 @@ private fun buildEmbeddedAppearance(
392407
colorsDark = flatCheckmarkColors,
393408
)
394409
}
395-
"flatWithChevron" -> {
410+
"flatWithDisclosure" -> {
396411
val flatParams = getBundleOrNull(rowParams, PaymentSheetAppearanceKeys.FLAT)
397-
val chevronParams = getBundleOrNull(flatParams, PaymentSheetAppearanceKeys.CHEVRON)
412+
val disclosureParams = getBundleOrNull(flatParams, PaymentSheetAppearanceKeys.DISCLOSURE)
398413
val separatorInsetsParams = getBundleOrNull(flatParams, PaymentSheetAppearanceKeys.SEPARATOR_INSETS)
399414

400-
// Default separator insets specific to FlatWithCheckmark and FlatWithChevron
415+
// Default separator insets specific to FlatWithCheckmark and FlatWithDisclosure
401416
val defaultSeparatorStartInsetDp = 0.0f
402417
val defaultSeparatorEndInsetDp = 0.0f
403418

@@ -418,32 +433,33 @@ private fun buildEmbeddedAppearance(
418433
Color.GRAY,
419434
)
420435

421-
val parsedChevronColor =
436+
val parsedDisclosureColor =
422437
dynamicColorFromParams(
423438
context,
424-
chevronParams,
439+
disclosureParams,
425440
PaymentSheetAppearanceKeys.COLOR,
426441
defaultColors.componentBorder, // Default to component border color like other elements
427442
)
428443

429444
// Create the required Colors object
430-
val flatChevronColors =
431-
PaymentSheet.Appearance.Embedded.RowStyle.FlatWithChevron.Colors(
445+
val flatDisclosureColors =
446+
PaymentSheet.Appearance.Embedded.RowStyle.FlatWithDisclosure.Colors(
432447
separatorColor = parsedSeparatorColor,
433-
chevronColor = parsedChevronColor,
448+
disclosureColor = parsedDisclosureColor,
434449
)
435450

436-
PaymentSheet.Appearance.Embedded.RowStyle.FlatWithChevron(
437-
separatorThicknessDp = separatorThickness,
438-
startSeparatorInsetDp = startSeparatorInset,
439-
endSeparatorInsetDp = endSeparatorInset,
440-
topSeparatorEnabled = topEnabled,
441-
bottomSeparatorEnabled = bottomEnabled,
442-
additionalVerticalInsetsDp = additionalInsets,
443-
horizontalInsetsDp = 0.0F, // We do not have an iOS equal for this API so it's not configurable in React Native
444-
colorsLight = flatChevronColors,
445-
colorsDark = flatChevronColors,
446-
)
451+
PaymentSheet.Appearance.Embedded.RowStyle.FlatWithDisclosure
452+
.Builder()
453+
.separatorThicknessDp(separatorThickness)
454+
.startSeparatorInsetDp(startSeparatorInset)
455+
.endSeparatorInsetDp(endSeparatorInset)
456+
.topSeparatorEnabled(topEnabled)
457+
.bottomSeparatorEnabled(bottomEnabled)
458+
.additionalVerticalInsetsDp(additionalInsets)
459+
.horizontalInsetsDp(0.0F) // We do not have an iOS equal for this API so it's not configurable in React Native
460+
.colorsLight(flatDisclosureColors)
461+
.colorsDark(flatDisclosureColors)
462+
.build()
447463
}
448464
"floatingButton" -> {
449465
val floatingParams = getBundleOrNull(rowParams, PaymentSheetAppearanceKeys.FLOATING)
@@ -654,6 +670,8 @@ private class PaymentSheetAppearanceKeys {
654670
const val PRIMARY_BUTTON = "primaryButton"
655671
const val TEXT = "text"
656672
const val BORDER = "border"
673+
const val SUCCESS_BACKGROUND = "successBackgroundColor"
674+
const val SUCCESS_TEXT = "successTextColor"
657675

658676
const val EMBEDDED_PAYMENT_ELEMENT = "embeddedPaymentElement"
659677
const val ROW = "row"
@@ -670,7 +688,7 @@ private class PaymentSheetAppearanceKeys {
670688
const val SELECTED_COLOR = "selectedColor"
671689
const val UNSELECTED_COLOR = "unselectedColor"
672690
const val CHECKMARK = "checkmark"
673-
const val CHEVRON = "chevron"
691+
const val DISCLOSURE = "disclosure"
674692
const val COLOR = "color"
675693
const val CHECKMARK_INSET = "inset"
676694

android/src/main/java/com/reactnativestripesdk/PaymentSheetFragment.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ import com.stripe.android.paymentelement.PaymentMethodOptionsSetupFutureUsagePre
4545
import com.stripe.android.paymentsheet.CreateIntentCallback
4646
import com.stripe.android.paymentsheet.CreateIntentResult
4747
import com.stripe.android.paymentsheet.ExperimentalCustomerSessionApi
48-
import com.stripe.android.paymentsheet.PaymentOptionCallback
48+
import com.stripe.android.paymentsheet.PaymentOptionResultCallback
4949
import com.stripe.android.paymentsheet.PaymentSheet
5050
import com.stripe.android.paymentsheet.PaymentSheetResult
5151
import com.stripe.android.paymentsheet.PaymentSheetResultCallback
@@ -124,9 +124,9 @@ class PaymentSheetFragment :
124124
}
125125

126126
val paymentOptionCallback =
127-
PaymentOptionCallback { paymentOption ->
127+
PaymentOptionResultCallback { paymentOptionResult ->
128128
val result =
129-
paymentOption?.let {
129+
paymentOptionResult.paymentOption?.let {
130130
val bitmap = getBitmapFromVectorDrawable(context, it.drawableResourceId)
131131
val imageString = getBase64FromBitmap(bitmap)
132132
val option: WritableMap = WritableNativeMap()
@@ -272,15 +272,15 @@ class PaymentSheetFragment :
272272
PaymentSheet.FlowController
273273
.Builder(
274274
resultCallback = paymentResultCallback,
275-
paymentOptionCallback = paymentOptionCallback,
275+
paymentOptionResultCallback = paymentOptionCallback,
276276
).createIntentCallback(createIntentCallback)
277277
.confirmCustomPaymentMethodCallback(this)
278278
.build(this)
279279
} else {
280280
PaymentSheet.FlowController
281281
.Builder(
282282
resultCallback = paymentResultCallback,
283-
paymentOptionCallback = paymentOptionCallback,
283+
paymentOptionResultCallback = paymentOptionCallback,
284284
).confirmCustomPaymentMethodCallback(this)
285285
.build(this)
286286
}
@@ -550,7 +550,7 @@ class PaymentSheetFragment :
550550
)
551551

552552
internal fun buildGooglePayConfig(params: Bundle?): PaymentSheet.GooglePayConfiguration? {
553-
if (params == null) {
553+
if (params == null || params.isEmpty) {
554554
return null
555555
}
556556

0 commit comments

Comments
 (0)