diff --git a/CHANGELOG.md b/CHANGELOG.md index bb9b1cfe3..1dd665f42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ ### New features - `confirmPayment` can now be called with _just_ a client secret (e.g. `await confirmPayment("payment-intent-id")`), in other words the payment method can be excluded. If the payment method is excluded, it is assumed by the SDK that you have attached the payment method on the server-side during payment intent creation. [#1084](https://github.com/stripe/stripe-react-native/pull/1084) +- Added `defaultValues` prop to `CardField`. You can now programmatically set the card number, CVC, expiry date, and postal code. [#1044](https://github.com/stripe/stripe-react-native/pull/1044) +- Expanded `CardForm`'s `defaultValues` prop. You can now programmatically set the card number, CVC, expiry date, and postal code. [#1044](https://github.com/stripe/stripe-react-native/pull/1044) ### Fixes diff --git a/android/src/main/java/com/reactnativestripesdk/CardFieldView.kt b/android/src/main/java/com/reactnativestripesdk/CardFieldView.kt index b071b4280..609520398 100644 --- a/android/src/main/java/com/reactnativestripesdk/CardFieldView.kt +++ b/android/src/main/java/com/reactnativestripesdk/CardFieldView.kt @@ -175,6 +175,14 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) { } } + fun setDefaultValues(defaults: ReadableMap) { + cardInputWidgetBinding.cvcEditText.setText(defaults.getString("cvc")) + cardInputWidgetBinding.cardNumberEditText.setText(defaults.getString("number")) + cardInputWidgetBinding.postalCodeEditText.setText(defaults.getString("postalCode")) + val expiryDate = defaults.getString("expiryMonth")?.plus("/").plus(defaults.getString("expiryYear")) + cardInputWidgetBinding.expiryDateEditText.setText(expiryDate) + } + fun setPlaceHolders(value: ReadableMap) { val numberPlaceholder = getValOr(value, "number", null) val expirationPlaceholder = getValOr(value, "expiration", null) diff --git a/android/src/main/java/com/reactnativestripesdk/CardFieldViewManager.kt b/android/src/main/java/com/reactnativestripesdk/CardFieldViewManager.kt index 5d18e7d2f..619652ea8 100644 --- a/android/src/main/java/com/reactnativestripesdk/CardFieldViewManager.kt +++ b/android/src/main/java/com/reactnativestripesdk/CardFieldViewManager.kt @@ -56,6 +56,12 @@ class CardFieldViewManager : SimpleViewManager() { view.setPlaceHolders(placeholders) } + @ReactProp(name = "defaultValues") + fun setDefaultValues(view: CardFieldView, defaults: ReadableMap) { + view.setDefaultValues(defaults) + } + + override fun createViewInstance(reactContext: ThemedReactContext): CardFieldView { val stripeSdkModule: StripeSdkModule? = reactContext.getNativeModule(StripeSdkModule::class.java) val view = CardFieldView(reactContext) diff --git a/android/src/main/java/com/reactnativestripesdk/CardFormView.kt b/android/src/main/java/com/reactnativestripesdk/CardFormView.kt index ea793f2ac..0b5b7c3f0 100644 --- a/android/src/main/java/com/reactnativestripesdk/CardFormView.kt +++ b/android/src/main/java/com/reactnativestripesdk/CardFormView.kt @@ -54,6 +54,11 @@ class CardFormView(context: ThemedReactContext) : FrameLayout(context) { fun setDefaultValues(defaults: ReadableMap) { setCountry(defaults.getString("countryCode")) + cardFormViewBinding.postalCode.setText(defaults.getString("postalCode")) + cardFormViewBinding.cardMultilineWidget.cvcEditText.setText(defaults.getString("cvc")) + cardFormViewBinding.cardMultilineWidget.cardNumberEditText.setText(defaults.getString("number")) + val expiryDate = defaults.getString("expiryMonth")?.plus("/").plus(defaults.getString("expiryYear")) + cardFormViewBinding.cardMultilineWidget.expiryDateEditText.setText(expiryDate) } private fun setCountry(countryString: String?) { diff --git a/example/src/screens/MultilineWebhookPaymentScreen.tsx b/example/src/screens/MultilineWebhookPaymentScreen.tsx index 9fce61a41..0647d688e 100644 --- a/example/src/screens/MultilineWebhookPaymentScreen.tsx +++ b/example/src/screens/MultilineWebhookPaymentScreen.tsx @@ -105,6 +105,11 @@ export default function MultilineWebhookPaymentScreen() { }} defaultValues={{ countryCode: 'US', + number: '4242424242424242', + postalCode: '98989', + expiryMonth: '01', + expiryYear: '24', + cvc: '123', }} /> diff --git a/example/src/screens/WebhookPaymentScreen.tsx b/example/src/screens/WebhookPaymentScreen.tsx index 545315313..cb70de72a 100644 --- a/example/src/screens/WebhookPaymentScreen.tsx +++ b/example/src/screens/WebhookPaymentScreen.tsx @@ -104,6 +104,14 @@ export default function WebhookPaymentScreen() { }} cardStyle={inputStyles} style={styles.cardField} + countryCode="US" + defaultValues={{ + number: '4242424242424242', + postalCode: '98989', + expiryMonth: '01', + expiryYear: '24', + cvc: '123', + }} /> STPPaymentMethodCardParams { + let params = STPPaymentMethodCardParams() + params.cvc = input?["cvc"] as? String + params.number = input?["number"] as? String + if let month = input?["expiryMonth"] as? String { + params.expMonth = NSNumber(value: Int(month) ?? 0) + } + if let year = input?["expiryYear"] as? String { + params.expYear = NSNumber(value: Int(year) ?? 0) + } + return params + } } diff --git a/src/components/CardField.tsx b/src/components/CardField.tsx index 90c92bb10..59c9c122e 100644 --- a/src/components/CardField.tsx +++ b/src/components/CardField.tsx @@ -34,6 +34,8 @@ export interface Props extends AccessibilityProps { postalCodeEnabled?: boolean; /** Controls the postal code entry shown (if the postalCodeEnabled prop is set to true). Defaults to the device's default locale. */ countryCode?: string; + /** Default values which will auto-fill the CardField component. This can be especially useful for testing purposes. */ + defaultValues?: CardFieldInput.DefaultCardValues; cardStyle?: CardFieldInput.Styles; placeholders?: CardFieldInput.Placeholders; autofocus?: boolean; diff --git a/src/types/components/CardFieldInput.ts b/src/types/components/CardFieldInput.ts index 26226f166..f51e5c030 100644 --- a/src/types/components/CardFieldInput.ts +++ b/src/types/components/CardFieldInput.ts @@ -73,3 +73,16 @@ export interface Methods { blur(): void; clear(): void; } + +export type DefaultCardValues = { + /** The month of expiry of the card. This should be a 1 or 2 digit string, e.g. "2" or "12". */ + expiryMonth?: string; + /** The year of expiry of the card. This should be a 2 or 4 digit string, e.g. "25" or "2025". */ + expiryYear?: string; + /** The postal code associated with the card. */ + postalCode?: string; + /** The 16-digit card number (can be just a portion of it). */ + number?: string; + /** The 3-digit cvc of the card. */ + cvc?: string; +}; diff --git a/src/types/components/CardFormView.ts b/src/types/components/CardFormView.ts index 1d3a98010..55bb13874 100644 --- a/src/types/components/CardFormView.ts +++ b/src/types/components/CardFormView.ts @@ -47,6 +47,16 @@ export interface Placeholders { export type DefaultValues = { /** The 2-letter country code for the country selected by default on Android. If this is null, it is set by the device's configured region in the Settings app. */ countryCode?: string; + /** The month of expiry of the card. This should be a 1 or 2 digit string, e.g. "2" or "12". */ + expiryMonth?: string; + /** The year of expiry of the card. This should be a 2 or 4 digit string, e.g. "25" or "2025". */ + expiryYear?: string; + /** The postal code associated with the card. */ + postalCode?: string; + /** The 16-digit card number (can be just a portion of it). */ + number?: string; + /** The 3-digit cvc of the card. */ + cvc?: string; }; /** @@ -59,7 +69,7 @@ export interface NativeProps { cardStyle?: Styles; /** Android only */ placeholders?: Placeholders; - /** Android only */ + /** Default values which will auto-fill the CardField component. This can be especially useful for testing purposes or for setting the default country. */ defaultValues?: DefaultValues; // postalCodeEnabled: boolean; onFocusChange(