Skip to content

Commit

Permalink
Merge branch 'main' into feat/retrieve-setup-intent
Browse files Browse the repository at this point in the history
  • Loading branch information
remonh87 committed Jul 17, 2023
2 parents f9a1e24 + 9361711 commit 77c6731
Show file tree
Hide file tree
Showing 23 changed files with 182 additions and 65 deletions.
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,16 @@ Future<void> onGooglePayResult(paymentResult) async {
- [Get your test Stripe API keys](https://stripe.com/docs/keys)
- `cp lib/.env.example.dart lib/.env.dart` and set your Stripe publishable key.
- `cp server/.env.example server/.env` and set the variable values in your newly created `.env` file.
- Install the server dependencies: `npm install` or `yarn --cwd "server"`
- Install the server dependencies in the `server` directory:
* `cd server`
* `npm install` or `yarn --cwd "server"`
- Start the example
- Terminal 1: `npm start` or `yarn --cwd "server" start`
- Terminal 2: `flutter run`
- Terminal 1:
* Move to the `server` directory: `cd server`
* Run npm or yarn: `npm start` or `yarn --cwd "server" start`
- Terminal 2:
* Move to the `lib` directory: `cd lib`
* Run flutter: `flutter run`

##### Additional steps for webhook forwarding

Expand Down
2 changes: 1 addition & 1 deletion docs/card_field.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ await Stripe.instance.confirmPayment(
);
```

### 3b Cardfirn
### 3b Cardform

In case you want to display the card entry fields in multiple lines you can use the `Cardform` widget.

Expand Down
1 change: 1 addition & 0 deletions example/ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@
files = (
);
inputPaths = (
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
Expand Down
35 changes: 27 additions & 8 deletions example/server/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4457,6 +4457,11 @@ qs@^6.11.0:
dependencies:
side-channel "^1.0.4"

querystringify@^2.1.1:
version "2.2.0"
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6"
integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==

range-parser@~1.2.1:
version "1.2.1"
resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz"
Expand Down Expand Up @@ -4617,6 +4622,11 @@ require-main-filename@^2.0.0:
resolved "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz"
integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==

requires-port@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==

reselect@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/reselect/-/reselect-4.0.0.tgz"
Expand Down Expand Up @@ -5323,13 +5333,14 @@ touch@^3.1.0:
nopt "~1.0.10"

tough-cookie@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz"
integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==
version "4.1.3"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf"
integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==
dependencies:
psl "^1.1.33"
punycode "^2.1.1"
universalify "^0.1.2"
universalify "^0.2.0"
url-parse "^1.5.3"

tr46@^2.0.2:
version "2.0.2"
Expand Down Expand Up @@ -5454,10 +5465,10 @@ unique-string@^1.0.0:
dependencies:
crypto-random-string "^1.0.0"

universalify@^0.1.2:
version "0.1.2"
resolved "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz"
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
universalify@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0"
integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==

[email protected], unpipe@~1.0.0:
version "1.0.0"
Expand Down Expand Up @@ -5517,6 +5528,14 @@ url-parse-lax@^1.0.0:
dependencies:
prepend-http "^1.0.1"

url-parse@^1.5.3:
version "1.5.10"
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1"
integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==
dependencies:
querystringify "^2.1.1"
requires-port "^1.0.0"

use@^3.1.0:
version "3.1.1"
resolved "https://registry.npmjs.org/use/-/use-3.1.1.tgz"
Expand Down
2 changes: 1 addition & 1 deletion packages/stripe/lib/src/stripe.dart
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ class Stripe {

/// Call this method when the user logs out from your app.
///
/// This will ensur ethat any persisted authentication state in the
/// This will ensure that any persisted authentication state in the
/// paymentsheet, such as authentication cookies are cleared during logout.
Future<void> resetPaymentSheetCustomer() async {
await _awaitForSettings();
Expand Down
10 changes: 10 additions & 0 deletions packages/stripe/lib/src/widgets/card_field.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class CardField extends StatefulWidget {
this.countryCode,
this.style,
this.autofocus = false,
this.disabled = false,
this.dangerouslyGetFullCardDetails = false,
this.dangerouslyUpdateFullCardDetails = false,
this.cursorColor,
Expand Down Expand Up @@ -77,6 +78,11 @@ class CardField extends StatefulWidget {
/// Default is `false`.
final bool autofocus;

/// When true it applies a state that does not allow the user to interact with
/// the card form field.
/// Default is `false`.
final bool disabled;

/// Controller that can be use to execute several operations on the cardfield
/// e.g (clear).
final CardEditController? controller;
Expand Down Expand Up @@ -178,6 +184,7 @@ class _CardFieldState extends State<CardField> {
delegate: const _NegativeMarginLayout(margin: platformMargin),
child: _MethodChannelCardField(
controller: controller,
disabled: widget.disabled,
height: platformCardHeight,
androidPlatformViewRenderType:
widget.androidPlatformViewRenderType,
Expand Down Expand Up @@ -274,6 +281,7 @@ class _MethodChannelCardField extends StatefulWidget {
this.style,
this.placeholder,
this.enablePostalCode = false,
this.disabled = false,
this.countryCode,
double? width,
double? height = kCardFieldDefaultHeight,
Expand All @@ -298,6 +306,7 @@ class _MethodChannelCardField extends StatefulWidget {
final String? countryCode;
final FocusNode focusNode;
final bool autofocus;
final bool disabled;
final CardEditController controller;
final bool dangerouslyGetFullCardDetails;
final bool dangerouslyUpdateFullCardDetails;
Expand Down Expand Up @@ -395,6 +404,7 @@ class _MethodChannelCardFieldState extends State<_MethodChannelCardField>
controller.initalDetails != null)
'cardDetails': controller.initalDetails?.toJson(),
'autofocus': widget.autofocus,
'disabled': widget.disabled,
};

Widget platform;
Expand Down
34 changes: 22 additions & 12 deletions packages/stripe/lib/src/widgets/card_form_field.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,19 @@ import 'keep_visible_on_focus.dart';
/// ![Sripe Card Form]
/// (https://github.com/flutter-stripe/flutter_stripe/tree/main/docs/assets/card_form.png)
class CardFormField extends StatefulWidget {
const CardFormField(
{this.onCardChanged,
Key? key,
this.onFocus,
this.enablePostalCode = true,
this.countryCode,
this.style,
this.autofocus = false,
this.dangerouslyGetFullCardDetails = false,
this.dangerouslyUpdateFullCardDetails = false,
this.controller})
: super(key: key);
const CardFormField({
this.onCardChanged,
Key? key,
this.onFocus,
this.enablePostalCode = true,
this.countryCode,
this.style,
this.autofocus = false,
this.dangerouslyGetFullCardDetails = false,
this.dangerouslyUpdateFullCardDetails = false,
this.disabled = false,
this.controller,
}) : super(key: key);

/// Callback that will be executed when a specific field gets focus.
final CardFocusCallback? onFocus;
Expand Down Expand Up @@ -80,6 +81,11 @@ class CardFormField extends StatefulWidget {
/// Default is `false`.
final bool dangerouslyUpdateFullCardDetails;

/// When true it applies a state that does not allow the user to interact with
/// the card form field.
/// Default is `false`.
final bool disabled;

@override
// ignore: library_private_types_in_public_api
_CardFormFieldState createState() => _CardFormFieldState();
Expand Down Expand Up @@ -187,6 +193,7 @@ class _CardFormFieldState extends State<CardFormField> {
enablePostalCode: widget.enablePostalCode,
onCardChanged: widget.onCardChanged,
autofocus: widget.autofocus,
disabled: widget.disabled,
onFocus: widget.onFocus,
countryCode: widget.countryCode,
);
Expand All @@ -212,6 +219,7 @@ class _MethodChannelCardFormField extends StatefulWidget {
this.dangerouslyGetFullCardDetails = false,
this.dangerouslyUpdateFullCardDetails = false,
this.autofocus = false,
this.disabled = false,
this.countryCode,
}) : assert(constraints == null || constraints.debugAssertIsValid()),
constraints = (width != null || height != null)
Expand All @@ -227,6 +235,7 @@ class _MethodChannelCardFormField extends StatefulWidget {
final bool enablePostalCode;
final FocusNode focusNode;
final bool autofocus;
final bool disabled;
final CardFormEditController controller;
final bool dangerouslyGetFullCardDetails;
final bool dangerouslyUpdateFullCardDetails;
Expand Down Expand Up @@ -299,6 +308,7 @@ class _MethodChannelCardFormFieldState
controller._initalDetails != null)
'cardDetails': controller._initalDetails?.toJson(),
'autofocus': widget.autofocus,
'disabled': widget.disabled,
'defaultValues': {
'countryCode': widget.countryCode,
}
Expand Down
2 changes: 1 addition & 1 deletion packages/stripe_android/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ version '1.0-SNAPSHOT'

buildscript {
ext.kotlin_version = '1.8.0'
ext.stripe_version = '20.23.+'
ext.stripe_version = '20.25.+'

repositories {
google()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import com.facebook.react.uimanager.ThemedReactContext
import com.reactnativestripesdk.*
import com.reactnativestripesdk.utils.getIntOrNull
import com.reactnativestripesdk.utils.getValOr
import com.stripe.android.databinding.CardMultilineWidgetBinding
import com.stripe.android.databinding.StripeCardMultilineWidgetBinding
import com.stripe.android.databinding.StripeCardFormViewBinding
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
Expand Down Expand Up @@ -48,6 +48,9 @@ class StripeSdkCardFormPlatformView(
if (creationParams?.containsKey("autofocus") == true) {
cardFormViewManager.setAutofocus(cardView, creationParams["autofocus"] as Boolean)
}
if (creationParams?.containsKey("disabled") == true) {
cardFormViewManager.setDisabled(cardView, creationParams["disabled"] as Boolean)
}
if (creationParams?.containsKey("cardDetails") == true) {
val value = ReadableMap(creationParams["cardDetails"] as Map<String, Any>)

Expand Down Expand Up @@ -101,8 +104,13 @@ class StripeSdkCardFormPlatformView(
cardFormViewManager.setAutofocus(cardView, arguments.getBoolean("autofocus"))
result.success(null)
}
"disabled" -> {
val arguments = ReadableMap(call.arguments as Map<String, Any>)
cardFormViewManager.setDisabled(cardView, arguments.getBoolean("disabled"))
result.success(null)
}
"requestFocus" -> {
val binding = CardMultilineWidgetBinding.bind(cardView.cardForm)
val binding = StripeCardMultilineWidgetBinding.bind(cardView.cardForm)
binding.etCardNumber.requestFocus()
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import com.facebook.react.uimanager.ThemedReactContext
import com.reactnativestripesdk.*
import com.reactnativestripesdk.utils.getIntOrNull
import com.reactnativestripesdk.utils.getValOr
import com.stripe.android.databinding.CardInputWidgetBinding
import com.stripe.android.databinding.StripeCardInputWidgetBinding
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.platform.PlatformView
Expand Down Expand Up @@ -43,6 +43,9 @@ class StripeSdkCardPlatformView(
if (creationParams?.containsKey("placeholder") == true) {
stripeSdkCardViewManager.setPlaceHolders(cardView, ReadableMap(creationParams["placeholder"] as Map<String, Any>))
}
if (creationParams?.containsKey("disabled") == true) {
stripeSdkCardViewManager.setDisabled(cardView, creationParams["disabled"] as Boolean)
}
if (creationParams?.containsKey("dangerouslyGetFullCardDetails") == true) {
stripeSdkCardViewManager.setDangerouslyGetFullCardDetails(cardView, creationParams["dangerouslyGetFullCardDetails"] as Boolean)
}
Expand All @@ -53,7 +56,7 @@ class StripeSdkCardPlatformView(
val value = ReadableMap(creationParams["cardDetails"] as Map<String, Any>)
stripeSdkCardViewManager.setCardDetails(value, themedContext)

val binding = CardInputWidgetBinding.bind(cardView.mCardWidget)
val binding = StripeCardInputWidgetBinding.bind(cardView.mCardWidget)
val number = getValOr(value, "number", null)
val expirationYear = getIntOrNull(value, "expiryYear")
val expirationMonth = getIntOrNull(value, "expiryMonth")
Expand Down Expand Up @@ -118,8 +121,13 @@ class StripeSdkCardPlatformView(
stripeSdkCardViewManager.setAutofocus(cardView, arguments.getBoolean("autofocus"))
result.success(null)
}
"disabled" -> {
val arguments = ReadableMap(call.arguments as Map<String, Any>)
stripeSdkCardViewManager.setDisabled(cardView, arguments.getBoolean("disabled"))
result.success(null)
}
"requestFocus" -> {
val binding = CardInputWidgetBinding.bind(cardView.mCardWidget)
val binding = StripeCardInputWidgetBinding.bind(cardView.mCardWidget)
binding.cardNumberEditText.requestFocus()
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import com.google.android.material.shape.MaterialShapeDrawable
import com.google.android.material.shape.ShapeAppearanceModel
import com.reactnativestripesdk.utils.getIntOrNull
import com.reactnativestripesdk.utils.getValOr
import com.stripe.android.databinding.BecsDebitWidgetBinding
import com.stripe.android.databinding.StripeBecsDebitWidgetBinding
import com.stripe.android.model.PaymentMethodCreateParams
import com.stripe.android.view.BecsDebitWidget
import com.stripe.android.view.StripeEditText
Expand All @@ -35,7 +35,7 @@ class AuBECSDebitFormView(private val context: ThemedReactContext) : FrameLayout
if (!this::becsDebitWidget.isInitialized || value == null) {
return
}
val binding = BecsDebitWidgetBinding.bind(becsDebitWidget)
val binding = StripeBecsDebitWidgetBinding.bind(becsDebitWidget)
val textColor = getValOr(value, "textColor", null)
val textErrorColor = getValOr(value, "textErrorColor", null)
val placeholderColor = getValOr(value, "placeholderColor", null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import com.reactnativestripesdk.utils.*
import com.reactnativestripesdk.utils.mapCardBrand
import com.stripe.android.core.model.CountryCode
import com.stripe.android.core.model.CountryUtils
import com.stripe.android.databinding.CardInputWidgetBinding
import com.stripe.android.databinding.StripeCardInputWidgetBinding
import com.stripe.android.model.Address
import com.stripe.android.model.PaymentMethodCreateParams
import com.stripe.android.view.CardInputListener
Expand All @@ -33,7 +33,7 @@ import java.lang.Exception

class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
internal var mCardWidget: CardInputWidget = CardInputWidget(context)
private val cardInputWidgetBinding = CardInputWidgetBinding.bind(mCardWidget)
private val cardInputWidgetBinding = StripeCardInputWidgetBinding.bind(mCardWidget)
val cardDetails: MutableMap<String, Any?> = mutableMapOf("brand" to "", "last4" to "", "expiryMonth" to null, "expiryYear" to null, "postalCode" to "", "validNumber" to "Unknown", "validCVC" to "Unknown", "validExpiryDate" to "Unknown")
var cardParams: PaymentMethodCreateParams.Card? = null
var cardAddress: Address? = null
Expand Down Expand Up @@ -210,6 +210,10 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
}
}

fun setDisabled(isDisabled: Boolean) {
mCardWidget.isEnabled = !isDisabled
}

/**
* 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 @@ -59,6 +59,11 @@ class CardFieldViewManager : SimpleViewManager<CardFieldView>() {
view.setPlaceHolders(placeholders)
}

@ReactProp(name = "disabled")
fun setDisabled(view: CardFieldView, isDisabled: Boolean) {
view.setDisabled(isDisabled)
}

override fun createViewInstance(reactContext: ThemedReactContext): CardFieldView {
val stripeSdkModule: StripeSdkModule? = reactContext.getNativeModule(StripeSdkModule::class.java)
val view = CardFieldView(reactContext)
Expand Down
Loading

0 comments on commit 77c6731

Please sign in to comment.