diff --git a/example/ios/Runner/AppDelegate.swift b/example/ios/Runner/AppDelegate.swift index 70693e4a..b6363034 100644 --- a/example/ios/Runner/AppDelegate.swift +++ b/example/ios/Runner/AppDelegate.swift @@ -1,7 +1,7 @@ import UIKit import Flutter -@UIApplicationMain +@main @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, diff --git a/packages/stripe/CHANGELOG.md b/packages/stripe/CHANGELOG.md index eecf786c..2f3a5ea9 100644 --- a/packages/stripe/CHANGELOG.md +++ b/packages/stripe/CHANGELOG.md @@ -1,3 +1,13 @@ +## 11.3.0 +Align with Stripe React Native [0.39.0](https://github.com/stripe/stripe-react-native/releases/tag/v0.39.0): +**Features** +- Adds support for CustomerSession in private beta 1744 +- Added onBehalfOf prop to CardField + +**Fixes** +- Updated stripe-ios to 23.30.* +- Updated stripe-android to 20.52.* + ## 11.2.0 **Features** diff --git a/packages/stripe/lib/src/widgets/card_field.dart b/packages/stripe/lib/src/widgets/card_field.dart index 2fe16c9f..4c001978 100644 --- a/packages/stripe/lib/src/widgets/card_field.dart +++ b/packages/stripe/lib/src/widgets/card_field.dart @@ -31,6 +31,7 @@ class CardField extends StatefulWidget { this.postalCodeHintText, this.controller, this.preferredNetworks, + this.onBehalfOf, this.androidPlatformViewRenderType = AndroidPlatformViewRenderType.expensiveAndroidView, }); @@ -50,6 +51,9 @@ class CardField extends StatefulWidget { /// Color of the cursor when a field gets focus. final Color? cursorColor; + /// The account (if any) for which the funds of the intent are intended. + final String? onBehalfOf; + /// Whether or not to show the postalcode field in the form. /// /// Defaults is `false`. If your configuration in Stripe requires a postalcode @@ -197,6 +201,7 @@ class _CardFieldState extends State { focusNode: _node, style: style, placeholder: placeholder, + onBehalfOf: widget.onBehalfOf, enablePostalCode: widget.enablePostalCode, countryCode: widget.countryCode, dangerouslyGetFullCardDetails: @@ -295,6 +300,7 @@ class _MethodChannelCardField extends StatefulWidget { this.preferredNetworks, this.dangerouslyGetFullCardDetails = false, this.dangerouslyUpdateFullCardDetails = false, + this.onBehalfOf, this.autofocus = false, }) : assert(constraints == null || constraints.debugAssertIsValid()), constraints = (width != null || height != null) @@ -317,6 +323,7 @@ class _MethodChannelCardField extends StatefulWidget { final bool dangerouslyUpdateFullCardDetails; final AndroidPlatformViewRenderType androidPlatformViewRenderType; final List? preferredNetworks; + final String? onBehalfOf; // This is used in the platform side to register the view. static const _viewType = 'flutter.stripe/card_field'; @@ -405,6 +412,7 @@ class _MethodChannelCardFieldState extends State<_MethodChannelCardField> 'placeholder': placeholder.toJson(), 'postalCodeEnabled': widget.enablePostalCode, 'countryCode': widget.countryCode, + if (widget.onBehalfOf != null) 'onBehalfOf': widget.onBehalfOf, if (widget.preferredNetworks != null) 'preferredNetworks': widget.preferredNetworks?.map((e) => e.brandValue).toList(), diff --git a/packages/stripe/pubspec.yaml b/packages/stripe/pubspec.yaml index a56dcfe5..ef101a80 100644 --- a/packages/stripe/pubspec.yaml +++ b/packages/stripe/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_stripe description: Flutter library for Stripe. Supports PaymentSheets, Apple & Google Pay, SCA, PSD2 and much more. -version: 11.2.0 +version: 11.3.0 homepage: https://github.com/flutter-stripe/flutter_stripe repository: https://github.com/flutter-stripe/flutter_stripe @@ -22,9 +22,9 @@ dependencies: flutter: sdk: flutter meta: ^1.8.0 - stripe_android: ^11.2.0 - stripe_ios: ^11.2.0 - stripe_platform_interface: ^11.2.0 + stripe_android: ^11.3.0 + stripe_ios: ^11.3.0 + stripe_platform_interface: ^11.3.0 dev_dependencies: flutter_test: sdk: flutter diff --git a/packages/stripe_android/CHANGELOG.md b/packages/stripe_android/CHANGELOG.md index 907ab5d0..2f3a5ea9 100644 --- a/packages/stripe_android/CHANGELOG.md +++ b/packages/stripe_android/CHANGELOG.md @@ -1,8 +1,20 @@ -## 11.2.1 -- Remove com.android.application gradle plugin version check +## 11.3.0 +Align with Stripe React Native [0.39.0](https://github.com/stripe/stripe-react-native/releases/tag/v0.39.0): +**Features** +- Adds support for CustomerSession in private beta 1744 +- Added onBehalfOf prop to CardField + +**Fixes** +- Updated stripe-ios to 23.30.* +- Updated stripe-android to 20.52.* ## 11.2.0 -- Minor fixes and improvements + +**Features** +- Add basic support for Expresscheckout on the web + +**Fixes** +- Export elementappearance and element theme ## 11.1.0 - Sync with Stripe [0.38.6](https://github.com/stripe/stripe-react-native/releases/tag/v0.38.6). @@ -19,10 +31,7 @@ **Fixes** - #1729 parse unknown error. - #1837 fix for deferred payment methods. - -## 10.2.1 -**Fixes** -- Run method channel messages on UI Thread to prevent crash (#1831) +- #1630 handle next action setup for ios. ## 10.2.0 diff --git a/packages/stripe_android/android/build.gradle b/packages/stripe_android/android/build.gradle index cb87ff3a..e2bc113a 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.48.+' + ext.stripe_version = '20.52.+' repositories { google() 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 3d8d4779..20fb31cb 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 @@ -38,6 +38,9 @@ class StripeSdkCardPlatformView( if (creationParams?.containsKey("postalCodeEnabled") == true) { stripeSdkCardViewManager.setPostalCodeEnabled(cardView, creationParams["postalCodeEnabled"] as Boolean) } + if (creationParams?.containsKey("onBehalfOf") == true){ + stripeSdkCardViewManager.setOnBehalfOf(cardView, creationParams["onBehalfOf"] as String) + } if (creationParams?.containsKey("countryCode") == true) { stripeSdkCardViewManager.setCountryCode(cardView, creationParams["countryCode"] as? String) } @@ -152,4 +155,4 @@ class StripeSdkCardPlatformView( override fun onFlutterViewAttached(flutterView: View) { stripeSdkCardViewManager.onAfterUpdateTransaction(cardView) } -} \ No newline at end of file +} 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 fb782ee6..505fe05f 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 @@ -220,6 +220,10 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) { mCardWidget.setPreferredNetworks(mapToPreferredNetworks(preferredNetworks)) } + fun setOnBehalfOf(onBehalfOf: String?) { + mCardWidget.onBehalfOf = onBehalfOf + } + /** * 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 6f870f52..ee1451fb 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 @@ -54,6 +54,11 @@ class CardFieldViewManager : SimpleViewManager() { view.setCountryCode(countryCode) } + @ReactProp(name = "onBehalfOf") + fun setOnBehalfOf(view: CardFieldView, onBehalfOf: String?) { + view.setOnBehalfOf(onBehalfOf) + } + @ReactProp(name = "placeholders") fun setPlaceHolders(view: CardFieldView, placeholders: ReadableMap) { view.setPlaceHolders(placeholders) diff --git a/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/GooglePayButtonManager.kt b/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/GooglePayButtonManager.kt index 39dc32f8..db558c4a 100644 --- a/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/GooglePayButtonManager.kt +++ b/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/GooglePayButtonManager.kt @@ -4,7 +4,7 @@ import com.facebook.react.uimanager.SimpleViewManager import com.facebook.react.uimanager.ThemedReactContext import com.facebook.react.uimanager.annotations.ReactProp -class GooglePayButtonManager : SimpleViewManager() { +class GooglePayButtonManager : SimpleViewManager() { override fun getName(): String { return REACT_CLASS } diff --git a/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/PaymentSheetFragment.kt b/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/PaymentSheetFragment.kt index a49ff6e4..15b4ea59 100644 --- a/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/PaymentSheetFragment.kt +++ b/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/PaymentSheetFragment.kt @@ -63,8 +63,6 @@ class PaymentSheetFragment( return } val primaryButtonLabel = arguments?.getString("primaryButtonLabel") - val customerId = arguments?.getString("customerId").orEmpty() - val customerEphemeralKeySecret = arguments?.getString("customerEphemeralKeySecret").orEmpty() val googlePayConfig = buildGooglePayConfig(arguments?.getBundle("googlePay")) val allowsDelayedPaymentMethods = arguments?.getBoolean("allowsDelayedPaymentMethods") val billingDetailsBundle = arguments?.getBundle("defaultBillingDetails") @@ -86,6 +84,13 @@ class PaymentSheetFragment( return } + val customerConfiguration = try { + buildCustomerConfiguration(arguments) + } catch (error: PaymentSheetException) { + initPromise.resolve(createError(ErrorType.Failed.toString(), error)) + return + } + val shippingDetails = arguments?.getBundle("defaultShippingDetails")?.let { AddressSheetView.buildAddressDetails(it) } @@ -190,12 +195,7 @@ class PaymentSheetFragment( val configurationBuilder = PaymentSheet.Configuration.Builder(merchantDisplayName) .allowsDelayedPaymentMethods(allowsDelayedPaymentMethods ?: false) .defaultBillingDetails(defaultBillingDetails) - .customer( - if (customerId.isNotEmpty() && customerEphemeralKeySecret.isNotEmpty()) PaymentSheet.CustomerConfiguration( - id = customerId, - ephemeralKeySecret = customerEphemeralKeySecret - ) else null - ) + .customer(customerConfiguration) .googlePay(googlePayConfig) .appearance(appearance) .shippingDetails(shippingDetails) @@ -428,6 +428,28 @@ class PaymentSheetFragment( ) } } + + @OptIn(ExperimentalCustomerSessionApi::class) + @Throws(PaymentSheetException::class) + private fun buildCustomerConfiguration(bundle: Bundle?): PaymentSheet.CustomerConfiguration? { + val customerId = bundle?.getString("customerId").orEmpty() + val customerEphemeralKeySecret = bundle?.getString("customerEphemeralKeySecret").orEmpty() + val customerSessionClientSecret = bundle?.getString("customerSessionClientSecret").orEmpty() + return if (customerSessionClientSecret.isNotEmpty() && customerEphemeralKeySecret.isNotEmpty()) { + throw PaymentSheetException("`customerEphemeralKeySecret` and `customerSessionClientSecret` cannot both be set") + } else if (customerId.isNotEmpty() && customerSessionClientSecret.isNotEmpty()) { + PaymentSheet.CustomerConfiguration.createWithCustomerSession( + id = customerId, + clientSecret = customerSessionClientSecret + ) + } + else if (customerId.isNotEmpty() && customerEphemeralKeySecret.isNotEmpty()) { + PaymentSheet.CustomerConfiguration( + id = customerId, + ephemeralKeySecret = customerEphemeralKeySecret + ) + } else null + } } } diff --git a/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/StripeSdkModule.kt b/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/StripeSdkModule.kt index f11aeeb4..275cc024 100644 --- a/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/StripeSdkModule.kt +++ b/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/StripeSdkModule.kt @@ -219,6 +219,7 @@ class StripeSdkModule(val reactContext: ReactApplicationContext) : ReactContextB } paymentSheetFragment?.paymentSheetIntentCreationCallback?.complete(params) + promise.resolve(null) } private fun payWithFpx() { @@ -883,7 +884,7 @@ class StripeSdkModule(val reactContext: ReactApplicationContext) : ReactContextB @ReactMethod fun customerAdapterAttachPaymentMethodCallback(paymentMethodJson: ReadableMap, promise: Promise) { customerSheetFragment?.let { - val paymentMethod = PaymentMethod.fromJson(JSONObject(paymentMethodJson.toHashMap())) + val paymentMethod = PaymentMethod.fromJson(JSONObject(paymentMethodJson.toHashMap() as HashMap<*, *>)) if (paymentMethod == null) { Log.e("StripeReactNative", "There was an error converting Payment Method JSON to a Stripe Payment Method") return @@ -898,7 +899,7 @@ class StripeSdkModule(val reactContext: ReactApplicationContext) : ReactContextB @ReactMethod fun customerAdapterDetachPaymentMethodCallback(paymentMethodJson: ReadableMap, promise: Promise) { customerSheetFragment?.let { - val paymentMethod = PaymentMethod.fromJson(JSONObject(paymentMethodJson.toHashMap())) + val paymentMethod = PaymentMethod.fromJson(JSONObject(paymentMethodJson.toHashMap() as HashMap<*, *>)) if (paymentMethod == null) { Log.e("StripeReactNative", "There was an error converting Payment Method JSON to a Stripe Payment Method") return diff --git a/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/customersheet/CustomerSheetFragment.kt b/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/customersheet/CustomerSheetFragment.kt index 0e1fdf74..9fe2b424 100644 --- a/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/customersheet/CustomerSheetFragment.kt +++ b/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/customersheet/CustomerSheetFragment.kt @@ -20,7 +20,6 @@ import com.stripe.android.customersheet.CustomerAdapter import com.stripe.android.customersheet.CustomerEphemeralKey import com.stripe.android.customersheet.CustomerSheet import com.stripe.android.customersheet.CustomerSheetResult -import com.stripe.android.customersheet.ExperimentalCustomerSheetApi import com.stripe.android.customersheet.PaymentOptionSelection import com.stripe.android.model.PaymentMethod import com.stripe.android.paymentsheet.* @@ -29,7 +28,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -@OptIn(ExperimentalCustomerSheetApi::class, ExperimentalAllowsRemovalOfLastSavedPaymentMethodApi::class) +@OptIn(ExperimentalAllowsRemovalOfLastSavedPaymentMethodApi::class) class CustomerSheetFragment : Fragment() { private var customerSheet: CustomerSheet? = null internal var customerAdapter: ReactNativeCustomerAdapter? = null @@ -111,11 +110,12 @@ class CustomerSheetFragment : Fragment() { customerSheet = CustomerSheet.create( fragment = this, - configuration = configuration.build(), customerAdapter = customerAdapter, callback = ::handleResult ) + customerSheet?.configure(configuration.build()) + initPromise.resolve(WritableNativeMap()) } diff --git a/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/customersheet/ReactNativeCustomerAdapter.kt b/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/customersheet/ReactNativeCustomerAdapter.kt index 46260b6b..0ae53d18 100644 --- a/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/customersheet/ReactNativeCustomerAdapter.kt +++ b/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/customersheet/ReactNativeCustomerAdapter.kt @@ -7,11 +7,9 @@ import com.facebook.react.bridge.ReadableMap import com.facebook.react.bridge.WritableMap import com.reactnativestripesdk.StripeSdkModule import com.stripe.android.customersheet.CustomerAdapter -import com.stripe.android.customersheet.ExperimentalCustomerSheetApi import com.stripe.android.model.PaymentMethod import kotlinx.coroutines.CompletableDeferred -@OptIn(ExperimentalCustomerSheetApi::class) class ReactNativeCustomerAdapter ( private val context: ReactApplicationContext, private val adapter: CustomerAdapter, diff --git a/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/pushprovisioning/AddToWalletButtonManager.kt b/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/pushprovisioning/AddToWalletButtonManager.kt index e932b27f..22df1d5a 100644 --- a/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/pushprovisioning/AddToWalletButtonManager.kt +++ b/packages/stripe_android/android/src/main/kotlin/com/reactnativestripesdk/pushprovisioning/AddToWalletButtonManager.kt @@ -9,7 +9,7 @@ import com.facebook.react.uimanager.ThemedReactContext import com.facebook.react.uimanager.annotations.ReactProp -class AddToWalletButtonManager(applicationContext: Context) : SimpleViewManager() { +class AddToWalletButtonManager(applicationContext: Context) : SimpleViewManager() { private val requestManager = Glide.with(applicationContext) override fun getName() = "AddToWalletButton" diff --git a/packages/stripe_android/pubspec.yaml b/packages/stripe_android/pubspec.yaml index aab15b82..f97f692a 100644 --- a/packages/stripe_android/pubspec.yaml +++ b/packages/stripe_android/pubspec.yaml @@ -1,6 +1,6 @@ name: stripe_android description: Stripe platform implementation for Android -version: 11.2.1 +version: 11.3.0 repository: https://github.com/flutter-stripe/flutter_stripe homepage: https://pub.dev/packages/flutter_stripe diff --git a/packages/stripe_ios/CHANGELOG.md b/packages/stripe_ios/CHANGELOG.md index 0609ab77..2f3a5ea9 100644 --- a/packages/stripe_ios/CHANGELOG.md +++ b/packages/stripe_ios/CHANGELOG.md @@ -1,5 +1,20 @@ +## 11.3.0 +Align with Stripe React Native [0.39.0](https://github.com/stripe/stripe-react-native/releases/tag/v0.39.0): +**Features** +- Adds support for CustomerSession in private beta 1744 +- Added onBehalfOf prop to CardField + +**Fixes** +- Updated stripe-ios to 23.30.* +- Updated stripe-android to 20.52.* + ## 11.2.0 -- Minor fixes and improvements + +**Features** +- Add basic support for Expresscheckout on the web + +**Fixes** +- Export elementappearance and element theme ## 11.1.0 - Sync with Stripe [0.38.6](https://github.com/stripe/stripe-react-native/releases/tag/v0.38.6). diff --git a/packages/stripe_ios/ios/Classes/CardFieldFactory.swift b/packages/stripe_ios/ios/Classes/CardFieldFactory.swift index 082a5582..59293d39 100644 --- a/packages/stripe_ios/ios/Classes/CardFieldFactory.swift +++ b/packages/stripe_ios/ios/Classes/CardFieldFactory.swift @@ -137,6 +137,10 @@ class CardFieldPlatformView: NSObject, FlutterPlatformView, STPPaymentCardTextFi cardField.disabled = disabled } + if let onBehalfOf = arguments["onBehalfOf"] as? String{ + cardField.onBehalfOf = onBehalfOf + } + if let preferredNetworks = arguments["preferredNetworks"] as? Array{ cardField.preferredNetworks = preferredNetworks } diff --git a/packages/stripe_ios/ios/Classes/Stripe Sdk/CardFieldView.swift b/packages/stripe_ios/ios/Classes/Stripe Sdk/CardFieldView.swift index ebcb0677..200fbba9 100644 --- a/packages/stripe_ios/ios/Classes/Stripe Sdk/CardFieldView.swift +++ b/packages/stripe_ios/ios/Classes/Stripe Sdk/CardFieldView.swift @@ -17,19 +17,25 @@ class CardFieldView: UIView, STPPaymentCardTextFieldDelegate { cardField.isUserInteractionEnabled = !disabled } } - + @objc var postalCodeEnabled: Bool = true { didSet { cardField.postalCodeEntryEnabled = postalCodeEnabled } } - + @objc var countryCode: String? { didSet { cardField.countryCode = countryCode } } - + + @objc var onBehalfOf: String? { + didSet { + cardField.onBehalfOf = onBehalfOf + } + } + @objc var preferredNetworks: Array? { didSet { if let preferredNetworks = preferredNetworks { @@ -37,7 +43,7 @@ class CardFieldView: UIView, STPPaymentCardTextFieldDelegate { } } } - + @objc var placeholders: NSDictionary = NSDictionary() { didSet { if let numberPlaceholder = placeholders["number"] as? String { @@ -56,7 +62,7 @@ class CardFieldView: UIView, STPPaymentCardTextFieldDelegate { } } } - + @objc var autofocus: Bool = false { didSet { if autofocus == true { @@ -64,7 +70,7 @@ class CardFieldView: UIView, STPPaymentCardTextFieldDelegate { } } } - + @objc var cardStyle: NSDictionary = NSDictionary() { didSet { if let borderWidth = cardStyle["borderWidth"] as? Int { @@ -91,7 +97,7 @@ class CardFieldView: UIView, STPPaymentCardTextFieldDelegate { cardField.textErrorColor = UIColor(hexString: textErrorColor) } let fontSize = cardStyle["fontSize"] as? Int ?? 14 - + if let fontFamily = cardStyle["fontFamily"] as? String { cardField.font = UIFont(name: fontFamily, size: CGFloat(fontSize)) ?? UIFont.systemFont(ofSize: CGFloat(fontSize)) } else { @@ -104,46 +110,46 @@ class CardFieldView: UIView, STPPaymentCardTextFieldDelegate { } } } - + override init(frame: CGRect) { super.init(frame: frame) cardField.delegate = self - + self.addSubview(cardField) } - + func focus() { cardField.becomeFirstResponder() } - + func blur() { cardField.resignFirstResponder() } - + func clear() { cardField.clear() } - + func paymentCardTextFieldDidEndEditing(_ textField: STPPaymentCardTextField) { onFocusChange?(["focusedField": NSNull()]) } - + func paymentCardTextFieldDidBeginEditingNumber(_ textField: STPPaymentCardTextField) { onFocusChange?(["focusedField": "CardNumber"]) } - + func paymentCardTextFieldDidBeginEditingCVC(_ textField: STPPaymentCardTextField) { onFocusChange?(["focusedField": "Cvc"]) } - + func paymentCardTextFieldDidBeginEditingExpiration(_ textField: STPPaymentCardTextField) { onFocusChange?(["focusedField": "ExpiryDate"]) } - + func paymentCardTextFieldDidBeginEditingPostalCode(_ textField: STPPaymentCardTextField) { onFocusChange?(["focusedField": "PostalCode"]) } - + func paymentCardTextFieldDidChange(_ textField: STPPaymentCardTextField) { if onCardChange != nil { let brand = STPCardValidator.brand(forNumber: textField.cardNumber ?? "") @@ -180,29 +186,29 @@ class CardFieldView: UIView, STPPaymentCardTextFieldDelegate { self.cardPostalCode = nil } } - + override func layoutSubviews() { cardField.frame = self.bounds } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + func paymentContext(_ paymentContext: STPPaymentContext, didFailToLoadWithError error: Error) { // } - + func paymentContextDidChange(_ paymentContext: STPPaymentContext) { // } - + func paymentContext(_ paymentContext: STPPaymentContext, didCreatePaymentResult paymentResult: STPPaymentResult, completion: @escaping STPPaymentStatusBlock) { // } - + func paymentContext(_ paymentContext: STPPaymentContext, didFinishWith status: STPPaymentStatus, error: Error?) { // } - + } diff --git a/packages/stripe_ios/ios/Classes/Stripe Sdk/StripeSdk+PaymentSheet.swift b/packages/stripe_ios/ios/Classes/Stripe Sdk/StripeSdk+PaymentSheet.swift index 497b330f..99ba2b78 100644 --- a/packages/stripe_ios/ios/Classes/Stripe Sdk/StripeSdk+PaymentSheet.swift +++ b/packages/stripe_ios/ios/Classes/Stripe Sdk/StripeSdk+PaymentSheet.swift @@ -6,7 +6,7 @@ // import Foundation -@_spi(ExperimentalAllowsRemovalOfLastSavedPaymentMethodAPI) @_spi(STP) import StripePaymentSheet +@_spi(ExperimentalAllowsRemovalOfLastSavedPaymentMethodAPI) @_spi(CustomerSessionBetaAccess) @_spi(STP) import StripePaymentSheet extension StripeSdk { internal func buildPaymentSheetConfiguration( @@ -91,11 +91,17 @@ extension StripeSdk { } if let customerId = params["customerId"] as? String { - if let customerEphemeralKeySecret = params["customerEphemeralKeySecret"] as? String { + var customerEphemeralKeySecret = params["customerEphemeralKeySecret"] as? String + var customerClientSecret = params["customerSessionClientSecret"] as? String + if let customerEphemeralKeySecret, let customerClientSecret { + return(error: Errors.createError(ErrorType.Failed, "`customerEphemeralKeySecret` and `customerSessionClientSecret cannot both be set"), configuration: nil) + } else if let customerEphemeralKeySecret { if (!Errors.isEKClientSecretValid(clientSecret: customerEphemeralKeySecret)) { return(error: Errors.createError(ErrorType.Failed, "`customerEphemeralKeySecret` format does not match expected client secret formatting."), configuration: nil) } configuration.customer = .init(id: customerId, ephemeralKeySecret: customerEphemeralKeySecret) + } else if let customerClientSecret { + configuration.customer = .init(id: customerId, customerSessionClientSecret: customerClientSecret) } } diff --git a/packages/stripe_ios/ios/Classes/StripePlugin.swift b/packages/stripe_ios/ios/Classes/StripePlugin.swift index 80494e01..e92fc950 100644 --- a/packages/stripe_ios/ios/Classes/StripePlugin.swift +++ b/packages/stripe_ios/ios/Classes/StripePlugin.swift @@ -645,6 +645,7 @@ extension StripePlugin { } intentCreationCallback(result: params, resolver: resolver(for: result), rejecter: rejecter(for: result)) + result(nil) } func dangerouslyUpdateCardDetails(_ call: FlutterMethodCall, result: @escaping FlutterResult) { diff --git a/packages/stripe_ios/ios/stripe_ios.podspec b/packages/stripe_ios/ios/stripe_ios.podspec index e4a0eb70..167db427 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.28.0' +stripe_version = '~> 23.30.0' Pod::Spec.new do |s| s.name = 'stripe_ios' s.version = '0.0.1' diff --git a/packages/stripe_ios/pubspec.yaml b/packages/stripe_ios/pubspec.yaml index cf583b52..abb29633 100644 --- a/packages/stripe_ios/pubspec.yaml +++ b/packages/stripe_ios/pubspec.yaml @@ -1,6 +1,6 @@ name: stripe_ios description: Stripe platform implementation for iOS -version: 11.2.0 +version: 11.3.0 repository: https://github.com/flutter-stripe/flutter_stripe homepage: https://pub.dev/packages/flutter_stripe diff --git a/packages/stripe_platform_interface/CHANGELOG.md b/packages/stripe_platform_interface/CHANGELOG.md index 2b79cf82..2f3a5ea9 100644 --- a/packages/stripe_platform_interface/CHANGELOG.md +++ b/packages/stripe_platform_interface/CHANGELOG.md @@ -1,3 +1,13 @@ +## 11.3.0 +Align with Stripe React Native [0.39.0](https://github.com/stripe/stripe-react-native/releases/tag/v0.39.0): +**Features** +- Adds support for CustomerSession in private beta 1744 +- Added onBehalfOf prop to CardField + +**Fixes** +- Updated stripe-ios to 23.30.* +- Updated stripe-android to 20.52.* + ## 11.2.0 **Features** @@ -6,10 +16,6 @@ **Fixes** - Export elementappearance and element theme -## 11.1.1 - - - #1912 wallet parsing. - ## 11.1.0 - Sync with Stripe [0.38.6](https://github.com/stripe/stripe-react-native/releases/tag/v0.38.6). - Minor fixes and improvements. diff --git a/packages/stripe_platform_interface/lib/src/models/payment_sheet.dart b/packages/stripe_platform_interface/lib/src/models/payment_sheet.dart index 74175f91..d3b05c99 100644 --- a/packages/stripe_platform_interface/lib/src/models/payment_sheet.dart +++ b/packages/stripe_platform_interface/lib/src/models/payment_sheet.dart @@ -32,6 +32,10 @@ class SetupPaymentSheetParameters with _$SetupPaymentSheetParameters { ///A temp key can be used for API operations that require a secret key. String? customerEphemeralKeySecret, + /// (Experimental) This parameter can be changed or removed at any time (use at your own risk). + /// The client secret of this Customer Session. Used on the client to set up secure access to the given customer. + String? customerSessionClientSecret, + /// Secret used for client-side retrieval using a publishable key. /// /// If this value is null make sure to add a [setupIntentClientSecret] diff --git a/packages/stripe_platform_interface/lib/src/models/payment_sheet.freezed.dart b/packages/stripe_platform_interface/lib/src/models/payment_sheet.freezed.dart index f254fa83..185da72b 100644 --- a/packages/stripe_platform_interface/lib/src/models/payment_sheet.freezed.dart +++ b/packages/stripe_platform_interface/lib/src/models/payment_sheet.freezed.dart @@ -38,6 +38,10 @@ mixin _$SetupPaymentSheetParameters { ///A temp key can be used for API operations that require a secret key. String? get customerEphemeralKeySecret => throw _privateConstructorUsedError; + /// (Experimental) This parameter can be changed or removed at any time (use at your own risk). + /// The client secret of this Customer Session. Used on the client to set up secure access to the given customer. + String? get customerSessionClientSecret => throw _privateConstructorUsedError; + /// Secret used for client-side retrieval using a publishable key. /// /// If this value is null make sure to add a [setupIntentClientSecret] @@ -138,6 +142,7 @@ abstract class $SetupPaymentSheetParametersCopyWith<$Res> { String? customerId, String? primaryButtonLabel, String? customerEphemeralKeySecret, + String? customerSessionClientSecret, String? paymentIntentClientSecret, String? setupIntentClientSecret, IntentConfiguration? intentConfiguration, @@ -184,6 +189,7 @@ class _$SetupPaymentSheetParametersCopyWithImpl<$Res, Object? customerId = freezed, Object? primaryButtonLabel = freezed, Object? customerEphemeralKeySecret = freezed, + Object? customerSessionClientSecret = freezed, Object? paymentIntentClientSecret = freezed, Object? setupIntentClientSecret = freezed, Object? intentConfiguration = freezed, @@ -218,6 +224,10 @@ class _$SetupPaymentSheetParametersCopyWithImpl<$Res, ? _value.customerEphemeralKeySecret : customerEphemeralKeySecret // ignore: cast_nullable_to_non_nullable as String?, + customerSessionClientSecret: freezed == customerSessionClientSecret + ? _value.customerSessionClientSecret + : customerSessionClientSecret // ignore: cast_nullable_to_non_nullable + as String?, paymentIntentClientSecret: freezed == paymentIntentClientSecret ? _value.paymentIntentClientSecret : paymentIntentClientSecret // ignore: cast_nullable_to_non_nullable @@ -378,6 +388,7 @@ abstract class _$$SetupParametersImplCopyWith<$Res> String? customerId, String? primaryButtonLabel, String? customerEphemeralKeySecret, + String? customerSessionClientSecret, String? paymentIntentClientSecret, String? setupIntentClientSecret, IntentConfiguration? intentConfiguration, @@ -427,6 +438,7 @@ class __$$SetupParametersImplCopyWithImpl<$Res> Object? customerId = freezed, Object? primaryButtonLabel = freezed, Object? customerEphemeralKeySecret = freezed, + Object? customerSessionClientSecret = freezed, Object? paymentIntentClientSecret = freezed, Object? setupIntentClientSecret = freezed, Object? intentConfiguration = freezed, @@ -461,6 +473,10 @@ class __$$SetupParametersImplCopyWithImpl<$Res> ? _value.customerEphemeralKeySecret : customerEphemeralKeySecret // ignore: cast_nullable_to_non_nullable as String?, + customerSessionClientSecret: freezed == customerSessionClientSecret + ? _value.customerSessionClientSecret + : customerSessionClientSecret // ignore: cast_nullable_to_non_nullable + as String?, paymentIntentClientSecret: freezed == paymentIntentClientSecret ? _value.paymentIntentClientSecret : paymentIntentClientSecret // ignore: cast_nullable_to_non_nullable @@ -541,6 +557,7 @@ class _$SetupParametersImpl implements _SetupParameters { this.customerId, this.primaryButtonLabel, this.customerEphemeralKeySecret, + this.customerSessionClientSecret, this.paymentIntentClientSecret, this.setupIntentClientSecret, this.intentConfiguration, @@ -586,6 +603,11 @@ class _$SetupParametersImpl implements _SetupParameters { @override final String? customerEphemeralKeySecret; + /// (Experimental) This parameter can be changed or removed at any time (use at your own risk). + /// The client secret of this Customer Session. Used on the client to set up secure access to the given customer. + @override + final String? customerSessionClientSecret; + /// Secret used for client-side retrieval using a publishable key. /// /// If this value is null make sure to add a [setupIntentClientSecret] @@ -707,7 +729,7 @@ class _$SetupParametersImpl implements _SetupParameters { @override String toString() { - return 'SetupPaymentSheetParameters(customFlow: $customFlow, customerId: $customerId, primaryButtonLabel: $primaryButtonLabel, customerEphemeralKeySecret: $customerEphemeralKeySecret, paymentIntentClientSecret: $paymentIntentClientSecret, setupIntentClientSecret: $setupIntentClientSecret, intentConfiguration: $intentConfiguration, merchantDisplayName: $merchantDisplayName, applePay: $applePay, style: $style, googlePay: $googlePay, allowsDelayedPaymentMethods: $allowsDelayedPaymentMethods, appearance: $appearance, billingDetails: $billingDetails, allowsRemovalOfLastSavedPaymentMethod: $allowsRemovalOfLastSavedPaymentMethod, paymentMethodOrder: $paymentMethodOrder, returnURL: $returnURL, billingDetailsCollectionConfiguration: $billingDetailsCollectionConfiguration, removeSavedPaymentMethodMessage: $removeSavedPaymentMethodMessage, preferredNetworks: $preferredNetworks)'; + return 'SetupPaymentSheetParameters(customFlow: $customFlow, customerId: $customerId, primaryButtonLabel: $primaryButtonLabel, customerEphemeralKeySecret: $customerEphemeralKeySecret, customerSessionClientSecret: $customerSessionClientSecret, paymentIntentClientSecret: $paymentIntentClientSecret, setupIntentClientSecret: $setupIntentClientSecret, intentConfiguration: $intentConfiguration, merchantDisplayName: $merchantDisplayName, applePay: $applePay, style: $style, googlePay: $googlePay, allowsDelayedPaymentMethods: $allowsDelayedPaymentMethods, appearance: $appearance, billingDetails: $billingDetails, allowsRemovalOfLastSavedPaymentMethod: $allowsRemovalOfLastSavedPaymentMethod, paymentMethodOrder: $paymentMethodOrder, returnURL: $returnURL, billingDetailsCollectionConfiguration: $billingDetailsCollectionConfiguration, removeSavedPaymentMethodMessage: $removeSavedPaymentMethodMessage, preferredNetworks: $preferredNetworks)'; } @override @@ -724,6 +746,9 @@ class _$SetupParametersImpl implements _SetupParameters { (identical(other.customerEphemeralKeySecret, customerEphemeralKeySecret) || other.customerEphemeralKeySecret == customerEphemeralKeySecret) && + (identical(other.customerSessionClientSecret, customerSessionClientSecret) || + other.customerSessionClientSecret == + customerSessionClientSecret) && (identical(other.paymentIntentClientSecret, paymentIntentClientSecret) || other.paymentIntentClientSecret == paymentIntentClientSecret) && (identical(other.setupIntentClientSecret, setupIntentClientSecret) || @@ -754,9 +779,7 @@ class _$SetupParametersImpl implements _SetupParameters { (identical(other.billingDetailsCollectionConfiguration, billingDetailsCollectionConfiguration) || other.billingDetailsCollectionConfiguration == billingDetailsCollectionConfiguration) && - (identical(other.removeSavedPaymentMethodMessage, removeSavedPaymentMethodMessage) || - other.removeSavedPaymentMethodMessage == - removeSavedPaymentMethodMessage) && + (identical(other.removeSavedPaymentMethodMessage, removeSavedPaymentMethodMessage) || other.removeSavedPaymentMethodMessage == removeSavedPaymentMethodMessage) && const DeepCollectionEquality().equals(other._preferredNetworks, _preferredNetworks)); } @@ -768,6 +791,7 @@ class _$SetupParametersImpl implements _SetupParameters { customerId, primaryButtonLabel, customerEphemeralKeySecret, + customerSessionClientSecret, paymentIntentClientSecret, setupIntentClientSecret, intentConfiguration, @@ -807,6 +831,7 @@ abstract class _SetupParameters implements SetupPaymentSheetParameters { final String? customerId, final String? primaryButtonLabel, final String? customerEphemeralKeySecret, + final String? customerSessionClientSecret, final String? paymentIntentClientSecret, final String? setupIntentClientSecret, final IntentConfiguration? intentConfiguration, @@ -853,6 +878,11 @@ abstract class _SetupParameters implements SetupPaymentSheetParameters { String? get customerEphemeralKeySecret; @override + /// (Experimental) This parameter can be changed or removed at any time (use at your own risk). + /// The client secret of this Customer Session. Used on the client to set up secure access to the given customer. + String? get customerSessionClientSecret; + @override + /// Secret used for client-side retrieval using a publishable key. /// /// If this value is null make sure to add a [setupIntentClientSecret] diff --git a/packages/stripe_platform_interface/lib/src/models/payment_sheet.g.dart b/packages/stripe_platform_interface/lib/src/models/payment_sheet.g.dart index 9c5c4177..99005f18 100644 --- a/packages/stripe_platform_interface/lib/src/models/payment_sheet.g.dart +++ b/packages/stripe_platform_interface/lib/src/models/payment_sheet.g.dart @@ -13,6 +13,8 @@ _$SetupParametersImpl _$$SetupParametersImplFromJson( customerId: json['customerId'] as String?, primaryButtonLabel: json['primaryButtonLabel'] as String?, customerEphemeralKeySecret: json['customerEphemeralKeySecret'] as String?, + customerSessionClientSecret: + json['customerSessionClientSecret'] as String?, paymentIntentClientSecret: json['paymentIntentClientSecret'] as String?, setupIntentClientSecret: json['setupIntentClientSecret'] as String?, intentConfiguration: json['intentConfiguration'] == null @@ -65,6 +67,7 @@ Map _$$SetupParametersImplToJson( 'customerId': instance.customerId, 'primaryButtonLabel': instance.primaryButtonLabel, 'customerEphemeralKeySecret': instance.customerEphemeralKeySecret, + 'customerSessionClientSecret': instance.customerSessionClientSecret, 'paymentIntentClientSecret': instance.paymentIntentClientSecret, 'setupIntentClientSecret': instance.setupIntentClientSecret, 'intentConfiguration': instance.intentConfiguration?.toJson(), diff --git a/packages/stripe_platform_interface/pubspec.yaml b/packages/stripe_platform_interface/pubspec.yaml index 238dee57..34e0ee26 100644 --- a/packages/stripe_platform_interface/pubspec.yaml +++ b/packages/stripe_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: stripe_platform_interface description: Platform interface for stripe sdk -version: 11.2.0 +version: 11.3.0 repository: https://github.com/flutter-stripe/flutter_stripe homepage: https://pub.dev/packages/flutter_stripe