Skip to content

Commit

Permalink
Merge branch 'main' into updatePledgeCTA
Browse files Browse the repository at this point in the history
  • Loading branch information
ifosli committed Mar 26, 2024
2 parents 59649ee + b9d1719 commit 76f347c
Show file tree
Hide file tree
Showing 15 changed files with 506 additions and 233 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ final class PledgePaymentMethodsViewController: UIViewController {

self.viewModel.outputs.reloadPaymentMethods
.observeForUI()
.observeValues { [weak self] cards, paymentSheetCards, selectedCard, selectedPaymentSheetCardId, shouldReload, isLoading in
.observeValues { [weak self] cards, paymentSheetCards, selectedPaymentMethod, shouldReload, isLoading in
guard let self = self else { return }

self.dataSource.load(
Expand All @@ -88,15 +88,17 @@ final class PledgePaymentMethodsViewController: UIViewController {
if shouldReload {
self.tableView.reloadData()
} else {
switch (selectedCard, selectedPaymentSheetCardId) {
case let (.none, .some(selectedPaymentSheetCardId)):
switch selectedPaymentMethod {
case let .paymentIntentClientSecret(selectedPaymentSheetCardId):
fallthrough
case let .setupIntentClientSecret(selectedPaymentSheetCardId):
self.tableView.visibleCells
.compactMap { $0 as? PledgePaymentSheetPaymentMethodCell }
.forEach { $0.setSelectedCard(selectedPaymentSheetCardId) }
case let (.some(selectedCard), .none):
case let .savedCreditCard(selectedCardId):
self.tableView.visibleCells
.compactMap { $0 as? PledgePaymentMethodCell }
.forEach { $0.setSelectedCard(selectedCard) }
.forEach { $0.setSelectedCardId(selectedCardId) }
default:
break
}
Expand Down Expand Up @@ -144,33 +146,48 @@ final class PledgePaymentMethodsViewController: UIViewController {
// MARK: - Functions

private func goToPaymentSheet(data: PaymentSheetSetupData) {
PaymentSheet.FlowController
.create(
setupIntentClientSecret: data.clientSecret,
configuration: data.configuration
) { [weak self] result in
guard let strongSelf = self else { return }
let completion: (Result<PaymentSheet.FlowController, Error>) -> Void = { [weak self] result in
guard let strongSelf = self else { return }

switch result {
case let .failure(error):
strongSelf.viewModel.inputs.shouldCancelPaymentSheetAppearance(state: true)
strongSelf.messageDisplayingDelegate?
.pledgeViewController(strongSelf, didErrorWith: error.localizedDescription)
case let .success(paymentSheetFlowController):
let topViewController = strongSelf.navigationController?.topViewController
let paymentSheetShownWithinPledgeContext = topViewController is PledgeViewController

if paymentSheetShownWithinPledgeContext {
strongSelf.paymentSheetFlowController = paymentSheetFlowController
strongSelf.paymentSheetFlowController?.presentPaymentOptions(from: strongSelf) { [weak self] in
guard let strongSelf = self else { return }

strongSelf.confirmPaymentResult(with: data.clientSecret)
}
}
strongSelf.viewModel.inputs.stripePaymentSheetDidAppear()
switch result {
case let .failure(error):
strongSelf.viewModel.inputs.shouldCancelPaymentSheetAppearance(state: true)
strongSelf.messageDisplayingDelegate?
.pledgeViewController(strongSelf, didErrorWith: error.localizedDescription)
case let .success(paymentSheetFlowController):
let topViewController = strongSelf.navigationController?.topViewController

assert(
topViewController is PledgeViewController ||
topViewController is PostCampaignCheckoutViewController,
"PledgePaymentMethodsViewController is only intended to be presented as part of a pledge flow."
)

strongSelf.paymentSheetFlowController = paymentSheetFlowController
strongSelf.paymentSheetFlowController?.presentPaymentOptions(from: strongSelf) { [weak self] in
guard let strongSelf = self else { return }

strongSelf.confirmPaymentResult(with: data.clientSecret)
}
strongSelf.viewModel.inputs.stripePaymentSheetDidAppear()
}
}

switch data.paymentSheetType {
case .setupIntent:
PaymentSheet.FlowController.create(
setupIntentClientSecret: data.clientSecret,
configuration: data.configuration,
completion: completion
)
case .paymentIntent:
PaymentSheet.FlowController
.create(
paymentIntentClientSecret: data.clientSecret,
configuration: data.configuration,
completion: completion
)
}
}

private func confirmPaymentResult(with clientSecret: String) {
Expand All @@ -195,7 +212,7 @@ final class PledgePaymentMethodsViewController: UIViewController {
label: existingPaymentOption.label
)
strongSelf.viewModel.inputs
.paymentSheetDidAdd(newCard: paymentDisplayData, setupIntent: clientSecret)
.paymentSheetDidAdd(newCard: paymentDisplayData, clientSecret: clientSecret)
case .canceled:
strongSelf.messageDisplayingDelegate?
.pledgeViewController(strongSelf, didErrorWith: Strings.general_error_something_wrong())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ final class PledgePaymentMethodsViewControllerTests: TestCase {
project: project,
reward: reward,
context: .pledge,
refTag: nil
refTag: nil,
pledgeTotal: Double.nan,
paymentSheetType: .setupIntent
)

controller.configure(with: data)
Expand Down Expand Up @@ -89,7 +91,9 @@ final class PledgePaymentMethodsViewControllerTests: TestCase {
project: project,
reward: reward,
context: .pledge,
refTag: nil
refTag: nil,
pledgeTotal: Double.nan,
paymentSheetType: .setupIntent
)

controller.configure(with: data)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,14 @@ final class PledgePaymentMethodsDataSourceTests: XCTestCase {
(
image: UIImage(),
redactedCardNumber: "test1",
setupIntent: "seti_1LVlHO4VvJ2PtfhK43R6p7FI_secret_MEDiGbxfYVnHGsQy8v8TbZJTQhlNKLZ",
clientSecret: "seti_1LVlHO4VvJ2PtfhK43R6p7FI_secret_MEDiGbxfYVnHGsQy8v8TbZJTQhlNKLZ",
isSelected: true,
isEnabled: true
),
(
image: UIImage(),
redactedCardNumber: "test2",
setupIntent: "seti_2LVlHO4VvJ2PtfhK43R6p7FI_secret_MEDiGbxfYVnHGsQy8v8TbZJTQhlNKLP",
clientSecret: "seti_2LVlHO4VvJ2PtfhK43R6p7FI_secret_MEDiGbxfYVnHGsQy8v8TbZJTQhlNKLP",
isSelected: false,
isEnabled: true
)
Expand Down Expand Up @@ -92,14 +92,14 @@ final class PledgePaymentMethodsDataSourceTests: XCTestCase {
(
image: UIImage(),
redactedCardNumber: "test1",
setupIntent: "seti_1LVlHO4VvJ2PtfhK43R6p7FI_secret_MEDiGbxfYVnHGsQy8v8TbZJTQhlNKLZ",
clientSecret: "seti_1LVlHO4VvJ2PtfhK43R6p7FI_secret_MEDiGbxfYVnHGsQy8v8TbZJTQhlNKLZ",
isSelected: true,
isEnabled: true
),
(
image: UIImage(),
redactedCardNumber: "test2",
setupIntent: "seti_2LVlHO4VvJ2PtfhK43R6p7FI_secret_MEDiGbxfYVnHGsQy8v8TbZJTQhlNKLP",
clientSecret: "seti_2LVlHO4VvJ2PtfhK43R6p7FI_secret_MEDiGbxfYVnHGsQy8v8TbZJTQhlNKLP",
isSelected: false,
isEnabled: true
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,8 @@ final class PledgePaymentMethodCell: UITableViewCell, ValueCell {

// MARK: - Accessors

func setSelectedCard(_ card: UserCreditCards.CreditCard) {
self.viewModel.inputs.setSelectedCard(card)
func setSelectedCardId(_ id: String) {
self.viewModel.inputs.setSelectedCardId(id)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import KsApi
import Library
import Prelude
import Stripe
import UIKit

private enum PostCampaignCheckoutLayout {
Expand Down Expand Up @@ -204,6 +205,13 @@ final class PostCampaignCheckoutViewController: UIViewController {
}

self.paymentMethodsViewController.view.rac.hidden = self.viewModel.outputs.paymentMethodsViewHidden

self.viewModel.outputs.configureStripeIntegration
.observeForUI()
.observeValues { merchantIdentifier, publishableKey in
STPAPIClient.shared.publishableKey = publishableKey
STPAPIClient.shared.configuration.appleMerchantIdentifier = merchantIdentifier
}
}

// MARK: - Functions
Expand Down
7 changes: 4 additions & 3 deletions Library/ViewModels/PaymentMethodsViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,13 @@ public final class PaymentMethodsViewModel: PaymentMethodsViewModelType,
return (
image: displayData.image,
redactedCardNumber: displayData.label,
setupIntent: setupIntent,
clientSecret: setupIntent,
isSelected: false,
isEnabled: true
)
}
.map { paymentMethodData -> String? in
guard let selectedPaymentSheetPaymentMethodCardId = paymentMethodData?.setupIntent else {
guard let selectedPaymentSheetPaymentMethodCardId = paymentMethodData?.clientSecret else {
return nil
}

Expand Down Expand Up @@ -155,7 +155,8 @@ public final class PaymentMethodsViewModel: PaymentMethodsViewModelType,
configuration.allowsDelayedPaymentMethods = true
let data = PaymentSheetSetupData(
clientSecret: envelope.clientSecret,
configuration: configuration
configuration: configuration,
paymentSheetType: .setupIntent
)
return SignalProducer(value: data)
}
Expand Down
16 changes: 13 additions & 3 deletions Library/ViewModels/PaymentSourceSelected.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import Foundation
public enum PaymentSourceSelected: Equatable {
case paymentSourceId(String)
case savedCreditCard(String)
case setupIntentClientSecret(String)
case paymentIntentClientSecret(String)

public var paymentSourceId: String? {
public var savedCreditCardId: String? {
switch self {
case let .paymentSourceId(value):
case let .savedCreditCard(value):
return value
default:
return nil
Expand All @@ -20,4 +21,13 @@ public enum PaymentSourceSelected: Equatable {
return nil
}
}

public var paymentIntentClientSecret: String? {
switch self {
case let .paymentIntentClientSecret(value):
return value
default:
return nil
}
}
}
16 changes: 9 additions & 7 deletions Library/ViewModels/PledgePaymentMethodCellViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public protocol PledgePaymentMethodCellViewModelInputs {
func configureWith(value: PledgePaymentMethodCellData)

/// Call with the currently selected card.
func setSelectedCard(_ creditCard: UserCreditCards.CreditCard)
func setSelectedCardId(_ id: String)
}

public protocol PledgePaymentMethodCellViewModelOutputs {
Expand Down Expand Up @@ -64,7 +64,7 @@ public final class PledgePaymentMethodCellViewModel: PledgePaymentMethodCellView
PledgePaymentMethodCellViewModelOutputs, PledgePaymentMethodCellViewModelType {
public init() {
let creditCard = self.configureValueProperty.signal.skipNil().map(\.card)
let selectedCard = self.selectedCardProperty.signal.skipNil()
let selectedCardId = self.selectedCardIdProperty.signal.skipNil()
let cardTypeIsAvailable = self.configureValueProperty.signal.skipNil().map(\.isEnabled)
let configuredAsSelected = self.configureValueProperty.signal.skipNil().map(\.isSelected)

Expand All @@ -90,10 +90,12 @@ public final class PledgePaymentMethodCellViewModel: PledgePaymentMethodCellView

let cardAndSelectedCard = Signal.combineLatest(
creditCard,
selectedCard
selectedCardId
)

let setAsSelected = cardAndSelectedCard.map(==)
let setAsSelected = cardAndSelectedCard.map { card, id in
card.id == id
}

let creditCardCheckImageName = Signal.merge(configuredAsSelected, setAsSelected)
.map { $0 ? "icon-payment-method-selected" : "icon-payment-method-unselected" }
Expand Down Expand Up @@ -135,9 +137,9 @@ public final class PledgePaymentMethodCellViewModel: PledgePaymentMethodCellView
self.configureValueProperty.value = value
}

private let selectedCardProperty = MutableProperty<UserCreditCards.CreditCard?>(nil)
public func setSelectedCard(_ creditCard: UserCreditCards.CreditCard) {
self.selectedCardProperty.value = creditCard
private let selectedCardIdProperty = MutableProperty<String?>(nil)
public func setSelectedCardId(_ id: String) {
self.selectedCardIdProperty.value = id
}

public let cardImageAlpha: Signal<CGFloat, Never>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ internal final class PledgePaymentMethodCellViewModelTests: TestCase {
self.unavailableCardText.assertDidNotEmitValue()

self.vm.inputs.configureWith(value: (UserCreditCards.generic, true, true, "Brooklyn, NY", false))
self.vm.inputs.setSelectedCard(UserCreditCards.diners)
self.vm.inputs.setSelectedCardId(UserCreditCards.diners.id)

self.cardImageName.assertValues(["icon--generic"])
self.cardImageAlpha.assertValues([1.0])
Expand Down Expand Up @@ -177,7 +177,7 @@ internal final class PledgePaymentMethodCellViewModelTests: TestCase {
self.unavailableCardText.assertDidNotEmitValue()

self.vm.inputs.configureWith(value: (UserCreditCards.generic, true, false, "Brooklyn, NY", false))
self.vm.inputs.setSelectedCard(UserCreditCards.generic)
self.vm.inputs.setSelectedCardId(UserCreditCards.generic.id)

self.cardImageName.assertValues(["icon--generic"])
self.cardImageAlpha.assertValues([1.0])
Expand Down Expand Up @@ -206,7 +206,7 @@ internal final class PledgePaymentMethodCellViewModelTests: TestCase {
self.unavailableCardText.assertDidNotEmitValue()

self.vm.inputs.configureWith(value: (UserCreditCards.generic, false, true, "Brooklyn, NY", false))
self.vm.inputs.setSelectedCard(UserCreditCards.generic)
self.vm.inputs.setSelectedCardId(UserCreditCards.generic.id)

self.cardImageName.assertValues(["icon--generic"])
self.cardImageAlpha.assertValues([0.5])
Expand Down

0 comments on commit 76f347c

Please sign in to comment.