Problem/Motivation

#326269: Split payment method pack into multiple modules, #2183813: Make payment method plugins configurable, and #700270: Remove hook_uc_order('submit') as it is never called for redirected payment methods have one thing in common: the current payment API is not suffiently abstracted. This is nothing strange, as it is hard to decouple such things and building a properly abstracted API takes a lot of work. However, it does impose limitations and fixing or especially rewriting the current API would be a duplicate effort, seeing as there are alternatives among Drupal's contributed modules.

Proposed resolution

I suggest Ubercart's payment API is replaced with Payment 8.x-2.x, which can also already be used with Ubercart 7.x-3.x through Payment for Ubercart. This is a reusable payment processing platform that is fully object-oriented (and therefore easily maintainable, extensible, and testable) and integrates with many useful Drupal 8 features.

It solves #326269: Split payment method pack into multiple modules by explicitly stating that no payment method will ever be added to the 'core' package, except for the existing Basic payment method which does not depend on any third party services.

It solves #2183813: Make payment method plugins configurable by using two plugin types and an entity type. This ensures maximum flexibility and testability, allowing developers to write payment methods that are linked to their own systems, or that can be infinitely instantiated and configured from the user interface.

It solves #700270: Remove hook_uc_order('submit') as it is never called for redirected payment methods by not caring about how payment methods execute payments at all. This ensures that it doesn't accidentally limit a type of payment method that none of the maintainers would ever think of, but that may exist in other countries.

It also aims to centralize payment method development as much as possible by leveraging Drupal modules and external libraries (such as Omnipay and PaymentSuite) that contain APIs to connect with PSP services. This lightens the load on the developers, because they won't have to learn another third party web service's API anymore. It also means changes in those web services will be dealt with much more quickly, as less code will have to be maintained. This lets us develop our platforms with much more agility.

It supports, but does not require, complex workflows where payments go through different states or get different statuses before they are completed. It uses a few simple, but very powerful events (hooks and Symfony events for now, but Rules events will be added once Rules for Drupal 8 is done) to allow developers to customize the payment processing workflows.

It uses Currency 8.x-3.x for multicurrency support, and this goes a long way to fixing #1097668: Multicurrency support.

Remaining tasks

T.B.D.

User interface changes

  • Payment includes a dedicated payment overview at admin/content/payment
  • Payment method administration will no longer be part of Ubercarts administration pages, but can be found at admin/config/services/payment/method.
  • Payment method plugins implement PluginFormInterface, and as such any form elements that allow payers to enter payment-specific or payment-method-specific information (such as credit card numbers, or the bank they want to pay through) can be easily embedded into other forms with a few lines of code to instantiate payment method plugins and call the build, validate, and submit handlers.
  • Ubercart could even use the payment method selector plugins that come with Payment. It can also choose not to and provide its own, without compromising the payment processing workflow.

API changes

The entire Ubercart payment API will be replaced with Payment's.

Comments

xano’s picture

If anyone has any questions, such as whether particular features are supported or facilitated by Payment, I'd be happy to answer them.

xano’s picture

Issue summary: View changes
xano’s picture

Issue summary: View changes
longwave’s picture

#2621258: Decide on payment methods to ship with 8.x-4.x is very related to this. I outlined my biggest concerns there in #5; now that Payment basically needs Composer for install, I am wary of simply replacing the entire API with Payment as this means you cannot install Ubercart without using the command line. I would not be adverse to including Payment for Ubercart in core, for people who are happy with that route, though.

xano’s picture

The Composer debate is settling down, as more and more projects introduce Composer dependencies or are working on it. Examples include Drupal Commerce, Currency (and therefore Payment), and Rules. It's the way forward. We can either fight it and make our lives harder (because those Composer packages are really shiny), or work on making this as easy as possible for people with less technical experience.

There's been talk about providing UIs. I'm not sure what the current status on those is, but you can try asking @webflo, @tstoeckler, or @bojanz.

longwave’s picture

These two issues seem the most relevant, but it looks like we are still at the very beginning of discussions on how to help site builders out:

#2575747: Proposed workflow for Composer + module download on cheap hosting / FTP
#2622420: Site-builders should be able to use projects with composer dependencies

I understand entirely from a developer point of view that it's the way forward. That doesn't mean that it's going to be easy for non-developer types to use any time soon, which is where I like to think Ubercart is positioned in the Drupal marketplace.

xano’s picture

It's the developer types that integrate Ubercart with all the different payment and shipping services. Someone started porting Payment for Ubercart to Drupal 8, and I noticed Ubercart's payment API still uses hooks and (magic) callbacks. In a time of dependency injection and OOP code, it's going to be difficult integrating this with modern packages, resulting in the need for more custom code and higher maintenance requirements. Reusing modern packages relieves the pressure on developers and makes it easier to integrate the platform with other packages and services.

I'm sure tools will be developed to make Composer easier for people who are unable to use a CLI, but it's harder to update a platform like Ubercart to modern standards, especially once 4.0 has been released.

xano’s picture

Just as a reference: we're working on a handbook page to document the different ways of installing Composer dependencies of Drupal 8 modules.

longwave’s picture

Are there any working Payment methods for Drupal 8 yet, other than Basic? I didn't find any dev branches or even open issues for porting when I looked just now.

wizonesolutions’s picture

@longwave I'm planning to port Stripe Checkout to it this month. But I think the point is that you shouldn't have to care about the internals, and if you implement against Basic it will work against anything else implementing the API.

Anonymous’s picture

It has been a long time since I've chimed in on an Übercart issue... just adding my 2¢ that using Payment module will hopefully consolidate the duplicate efforts supporting payment gateways across different types of projects. Strongly in favor of this idea.

Anonymous’s picture

Re: #9... I'm planning to help wizonesolutions with stripe_checkout porting. I'm also working on an authorize.net sim/dpm Payment module.

longwave’s picture

I would still want to be able to do an end to end test with a real payment method, and I was wondering about how to handle the different kinds of flows - on site vs offsite redirect vs Express Checkout style etc.

xano’s picture

If you have such specific questions, just ask them and I'll be happy to provide you with detailed answers, although @Ryan Weal and @wizonesolutions may know these things by now as well.

Redirects are one of the nicer features: payment methods provide Symfony responses. Calling code can let those bubble up whenever they want. This means there are no forced redirects and interrupted requests, which are hard to test and prevent more complex workflows. PSPs redirect users back to a route controlled by the payment method. The payment method can then do whatever it wants, but ultimately it must return the response that is provided by the payment type, which is charged with resuming the user's original workflow.