From 9864b47c1231e7cfd786accdc64e7e22c0d27eee Mon Sep 17 00:00:00 2001 From: finn Date: Tue, 11 Jul 2023 13:18:22 -0700 Subject: [PATCH 1/7] update 'run the example app' in readme (#1307) --- README.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b615c318f..6c1495599 100644 --- a/README.md +++ b/README.md @@ -156,10 +156,16 @@ Future 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 From 2da56e23ca670bc8ad796ca698372bc552e0e21c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Jul 2023 21:18:52 +0100 Subject: [PATCH 2/7] chore(deps): bump tough-cookie from 4.0.0 to 4.1.3 in /example/server (#1305) Bumps [tough-cookie](https://github.com/salesforce/tough-cookie) from 4.0.0 to 4.1.3. - [Release notes](https://github.com/salesforce/tough-cookie/releases) - [Changelog](https://github.com/salesforce/tough-cookie/blob/master/CHANGELOG.md) - [Commits](https://github.com/salesforce/tough-cookie/compare/v4.0.0...v4.1.3) --- updated-dependencies: - dependency-name: tough-cookie dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- example/server/yarn.lock | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/example/server/yarn.lock b/example/server/yarn.lock index a93846aef..5a3500776 100644 --- a/example/server/yarn.lock +++ b/example/server/yarn.lock @@ -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" @@ -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" @@ -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" @@ -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== unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" @@ -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" From 9361711a501c3b2238677c8b7712490d1a1b18ee Mon Sep 17 00:00:00 2001 From: jonasbark Date: Tue, 11 Jul 2023 22:19:36 +0200 Subject: [PATCH 3/7] Sync with Stripe React Native 0.28.0 (#1304) * sync Android + iOS with 0.28.0 * add missing method callers + update Stripe iOS version * sync dart side with version 0.28 --------- Co-authored-by: Remon <> --- example/ios/Runner.xcodeproj/project.pbxproj | 1 + packages/stripe/lib/src/stripe.dart | 2 +- .../stripe/lib/src/widgets/card_field.dart | 10 +++++ .../lib/src/widgets/card_form_field.dart | 34 ++++++++++------ packages/stripe_android/android/build.gradle | 2 +- .../stripe/StripeSdkCardFormPlatformView.kt | 12 +++++- .../stripe/StripeSdkCardPlatformView.kt | 14 +++++-- .../AuBECSDebitFormView.kt | 4 +- .../com/reactnativestripesdk/CardFieldView.kt | 8 +++- .../CardFieldViewManager.kt | 5 +++ .../com/reactnativestripesdk/CardFormView.kt | 8 +++- .../CardFormViewManager.kt | 5 +++ .../FinancialConnectionsSheetFragment.kt | 40 +++++++++++++++---- .../pushprovisioning/AddToWalletButtonView.kt | 2 +- .../ios/Classes/CardFieldFactory.swift | 7 +++- .../ios/Classes/CardFormFactory.swift | 7 ++-- .../Classes/Stripe Sdk/CardFieldView.swift | 6 +++ .../ios/Classes/Stripe Sdk/CardFormView.swift | 18 ++++----- .../ios/Classes/Stripe Sdk/StripeSdk.swift | 11 +++-- packages/stripe_ios/ios/stripe_ios.podspec | 2 +- 20 files changed, 145 insertions(+), 53 deletions(-) diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 729c8c8e8..d402467cc 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -299,6 +299,7 @@ files = ( ); inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", ); name = "Thin Binary"; outputPaths = ( diff --git a/packages/stripe/lib/src/stripe.dart b/packages/stripe/lib/src/stripe.dart index 65ade184f..bb2ca9cdc 100644 --- a/packages/stripe/lib/src/stripe.dart +++ b/packages/stripe/lib/src/stripe.dart @@ -506,7 +506,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 resetPaymentSheetCustomer() async { await _awaitForSettings(); diff --git a/packages/stripe/lib/src/widgets/card_field.dart b/packages/stripe/lib/src/widgets/card_field.dart index b0419c5a4..82e9d7562 100644 --- a/packages/stripe/lib/src/widgets/card_field.dart +++ b/packages/stripe/lib/src/widgets/card_field.dart @@ -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, @@ -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; @@ -178,6 +184,7 @@ class _CardFieldState extends State { delegate: const _NegativeMarginLayout(margin: platformMargin), child: _MethodChannelCardField( controller: controller, + disabled: widget.disabled, height: platformCardHeight, androidPlatformViewRenderType: widget.androidPlatformViewRenderType, @@ -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, @@ -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; @@ -395,6 +404,7 @@ class _MethodChannelCardFieldState extends State<_MethodChannelCardField> controller.initalDetails != null) 'cardDetails': controller.initalDetails?.toJson(), 'autofocus': widget.autofocus, + 'disabled': widget.disabled, }; Widget platform; diff --git a/packages/stripe/lib/src/widgets/card_form_field.dart b/packages/stripe/lib/src/widgets/card_form_field.dart index 4797e0642..7ab7de580 100644 --- a/packages/stripe/lib/src/widgets/card_form_field.dart +++ b/packages/stripe/lib/src/widgets/card_form_field.dart @@ -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; @@ -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(); @@ -187,6 +193,7 @@ class _CardFormFieldState extends State { enablePostalCode: widget.enablePostalCode, onCardChanged: widget.onCardChanged, autofocus: widget.autofocus, + disabled: widget.disabled, onFocus: widget.onFocus, countryCode: widget.countryCode, ); @@ -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) @@ -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; @@ -299,6 +308,7 @@ class _MethodChannelCardFormFieldState controller._initalDetails != null) 'cardDetails': controller._initalDetails?.toJson(), 'autofocus': widget.autofocus, + 'disabled': widget.disabled, 'defaultValues': { 'countryCode': widget.countryCode, } diff --git a/packages/stripe_android/android/build.gradle b/packages/stripe_android/android/build.gradle index a1221b8ab..c7e2e2ff1 100644 --- a/packages/stripe_android/android/build.gradle +++ b/packages/stripe_android/android/build.gradle @@ -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() diff --git a/packages/stripe_android/android/src/main/kotlin/com/flutter/stripe/StripeSdkCardFormPlatformView.kt b/packages/stripe_android/android/src/main/kotlin/com/flutter/stripe/StripeSdkCardFormPlatformView.kt index b472608b9..c7a16a116 100644 --- a/packages/stripe_android/android/src/main/kotlin/com/flutter/stripe/StripeSdkCardFormPlatformView.kt +++ b/packages/stripe_android/android/src/main/kotlin/com/flutter/stripe/StripeSdkCardFormPlatformView.kt @@ -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 @@ -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) @@ -101,8 +104,13 @@ class StripeSdkCardFormPlatformView( cardFormViewManager.setAutofocus(cardView, arguments.getBoolean("autofocus")) result.success(null) } + "disabled" -> { + val arguments = ReadableMap(call.arguments as Map) + 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); diff --git a/packages/stripe_android/android/src/main/kotlin/com/flutter/stripe/StripeSdkCardPlatformView.kt b/packages/stripe_android/android/src/main/kotlin/com/flutter/stripe/StripeSdkCardPlatformView.kt index 9b7cf7c5f..ba4e9adad 100644 --- a/packages/stripe_android/android/src/main/kotlin/com/flutter/stripe/StripeSdkCardPlatformView.kt +++ b/packages/stripe_android/android/src/main/kotlin/com/flutter/stripe/StripeSdkCardPlatformView.kt @@ -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 @@ -43,6 +43,9 @@ class StripeSdkCardPlatformView( if (creationParams?.containsKey("placeholder") == true) { stripeSdkCardViewManager.setPlaceHolders(cardView, ReadableMap(creationParams["placeholder"] as Map)) } + if (creationParams?.containsKey("disabled") == true) { + stripeSdkCardViewManager.setDisabled(cardView, creationParams["disabled"] as Boolean) + } if (creationParams?.containsKey("dangerouslyGetFullCardDetails") == true) { stripeSdkCardViewManager.setDangerouslyGetFullCardDetails(cardView, creationParams["dangerouslyGetFullCardDetails"] as Boolean) } @@ -53,7 +56,7 @@ class StripeSdkCardPlatformView( val value = ReadableMap(creationParams["cardDetails"] as Map) 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") @@ -118,8 +121,13 @@ class StripeSdkCardPlatformView( stripeSdkCardViewManager.setAutofocus(cardView, arguments.getBoolean("autofocus")) result.success(null) } + "disabled" -> { + val arguments = ReadableMap(call.arguments as Map) + 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); diff --git a/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/AuBECSDebitFormView.kt b/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/AuBECSDebitFormView.kt index f158db3c4..c95177847 100644 --- a/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/AuBECSDebitFormView.kt +++ b/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/AuBECSDebitFormView.kt @@ -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 @@ -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) diff --git a/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/CardFieldView.kt b/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/CardFieldView.kt index 27f1b1dfb..4475bd170 100644 --- a/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/CardFieldView.kt +++ b/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/CardFieldView.kt @@ -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 @@ -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 = 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 @@ -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 diff --git a/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/CardFieldViewManager.kt b/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/CardFieldViewManager.kt index a87bca3b6..dcc2e911a 100644 --- a/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/CardFieldViewManager.kt +++ b/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/CardFieldViewManager.kt @@ -59,6 +59,11 @@ class CardFieldViewManager : SimpleViewManager() { 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) diff --git a/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/CardFormView.kt b/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/CardFormView.kt index 0e2d2c0ff..88200926d 100644 --- a/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/CardFormView.kt +++ b/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/CardFormView.kt @@ -20,7 +20,7 @@ import com.google.android.material.shape.ShapeAppearanceModel import com.reactnativestripesdk.utils.* import com.reactnativestripesdk.utils.mapCardBrand import com.stripe.android.core.model.CountryCode -import com.stripe.android.databinding.CardMultilineWidgetBinding +import com.stripe.android.databinding.StripeCardMultilineWidgetBinding import com.stripe.android.databinding.StripeCardFormViewBinding import com.stripe.android.model.Address import com.stripe.android.model.PaymentMethodCreateParams @@ -37,7 +37,7 @@ class CardFormView(context: ThemedReactContext) : FrameLayout(context) { var cardParams: PaymentMethodCreateParams.Card? = null var cardAddress: Address? = null private val cardFormViewBinding = StripeCardFormViewBinding.bind(cardForm) - private val multilineWidgetBinding = CardMultilineWidgetBinding.bind(cardFormViewBinding.cardMultilineWidget) + private val multilineWidgetBinding = StripeCardMultilineWidgetBinding.bind(cardFormViewBinding.cardMultilineWidget) init { cardFormViewBinding.cardMultilineWidgetContainer.isFocusable = true @@ -60,6 +60,10 @@ class CardFormView(context: ThemedReactContext) : FrameLayout(context) { setCountry(defaults.getString("countryCode")) } + fun setDisabled(isDisabled: Boolean) { + cardForm.isEnabled = !isDisabled + } + private fun setCountry(countryString: String?) { if (countryString != null) { cardFormViewBinding.countryLayout.setSelectedCountryCode(CountryCode(countryString)) diff --git a/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/CardFormViewManager.kt b/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/CardFormViewManager.kt index 473db495a..45000acc9 100644 --- a/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/CardFormViewManager.kt +++ b/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/CardFormViewManager.kt @@ -56,6 +56,11 @@ class CardFormViewManager : SimpleViewManager() { view.setDefaultValues(defaults) } + @ReactProp(name = "disabled") + fun setDisabled(view: CardFormView, isDisabled: Boolean) { + view.setDisabled(isDisabled) + } + override fun createViewInstance(reactContext: ThemedReactContext): CardFormView { val stripeSdkModule: StripeSdkModule? = reactContext.getNativeModule(StripeSdkModule::class.java) val view = CardFormView(reactContext) diff --git a/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/FinancialConnectionsSheetFragment.kt b/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/FinancialConnectionsSheetFragment.kt index dd202a824..bb41e4363 100644 --- a/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/FinancialConnectionsSheetFragment.kt +++ b/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/FinancialConnectionsSheetFragment.kt @@ -180,18 +180,44 @@ class FinancialConnectionsSheetFragment : Fragment() { val map = WritableNativeMap() map.putDouble("asOf", balance.asOf * 1000.0) map.putString("type", mapFromBalanceType(balance.type)) - map.putMap("current", balance.current as ReadableMap) WritableNativeMap().also { - it.putMap("available", balance.cash?.available as ReadableMap) - map.putMap("cash", it) - } - WritableNativeMap().also { - it.putMap("used", balance.credit?.used as ReadableMap) - map.putMap("credit", it) + for (entry in balance.current.entries) { + it.putInt(entry.key, entry.value) + } + map.putMap("current", it) } + map.putMap("cash", mapFromCashAvailable(balance)) + map.putMap("credit", mapFromCreditUsed(balance)) + return map } + private fun mapFromCashAvailable(balance: Balance): WritableNativeMap { + return WritableNativeMap().also { cashMap -> + WritableNativeMap().also { availableMap -> + balance.cash?.available?.entries?.let { entries -> + for (entry in entries) { + availableMap.putInt(entry.key, entry.value) + } + } + cashMap.putMap("available", availableMap) + } + } + } + + private fun mapFromCreditUsed(balance: Balance): WritableNativeMap { + return WritableNativeMap().also { creditMap -> + WritableNativeMap().also { usedMap -> + balance.credit?.used?.entries?.let { entries -> + for (entry in entries) { + usedMap.putInt(entry.key, entry.value) + } + } + creditMap.putMap("used", usedMap) + } + } + } + private fun mapFromAccountBalanceRefresh(balanceRefresh: BalanceRefresh?): WritableMap? { if (balanceRefresh == null) { return null diff --git a/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/pushprovisioning/AddToWalletButtonView.kt b/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/pushprovisioning/AddToWalletButtonView.kt index e9c8f6f84..6a69c2e30 100644 --- a/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/pushprovisioning/AddToWalletButtonView.kt +++ b/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/pushprovisioning/AddToWalletButtonView.kt @@ -95,7 +95,7 @@ class AddToWalletButtonView(private val context: ThemedReactContext, private val } }) .centerCrop() - .override((widthOverride * scale.toFloat()).toInt(), (heightOverride * scale.toFloat()).toInt()) + .override((widthOverride * scale.toInt()), (heightOverride * scale.toInt())) .into(this) } } diff --git a/packages/stripe_ios/ios/Classes/CardFieldFactory.swift b/packages/stripe_ios/ios/Classes/CardFieldFactory.swift index 1515562e0..c0864c950 100644 --- a/packages/stripe_ios/ios/Classes/CardFieldFactory.swift +++ b/packages/stripe_ios/ios/Classes/CardFieldFactory.swift @@ -75,7 +75,8 @@ class CardFieldPlatformView: NSObject, FlutterPlatformView, STPPaymentCardTextFi "onCountryCodeChangedEvent", "onPlaceholderChanged", "dangerouslyGetFullCardDetails", - "autofocus": + "autofocus", + "disabled": updateProps(call.arguments as? [String : Any]) result(nil) case "focus": @@ -132,6 +133,10 @@ class CardFieldPlatformView: NSObject, FlutterPlatformView, STPPaymentCardTextFi cardField.postalCodeEnabled = postalCodeEnabled } + if let disabled = arguments["disabled"] as? Bool{ + cardField.disabled = disabled + } + if let cardDetails = arguments["cardDetails"] as? NSDictionary { cardField.dangerouslyUpdateCardDetails(params: cardDetails) } diff --git a/packages/stripe_ios/ios/Classes/CardFormFactory.swift b/packages/stripe_ios/ios/Classes/CardFormFactory.swift index e62a28c02..9cc50b829 100644 --- a/packages/stripe_ios/ios/Classes/CardFormFactory.swift +++ b/packages/stripe_ios/ios/Classes/CardFormFactory.swift @@ -75,7 +75,8 @@ class CardFormPlatformView : NSObject, FlutterPlatformView { "onPostalCodeEnabledChanged", "dangerouslyGetFullCardDetails", "isUserInteractionEnabledValue", - "autofocus": + "autofocus", + "disabled": updateProps(call.arguments) result(nil) case "focus": @@ -104,8 +105,8 @@ class CardFormPlatformView : NSObject, FlutterPlatformView { cardForm.dangerouslyGetFullCardDetails = dangerouslyGetFullCardDetails } - if let isUserInteractionEnabledValue = arguments["isUserInteractionEnabledValue"] as? Bool{ - cardForm.isUserInteractionEnabledValue = isUserInteractionEnabledValue + if let disabled = arguments["disabled"] as? Bool{ + cardForm.disabled = disabled } if let autofocus = arguments["autofocus"] as? Bool{ cardForm.autofocus = autofocus diff --git a/packages/stripe_ios/ios/Classes/Stripe Sdk/CardFieldView.swift b/packages/stripe_ios/ios/Classes/Stripe Sdk/CardFieldView.swift index 65b8b7cac..742c754e5 100644 --- a/packages/stripe_ios/ios/Classes/Stripe Sdk/CardFieldView.swift +++ b/packages/stripe_ios/ios/Classes/Stripe Sdk/CardFieldView.swift @@ -12,6 +12,12 @@ class CardFieldView: UIView, STPPaymentCardTextFieldDelegate { public var cardParams: STPPaymentMethodParams? = nil public var cardPostalCode: String? = nil + @objc var disabled: Bool = false { + didSet { + cardField.isUserInteractionEnabled = !disabled + } + } + @objc var postalCodeEnabled: Bool = true { didSet { cardField.postalCodeEntryEnabled = postalCodeEnabled diff --git a/packages/stripe_ios/ios/Classes/Stripe Sdk/CardFormView.swift b/packages/stripe_ios/ios/Classes/Stripe Sdk/CardFormView.swift index f0bc39b2a..5d68322fb 100644 --- a/packages/stripe_ios/ios/Classes/Stripe Sdk/CardFormView.swift +++ b/packages/stripe_ios/ios/Classes/Stripe Sdk/CardFormView.swift @@ -10,7 +10,7 @@ class CardFormView: UIView, STPCardFormViewDelegate { @objc var dangerouslyGetFullCardDetails: Bool = false @objc var onFormComplete: RCTDirectEventBlock? @objc var autofocus: Bool = false - @objc var isUserInteractionEnabledValue: Bool = true + @objc var disabled: Bool = false override func didSetProps(_ changedProps: [String]!) { if let cardForm = self.cardForm { @@ -20,7 +20,7 @@ class CardFormView: UIView, STPCardFormViewDelegate { let style = self.cardStyle["type"] as? String == "borderless" ? STPCardFormViewStyle.borderless : STPCardFormViewStyle.standard let _cardForm = STPCardFormView(style: style) _cardForm.delegate = self - // _cardForm.isUserInteractionEnabled = isUserInteractionEnabledValue + _cardForm.isUserInteractionEnabled = !disabled if autofocus == true { let _ = _cardForm.becomeFirstResponder() @@ -33,10 +33,10 @@ class CardFormView: UIView, STPCardFormViewDelegate { @objc var cardStyle: NSDictionary = NSDictionary() { didSet { - setStyles() + setStyles() } } - + func cardFormView(_ form: STPCardFormView, didChangeToStateComplete complete: Bool) { if onFormComplete != nil { let brand = STPCardValidator.brand(forNumber: cardForm?.cardParams?.card?.number ?? "") @@ -49,7 +49,7 @@ class CardFormView: UIView, STPCardFormViewDelegate { "postalCode": cardForm?.cardParams?.billingDetails?.address?.postalCode ?? "", "country": cardForm?.cardParams?.billingDetails?.address?.country ] - + if (dangerouslyGetFullCardDetails) { cardData["number"] = cardForm?.cardParams?.card?.number ?? "" cardData["cvc"] = cardForm?.cardParams?.card?.cvc ?? "" @@ -76,13 +76,13 @@ class CardFormView: UIView, STPCardFormViewDelegate { cardForm?.backgroundColor = UIColor(hexString: backgroundColor) } /** - The following reveals a bug in STPCardFormView where there's a extra space in the layer, - and thus must remain commented out for now. + The following reveals a bug in STPCardFormView where there's a extra space in the layer, + and thus must remain commented out for now. if let borderWidth = cardStyle["borderWidth"] as? Int { - cardForm?.layer.borderWidth = CGFloat(borderWidth) + cardForm?.layer.borderWidth = CGFloat(borderWidth) } else { - cardForm?.layer.borderWidth = CGFloat(0) + cardForm?.layer.borderWidth = CGFloat(0) } */ diff --git a/packages/stripe_ios/ios/Classes/Stripe Sdk/StripeSdk.swift b/packages/stripe_ios/ios/Classes/Stripe Sdk/StripeSdk.swift index 90cd5c130..047ae6be0 100644 --- a/packages/stripe_ios/ios/Classes/Stripe Sdk/StripeSdk.swift +++ b/packages/stripe_ios/ios/Classes/Stripe Sdk/StripeSdk.swift @@ -145,9 +145,8 @@ class StripeSdk: RCTEventEmitter, STPBankSelectionViewControllerDelegate, UIAdap case .canceled: resolve(Errors.createError(ErrorType.Canceled, "The payment flow has been canceled")) case .failed(let error): - resolve(Errors.createError(ErrorType.Failed, error.localizedDescription)) + resolve(Errors.createError(ErrorType.Failed, error)) } - } } else { resolve(Errors.createError(ErrorType.Failed, "No payment sheet has been initialized yet")) @@ -221,7 +220,7 @@ class StripeSdk: RCTEventEmitter, STPBankSelectionViewControllerDelegate, UIAdap STPAPIClient.shared.createToken(forCVCUpdate: cvc) { (token, error) in if error != nil || token == nil { - resolve(Errors.createError(ErrorType.Failed, error?.localizedDescription ?? "")) + resolve(Errors.createError(ErrorType.Failed, error as? NSError)) } else { let tokenId = token?.tokenId resolve(["tokenId": tokenId]) @@ -558,7 +557,7 @@ class StripeSdk: RCTEventEmitter, STPBankSelectionViewControllerDelegate, UIAdap if let paymentMethodParams = paymentMethodParams { STPAPIClient.shared.createPaymentMethod(with: paymentMethodParams) { paymentMethod, error in if let createError = error { - resolve(Errors.createError(ErrorType.Failed, createError.localizedDescription)) + resolve(Errors.createError(ErrorType.Failed, createError as NSError)) } else { resolve( Mappers.createResult("paymentMethod", Mappers.mapFromPaymentMethod(paymentMethod)) @@ -908,7 +907,7 @@ class StripeSdk: RCTEventEmitter, STPBankSelectionViewControllerDelegate, UIAdap if let lastPaymentError = paymentIntent?.lastPaymentError { resolve(Errors.createError(ErrorType.Unknown, lastPaymentError)) } else { - resolve(Errors.createError(ErrorType.Unknown, error?.localizedDescription)) + resolve(Errors.createError(ErrorType.Unknown, error as? NSError)) } return } @@ -932,7 +931,7 @@ class StripeSdk: RCTEventEmitter, STPBankSelectionViewControllerDelegate, UIAdap if let lastSetupError = setupIntent?.lastSetupError { resolve(Errors.createError(ErrorType.Unknown, lastSetupError)) } else { - resolve(Errors.createError(ErrorType.Unknown, error?.localizedDescription)) + resolve(Errors.createError(ErrorType.Unknown, error as? NSError)) } return } diff --git a/packages/stripe_ios/ios/stripe_ios.podspec b/packages/stripe_ios/ios/stripe_ios.podspec index d40dd97b5..62cfa3aab 100644 --- a/packages/stripe_ios/ios/stripe_ios.podspec +++ b/packages/stripe_ios/ios/stripe_ios.podspec @@ -2,7 +2,7 @@ # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. # Run `pod lib lint stripe_ios.podspec' to validate before publishing. # -stripe_version = '~> 23.7.0' +stripe_version = '~> 23.8.0' Pod::Spec.new do |s| s.name = 'stripe_ios' s.version = '0.0.1' From 6dd8944b8d66b055df1529df600298d5aa8a2417 Mon Sep 17 00:00:00 2001 From: fachrifaul Date: Tue, 18 Jul 2023 02:32:39 +0700 Subject: [PATCH 4/7] Fix wrong key for buttonStyle in iOS (#1185) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update StripePlugin.swift fix key usesDeprecatedTokenFlow * Fix wrong key for buttonStyle in iOS * Update ApplePayButtonView.swift --------- Co-authored-by: Rémon --- packages/stripe_ios/ios/Classes/ApplePayButtonView.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/stripe_ios/ios/Classes/ApplePayButtonView.swift b/packages/stripe_ios/ios/Classes/ApplePayButtonView.swift index a439f7886..2189aab27 100644 --- a/packages/stripe_ios/ios/Classes/ApplePayButtonView.swift +++ b/packages/stripe_ios/ios/Classes/ApplePayButtonView.swift @@ -83,7 +83,7 @@ class ApplePayButtonView: NSObject, FlutterPlatformView { onOrderTrackingAction = onOrderTracking if let arguments = args as? Dictionary { type = arguments["type"] as? NSNumber - buttonStyle = arguments["buttonStyle"] as? NSNumber + buttonStyle = arguments["style"] as? NSNumber borderRadius = arguments["borderRadius"] as? NSNumber } // iOS views can be created here @@ -114,7 +114,7 @@ class ApplePayButtonView: NSObject, FlutterPlatformView { case "updateStyle": if let arguments = call.arguments as? Dictionary { self.type = arguments["type"] as? NSNumber - self.buttonStyle = arguments["buttonStyle"] as? NSNumber + self.buttonStyle = arguments["style"] as? NSNumber self.borderRadius = arguments["borderRadius"] as? NSNumber } From 0a6cf2298ba0d5b1c21ae4bfcd4df95b4a0f1e32 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Jul 2023 20:33:04 +0100 Subject: [PATCH 5/7] chore(deps): bump semver from 5.7.1 to 5.7.2 in /example/server (#1312) Bumps [semver](https://github.com/npm/node-semver) from 5.7.1 to 5.7.2. - [Release notes](https://github.com/npm/node-semver/releases) - [Changelog](https://github.com/npm/node-semver/blob/v5.7.2/CHANGELOG.md) - [Commits](https://github.com/npm/node-semver/compare/v5.7.1...v5.7.2) --- updated-dependencies: - dependency-name: semver dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- example/server/yarn.lock | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/example/server/yarn.lock b/example/server/yarn.lock index 5a3500776..c18656c86 100644 --- a/example/server/yarn.lock +++ b/example/server/yarn.lock @@ -3650,6 +3650,13 @@ lru-cache@^4.0.1: pseudomap "^1.0.2" yallist "^2.1.2" +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + make-dir@^1.0.0: version "1.3.0" resolved "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz" @@ -4795,19 +4802,21 @@ semver-regex@^2.0.0: integrity sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw== "semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: - version "5.7.1" - resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== semver@7.x, semver@^7.3.2: - version "7.3.2" - resolved "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz" - integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" semver@^6.0.0, semver@^6.1.2, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== send@0.17.2: version "0.17.2" @@ -5769,6 +5778,11 @@ yallist@^3.0.0, yallist@^3.1.1: resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + yaml@^1.7.2: version "1.8.0" resolved "https://registry.npmjs.org/yaml/-/yaml-1.8.0.tgz" From 090eb21fdd92d3c0e41664b4214388f6eac924eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mon?= Date: Tue, 18 Jul 2023 08:50:51 +0100 Subject: [PATCH 6/7] Fix #1313 accept cash app payments (#1318) Co-authored-by: Remon <> --- .../cash_app_screen.dart | 89 +++++++++++++++++++ example/lib/screens/screens.dart | 6 ++ packages/stripe/README.md | 12 ++- .../lib/src/models/payment_methods.dart | 4 +- .../src/models/payment_methods.freezed.dart | 4 +- 5 files changed, 108 insertions(+), 7 deletions(-) create mode 100644 example/lib/screens/regional_payment_methods/cash_app_screen.dart diff --git a/example/lib/screens/regional_payment_methods/cash_app_screen.dart b/example/lib/screens/regional_payment_methods/cash_app_screen.dart new file mode 100644 index 000000000..fa5f419c8 --- /dev/null +++ b/example/lib/screens/regional_payment_methods/cash_app_screen.dart @@ -0,0 +1,89 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:flutter_stripe/flutter_stripe.dart'; +import 'package:http/http.dart' as http; +import 'package:stripe_example/widgets/example_scaffold.dart'; +import 'package:stripe_example/widgets/loading_button.dart'; + +import '../../config.dart'; + +class CashAppScreen extends StatelessWidget { + const CashAppScreen({Key? key}) : super(key: key); + + Future> _createPaymentIntent() async { + final url = Uri.parse('$kApiUrl/create-payment-intent'); + final response = await http.post( + url, + headers: { + 'Content-Type': 'application/json', + }, + body: json.encode({ + 'currency': 'usd', + 'payment_method_types': ['cashapp'], + 'amount': 6000 + }), + ); + + return json.decode(response.body); + } + + Future _pay(BuildContext context) async { + // Precondition: + //Make sure to have set a custom URI scheme in your app and add it to Stripe SDK + // see file main.dart in this example app. + // 1. on the backend create a payment intent for payment method and save the + // client secret. + final result = await _createPaymentIntent(); + final clientSecret = await result['clientSecret']; + + // 2. use the client secret to confirm the payment and handle the result. + try { + await Stripe.instance.confirmPayment( + paymentIntentClientSecret: clientSecret, + data: PaymentMethodParams.cashAppPay( + paymentMethodData: PaymentMethodData(), + ), + ); + + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Payment succesfully completed'), + ), + ); + } on Exception catch (e) { + if (e is StripeException) { + print('blaat $e'); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + 'Error from Stripe: ${e.error.localizedMessage ?? e.error.code}'), + ), + ); + } else { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Unforeseen error: ${e}'), + ), + ); + } + } + } + + @override + Widget build(BuildContext context) { + return ExampleScaffold( + title: 'Cashapp', + tags: ['Payment method'], + padding: EdgeInsets.all(16), + children: [ + LoadingButton( + onPressed: () async { + await _pay(context); + }, + text: 'Pay', + ), + ], + ); + } +} diff --git a/example/lib/screens/screens.dart b/example/lib/screens/screens.dart index 1e9fac18e..b6a27baff 100644 --- a/example/lib/screens/screens.dart +++ b/example/lib/screens/screens.dart @@ -5,6 +5,7 @@ import 'package:stripe_example/screens/payment_sheet/payment_sheet_screen.dart'; import 'package:stripe_example/screens/payment_sheet/payment_sheet_screen_custom_flow.dart'; import 'package:stripe_example/screens/regional_payment_methods/ali_pay_screen.dart'; import 'package:stripe_example/screens/regional_payment_methods/aubecs_debit.dart'; +import 'package:stripe_example/screens/regional_payment_methods/cash_app_screen.dart'; import 'package:stripe_example/screens/regional_payment_methods/fpx_screen.dart'; import 'package:stripe_example/screens/regional_payment_methods/ideal_screen.dart'; import 'package:stripe_example/screens/regional_payment_methods/klarna_screen.dart'; @@ -221,6 +222,11 @@ class Example extends StatelessWidget { builder: (context) => AliPayScreen(), platformsSupported: [DevicePlatform.android, DevicePlatform.ios], ), + Example( + title: 'Cash app Pay', + builder: (context) => CashAppScreen(), + platformsSupported: [DevicePlatform.android, DevicePlatform.ios], + ), Example( title: 'Ideal', leading: Image.asset( diff --git a/packages/stripe/README.md b/packages/stripe/README.md index b615c318f..6c1495599 100644 --- a/packages/stripe/README.md +++ b/packages/stripe/README.md @@ -156,10 +156,16 @@ Future 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 diff --git a/packages/stripe_platform_interface/lib/src/models/payment_methods.dart b/packages/stripe_platform_interface/lib/src/models/payment_methods.dart index 0ad158ded..72cd426e4 100644 --- a/packages/stripe_platform_interface/lib/src/models/payment_methods.dart +++ b/packages/stripe_platform_interface/lib/src/models/payment_methods.dart @@ -358,9 +358,9 @@ class PaymentMethodParams with _$PaymentMethodParams { }) = _PaymentMethodParamsAlipay; @JsonSerializable(explicitToJson: true) - @FreezedUnionValue('CashAppPay') + @FreezedUnionValue('CashApp') - /// Config parameters for Alipay card payment method. + /// Config parameters for cashapp payment method. const factory PaymentMethodParams.cashAppPay({ /// Paymentmethod data for this paymentmethod. required PaymentMethodData paymentMethodData, diff --git a/packages/stripe_platform_interface/lib/src/models/payment_methods.freezed.dart b/packages/stripe_platform_interface/lib/src/models/payment_methods.freezed.dart index 9d3a45431..c47b978ea 100644 --- a/packages/stripe_platform_interface/lib/src/models/payment_methods.freezed.dart +++ b/packages/stripe_platform_interface/lib/src/models/payment_methods.freezed.dart @@ -2859,7 +2859,7 @@ PaymentMethodParams _$PaymentMethodParamsFromJson(Map json) { return _PaymentMethodParamsCardWithMethodId.fromJson(json); case 'Alipay': return _PaymentMethodParamsAlipay.fromJson(json); - case 'CashAppPay': + case 'CashApp': return _PaymentMethodParamsCashAppPay.fromJson(json); case 'Ideal': return _PaymentMethodParamsIdeal.fromJson(json); @@ -4389,7 +4389,7 @@ class _$_PaymentMethodParamsCashAppPay implements _PaymentMethodParamsCashAppPay { const _$_PaymentMethodParamsCashAppPay( {required this.paymentMethodData, final String? $type}) - : $type = $type ?? 'CashAppPay'; + : $type = $type ?? 'CashApp'; factory _$_PaymentMethodParamsCashAppPay.fromJson( Map json) => From 63ab342639d9f3248bcdbd50cccac6fbd6142577 Mon Sep 17 00:00:00 2001 From: Behnam Sattar Date: Tue, 18 Jul 2023 03:51:08 -0400 Subject: [PATCH 7/7] feat: add retrieveSetupIntent (#1302) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Rémon --- packages/stripe/lib/src/stripe.dart | 13 +++++++++++++ .../com/flutter/stripe/StripeAndroidPlugin.kt | 4 ++++ .../lib/src/method_channel_stripe.dart | 12 ++++++++++++ .../lib/src/stripe_platform_interface.dart | 1 + packages/stripe_web/lib/src/web_stripe.dart | 5 +++++ 5 files changed, 35 insertions(+) diff --git a/packages/stripe/lib/src/stripe.dart b/packages/stripe/lib/src/stripe.dart index bb2ca9cdc..297fb7676 100644 --- a/packages/stripe/lib/src/stripe.dart +++ b/packages/stripe/lib/src/stripe.dart @@ -331,6 +331,19 @@ class Stripe { } } + /// Retrieves a [SetupIntent] using the provided [clientSecret]. + /// + /// Throws a [StripeException] in case retrieving the intent fails. + Future retrieveSetupIntent(String clientSecret) async { + await _awaitForSettings(); + try { + final setupIntent = await _platform.retrieveSetupIntent(clientSecret); + return setupIntent; + } on StripeError catch (error) { + throw StripeError(message: error.message, code: error.message); + } + } + /// Opens the UI to set up credit cards for Apple Pay. Future openApplePaySetup() async { await _platform.openApplePaySetup(); diff --git a/packages/stripe_android/android/src/main/kotlin/com/flutter/stripe/StripeAndroidPlugin.kt b/packages/stripe_android/android/src/main/kotlin/com/flutter/stripe/StripeAndroidPlugin.kt index 67412317a..8127bbd03 100644 --- a/packages/stripe_android/android/src/main/kotlin/com/flutter/stripe/StripeAndroidPlugin.kt +++ b/packages/stripe_android/android/src/main/kotlin/com/flutter/stripe/StripeAndroidPlugin.kt @@ -119,6 +119,10 @@ If you continue to have trouble, follow this discussion to get some support http clientSecret = call.requiredArgument("clientSecret"), promise = Promise(result) ) + "retrieveSetupIntent" -> stripeSdk.retrieveSetupIntent( + clientSecret = call.requiredArgument("clientSecret"), + promise = Promise(result) + ) "initPaymentSheet" -> stripeSdk.initPaymentSheet( params = call.requiredArgument("params"), promise = Promise(result) diff --git a/packages/stripe_platform_interface/lib/src/method_channel_stripe.dart b/packages/stripe_platform_interface/lib/src/method_channel_stripe.dart index c93592b9a..f8db5f149 100644 --- a/packages/stripe_platform_interface/lib/src/method_channel_stripe.dart +++ b/packages/stripe_platform_interface/lib/src/method_channel_stripe.dart @@ -225,6 +225,18 @@ class MethodChannelStripe extends StripePlatform { .parse(result: result!, successResultKey: 'paymentIntent'); } + @override + Future retrieveSetupIntent(String clientSecret) async { + final result = await _methodChannel + .invokeMapMethod('retrieveSetupIntent', { + 'clientSecret': clientSecret, + }); + + return ResultParser( + parseJson: (json) => SetupIntent.fromJson(json)) + .parse(result: result!, successResultKey: 'setupIntent'); + } + @override Future initPaymentSheet( SetupPaymentSheetParameters params) async { diff --git a/packages/stripe_platform_interface/lib/src/stripe_platform_interface.dart b/packages/stripe_platform_interface/lib/src/stripe_platform_interface.dart index 326bf30f7..3261f2c27 100644 --- a/packages/stripe_platform_interface/lib/src/stripe_platform_interface.dart +++ b/packages/stripe_platform_interface/lib/src/stripe_platform_interface.dart @@ -130,6 +130,7 @@ abstract class StripePlatform extends PlatformInterface { PaymentMethodOptions? options, ); Future retrievePaymentIntent(String clientSecret); + Future retrieveSetupIntent(String clientSecret); Future createTokenForCVCUpdate(String cvc); /// Methods related to ACH payments diff --git a/packages/stripe_web/lib/src/web_stripe.dart b/packages/stripe_web/lib/src/web_stripe.dart index 2b6c8eeed..01daabab8 100644 --- a/packages/stripe_web/lib/src/web_stripe.dart +++ b/packages/stripe_web/lib/src/web_stripe.dart @@ -359,6 +359,11 @@ class WebStripe extends StripePlatform { throw UnimplementedError(); } + @override + Future retrieveSetupIntent(String clientSecret) async { + throw UnimplementedError(); + } + @override Future createGooglePayPaymentMethod( CreateGooglePayPaymentParams params) {