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

Payments Roadmap #378

Closed
jhawthorn opened this issue Sep 18, 2015 · 7 comments
Closed

Payments Roadmap #378

jhawthorn opened this issue Sep 18, 2015 · 7 comments

Comments

@jhawthorn
Copy link
Contributor

Ideas regarding payments from a brainstorm with @allisonlarson @cbrunsdon @Dkendal

The way payments are handled needs some work. The current implementation has a lot of drawbacks:

  • Poor error handling
  • auto_capture is dangerous
  • Difficult to implement PaymentMethods that don't use CreditCard
  • Payments are processed as part of the Order state machine using transient attributes on the CreditCard

Our current payments have three ways they may be used:

  • Vaulted - A CreditCard with a gateway_payment_profile_id, usually created in one Payment and then allowed to be reused in future Payments
  • Auth/Capture - When filling in CC details, an authorization is made in the gateway
  • Sale - When auto_capture is turned on, a sale transaction is made immediately when completing the order. A sale transaction combines and auth and a capture in a single call.

Proposals

Remove sale transactions

I want to remove "sale" transactions entirely. They can't be used safely since they always charge immediately. Instead we should always authorize out of the payment step. We can keep most of the intention of auto_capture by instead performing a capture once the order is complete. This will break compatibility with any gateways which only implement purchase.

Remove Payment state machine

There's currently a state_machine on payment which switches between the processing, checkout, pending, completed, ... states. This is of basically no use as all states are allowed to move to pending, and pending can move to any other state. This has been done intentionally to bypass the state machine since we really do not want to rollback a transaction instead of saving the result of the transaction. We can replicate the current behaviour just by setting the state directly, and could improve on it by manually checking the current state when performing an action before moving to processing.

Move source construction to PaymentMethod

The PaymentMethod should be responsible for building sources. This will allow PaymentMethods like Braintree v.zero to create their CC payment source from the payment nonce with out having to override any Payment or CreditCard methods.

This may eventually help us remove the transient attributes on CreditCard

@gmacdougall
Copy link
Member

👍 on removing the state machine and moving source construction around.

I also want to get rid of sale transactions, because I agree that they're wrong. However, it is a pretty invasive change for our users, so I want to make sure we have a good migration guide.

@jhawthorn
Copy link
Contributor Author

I also want to get rid of sale transactions, because I agree that they're wrong. However, it is a pretty invasive change for our users, so I want to make sure we have a good migration guide.

It is, and I fear that there's some gateways which only implement purchase.

I think some users will be using auto_capture just to capture on complete (which is what it sounds like it does) rather than because their gateway requires it.

@jhawthorn
Copy link
Contributor Author

Maybe adding a capture_on_complete and deprecating auto_capture would be a good transition

@mamhoff
Copy link
Contributor

mamhoff commented Oct 30, 2015

One thing that we needed was the ability to create payment sources without an associated payment, so we could allow users with subscriptions to switch their payment method between "orders".

Also, with the European payment sources, we needed some kind of abstract idea of a payment source, and a #payment_sources association on the User model that supports polymorphism. I know polymorphic associations are a pain, but here I think they actually make sense. There's a PR on the Spree repo already which probably won't get merged anymore: spree/spree#6831

I'm really not set on the details here, mostly I'm interested in something like this being possible without too much patching.

@Kingdutch
Copy link
Contributor

Kingdutch commented Jun 22, 2016

EDIT: I may have spoken too soon as I see that payments without payment sources already seem possible. However since my understanding is limited at the moment I'm leaving the original message below in the hope that it contributes anyhow.

I would really like to see work on this or see how I could help with this. I've currently been trying to roll my own subscription service, mostly because most that's out there is aimed at using Credit Cards. Solidus can take a lot of work out of my hands in building my own service but I would need support for extendable payments that don't use credit cards.

The payment methods I would need (and would be willing to help implement as I would have to do that anyway) are iDeal (used by 85% of Dutch online shoppers) for one-off payments and SEPA which is used for recurring payments.

I must admit I'm not familiar with the current state of Solidus payments but one thing that I see as a potential problem is the requirement for a Payment Source (unless I misinterpreted this issue). For example, iDeal is trusted and used in the Netherlands precisely because it is not a payment source. (SEPA comes closer to this, especially with Stripe's implementation which I would like to use).

iDeal works roughly as follows, which is why I think it doesn't qualify as a payment source:
The website requesting a payment contacts its iDeal service provider (usually their own bank or an intermediary) and requests a payment with a description for a certain amount. It then receives a token identifying the payment. Using this token it redirects the user to the website of the user's bank where the user can complete the payment in a trusted environment. After the payment is completed (or cancelled) the user is redirected back to the merchant's website. The earlier token that was used to identify the transaction can then be used (either in webhook or query form I'm not sure, both should be possible) to retrieve the status of the transaction.

As described I don't think iDeal constitutes a payment source but rather only gives information about whether a payment was succesful or unsuccesful and allows the website to act accordingly.

As stated I would be happy to help in see how payments could be implemented. In other frameworks that I have used I think this would be a great place for polymorphism. Having a Payment interface class that can be used to query the status of a payment and complete a payment and having various subclasses that actually implement the inner workings (e.g. storing credit card details and billing, redirecting to Stripe for secure credit card handling, redirecting to iDeal or using SEPA for a recurring charge).

@mamhoff
Copy link
Contributor

mamhoff commented Jun 23, 2016

@Kingdutch in my opinion, iDeal does constitute a payment source, maybe something like an IdealWallet, especially if there's any way of re-using an iDeal payment source for a future payment.

The payment interface class you're talking about exists already, it would be Spree::PaymentMethod.

@gmacdougall
Copy link
Member

Closing due to staleness

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

No branches or pull requests

4 participants