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

Maintain the same Stripe Customer across multiple cards #77

Closed
wants to merge 3 commits into from

Conversation

brchristian
Copy link
Contributor

@brchristian brchristian commented Jul 24, 2020

The initial commit creates a (currently failing) spec to test whether multiple cards used by the same Solidus user produce the same Stripe customer (i.e., the same gateway_customer_profile_id).

This is the beginning of progress to address #26. The following commits resolve the issue.

@brchristian
Copy link
Contributor Author

brchristian commented Jul 25, 2020

I've created a fix that addresses #26, and the specs should now be green.

It's a bit inelegant, but I am hoping we can refactor anyway once we move away from ActiveMerchant.

This should solve #26.

@brchristian brchristian changed the title add Stripe Customer spec Maintain the same Stripe Customer across multiple cards Jul 25, 2020
@brchristian
Copy link
Contributor Author

Specs are passing for both V2 and V3 with Elements! 🎉

I have never used V3 with Intents before and am unfamiliar with how it works, so I am not sure what to do there. @spaghetticode what do you think?

@brchristian
Copy link
Contributor Author

Now that #78 has been merged, we can make these new specs a bit cleaner / more concise. I have rebased to current master and added a new commit 39fbb69 to use the fill_in_card helper.

Copy link
Member

@spaghetticode spaghetticode left a comment

Choose a reason for hiding this comment

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

@brchristian thank you so much for this PR! 💳 🎉

The approach looks good to me, I think it just needs some polishing before merging. In general, I noticed that there are some commits that can be squashed, as they modify stuff that was introduced earlier with this PR and IMO they have no real reason to be separated. Then there's some code duplication in the specs that would be great if could be avoided somehow.

Also, it would be great if you could review the commit messages. Generally speaking we tend to prefer commits with a body description and capitalized title. This is a great reference for writing good commit messages, it really helped me in the past: https://chris.beams.io/posts/git-commit/

@@ -130,8 +136,8 @@ def create_profile(payment)
else
payment.source.update!(
cc_type: payment.source.cc_type,
gateway_customer_profile_id: response.params['id'],
gateway_payment_profile_id: response.params['default_source'] || response.params['default_card']
gateway_customer_profile_id: options[:customer] ? response.params['customer'] : response.params['id'],
Copy link
Member

Choose a reason for hiding this comment

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

I guess the ternary can become: response.params['customer'] || response.params['id']. Currently response.params['customer'] is nil when not reusing a customer, but we can make it a little more future proof with response.params['customer'].presence, so it will work properly also if we start receiving empty-string values.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In general I would agree with you, but I think in context with the line that follows, it's a bit more complicated. As you can see, both ternaries use the same setup with options[:customer] ? .

So I think there's an argument for keeping the logic parallel between the two, even if the first one could be made shorter.

@brchristian brchristian force-pushed the customer_spec branch 2 times, most recently from 337451a to 8eb6d6f Compare August 7, 2020 20:01
@brchristian
Copy link
Contributor Author

@spaghetticode Thanks for the code review!

I squashed into two commits (specs + change) and made all of your suggested changes with two exceptions where I've followed up and which you can see above. LMK on those last two and then we should be just about there!

@brchristian brchristian force-pushed the customer_spec branch 2 times, most recently from 6ca923d to 5d43fed Compare August 8, 2020 00:15
@brchristian
Copy link
Contributor Author

Update: I returned to the specs and was able to dedupe 172 lines by following your suggestion. :)

That just leaves the last question about stripe_credit_card.rb. My personal opinion is to leave it as is, for the reasons I explained on the diff, but if you think it’s better to make that change, LMK and I defer to you.

@igorbp
Copy link

igorbp commented Oct 14, 2020

Hi, I just want to raise a question here :

It's possible to delete a customer in the stripe dashboard, and I couldn't find a way to recreate it with the same ID. When it happens it will break this code. I'm not sure if this should be considered or not.

@brchristian @spaghetticode

@spaghetticode
Copy link
Member

@igorbp thanks for raising this question 💯

I don't know if it's very common for admins to delete accounts on the stripe dashboards, but I think it's something that we should consider fixing although not necessarily in the first implementation of this feature.

@igorbp
Copy link

igorbp commented Oct 14, 2020

@spaghetticode I agree with you.

Also, I'm aware of #81 and #82. But I think we could move this forward before start the change to the official stripe gem.

@brchristian
Copy link
Contributor Author

Hi @igorbp I second @spaghetticode in saying this is a very good point. Though we might want to visit that in a future PR.

@spaghetticode I agree with @igorbp that it might make sense to merge this before we look at either #81 or #82 which introduce additional changes. Ideally I would like to add some tests as well, because there is certain behavior that differs between Active Merchant and the Stripe Gem – for instance, whether to return nil or throw an exception when card data is bad – which is not part of current specs (or exists in Active Merchant specs but should probably go here as well, especially if we move away from Active Merchant). But I think all of that we can deal with later when thinking about #81 and/or #82.

