Skip to content

Commit

Permalink
MBL-1368: Fetch PaymentMethod to display Stripe Link in pledge flow
Browse files Browse the repository at this point in the history
  • Loading branch information
amy-at-kickstarter committed May 7, 2024
1 parent 23c767f commit c55a641
Showing 1 changed file with 98 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ final class PledgePaymentMethodsViewController: UIViewController {
strongSelf.paymentSheetFlowController?.presentPaymentOptions(from: strongSelf) { [weak self] in
guard let strongSelf = self else { return }

strongSelf.confirmPaymentResult(with: data.clientSecret)
strongSelf.confirmPaymentResult(with: data)
}
strongSelf.viewModel.inputs.stripePaymentSheetDidAppear()
}
Expand All @@ -190,7 +190,7 @@ final class PledgePaymentMethodsViewController: UIViewController {
}
}

private func confirmPaymentResult(with clientSecret: String) {
private func confirmPaymentResult(with data: PaymentSheetSetupData) {
guard self.paymentSheetFlowController?.paymentOption != nil else {
self.viewModel.inputs.shouldCancelPaymentSheetAppearance(state: true)

Expand All @@ -207,12 +207,11 @@ final class PledgePaymentMethodsViewController: UIViewController {

switch paymentResult {
case .completed:
let paymentDisplayData = PaymentSheetPaymentOptionsDisplayData(
image: existingPaymentOption.image,
label: existingPaymentOption.label
strongSelf.didConfirmAddedPaymentOption(
paymentOption: existingPaymentOption,
forClientSecret: data.clientSecret,
forPaymentSheetType: data.paymentSheetType
)
strongSelf.viewModel.inputs
.paymentSheetDidAdd(newCard: paymentDisplayData, clientSecret: clientSecret)
case .canceled:
// User cancelled intentionally so do nothing.
break
Expand All @@ -223,6 +222,98 @@ final class PledgePaymentMethodsViewController: UIViewController {
}
}

private func didConfirmAddedPaymentOption(
paymentOption: PaymentSheet.FlowController.PaymentOptionDisplayData,
forClientSecret clientSecret: String,
forPaymentSheetType paymentSheetType: PledgePaymentSheetType
) {
// Stripe also defines this constant, but it's defined internally to the Stripe SDK :(
let linkIdentifier = "link"

// For regular payment types, continue with the display information they gave us
if paymentOption.paymentMethodType != linkIdentifier {
let paymentDisplayData = PaymentSheetPaymentOptionsDisplayData(
image: paymentOption.image,
label: paymentOption.label
)

self.viewModel.inputs.paymentSheetDidAdd(newCard: paymentDisplayData, clientSecret: clientSecret)
return
}

// For link payment types, fetch the underlying payment method so we can get at the card type and label

switch paymentSheetType {
case .setupIntent:
STPAPIClient.shared
.retrieveSetupIntent(
withClientSecret: clientSecret,
expand: ["payment_method"]
) { [weak self] intent, _ in
guard let strongSelf = self else { return }
guard let paymentDisplayData = strongSelf.paymentDisplayData(forLink: intent?.paymentMethod)
else { return }
strongSelf.viewModel.inputs.paymentSheetDidAdd(
newCard: paymentDisplayData,
clientSecret: clientSecret
)
}

case .paymentIntent:
STPAPIClient.shared
.retrievePaymentIntent(
withClientSecret: clientSecret,
expand: ["payment_method"]
) { [weak self] intent, _ in
guard let strongSelf = self else { return }
guard let paymentDisplayData = strongSelf.paymentDisplayData(forLink: intent?.paymentMethod)
else { return }
strongSelf.viewModel.inputs.paymentSheetDidAdd(
newCard: paymentDisplayData,
clientSecret: clientSecret
)
}
}
}

private func paymentDisplayData(forLink optionalPaymentMethod: STPPaymentMethod?)
-> PaymentSheetPaymentOptionsDisplayData? {
guard let paymentMethod = optionalPaymentMethod else {
return nil
}

let formattedLabel = self.formatLinkLabel(paymentMethod.label)
return PaymentSheetPaymentOptionsDisplayData(
image: paymentMethod.image,
label: formattedLabel ?? paymentMethod.label
)
}

private func formatLinkLabel(_ label: String) -> String? {
// Link gives us a label like "Visa 1234"; reformat it to match our UI
do {
let regex = try NSRegularExpression(pattern: "\\d{4}")
let matches = regex.matches(
in: label,
range: NSRange(location: 0, length: label.count)
)

guard let match = matches.first else {
return nil
}

guard let range = Range(match.range, in: label) else {
return nil
}

let lastFour = label[range]
return "•••• \(lastFour)"

} catch {
return nil
}
}

private func updateAddNewPaymentMethodButtonLoading(state: Bool) {
self.dataSource.updateAddNewPaymentCardLoad(state: state)

Expand Down

0 comments on commit c55a641

Please sign in to comment.