Skip to content

Commit

Permalink
Sync with Stripe React Native 0.39.0
Browse files Browse the repository at this point in the history
  • Loading branch information
jonasbark committed Oct 31, 2024
1 parent d73d633 commit 21b0300
Show file tree
Hide file tree
Showing 12 changed files with 87 additions and 46 deletions.
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 @@ -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 @@ -883,7 +883,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 +898,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
56 changes: 31 additions & 25 deletions packages/stripe_ios/ios/Classes/Stripe Sdk/CardFieldView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,33 @@ 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? {

Check warning on line 33 in packages/stripe_ios/ios/Classes/Stripe Sdk/CardFieldView.swift

View workflow job for this annotation

GitHub Actions / Typo CI

objc

"objc" is a typo. Did you mean "obj"?
didSet {
cardField.onBehalfOf = onBehalfOf
}
}

@objc var preferredNetworks: Array<Int>? {
didSet {
if let preferredNetworks = preferredNetworks {
cardField.preferredNetworks = preferredNetworks.map(Mappers.intToCardBrand).compactMap { $0 }
}
}
}

@objc var placeholders: NSDictionary = NSDictionary() {
didSet {
if let numberPlaceholder = placeholders["number"] as? String {
Expand All @@ -56,15 +62,15 @@ class CardFieldView: UIView, STPPaymentCardTextFieldDelegate {
}
}
}

@objc var autofocus: Bool = false {
didSet {
if autofocus == true {
cardField.reactFocus()
}
}
}

@objc var cardStyle: NSDictionary = NSDictionary() {
didSet {
if let borderWidth = cardStyle["borderWidth"] as? Int {
Expand All @@ -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 {
Expand All @@ -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 ?? "")
Expand Down Expand Up @@ -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?) {
//
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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)
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/stripe_ios/ios/stripe_ios.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down

0 comments on commit 21b0300

Please sign in to comment.