-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
[RFC] Wallet & Support for non-credit card payment sources #1091
[RFC] Wallet & Support for non-credit card payment sources #1091
Conversation
Extracted from these commits from mamhoff: - spree/spree@7f706d0 - spree/spree@a3b66ae
Based largely on this commit from mamhoff: - spree/spree@a3b66ae
To help tell whether payment sources should be saved in the Wallet or just reused in general (e.g. for unreturned exchange charges).
TODO: Use this in frontend and deprecate `existing_card_id`.
TODO: Deprecate existing_card and existing_card_id
And deprecate User#default_credit_card
c742bb9
to
0ec099f
Compare
I'm good with this, but we also paired on it so it doesn't count as team thumbs-up. :) |
@jhawthorn did you mean to close this? |
@jordan-brough Now the PR is targeting a non-master branch. Is this intentional? |
I really like this change. Looks very sensible, will start simplifying a lot of junk in a lot of extensions. |
@jordan-brough @mamhoff checking this out now, what's the status? Would love to help out where I can. I have some real life samples to work with as well. |
For any stores using legacy payment sources that do not inherit from PaymentSource.
@peterberkenbosch great! Things on my list:
Does any of that, or anything else sound interesting to you? I'm happy to have any help available. |
@mamhoff yes the non-master branch is intentional. I wanted to exclude the commits from the three PRs that I mentioned in the description from showing up here. I need to get that last one figured out and then I'll reopen this against master. |
Thanks @jordan-brough, will put some time in this the next few days. |
…ources make Spree::StoreCredit inherit from Spree::PaymentSource
user.wallet_sources.find_or_create_by!(source: source) | ||
end | ||
|
||
# Remove a PaymentSource to the wallet. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to
should probably be from
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Kingdutch updated. Thanks!
These comments focus on the data modelling, especially how it's reflected in the ActiveRecord classes and their names.
|
Different payment source can have very different fields, and as soon as we start providing support for e.g. SEPA payments, we'll run into a big table with lots of accessors that don't make sense in many contexts. We have the solution @jordan-brough is proposing running in production, and this is the schema for just credit cards and SEPA payments: create_table "spree_credit_cards", force: :cascade do |t|
t.string "month"
t.string "year"
t.string "cc_type"
t.string "last_digits"
t.integer "address_id"
t.string "gateway_customer_profile_id"
t.string "gateway_payment_profile_id"
t.datetime "created_at"
t.datetime "updated_at"
t.string "name"
t.integer "payment_method_id"
end
create_table "payone_sepa_mandates", force: :cascade do |t|
t.string "bank_country"
t.string "bank_account"
t.string "bank_code"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "payment_method_id"
t.string "iban"
t.string "bic"
t.string "gateway_customer_profile_id"
t.string "mandate_identification"
t.string "mandate_status"
t.text "mandate_text"
t.string "creditor_identifier"
t.string "street"
t.string "city"
t.string "company"
t.string "zip"
t.string "country"
t.string "email"
t.string "name"
end I would not want to merge these two into the same table. As for the Thanks a lot for taking the time to comment here, especially the naming suggestions are very much appreciated. |
Sounds reasonable to me. I'll update to this naming unless anyone objects. @mamhoff @cbrunsdon any preferences? |
Great idea, I'll add that. |
I'm not completely opposed to this idea but I think it expands the scope right now unnecessarily without some solid use cases. A table like Part of the reason to provide the PORO I do think one thing that might be nice to do right now though is to add |
@jordan-brough I'm unsure what the |
👍 on adding |
@jrochkind Coming to think of it, most of that data does not have to be particularly query-able, so we might get do well with STI and a JSON |
@mamhoff I don't know that STI is used anywhere else in Solidus, do we really want to open this box? When is a JSON data structure vs tables the answer and when is it not? ( And I am pro STI, in general I think it leads to elegance in design, just not sure we want to introduce it if it is not already used.) |
There's no ideal solution, but I think STI is probably less complex than an approximation of a polymorphic many-to-many, which is kind of what's there now. (AR can't actually do a polymorphic many-to-many reliably, which is maybe why the many-to-many association isn't actually defined here, despite the many-to-many-like join table). But there are definitely plusses and minuses either way, I can see either decision, none we have in front of us seem ideal. I would say the relevant pattern that maybe makes the JSON data structure @mamhoff suggests appropriate, is when you have a bunch of rows in the same table that need wildly different attributes, and those attributes do not (ever!) need to be queryable. One place this is used in current Solidus is PromotionRule preferences -- which are actually also STI, I think? (So STI is not totally new to Solidus, I think?) (And any other place that use Serialized-in-one-column data struture is basically a hacky workaround escape hatch, but sometimes you need a workaround escape hatch. :) But yeah, I'm not sure which is the best decision here, just that it's probably worth considering -- whatever ends up merged is gonna be with us a while (hopefully, we don't want another backwards breaking change soon), and is part of the core bones of solidus so everyone will be dealing with it. |
@jrochkind exactly. There are so many places we could potentially use STI, that I think its important we know exactly why we are introducing it, and when it is justified. Once it is introduced, then you will see lots of proposals using STI. If we are going to introduce this design, then we musn't let it fall into the pervasive documentation vacuum that exists. We should clearly document it and say, this design emerged for specific conditions, etc. Its totally true that every payment method will have an unpredictable field set in a wallet that might contain, NFC, direct banking such as ACH and credit card sources. So this is a sensible hack from that point. |
Some places we currently use STI:
I'm not sure whether it's the right choice here, but definitely worth considering. |
@dhonig So STI has already been 'introduced', this would not be introducing it. If Spree::PaymentMethod and Spree::Gateway are both already STI, that does seem rather tantalizingly analagous, doesn't it? (Unless it hasn't worked out well and seems a bad idea in retrospect for them!) The part of this PR that moves further toward abstracting away from CreditCard to a generalized polymorphic PaymentSource is, I'd suggest, more significant (and important to get right) than the Wallet part. Order is gonna need an association to PaymentSource too, isn't it? At least eventually. I don't completely follow how it's being done in this PR. And Order to PaymentSource might even need to be many-to-many --- you can theoretically pay for an order with more than one PaymentSource, right? Wouldn't it be nice if the Order/PaymentSource relationship were an ordinary rails many-to-many ( |
I don't see the need for anything to change in that area. |
Re polymorphic vs STI: I think I lean toward continuing with polymorphic relationships, with the addition of the validation that @jrochkind suggested so that |
One extra thought: One part of |
Re polymorphic vs STI: I chatted with @jhawthorn today and he is also in favor of using an abstract base class and a polymorphic relationship (instead of STI). Among other things, he made the point that it's likely that we'll want to search by these provider-unique fields (e.g. the email address of a PayPal account) and cross-db support for json fields is complex and/or not all there right now. So the STI+JSON idea might not work very well, and STI w/o JSON doesn't seem like a great fit for a table where the fields vary greatly between child classes. |
Makes sense, thanks @jordan-brough |
renamed wallet_source#source to payment_source reflected the name change in the migrations as well. forgot to add the renamed files
Makes sure the `payment_source` is a `Spree::PaymentSource` add spec for wallet_payment_source#payment_source validation fixed typo on the error key message add locale for invalid payment_source
3e4cbf2
to
4cdc669
Compare
@jordan-brough should we merge in (or rebase) master on this PR? The dependent PR's are merged in, would love to see a green CI build here as well :) |
Closing this. @peterberkenbosch is taking this over and pushing it forward in #1414. |
Note: This is now being moved forward by #1707 |
This is an attempt to update Solidus to fully support non-credit-card payment sources, and to make that easier to do it also introduces the concept of
Spree::Wallet
(see the code comments in wallet.rb for a summary of that class).I've based this on top of three other PRs that I hope will be merged first:
This is based on and heavily influenced by @mamhoff's Spree PR from last year:
spree/spree#6831
The major difference is the "Wallet" concept that he and I have discussed a bunch in the past month.
Comments and suggestions are very welcome.
I have not added new specs. If we think this general direction looks good then I will add them. There are also a couple todos that I will tackle if this looks generally OK.