Skip to content

Commit

Permalink
Sync (#1987)
Browse files Browse the repository at this point in the history
* Sync with Stripe React Native 0.39.0

* fix #1949

* feat: add customer session client secret to payment sheet

* feat: add onbehalfof to cardfield

* fix formatting

* update changelog, version

---------

Co-authored-by: Jonas Bark <[email protected]>
Co-authored-by: Remon <[email protected]>
  • Loading branch information
3 people authored Nov 19, 2024
1 parent 7a5bb7e commit 9c2e704
Show file tree
Hide file tree
Showing 28 changed files with 206 additions and 71 deletions.
2 changes: 1 addition & 1 deletion example/ios/Runner/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import UIKit
import Flutter

@UIApplicationMain
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
Expand Down
10 changes: 10 additions & 0 deletions packages/stripe/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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**
Expand Down
8 changes: 8 additions & 0 deletions packages/stripe/lib/src/widgets/card_field.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class CardField extends StatefulWidget {
this.postalCodeHintText,
this.controller,
this.preferredNetworks,
this.onBehalfOf,
this.androidPlatformViewRenderType =
AndroidPlatformViewRenderType.expensiveAndroidView,
});
Expand All @@ -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
Expand Down Expand Up @@ -197,6 +201,7 @@ class _CardFieldState extends State<CardField> {
focusNode: _node,
style: style,
placeholder: placeholder,
onBehalfOf: widget.onBehalfOf,
enablePostalCode: widget.enablePostalCode,
countryCode: widget.countryCode,
dangerouslyGetFullCardDetails:
Expand Down Expand Up @@ -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)
Expand All @@ -317,6 +323,7 @@ class _MethodChannelCardField extends StatefulWidget {
final bool dangerouslyUpdateFullCardDetails;
final AndroidPlatformViewRenderType androidPlatformViewRenderType;
final List<CardBrand>? preferredNetworks;
final String? onBehalfOf;

// This is used in the platform side to register the view.
static const _viewType = 'flutter.stripe/card_field';
Expand Down Expand Up @@ -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(),
Expand Down
8 changes: 4 additions & 4 deletions packages/stripe/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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
Expand Down
23 changes: 16 additions & 7 deletions packages/stripe_android/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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).
Expand All @@ -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

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.48.+'
ext.stripe_version = '20.52.+'

repositories {
google()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down Expand Up @@ -152,4 +155,4 @@ class StripeSdkCardPlatformView(
override fun onFlutterViewAttached(flutterView: View) {
stripeSdkCardViewManager.onAfterUpdateTransaction(cardView)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ class CardFieldViewManager : SimpleViewManager<CardFieldView>() {
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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<GooglePayButtonView?>() {
class GooglePayButtonManager : SimpleViewManager<GooglePayButtonView>() {
override fun getName(): String {
return REACT_CLASS
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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)
}
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ class StripeSdkModule(val reactContext: ReactApplicationContext) : ReactContextB
}

paymentSheetFragment?.paymentSheetIntentCreationCallback?.complete(params)
promise.resolve(null)
}

private fun payWithFpx() {
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.*
Expand All @@ -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
Expand Down Expand Up @@ -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())
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
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.facebook.react.uimanager.annotations.ReactProp


class AddToWalletButtonManager(applicationContext: Context) : SimpleViewManager<AddToWalletButtonView?>() {
class AddToWalletButtonManager(applicationContext: Context) : SimpleViewManager<AddToWalletButtonView>() {
private val requestManager = Glide.with(applicationContext)
override fun getName() = "AddToWalletButton"

Expand Down
2 changes: 1 addition & 1 deletion packages/stripe_android/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -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

Expand Down
17 changes: 16 additions & 1 deletion packages/stripe_ios/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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).
Expand Down
4 changes: 4 additions & 0 deletions packages/stripe_ios/ios/Classes/CardFieldFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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<Int>{
cardField.preferredNetworks = preferredNetworks
}
Expand Down
Loading

0 comments on commit 9c2e704

Please sign in to comment.