Skip to content

Commit

Permalink
Merge branch 'releases/23.25.1' of github.com:stripe/stripe-ios into …
Browse files Browse the repository at this point in the history
…releases/23.25.1
  • Loading branch information
porter-stripe committed Mar 18, 2024
2 parents c254c16 + c1ae857 commit f6b9e5e
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2818,7 +2818,14 @@ class PaymentSheetLinkUITests: PaymentSheetUITestCase {
// let addCardButton = app.buttons["+ Add"]
// XCTAssertTrue(addCardButton.waitForExistence(timeout: 4.0))
// addCardButton.tap()
// fillLinkAndPay(mode: .fieldConsent)
// fillLinkAndPay(mode: .fieldConsent, cardNumber: "5555555555554444")
//
// // reload w/ same customer
// reload(app, settings: settings)
// app.buttons["Present PaymentSheet"].waitForExistenceAndTap()
// // Ensure both PMs exist
// XCTAssertTrue(app.staticTexts["••••4242"].waitForExistence(timeout: 5.0))
// XCTAssertTrue(app.staticTexts["••••4444"].waitForExistence(timeout: 5.0))
// }

// Tests the #6 flow in PaymentSheet where the merchant enables saved payment methods, buyer has SPMs and returning Link user
Expand Down Expand Up @@ -3084,9 +3091,10 @@ class PaymentSheetLinkUITests: PaymentSheetUITestCase {

private func fillLinkAndPay(mode: LinkMode,
uiStyle: PaymentSheetTestPlaygroundSettings.UIStyle = .paymentSheet,
showLinkWalletButton: Bool = true) {
showLinkWalletButton: Bool = true,
cardNumber: String? = nil) {

try! fillCardData(app)
try! fillCardData(app, cardNumber: cardNumber)

if showLinkWalletButton {
// Confirm Link wallet button is visible
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ final class LinkEnabledPaymentMethodElement: ContainerElement {
phoneNumber: phoneNumber,
consentAction: inlineSignupElement.viewModel.consentAction,
legalName: legalName,
paymentMethodParams: params.paymentMethodParams
intentConfirmParams: params
)
)
case .continueWithoutLink:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ import UIKit
}
}
case .deferredIntent(let intentConfiguration):
let paymentMethod = STPPaymentMethod(stripeId: paymentMethodId)
let paymentMethod = STPPaymentMethod(stripeId: paymentMethodId, type: .link)
PaymentSheet
.handleDeferredIntentConfirmation(
confirmType: .saved(paymentMethod, paymentOptions: nil),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ extension PaymentSheet {
phoneNumber: PhoneNumber,
consentAction: PaymentSheetLinkAccount.ConsentAction,
legalName: String?,
paymentMethodParams: STPPaymentMethodParams
intentConfirmParams: IntentConfirmParams
)

/// Confirm with Payment Method.
Expand Down Expand Up @@ -52,8 +52,8 @@ extension PaymentSheet.LinkConfirmOption {
switch self {
case .wallet:
return STPPaymentMethodType.link.displayName
case .signUp(_, _, _, _, let paymentMethodParams):
return paymentMethodParams.paymentSheetLabel
case .signUp(_, _, _, _, let intentConfirmParams):
return intentConfirmParams.paymentMethodParams.paymentSheetLabel
case .withPaymentMethod(let paymentMethod):
return paymentMethod.paymentSheetLabel
}
Expand All @@ -63,8 +63,8 @@ extension PaymentSheet.LinkConfirmOption {
switch self {
case .wallet:
return nil
case .signUp(_, _, _, _, let paymentMethodParams):
return paymentMethodParams.billingDetails
case .signUp(_, _, _, _, let intentConfirmParams):
return intentConfirmParams.paymentMethodParams.billingDetails
case .withPaymentMethod(let paymentMethod):
return paymentMethod.billingDetails
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,12 +261,15 @@ extension PaymentSheet {
// Parameters:
// - paymentMethodParams: The params to use for the payment.
// - linkAccount: The Link account used for payment. Will be logged out if present after payment completes, whether it was successful or not.
let confirmWithPaymentMethodParams: (STPPaymentMethodParams, PaymentSheetLinkAccount?) -> Void = { paymentMethodParams, linkAccount in
let confirmWithPaymentMethodParams: (STPPaymentMethodParams, PaymentSheetLinkAccount?, Bool) -> Void = { paymentMethodParams, linkAccount, shouldSave in
switch intent {
case .paymentIntent(_, let paymentIntent):
let paymentIntentParams = STPPaymentIntentParams(clientSecret: paymentIntent.clientSecret)
paymentIntentParams.paymentMethodParams = paymentMethodParams
paymentIntentParams.returnURL = configuration.returnURL
let paymentOptions = paymentIntentParams.paymentMethodOptions ?? STPConfirmPaymentMethodOptions()
paymentOptions.setSetupFutureUsageIfNecessary(shouldSave, paymentMethodType: paymentMethodParams.type, customer: configuration.customer)
paymentIntentParams.paymentMethodOptions = paymentOptions
paymentIntentParams.shipping = makeShippingParams(for: paymentIntent, configuration: configuration)
paymentHandler.confirmPayment(
paymentIntentParams,
Expand All @@ -293,7 +296,7 @@ extension PaymentSheet {
confirmType: .new(
params: paymentMethodParams,
paymentOptions: STPConfirmPaymentMethodOptions(),
shouldSave: false
shouldSave: shouldSave
),
configuration: configuration,
intentConfig: intentConfig,
Expand All @@ -307,7 +310,7 @@ extension PaymentSheet {
)
}
}
let confirmWithPaymentMethod: (STPPaymentMethod, PaymentSheetLinkAccount?) -> Void = { paymentMethod, linkAccount in
let confirmWithPaymentMethod: (STPPaymentMethod, PaymentSheetLinkAccount?, Bool) -> Void = { paymentMethod, linkAccount, shouldSave in
let mandateCustomerAcceptanceParams = STPMandateCustomerAcceptanceParams()
let onlineParams = STPMandateOnlineParams(ipAddress: "", userAgent: "")
// Tell Stripe to infer mandate info from client
Expand All @@ -321,6 +324,9 @@ extension PaymentSheet {
paymentIntentParams.paymentMethodId = paymentMethod.stripeId
paymentIntentParams.returnURL = configuration.returnURL
paymentIntentParams.shipping = makeShippingParams(for: paymentIntent, configuration: configuration)
let paymentOptions = paymentIntentParams.paymentMethodOptions ?? STPConfirmPaymentMethodOptions()
paymentOptions.setSetupFutureUsageIfNecessary(shouldSave, paymentMethodType: paymentMethod.type, customer: configuration.customer)
paymentIntentParams.paymentMethodOptions = paymentOptions
paymentIntentParams.mandateData = mandateData
paymentHandler.confirmPayment(
paymentIntentParams,
Expand Down Expand Up @@ -363,29 +369,31 @@ extension PaymentSheet {
(
PaymentSheetLinkAccount,
ConsumerPaymentDetails,
String?
) -> Void = { linkAccount, paymentDetails, cvc in
String?,
Bool
) -> Void = { linkAccount, paymentDetails, cvc, shouldSave in
guard let paymentMethodParams = linkAccount.makePaymentMethodParams(from: paymentDetails, cvc: cvc) else {
let error = PaymentSheetError.payingWithoutValidLinkSession
completion(.failed(error: error), nil)
return
}

confirmWithPaymentMethodParams(paymentMethodParams, linkAccount)
confirmWithPaymentMethodParams(paymentMethodParams, linkAccount, shouldSave)
}

let createPaymentDetailsAndConfirm:
(
PaymentSheetLinkAccount,
STPPaymentMethodParams
) -> Void = { linkAccount, paymentMethodParams in
STPPaymentMethodParams,
Bool
) -> Void = { linkAccount, paymentMethodParams, shouldSave in
guard linkAccount.sessionState == .verified else {
// We don't support 2FA in the native mobile Link flow, so if 2FA is required then this is a no-op.
// Just fall through and don't save the card details to Link.
STPAnalyticsClient.sharedClient.logLinkPopupSkipped()

// Attempt to confirm directly with params
confirmWithPaymentMethodParams(paymentMethodParams, linkAccount)
confirmWithPaymentMethodParams(paymentMethodParams, linkAccount, shouldSave)
return
}

Expand All @@ -397,21 +405,21 @@ extension PaymentSheet {
linkAccount.sharePaymentDetails(id: paymentDetails.stripeID, cvc: paymentMethodParams.card?.cvc) { result in
switch result {
case .success(let shareResponse):
confirmWithPaymentMethod(STPPaymentMethod(stripeId: shareResponse.paymentMethod), linkAccount)
confirmWithPaymentMethod(STPPaymentMethod(stripeId: shareResponse.paymentMethod, type: .card), linkAccount, shouldSave)
case .failure(let error):
STPAnalyticsClient.sharedClient.logLinkSharePaymentDetailsFailure(error: error)
// If this fails, confirm directly
confirmWithPaymentMethodParams(paymentMethodParams, linkAccount)
confirmWithPaymentMethodParams(paymentMethodParams, linkAccount, shouldSave)
}
}
} else {
// If not passthrough mode, confirm details directly
confirmWithPaymentDetails(linkAccount, paymentDetails, paymentMethodParams.card?.cvc)
confirmWithPaymentDetails(linkAccount, paymentDetails, paymentMethodParams.card?.cvc, shouldSave)
}
case .failure(let error):
STPAnalyticsClient.sharedClient.logLinkCreatePaymentDetailsFailure(error: error)
// Attempt to confirm directly with params
confirmWithPaymentMethodParams(paymentMethodParams, linkAccount)
confirmWithPaymentMethodParams(paymentMethodParams, linkAccount, shouldSave)
}
}
}
Expand All @@ -420,22 +428,22 @@ extension PaymentSheet {
case .wallet:
let linkController = PayWithLinkController(intent: intent, configuration: configuration)
linkController.present(completion: completion)
case .signUp(let linkAccount, let phoneNumber, let consentAction, let legalName, let paymentMethodParams):
case .signUp(let linkAccount, let phoneNumber, let consentAction, let legalName, let intentConfirmParams):
linkAccount.signUp(with: phoneNumber, legalName: legalName, consentAction: consentAction) { result in
UserDefaults.standard.markLinkAsUsed()
switch result {
case .success:
STPAnalyticsClient.sharedClient.logLinkSignupComplete()

createPaymentDetailsAndConfirm(linkAccount, paymentMethodParams)
createPaymentDetailsAndConfirm(linkAccount, intentConfirmParams.paymentMethodParams, intentConfirmParams.saveForFutureUseCheckboxState == .selected)
case .failure(let error as NSError):
STPAnalyticsClient.sharedClient.logLinkSignupFailure(error: error)
// Attempt to confirm directly with params as a fallback.
confirmWithPaymentMethodParams(paymentMethodParams, linkAccount)
confirmWithPaymentMethodParams(intentConfirmParams.paymentMethodParams, linkAccount, intentConfirmParams.saveForFutureUseCheckboxState == .selected)
}
}
case .withPaymentMethod(let paymentMethod):
confirmWithPaymentMethod(paymentMethod, nil)
confirmWithPaymentMethod(paymentMethod, nil, false)
}
case let .external(paymentMethod, billingDetails):
guard let confirmHandler = configuration.externalPaymentMethodConfiguration?.externalPaymentMethodConfirmHandler else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,11 +267,30 @@ final class PaymentSheetLoader {
continuation.resume(throwing: error)
return
}
// Remove cards that originated from Apple Pay, Google Pay, or Link
// Get Link payment methods
var dedupedLinkPaymentMethods: [STPPaymentMethod] = []
let linkPaymentMethods = paymentMethods.filter { paymentMethod in
let isLinkCard = paymentMethod.type == .card && paymentMethod.card?.wallet?.type == .link
return isLinkCard
}
for linkPM in linkPaymentMethods {
// Only add the card if it doesn't already exist
if !dedupedLinkPaymentMethods.contains(where: { existingPM in
existingPM.card?.last4 == linkPM.card?.last4 &&
existingPM.card?.expYear == linkPM.card?.expYear &&
existingPM.card?.expMonth == linkPM.card?.expMonth &&
existingPM.card?.brand == linkPM.card?.brand
}) {
dedupedLinkPaymentMethods.append(linkPM)
}
}
// Remove cards that originated from Apple Pay, Google Pay, Link
paymentMethods = paymentMethods.filter { paymentMethod in
let isWalletCard = paymentMethod.type == .card && [.applePay, .googlePay, .link].contains(paymentMethod.card?.wallet?.type)
return !isWalletCard
}
// Add in our deduped Link PMs, if any
paymentMethods += dedupedLinkPaymentMethods
continuation.resume(returning: paymentMethods)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,6 @@ class PaymentSheetAPITest: XCTestCase {
return newCardPaymentOption
}()

override class func setUp() {
super.setUp()
}

// MARK: - load and confirm tests

func testPaymentSheetLoadAndConfirmWithPaymentIntent() {
Expand Down Expand Up @@ -298,7 +294,7 @@ class PaymentSheetAPITest: XCTestCase {
configuration: self.configuration,
authenticationContext: self,
intent: paymentIntent,
paymentOption: .saved(paymentMethod: .init(stripeId: "pm_card_visa"), confirmParams: nil),
paymentOption: .saved(paymentMethod: .init(stripeId: "pm_card_visa", type: .card), confirmParams: nil),
paymentHandler: self.paymentHandler
) { result, _ in
switch result {
Expand Down Expand Up @@ -504,7 +500,7 @@ class PaymentSheetAPITest: XCTestCase {
}

func testDeferredConfirm_saved_insufficient_funds_card() {
let insufficient_funds_saved_PM = STPPaymentMethod(stripeId: "pm_card_visa_chargeDeclinedInsufficientFunds")
let insufficient_funds_saved_PM = STPPaymentMethod(stripeId: "pm_card_visa_chargeDeclinedInsufficientFunds", type: .card)
_testDeferredConfirm(
inputPaymentOption: .saved(paymentMethod: insufficient_funds_saved_PM, confirmParams: nil),
expectedShouldSavePaymentMethod: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,11 @@ public class STPPaymentMethod: NSObject, STPAPIResponseDecodable {
// MARK: - STPAPIResponseDecodable
/// :nodoc:
@objc @_spi(STP) public required init(
stripeId: String
stripeId: String,
type: STPPaymentMethodType
) {
self.stripeId = stripeId
self.type = type
super.init()
}

Expand All @@ -203,7 +205,8 @@ public class STPPaymentMethod: NSObject, STPAPIResponseDecodable {
return nil
}

let paymentMethod = self.init(stripeId: stripeId)
let paymentMethod = self.init(stripeId: stripeId,
type: self.type(from: dict.stp_string(forKey: "type") ?? ""))
paymentMethod.allResponseFields = response
paymentMethod.stripeId = stripeId
paymentMethod.created = dict.stp_date(forKey: "created")
Expand All @@ -214,7 +217,6 @@ public class STPPaymentMethod: NSObject, STPAPIResponseDecodable {
paymentMethod.card = STPPaymentMethodCard.decodedObject(
fromAPIResponse: dict.stp_dictionary(forKey: "card")
)
paymentMethod.type = self.type(from: dict.stp_string(forKey: "type") ?? "")
paymentMethod.iDEAL = STPPaymentMethodiDEAL.decodedObject(
fromAPIResponse: dict.stp_dictionary(forKey: "ideal")
)
Expand Down

0 comments on commit f6b9e5e

Please sign in to comment.