In the meantime, however, anything else that I can do to help get this over the finish line?

Gemfile Outdated
@@ -27,6 +27,7 @@ group :development, :test do
gem "pry-rails"
gem "ffaker"
gem "rails-controller-testing"
gem "stripe"
Copy link
Member

Choose a reason for hiding this comment

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

Why do we need to introduce this development dependency? Is it just for testing purposes?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@kennyadsl Exactly, I used the Stripe gem in the specs as a source for "ground-truth" customer and payment info.

Copy link
Member

@spaghetticode spaghetticode left a comment

Choose a reason for hiding this comment

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

@brchristian thanks for addressing the issues ❤️

I think the change is good, I left some more comments on the code.

One more thing, I would expand the commit message for 5d43f as it's currently not explaining the reason of the change. A good description may help people debugging and understanding what's going on in case of unexpected behavior.

@@ -119,6 +119,14 @@ def create_profile(payment)
creditcard = source
end

user_stripe_payment_sources = payment.source.user&.wallet&.wallet_payment_sources&.select do |wps|
wps.payment_source.payment_method.type == 'Spree::PaymentMethod::StripeCreditCard'
Copy link
Member

Choose a reason for hiding this comment

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

We can avoid hardcoding the class name here by replacing 'Spree::PaymentMethod::StripeCreditCard' with self.class.name

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great idea! I’ve made the change and force-pushed.

@@ -0,0 +1,176 @@
# frozen_string_literal: true

Copy link
Member

Choose a reason for hiding this comment

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

The first 100 lines here are still almost identical to the ones in stripe_checkout.spec. I think that all this duplication may become an issue in the future, as changes in one file will need to be ported to the other, for example if something changes on Solidus FE flow.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point. I’ve moved this to a checkout_helper, into a method called initialize_checkout. This deduplicates almost all of the code that was shared between stripe_checkout_spec and stripe_customer_spec.

@brchristian brchristian force-pushed the customer_spec branch 2 times, most recently from 1f10984 to 59f152b Compare October 27, 2020 04:35
@brchristian
Copy link
Contributor Author

@spaghetticode I've gone ahead and followed all of your suggestions! I've...

  • Updated self.class.name in place of the hardcoded string
  • Deduplicated the spec code into a checkout_helper in the testing_support folder as in Refactor spec with fill_in_card helper #78
  • Expanded the commit message (which now has the hash 74f5abb).
  • Rebased to the current master
  • Force-pushed

...and CI is green!

@@ -0,0 +1,57 @@
# frozen_string_literal: true

module SolidusCheckoutHelper
Copy link
Member

Choose a reason for hiding this comment

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

I think it would be better to have the module name match the filename. Also, since we're in the Solidus Stripe gem, I would rather name the module StripeCheckoutHelper or something similar, what do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@spaghetticode Sounds good. I've renamed to StripeCheckoutHelper and stripe_checkout_helper.rb and have force-pushed the latest!

@brchristian
Copy link
Contributor Author

@spaghetticode What else is needed to push this over the finish line?

@spaghetticode
Copy link
Member

@brchristian sorry for the late answer. I think the changes look good, but the CI is failing. The failure is not related to your changes, but I think it's best to wait for the green. I'll keep an eye on the fix (either in Solidus or Solidus Support) and ping you back if any rebase/change is needed, thanks!

@brchristian
Copy link
Contributor Author

@spaghetticode Now that #99 has been merged, the specs are looking good except for one issue, that only seems to come up in Solidus v2.10 and seems unrelated to these changes – I also notice it in the failing specs for #92, for example.

Is this just a fluke, or is there more work to be done on master to get that passing? LMK if I can help.

@spaghetticode
Copy link
Member

@brchristian can you please rebase this branch with master? The postgres build is now failing because of Solidus gem incompatibilities that are solved in master, so hopefully after that it should be passing again. Thanks 🙏

These specs address the need in solidusio#26 for maintaining
a stable Stripe customer object across multiple credit
cards. Currently V2 and V3 Elements are supported, with
V3 Intents functionality remaining as a TODO for a later
PR.
Avoid creating a new Stripe customer during checkout in both V2
and V3 Elements by checking to see whether this Solidus user has
a previous Stripe payment source. Support for V3 Intents will
require further work, and will be included in a subsequent PR.
@stale
Copy link

stale bot commented Nov 11, 2022

This issue has been automatically marked as stale because it has not had recent activity. It might be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Nov 11, 2022
@gsmendoza gsmendoza removed the stale label Nov 11, 2022
@elia elia added the v4.x Issues and PRs targeting the classic frontend (before v5) label Nov 29, 2022
@elia elia changed the base branch from master to v4 December 20, 2022 10:25
@kennyadsl
Copy link
Member

I think we can close this one. It is covered in the new stripe version (v5). Thanks anyway!

@kennyadsl kennyadsl closed this Jul 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
v4.x Issues and PRs targeting the classic frontend (before v5)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants