Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MBL-1123: Implement CreatePaymentIntent #1994

Merged
merged 6 commits into from Mar 25, 2024

Conversation

amy-at-kickstarter
Copy link
Contributor

@amy-at-kickstarter amy-at-kickstarter commented Mar 22, 2024

📲 What

For late pledges, create an PaymentIntent instead of a SetupIntent, and use the associated Stripe payment sheet.

This PR includes quite a bit of refactoring, which is to make the intent type significantly more explicit in PledgePaymentsViewController/ViewModel.

🤔 Why

Swapping late pledges to use PaymentIntent is a requirement of the broader project.

👀 See

setupintent

clientSecretSignal = AppEnvironment.current.apiService
.createPaymentIntentInput(input: CreatePaymentIntentInput(
projectId: project.graphID,
amountDollars: "10.00",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the important // TODO here - we need the actual pledge amount in this view model.

@amy-at-kickstarter amy-at-kickstarter force-pushed the feat/adyer/MBL-1123/create-payment-intent-2 branch from a494263 to daa6386 Compare March 25, 2024 13:44
@amy-at-kickstarter amy-at-kickstarter force-pushed the feat/adyer/MBL-1123/create-payment-intent-2 branch 2 times, most recently from 10b8daa to 921c2a7 Compare March 25, 2024 17:19
@nativeksr
Copy link
Collaborator

1 Warning
⚠️ Big PR

Generated by 🚫 Danger

@amy-at-kickstarter amy-at-kickstarter force-pushed the feat/adyer/MBL-1123/create-payment-intent-2 branch from 921c2a7 to 3c48918 Compare March 25, 2024 17:39
case let .success(paymentSheetFlowController):
let topViewController = strongSelf.navigationController?.topViewController

assert(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that I got rid of the if paymentSheetShownWithinPledgeContext and changed it to an assert, instead. AFAIK this view controller is already only ever used from a pledge context.

@amy-at-kickstarter amy-at-kickstarter marked this pull request as ready for review March 25, 2024 17:47
@@ -195,7 +212,7 @@ final class PledgePaymentMethodsViewController: UIViewController {
label: existingPaymentOption.label
)
strongSelf.viewModel.inputs
.paymentSheetDidAdd(newCard: paymentDisplayData, setupIntent: clientSecret)
.paymentSheetDidAdd(newCard: paymentDisplayData, clientSecret: clientSecret)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been trying to rename setupIntent to clientSecret or stripeIntent wherever I can, but definitely have missed some spots.

@@ -50,7 +50,9 @@ final class PledgePaymentMethodsViewControllerTests: TestCase {
project: project,
reward: reward,
context: .pledge,
refTag: nil
refTag: nil,
pledgeTotal: Double.nan,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self.viewModel.outputs.configureStripeIntegration
.observeForUI()
.observeValues { merchantIdentifier, publishableKey in
STPAPIClient.shared.publishableKey = publishableKey
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @scottkicks! Just copied this directly over from PledgeViewModel/PledgeViewController.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear to me why we only set the Stripe keys if the payment view isn't hidden - does Stripe charge us for setup? Seems odd, but I'm not willing to plumb those depths right now.

@@ -155,7 +155,8 @@ public final class PaymentMethodsViewModel: PaymentMethodsViewModelType,
configuration.allowsDelayedPaymentMethods = true
let data = PaymentSheetSetupData(
clientSecret: envelope.clientSecret,
configuration: configuration
configuration: configuration,
paymentSheetType: .setupIntent
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PaymentMethodsViewModel is used by PaymentMethodSettingsViewControllerDelegate, which is in the settings. That page only ever needs to use a SetupIntent.

@@ -16,12 +16,20 @@ public typealias PledgePaymentMethodsValue = (
project: Project,
reward: Reward,
context: PledgeViewContext,
refTag: RefTag?
refTag: RefTag?,
pledgeTotal: Double,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passing the pledgeTotal in this way is a bit ugly, since it means I'm setting it to an empty value for non-late-pledge usages of this screen. I tried to document it in the code with asserts.

@@ -198,22 +207,26 @@ public final class PledgePaymentMethodsViewModel: PledgePaymentMethodsViewModelT

if indexPath.row < paymentSheetPaymentMethodCount {
// we are selecting a new payment sheet card
let setupIntent = data.paymentSheetPaymentMethodsCellData[indexPath.row].setupIntent
let clientSecret = data.paymentSheetPaymentMethodsCellData[indexPath.row].clientSecret
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the level of each individual payment row, it just tracks a clientSecret as a string. The PledgePaymentMethodsViewModel, one level up, keeps track of whether that string is a PaymentIntent or a SetupIntent.

configuration.allowsDelayedPaymentMethods = true
case .paymentIntent:
assert(
!pledgeTotal.isNaN,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is my protection for the slightly ugly plumbing, here. I can't think of a good way around passing in the pledgeTotal in the overall configuration of this page - there's nowhere else we can get it from, correct?

// This second to last value - pledgeTotal - is only needed when the payment methods controller
// is used in late campaign pledges. There is an assert in PledgePaymentMethodsViewModel to ensure
// we don't accidentally propagate this nan downstream.
return (user, project, reward, context, refTag, Double.nan, .setupIntent)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@scottkicks @ifosli Can someone confirm that PledgeViewModel is never used for late pledges?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can confirm! We're only using PostCampaignCheckoutViewModel in this new flow. PledgeViewModel should never get initialized.

@@ -67,7 +67,7 @@ public class PostCampaignCheckoutViewModel: PostCampaignCheckoutViewModelType,
guard let user = AppEnvironment.current.currentUser else { return nil }
guard let reward = data.rewards.first else { return nil }

return (user, data.project, reward, data.context, data.refTag)
return (user, data.project, reward, data.context, data.refTag, data.total, .paymentIntent)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@scottkicks @ifosli Can someone confirm that data.total is the correct value for the pledge total?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct 👍

@amy-at-kickstarter amy-at-kickstarter force-pushed the feat/adyer/MBL-1123/create-payment-intent-2 branch from 3c48918 to 5e9baef Compare March 25, 2024 18:04
Copy link
Contributor

@scottkicks scottkicks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍
Great Job!

@amy-at-kickstarter amy-at-kickstarter changed the title [WIP] MBL-1123: Implement CreatePaymentIntent MBL-1123: Implement CreatePaymentIntent Mar 25, 2024
@amy-at-kickstarter amy-at-kickstarter merged commit ee1d256 into main Mar 25, 2024
5 checks passed
@amy-at-kickstarter amy-at-kickstarter deleted the feat/adyer/MBL-1123/create-payment-intent-2 branch March 25, 2024 19:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants