Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: upgrade native libraries and add small new features #1598

Merged
merged 7 commits into from
Jan 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,23 @@

## Unreleased

**Features**

- Use `preferredNetworks` on `CardField`, `CardForm`, `CustomerSheet`, and `PaymentSheet` to set the list of preferred networks that should be used to process payments made with a co-branded card.
- Set the Google Pay button type that is used in PaymentSheet with the `googlePay.buttonType` parameter.

**Fixes**

- Fixed an issue on Android where `CardField`'s `placeholderColor` wasn't being applied to the card brand icon.

## 0.35.1 - 2024-01-16

**Fixes**

- Fixed a build error on Android when using React Native 0.73.0 and higher [#1579](https://github.com/stripe/stripe-react-native/pull/1579)
- Fixed the test mock for `useStripe` [#1559](https://github.com/stripe/stripe-react-native/pull/1559)
- Fixed a build error on Android that would only occur when using the `nx` build tool [#1586](https://github.com/stripe/stripe-react-native/pull/1586)

## 0.35.0 - 2023-11-02

**Features**
Expand Down
2 changes: 1 addition & 1 deletion android/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
StripeSdk_kotlinVersion=1.8.0
# Keep StripeSdk_stripeVersion in sync with https://github.com/stripe/stripe-identity-react-native/blob/main/android/gradle.properties
StripeSdk_stripeVersion=20.34.+
StripeSdk_stripeVersion=20.36.+
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,17 @@ class PaymentSheetFragmentTest {
bundleOf(
"merchantCountryCode" to "US",
"currencyCode" to "USD",
"testEnv" to true
"testEnv" to true,
"buttonType" to 4
)
)
Assert.assertEquals(
config,
PaymentSheet.GooglePayConfiguration(
environment = PaymentSheet.GooglePayConfiguration.Environment.Test,
countryCode = "US",
currencyCode = "USD"
currencyCode = "USD",
buttonType = PaymentSheet.GooglePayConfiguration.ButtonType.Donate
)
)
}
Expand All @@ -46,7 +48,8 @@ class PaymentSheetFragmentTest {
PaymentSheet.GooglePayConfiguration(
environment = PaymentSheet.GooglePayConfiguration.Environment.Production,
countryCode = "",
currencyCode = ""
currencyCode = "",
buttonType = PaymentSheet.GooglePayConfiguration.ButtonType.Pay
)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,11 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {

private fun setCardBrandTint(color: Int) {
try {
cardInputWidgetBinding.cardBrandView::class.java.getDeclaredField("tintColorInt").let { internalTintColor ->
internalTintColor.isAccessible = true
internalTintColor.set(cardInputWidgetBinding.cardBrandView, color)
}
cardInputWidgetBinding.cardBrandView::class.java
.getDeclaredMethod("setTintColorInt\$payments_core_release", Int::class.java)
.let {
it(cardInputWidgetBinding.cardBrandView, color)
}
} catch (e: Exception) {
Log.e(
"StripeReactNative",
Expand Down Expand Up @@ -214,6 +215,10 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
mCardWidget.isEnabled = !isDisabled
}

fun setPreferredNetworks(preferredNetworks: ArrayList<Int>?) {
mCardWidget.setPreferredNetworks(mapToPreferredNetworks(preferredNetworks))
}

/**
* We can reliable assume that setPostalCodeEnabled is called before
* setCountryCode because of the order of the props in CardField.tsx
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ class CardFieldViewManager : SimpleViewManager<CardFieldView>() {
view.setDisabled(isDisabled)
}

@ReactProp(name = "preferredNetworks")
fun setPreferredNetworks(view: CardFieldView, preferredNetworks: ReadableArray?) {
val networks = preferredNetworks?.toArrayList()?.filterIsInstance<Int>()?.let { ArrayList(it) }
view.setPreferredNetworks(networks)
}

override fun createViewInstance(reactContext: ThemedReactContext): CardFieldView {
val stripeSdkModule: StripeSdkModule? = reactContext.getNativeModule(StripeSdkModule::class.java)
val view = CardFieldView(reactContext)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ class CardFormView(context: ThemedReactContext) : FrameLayout(context) {
cardForm.isEnabled = !isDisabled
}

fun setPreferredNetworks(preferredNetworks: ArrayList<Int>?) {
cardForm.setPreferredNetworks(mapToPreferredNetworks(preferredNetworks))
}

@SuppressLint("RestrictedApi")
private fun setCountry(countryString: String?) {
if (countryString != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ class CardFormViewManager : SimpleViewManager<CardFormView>() {
view.setDisabled(isDisabled)
}

@ReactProp(name = "preferredNetworks")
fun setPreferredNetworks(view: CardFormView, preferredNetworks: ReadableArray?) {
val networks = preferredNetworks?.toArrayList()?.filterIsInstance<Int>()?.let { ArrayList(it) }
view.setPreferredNetworks(networks)
}

override fun createViewInstance(reactContext: ThemedReactContext): CardFormView {
val stripeSdkModule: StripeSdkModule? = reactContext.getNativeModule(StripeSdkModule::class.java)
val view = CardFormView(reactContext)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,8 @@ class PaymentSheetFragment(
appearance = appearance,
shippingDetails = shippingDetails,
primaryButtonLabel = primaryButtonLabel,
billingDetailsCollectionConfiguration = billingDetailsConfig
billingDetailsCollectionConfiguration = billingDetailsConfig,
preferredNetworks = mapToPreferredNetworks(arguments?.getIntegerArrayList("preferredNetworks"))
)

if (arguments?.getBoolean("customFlow") == true) {
Expand Down Expand Up @@ -342,6 +343,17 @@ class PaymentSheetFragment(
companion object {
internal const val TAG = "payment_sheet_launch_fragment"

private val mapIntToButtonType = mapOf(
1 to PaymentSheet.GooglePayConfiguration.ButtonType.Buy,
6 to PaymentSheet.GooglePayConfiguration.ButtonType.Book,
5 to PaymentSheet.GooglePayConfiguration.ButtonType.Checkout,
4 to PaymentSheet.GooglePayConfiguration.ButtonType.Donate,
11 to PaymentSheet.GooglePayConfiguration.ButtonType.Order,
1000 to PaymentSheet.GooglePayConfiguration.ButtonType.Pay,
7 to PaymentSheet.GooglePayConfiguration.ButtonType.Subscribe,
1001 to PaymentSheet.GooglePayConfiguration.ButtonType.Plain,
)

internal fun createMissingInitError(): WritableMap {
return createError(PaymentSheetErrorType.Failed.toString(), "No payment sheet has been initialized yet. You must call `initPaymentSheet` before `presentPaymentSheet`.")
}
Expand All @@ -356,13 +368,16 @@ class PaymentSheetFragment(
val testEnv = params.getBoolean("testEnv")
val amount = params.getString("amount")?.toLongOrNull()
val label = params.getString("label")
val buttonType = mapIntToButtonType.get(params.getInt("buttonType")) ?: PaymentSheet.GooglePayConfiguration.ButtonType.Pay


return PaymentSheet.GooglePayConfiguration(
environment = if (testEnv) PaymentSheet.GooglePayConfiguration.Environment.Test else PaymentSheet.GooglePayConfiguration.Environment.Production,
countryCode = countryCode,
currencyCode = currencyCode,
amount = amount,
label = label
label = label,
buttonType = buttonType
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,11 @@ class CustomerSheetFragment : Fragment() {
return
}

val configuration = CustomerSheet.Configuration.builder()
val configuration = CustomerSheet.Configuration.builder(merchantDisplayName ?: "")
.appearance(appearance)
.googlePayEnabled(googlePayEnabled)
.merchantDisplayName(merchantDisplayName)
.headerTextForSelectionScreen(headerTextForSelectionScreen)
.preferredNetworks(mapToPreferredNetworks(arguments?.getIntegerArrayList("preferredNetworks")))

billingDetailsBundle?.let {
configuration.defaultBillingDetails(createDefaultBillingDetails(billingDetailsBundle))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -912,7 +912,7 @@ internal fun mapFromShippingContact(googlePayResult: GooglePayResult): WritableM
googlePayResult.shippingInformation?.phone?.let {
map.putString("phoneNumber", it)
} ?: run {
map.putString("phoneNumber", googlePayResult?.phoneNumber)
map.putString("phoneNumber", googlePayResult.phoneNumber)
}
val postalAddress = WritableNativeMap()
postalAddress.putString("city", googlePayResult.shippingInformation?.address?.city)
Expand All @@ -929,3 +929,25 @@ internal fun mapFromShippingContact(googlePayResult: GooglePayResult): WritableM
map.putMap("postalAddress", postalAddress)
return map
}

internal fun mapToPreferredNetworks(networksAsInts: ArrayList<Int>?): List<CardBrand> {
if (networksAsInts == null) {
return emptyList()
}

val intToCardBrand = mapOf(
0 to CardBrand.JCB,
1 to CardBrand.AmericanExpress,
2 to CardBrand.CartesBancaires,
3 to CardBrand.DinersClub,
4 to CardBrand.Discover,
5 to CardBrand.MasterCard,
6 to CardBrand.UnionPay,
7 to CardBrand.Visa,
8 to CardBrand.Unknown,
)

return networksAsInts.mapNotNull {
intToCardBrand[it]
}
}
102 changes: 51 additions & 51 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -364,50 +364,50 @@ PODS:
- React-Core
- React-RCTImage
- SocketRocket (0.6.0)
- Stripe (23.18.0):
- StripeApplePay (= 23.18.0)
- StripeCore (= 23.18.0)
- StripePayments (= 23.18.0)
- StripePaymentsUI (= 23.18.0)
- StripeUICore (= 23.18.0)
- stripe-react-native (0.35.0):
- Stripe (23.21.1):
- StripeApplePay (= 23.21.1)
- StripeCore (= 23.21.1)
- StripePayments (= 23.21.1)
- StripePaymentsUI (= 23.21.1)
- StripeUICore (= 23.21.1)
- stripe-react-native (0.35.1):
- React-Core
- Stripe (~> 23.18.0)
- StripeApplePay (~> 23.18.0)
- StripeFinancialConnections (~> 23.18.0)
- StripePayments (~> 23.18.0)
- StripePaymentSheet (~> 23.18.0)
- StripePaymentsUI (~> 23.18.0)
- stripe-react-native/Tests (0.35.0):
- Stripe (~> 23.21.0)
- StripeApplePay (~> 23.21.0)
- StripeFinancialConnections (~> 23.21.0)
- StripePayments (~> 23.21.0)
- StripePaymentSheet (~> 23.21.0)
- StripePaymentsUI (~> 23.21.0)
- stripe-react-native/Tests (0.35.1):
- React-Core
- Stripe (~> 23.18.0)
- StripeApplePay (~> 23.18.0)
- StripeFinancialConnections (~> 23.18.0)
- StripePayments (~> 23.18.0)
- StripePaymentSheet (~> 23.18.0)
- StripePaymentsUI (~> 23.18.0)
- StripeApplePay (23.18.0):
- StripeCore (= 23.18.0)
- StripeCore (23.18.0)
- StripeFinancialConnections (23.18.0):
- StripeCore (= 23.18.0)
- StripeUICore (= 23.18.0)
- StripePayments (23.18.0):
- StripeCore (= 23.18.0)
- StripePayments/Stripe3DS2 (= 23.18.0)
- StripePayments/Stripe3DS2 (23.18.0):
- StripeCore (= 23.18.0)
- StripePaymentSheet (23.18.0):
- StripeApplePay (= 23.18.0)
- StripeCore (= 23.18.0)
- StripePayments (= 23.18.0)
- StripePaymentsUI (= 23.18.0)
- StripePaymentsUI (23.18.0):
- StripeCore (= 23.18.0)
- StripePayments (= 23.18.0)
- StripeUICore (= 23.18.0)
- StripeUICore (23.18.0):
- StripeCore (= 23.18.0)
- Stripe (~> 23.21.0)
- StripeApplePay (~> 23.21.0)
- StripeFinancialConnections (~> 23.21.0)
- StripePayments (~> 23.21.0)
- StripePaymentSheet (~> 23.21.0)
- StripePaymentsUI (~> 23.21.0)
- StripeApplePay (23.21.1):
- StripeCore (= 23.21.1)
- StripeCore (23.21.1)
- StripeFinancialConnections (23.21.1):
- StripeCore (= 23.21.1)
- StripeUICore (= 23.21.1)
- StripePayments (23.21.1):
- StripeCore (= 23.21.1)
- StripePayments/Stripe3DS2 (= 23.21.1)
- StripePayments/Stripe3DS2 (23.21.1):
- StripeCore (= 23.21.1)
- StripePaymentSheet (23.21.1):
- StripeApplePay (= 23.21.1)
- StripeCore (= 23.21.1)
- StripePayments (= 23.21.1)
- StripePaymentsUI (= 23.21.1)
- StripePaymentsUI (23.21.1):
- StripeCore (= 23.21.1)
- StripePayments (= 23.21.1)
- StripeUICore (= 23.21.1)
- StripeUICore (23.21.1):
- StripeCore (= 23.21.1)
- Yoga (1.14.0)
- YogaKit (1.18.1):
- Yoga (~> 1.14)
Expand Down Expand Up @@ -628,15 +628,15 @@ SPEC CHECKSUMS:
RNCPicker: 0bf8ef8f7800524f32d2bb2a8bcadd53eda0ecd1
RNScreens: 34cc502acf1b916c582c60003dc3089fa01dc66d
SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608
Stripe: 4092bc51f41ca1758166aef921aa0dd2f0fbc639
stripe-react-native: 2e2dad1734c1c2b71564b66bae4395bfd8419af4
StripeApplePay: aedbcb53f5324d527a52a5888bd0eeee25b3ca36
StripeCore: f86db23fb3f984808e6f5d3876397b953bf58a52
StripeFinancialConnections: 0aaddb3593a7cc76b5f01eab185f16ef60798b15
StripePayments: 050a2c5e2cc6f9492d80fddbc9bb3e7d00ddb0c8
StripePaymentSheet: 7a1e68dacbd280bb67ff299a9f9e3337710bbcaf
StripePaymentsUI: cec7249a59f0031050cb08e1bf27cad30654d73c
StripeUICore: 1b23b5c211091c3675f1cc446df9c14f8836630a
Stripe: d55e7338dabc599eddeee3b09eacd5c13457e1a2
stripe-react-native: 7ce5a0451633125e69dae95dd601e6f678ff447e
StripeApplePay: 48973391091a96e30e6ef6b9b331dbaa31449dcb
StripeCore: 2ad2bf779ed5b34c1af0800d8304222d3a98440f
StripeFinancialConnections: d75c000ffe2f09b14f9aebf02a571d91658ae73b
StripePayments: 9961532054e6d4176f54d681cab876cefe60de14
StripePaymentSheet: 2ef84d80a938e8c6c59ba0639007b4108d0a6bfb
StripePaymentsUI: 1f8addf41697d0f298fd8a15e4edf3999fbc66bc
StripeUICore: 95c5235db01a2d90b5bb72c85a804eaed4e64f17
Yoga: 7a4d48cfb35dfa542151e615fa73c1a0d88caf21
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a

Expand Down
2 changes: 2 additions & 0 deletions example/src/screens/PaymentsUICompleteScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
PaymentSheetError,
AddressSheet,
AddressSheetError,
CardBrand,
} from '@stripe/stripe-react-native';
import Button from '../components/Button';
import PaymentScreen from '../components/PaymentScreen';
Expand Down Expand Up @@ -111,6 +112,7 @@ export default function PaymentsUICompleteScreen() {
appearance,
primaryButtonLabel: 'purchase!',
removeSavedPaymentMethodMessage: 'remove this payment method?',
preferredNetworks: [CardBrand.Amex, CardBrand.Visa],
});
if (!error) {
setPaymentSheetEnabled(true);
Expand Down
7 changes: 6 additions & 1 deletion example/src/screens/WebhookPaymentScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import type {
} from '@stripe/stripe-react-native';
import React, { useState } from 'react';
import { Alert, StyleSheet, Text, TextInput, View, Switch } from 'react-native';
import { CardField, useConfirmPayment } from '@stripe/stripe-react-native';
import {
CardBrand,
CardField,
useConfirmPayment,
} from '@stripe/stripe-react-native';
import Button from '../components/Button';
import PaymentScreen from '../components/PaymentScreen';
import { API_URL } from '../Config';
Expand Down Expand Up @@ -108,6 +112,7 @@ export default function WebhookPaymentScreen() {
}}
cardStyle={inputStyles}
style={styles.cardField}
preferredNetworks={[CardBrand.Amex]}
/>
<View style={styles.row}>
<Switch
Expand Down
1 change: 1 addition & 0 deletions ios/CardFieldManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ @interface RCT_EXTERN_MODULE(CardFieldManager, RCTViewManager)
RCT_EXPORT_VIEW_PROPERTY(autofocus, BOOL)
RCT_EXPORT_VIEW_PROPERTY(disabled, BOOL)
RCT_EXPORT_VIEW_PROPERTY(dangerouslyGetFullCardDetails, BOOL)
RCT_EXPORT_VIEW_PROPERTY(preferredNetworks, NSArray)
RCT_EXTERN_METHOD(focus:(nonnull NSNumber*) reactTag)
RCT_EXTERN_METHOD(blur:(nonnull NSNumber*) reactTag)
RCT_EXTERN_METHOD(clear:(nonnull NSNumber*) reactTag)
Expand Down
8 changes: 8 additions & 0 deletions ios/CardFieldView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ class CardFieldView: UIView, STPPaymentCardTextFieldDelegate {
}
}

@objc var preferredNetworks: Array<Int>? {
didSet {
if let preferredNetworks = preferredNetworks {
cardField.preferredNetworks = preferredNetworks.map(Mappers.intToCardBrand).compactMap { $0 }
}
}
}

@objc var placeholders: NSDictionary = NSDictionary() {
didSet {
if let numberPlaceholder = placeholders["number"] as? String {
Expand Down
Loading