Problem/Motivation

I want to port Commerce Custom Offline Payments module for Commerce 2.x.
But after a discussion with Bojan and Matt it seems we need to discuss first what should be done in Commerce 2.x Payment before implementing any Commerce Offline Payments.
So we need to define in Commerce Payments a way how the offline payments should be taken care of.
Also to investigate is this could or should be part of Commerce 2.x Payments or keep it as individual module.

Proposed resolution

The Commerce 1.x version was built as solution for Store that needs more than one offline payments, already existing modules

Easier implementation and maintenance + extra things available (all in one).

And it works:

  • Store administrators can create custom DISTINCT offline payments.
  • For every custom offline payment the store administrator can set the Title (& id), description of the payment method and also an information that could be used for payment option information.
  • The custom offline payments will automatically added as payment method, disabled or enabled, based on their status property.
  • With every custom offline payment defined the store administrators can create new Payment method Rules.
  • Features integration - The custom offline payments can be used as Features.
  • Drupal Commerce Payment Transaction Fields integration - Define fieldable payment to build extra data.
    Implementation issue : #2220197: Integration with Drupal Commerce Payment Transaction Fields.

For Commerce 2.x i imagine something similar,
+ :

  • Maybe some configs as title/label for the checkout of the payment gateway is something good to have for all the payments methods.
    Also about extra info that a Store admin could choose to display about the payment.
  • Maybe some more data needed the be configured for capturing.
  • What about refunding here?
  • Could we have offline payment without billing info profile data?
  • Payments Fields UI?

Open a GitHub repo for working on a version of this module
https://github.com/vasike/commerce_cop

User interface changes

Could be ToDo

API changes

Probably ToDo

Data model changes

Could be ToDo

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

vasike created an issue. See original summary.

vasike’s picture

vasike’s picture

First try of this module on GitHub
https://github.com/vasike/commerce_cop

I didn't keep the title config from D7 version, as the Payment gateway have the Name for this.

More Questions/discussions:
- What about capturing works, i assume it should do authorization only in the Checkout and Authorization & Capturing in the payment terminal
or Do we need some configs in the payment gateway?

- I think we need some fields for the payment here, but should we "force" them in the code, or maybe it's best to have the fields UI available for the offline payments
So maybe for a offline payment we need some data from Customer in the checkout
and maybe some data when i capture it in the terminal

- Is it Usual to have voids/refunds for those payments?
Should remove them or keep it as "options" in the gateway?

- What data should we use for Remote data (remote id/remote status)
Could be this related with defining fields for this payment?

- Expires date: should we use this? or make it not usable here.
If used : do we need a config in the Gateway (3days from now, 1 week from now, 1 month)?

There could be some other aspects, but i think this is it for now.

... Waiting for review and feedback

mattferderer’s picture

I would love to help get this up or at least a very simple version of this up and running soon. We're trying out Drupal Commerce 2 on a site & the only thing holding us back is the checkout functionality. For this use case, all the billing is done offline over e-mail anyways.

Please let me know if there is any way I can help, even if it is working with you & just writing up documentation. That benefits me in learning how to use it & others in learning what I am.

maciej.zgadzaj’s picture

maciej.zgadzaj’s picture

vasike’s picture

vasike’s picture

Status: Active » Needs review

About the importance of the Offline payments for Drupal Commerce (imho).

Here is a list of the most installed contrib modules.

More than 14,000 installs

Probably some others custom Offline payment are implemented in many Drupal commerce sites.

It looks like a second important payment method/gateway for Drupal Commerce.

Having this in mind, i want to share some thoughts (working on this)
The current payment system won't provide UI and Configs to extend the payments structure (payment methods & gateways).
So to have different solutions for Offline payments, we need to do it by defining new Offline Payment methods and new Payments types if needed for different Offline payments flows.

Which i think it's a "regression" from what it could be achieved in Commerce 1.x with Commerce Custom Offline Payments & Drupal Commerce Payment Transaction Fields

Berdir’s picture

I opened #2857064: Improve the handling of unknown gateway types in the PaymentProcess pane as a quick fix for this, fine with closing that as a duplicate or using it to get a first part of this working.

bojanz’s picture

Committed #2857064: Improve the handling of unknown gateway types in the PaymentProcess pane for now, this issue can change it once there's an actual OfflinePaymentGatewayInterface.

bojanz’s picture

It's time to discuss this. I've gone over the D7 modules and solutions in other systems.

We currently have two categories of payment gateways:
1) Onsite
2) Offsite
This issue needs to introduce a third category. The original idea was to call it "Offline", matching how D7 and many other systems call it, but the level of confusion between Offsite and Offline is large (I even managed to confuse berdir on IRC for a moment). So I propose that we follow Shopify's example and call it "Manual" instead.

The flow becomes:
1) User selects gateway (Check, Bank transfer, etc)
2) PaymentProcess calls $gateway->createPayment()
3) At checkout complete the payment instructions are shown.

We need:
1) HasPaymentInstructionsInterface that provides getPaymentInstructions() which is a renderable array
2) ManualPaymentGatewayInterface which extends HasPaymentInstructionsInterface
3) Modifications to the PaymentProcess and CompletionMessage checkout panes
4) The Manual payment gateway with a custom workflow (new/pending/completed/refunded/partially_refunded)

Notes / things to discuss:
1) Some solutions provide separate fields for each part of the bank transfer details (Account name, SWIFT, etc). This is not practical for us since these fields can vary from country to country. We'll need to provide a documentation link with examples below the "Payment Instructions" textbox (in gateway config), so that users know what to enter. I thought about introducing a child plugin that prefills the Payment instructions with a template, but it seems unnecessary for now.

2) When adding a payment gateway, it's confusing that Money order / Cash on delivery / Credit card on delivery / Pay in person / Check / Bank transfer are all handled by the same "Manual" gateway plugin. On the other hand, it doesn't feel right to expose separate options for what is essentially the same thing.

3) Checks are the only ones with special needs:
a) They often have a custom workflow: Check received -> Check deposited -> Check cleared
b) They sometimes have custom payment fields for the admin to fill out (Check date, Payee name)
I'd leave b) to custom code, but we could handle a) in Commerce, by providing a "Manual (Check)" plugin that defines a custom workflow. We need to see if there's demand first, probably by tracking it as a separate feature request.

bojanz’s picture

Title: Offline payments methods - Architecture & discussion » Implement manual payment gateways
Category: Plan » Feature request
Status: Needs review » Active
smccabe’s picture

Could we handle all the different manual types with just a type dropdown/radio/whatever on the manual option? Something like handling credit card type, it doesn't really do anything, but provides information to the admin, as the difference is important from a processing standpoint?

vasike’s picture

Assigned: Unassigned » vasike

working on.

Utilvideo’s picture

Ppl exist some "Commerce Cash on Delivery" module on D8 ?:) I need quick as posible this module to give client project in commerce, and i have 3 project in commerce, every where is the same problem, i dont have default module cash on delivery, not need payment online or system, i need just this simple module Cash on Delivery.

@vasike, then maybe will stable module realease commerce_cop?:)

vasike’s picture

Status: Active » Needs review

PR about this:
https://github.com/drupalcommerce/commerce/pull/672

For PATCH please use the diff link from PR
https://patch-diff.githubusercontent.com/raw/drupalcommerce/commerce/pul...

What's there
- New "Manual" payment method type
- New "Manual" payment type with new "Manual" payment workflow
- New "Manual" payment gateway that implements HasPaymentInstructionsInterface & SupportsManualWorkflowInterface within ManualPaymentGatewayBase
- New "PaymentInstructions" pane for gateways with HasPaymentInstructionsInterface that add "Instruction" to checkout complete
- HasPaymentInstructionsInterface used to add renderable array to PaymentInstructions pane
- SupportsManualWorkflowInterface : add operations for Payment with "Manual" workflow as completePayment & cancelPayment
- Manual gateways provides the posibility to set if the method is Reusable, Expires settings and Instructions
- On checkout this Manual payment gateway uses the "add-payment-method" - similar with On-site payment.
So "it's integrated there".
- Add tests for Manual payments admin UI (ManualPaymentAdminTest), admin Manual payment gateway UI (ManualPaymentGatewayTest), admin Manual payment method UI (ManualPaymentMethodTest) & Manual on checkout (ManualPaymentCheckoutTest)
- Others: some "fixes" for using isExpired vs. payment_method->getExpiresTime()

Questions:
- Reusable setting, this could be a setting for all.
Or a "Reusable option" for customer to choose if he want to "save" the payment method

- How this payment system could be extended with data (fields) easily - UI???.
Also with workflow?

- a Manual Check into Commerce Payment Example???

needs testing/review/feedback and all suggestions possible

Utilvideo’s picture

Custom Edited, forgot.

smaz’s picture

@vasike, I've just given this a quick test, against 8.2.x: It's not working for me. Perhaps I'm doing something wrong?

My requirements: Have a manual payment option of 'Bank Transfer / Cheque'. When chosen, it just needs to allow the user to complete the order - nothing else like capturing further details.

I've patched with the following: https://patch-diff.githubusercontent.com/raw/drupalcommerce/commerce/pul... (Attached for reference, as it will change with any further commits).

I have done the following:

  1. Created a new payment gateway
    • Named it: Bank Transfer / Cheque
    • Set the plugin to be 'Manual'
    • Did not select the 'Reusable' option
    • Not set an expiry
    • Entered 'Lorem ipsum' for the Instructions, so that I can see where it is displayed
  2. Added an item to my cart, then begun the checkout process
  3. note: I was not given an option to choose a payment gateway, as this is the only one
  4. Entered my billing details
  5. Was taken to the review step. On here, it had "Expires Never" - it would be better if it hid that, as that's a little confusing potentially? If the payment method was 'cash' for example, why would it show something about expiring?
  6. Clicked pay & complete purchase

At this point, it then errors & takes me back to the payment information step. The error I receive is:

Notice: Undefined variable: next_step_id in Drupal\commerce_payment\Plugin\Commerce\CheckoutPane\PaymentProcess->buildPaneForm() (line 195 of modules/contrib/commerce/modules/payment/src/Plugin/Commerce/CheckoutPane/PaymentProcess.php).
 

When I am back on the payment information step, I now have two options to choose from for the payment gateway - the one I created (Bank Transfer / Cheque), and 'New manual'. I cannot edit the billing information, I seem to have to choose the 'New manual' option to do that.

I also did not see the 'Lorem ipsum' Instructions value anywhere during the checkout.

Attached are the screenshots of the checkout process with everything described above.

Cheers

vasike’s picture

@smaz
thanks a lot for reviewing this.

1. First i want to ask you about the patch you attached - what there? is an updated patch for PR?
could you, please, provide a diff?

2.

6. Was taken to the review step. On here, it had "Expires Never" - it would be better if it hid that, as that's a little confusing potentially? If the payment method was 'cash' for example, why would it show something about expiring?

I know about this, let it intentionally as there could be some improvements for payment api

3. about the errors i need to check, maybe there were some updates on commerce 2 lately - that could affect

4.

the one I created (Bank Transfer / Cheque)

This is a payment method saved - which contains also the Billing information - for re-use.

5.

and 'New manual'.

This is actually about setting a new "Bank Transfer / Cheque" payment method and used it for the payment on checkout complete.

that would be all for now.
Thank you

i'm back on this to see how it works with the latest code.

vasike’s picture

@smaz

about the error:
Notice: Undefined variable: next_step_id in Drupal\commerce_payment\Plugin\Commerce\CheckoutPane\PaymentProcess->buildPaneForm() (line 195 of modules/contrib/commerce/modules/payment/src/Plugin/Commerce/CheckoutPane/PaymentProcess.php).

I think you're using an older version of commerce.

Could you, please, use the latest dev, before using the PR patch?
thank you

smaz’s picture

Apologies, I was using a slightly older version of commerce (ran composer install rather than composer update).

That has now fixed the error.

Responses to your points:

1) The patch is just your pull request, as of the latest commit to it (https://github.com/drupalcommerce/commerce/pull/672/commits/34563ccfa882...) -
no other changes. I attached it as a patch so we have it for reference,
as if you add changes to the PR it will update the patch github generates. It can be ignored :)

3) Yes, it was an outdated commerce.

4) Should you be able to edit this saved payment method, if you've not completed checkout yet (i.e. first time you check out)? If you enter your billing information, go to review, realise something is wrong & go back to edit your billing information, you can't - you'd have to choose the new option & fill in the details again. I'm not sure if that's core commerce or this PR though that needs to provide that.

Cheers

bojanz’s picture

4) Should you be able to edit this saved payment method, if you've not completed checkout yet (i.e. first time you check out)? If you enter your billing information, go to review, realise something is wrong & go back to edit your billing information, you can't - you'd have to choose the new option & fill in the details again. I'm not sure if that's core commerce or this PR though that needs to provide that.

It's theoretically not possible to edit saved payment methods, because they've been tokenized and no CC info was kept on the site, so there's nothing to edit. We could allow editing just the billing profile part of it though.

vasike’s picture

@bojanz: thanks for the support

as @smaz noticed, i also not happy about limitation of using the "create_label" annotation for the Payment method options in the Payment information checkout pane.

So i update the PR with a proposal to use the payment gateway for getCreateLabel() method, so we could use the payment gateway data (& configs) to set the needed Payment method option label.
Having this, i also update the Manual to use the payment gateway label defined.

For example for @smaz's example, we should have a "Bank Transfer / Cheque" option (instead of "New manual").

This is just a proposal, i think we could make some improvements there to ease the process of "labeling" the payments for the site builders/store managers.
Should we open a new (discussion) issue on this?

smaz’s picture

It's theoretically not possible to edit saved payment methods, because they've been tokenized and no CC info was kept on the site, so there's nothing to edit. We could allow editing just the billing profile part of it though.

I think editing the billing profile part may be a good idea, for at least the following 2 use cases:
* User entered details incorrectly
* Billing address has changed (i.e. user moved house, or company moved offices) but payment details remain the same.

vasike’s picture

@smaz : i agree, we need to have some editable data there in the checkout.
As customer notice in the review he put the wrong number/postal code/last name.
But i think this is other issue (feature request).

p.s. Usually to change address data we have the addressbook ;).

Utilvideo’s picture

Install Drupal 8.2 and module commerce-dev apply patch 672.patch

After Create product, add product to cart, and press checkout appear such error.

Recoverable fatal error: Argument 5 passed to Drupal\commerce_checkout\Plugin\Commerce\CheckoutPane\CheckoutPaneBase::__construct() must implement interface Drupal\Core\Entity\EntityTypeManagerInterface, none given, called in C:\wamp\www\d8commerce.dev\www\modules\commerce\modules\payment\src\Plugin\Commerce\CheckoutPane\PaymentInstructions.php on line 47

tested twice.

Same error if Commerce->Configuration->Checkout flows and edit . appear same error

vasike’s picture

---

vasike’s picture

i think it could be good to link this issue #2858179: Allow gateways to show text at checkout (in PaymentInformation)

Probably this is desired for Manual payment as extra feature

Utilvideo’s picture

---

Utilvideo’s picture

@vasike i agree with @smaz about

For example for @smaz's example, we should have a "Bank Transfer / Cheque" option (instead of "New manual").

In my example it will be good to be Pay on Delivery instead of "New manual"

Feature request add possibility add custom field. for example Bank Transfer user add additional data.

But this update is good, and many many thanks gays.

vasike’s picture

---

smaz’s picture

Hiding the patch I uploaded to prevent confusion.

As mentioned, to get the latest patch for the pull request use the following:

https://patch-diff.githubusercontent.com/raw/drupalcommerce/commerce/pul...

Utilvideo’s picture

Fixed use .diff

vasike’s picture

---

Utilvideo’s picture

Fixed use .diff

Utilvideo’s picture

Fixed use .diff

vasike’s picture

---

drugan’s picture

As for my experience I never use *.patch files on a PR, always *.diff. Documentation states they are basically the same but actually they are not. It may happen that you don't have some latest changes reflected in a *.patch file.

@Regnoy

Did you try .diff?

https://patch-diff.githubusercontent.com/raw/drupalcommerce/commerce/pul...

Utilvideo’s picture

I tried, right know .diff, work like a charm, sorry for flood, but i think some people will have same error, I will edited all my messages. I always worked with patches not diff.

Remove from all comments this link https://patch-diff.githubusercontent.com/raw/drupalcommerce/commerce/pul...

Thanks

smaz’s picture

vasike, I think the patch needs re-rolling against the latest commerce dev - I've just tried applying it against the latest dev release (2017-Apr-08):

patching file modules/payment_example/src/Plugin/Commerce/PaymentGateway/Onsite.php
Hunk #1 FAILED at 92.
1 out of 1 hunk FAILED -- saving rejects to file modules/payment_example/src/Plugin/Commerce/PaymentGateway/Onsite.php.rej
patching file modules/payment/src/Entity/PaymentMethod.php
Hunk #1 FAILED at 188.
1 out of 1 hunk FAILED -- saving rejects to file modules/payment/src/Entity/PaymentMethod.php.rej

Full output:

patching file modules/payment/commerce_payment.module
patching file modules/payment/commerce_payment.workflows.yml
patching file modules/payment/config/schema/commerce_payment.schema.yml
patching file modules/payment/src/PaymentMethodStorage.php
patching file modules/payment/src/Plugin/Commerce/CheckoutPane/PaymentInstructions.php
patching file modules/payment/src/Plugin/Commerce/CheckoutPane/PaymentProcess.php
Hunk #1 succeeded at 6 with fuzz 1 (offset -1 lines).
Hunk #2 succeeded at 102 (offset -44 lines).
Hunk #3 succeeded at 145 with fuzz 2 (offset -43 lines).
patching file modules/payment/src/Plugin/Commerce/PaymentGateway/HasPaymentInstructionsInterface.php
patching file modules/payment/src/Plugin/Commerce/PaymentGateway/Manual.php
patching file modules/payment/src/Plugin/Commerce/PaymentGateway/ManualPaymentGatewayBase.php
patching file modules/payment/src/Plugin/Commerce/PaymentGateway/ManualPaymentGatewayInterface.php
patching file modules/payment/src/Plugin/Commerce/PaymentGateway/PaymentGatewayBase.php
Hunk #2 succeeded at 246 (offset 11 lines).
Hunk #3 succeeded at 295 (offset 11 lines).
Hunk #4 succeeded at 324 (offset 11 lines).
patching file modules/payment/src/Plugin/Commerce/PaymentGateway/SupportsManualWorkflowInterface.php
patching file modules/payment/src/Plugin/Commerce/PaymentMethodType/Manual.php
patching file modules/payment/src/Plugin/Commerce/PaymentType/PaymentManual.php
patching file modules/payment/src/PluginForm/PaymentCancelForm.php
patching file modules/payment/src/PluginForm/PaymentCompleteForm.php
patching file modules/payment/src/PluginForm/PaymentMethodAddForm.php
patching file modules/payment/templates/commerce-payment-method.html.twig
patching file modules/payment_example/src/Plugin/Commerce/PaymentGateway/Onsite.php
Hunk #1 FAILED at 92.
1 out of 1 hunk FAILED -- saving rejects to file modules/payment_example/src/Plugin/Commerce/PaymentGateway/Onsite.php.rej
patching file modules/payment/src/Entity/PaymentMethod.php
Hunk #1 FAILED at 188.
1 out of 1 hunk FAILED -- saving rejects to file modules/payment/src/Entity/PaymentMethod.php.rej
patching file modules/payment/src/Plugin/Commerce/PaymentGateway/HasPaymentInstructionsInterface.php
patching file modules/payment/src/Plugin/Commerce/PaymentGateway/Manual.php
patching file modules/payment/src/Plugin/Commerce/PaymentGateway/ManualPaymentGatewayInterface.php
patching file modules/payment/src/Plugin/Commerce/CheckoutPane/PaymentProcess.php
Hunk #1 succeeded at 149 (offset -44 lines).
patching file modules/payment/src/Plugin/Commerce/PaymentGateway/Manual.php
patching file modules/payment/src/Plugin/Commerce/PaymentGateway/PaymentGatewayBase.php
Hunk #1 succeeded at 340 (offset 11 lines).
patching file modules/payment/tests/src/Functional/ManualPaymentAdminTest.php
patching file modules/payment/tests/src/Functional/ManualPaymentMethodTest.php
patching file modules/payment/tests/src/FunctionalJavascript/ManualPaymentCheckoutTest.php
patching file modules/payment/tests/src/Functional/ManualPaymentAdminTest.php
patching file modules/payment/tests/src/Functional/ManualPaymentMethodTest.php
patching file modules/payment/tests/src/FunctionalJavascript/ManualPaymentCheckoutTest.php
patching file modules/payment/src/Plugin/Commerce/CheckoutPane/PaymentInstructions.php
patching file modules/payment/tests/src/Functional/ManualPaymentAdminTest.php
patching file modules/payment/tests/src/Functional/ManualPaymentGatewayTest.php
patching file modules/payment/tests/src/FunctionalJavascript/ManualPaymentCheckoutTest.php
patching file modules/payment/src/Plugin/Commerce/CheckoutPane/PaymentInformation.php
patching file modules/payment/src/Plugin/Commerce/PaymentMethodType/Manual.php
patching file modules/payment/src/Plugin/Commerce/PaymentMethodType/PaymentMethodTypeBase.php
patching file modules/payment/src/Plugin/Commerce/PaymentMethodType/PaymentMethodTypeInterface.php
patching file modules/payment/tests/src/FunctionalJavascript/ManualPaymentCheckoutTest.php
patching file modules/payment/src/Plugin/Commerce/PaymentGateway/Manual.php
vasike’s picture

@smaz: are you sure, you're using a clean 8.x-2.x branch?
and the latest diff available.

The PR is updated with latest 8.x-2.x
And you can see at https://github.com/drupalcommerce/commerce/pull/672
This branch has no conflicts with the base branch
which means we're ok there.

smccabe’s picture

Note, PRs will merge in more intelligently than patches, so a PR can pass when a patch won't. Try applying the patch with '-3' as an option, which will attempt to do a 3 way merge one the patch.

git apply whatever.patch -3
Eric Heydrich’s picture

Works like a charm. Thanks for your work.

Utilvideo’s picture

Why is not release in new branch commerce ?:(((

Sebastien M.’s picture

Seems to be still in "Needs review".
Someone missed to change to "RBTC" ?

smaz’s picture

I've been using this for a few weeks now, and it appears to work fine - I've been using it to provide a Bank Transfer payment option.

I've just had the client raise an issue though (whilst writing this) that the payment method selection is a little confusing:

If you choose the Bank Transfer option, fill in your billing details & advance to the next step, if you then return to the payment method pane you have two (or more, depending on the number of payment gateways) options:

* Bank Transfer for Firstname Lastname (Address 1, City) -- selected by default
* Bank Transfer

The second option is the one for creating a new payment method. This is a little confusing - should we add 'New ' before this? i.e.

* Bank Transfer for Firstname Lastname (Address 1, City) -- selected by default
* New Bank Transfer

Apart from that, I've not come across any other issues. I don't think I could set it to RTBC though however, as I can't say from a code perspective / technical approach level, I guess that would need to be @bojanz?

smaz’s picture

One more issue I've just spotted:

If you have more than 1 manual gateway, (manual) gets appended to the end of each, which isn't needed? That may be commerce, rather than this PR though.

Multiple manual gateways

Londova’s picture

Hi,
Is there any chance to get these updates released?
How long it takes to review the modifications?

bojanz’s picture

Assigned: vasike » bojanz

@Londova
Wrapping up a a huge piece of functionality like this one can easily take a full day of work, or more.
Feature requests are not a review priority so it's normal for them to wait while more pressing work happens.

Assigning the issue to myself, since it's on my plate for next week.

bojanz’s picture

@@ -241,14 +246,27 @@ abstract class PaymentGatewayBase extends PluginBase implements PaymentGatewayIn
       return $payment_method_type->getLabel();
     }, $this->paymentMethodTypes);
 
-    $form['mode'] = [
-      '#type' => 'radios',
-      '#title' => $this->t('Mode'),
-      '#options' => $modes,
-      '#default_value' => $this->configuration['mode'],
-      '#required' => TRUE,
-      '#access' => !empty($modes),
-    ];
+    if (count($modes) > 1) {
+      // Ajax sometimes mixes up with modes.
+      if (!in_array($this->configuration['mode'], array_keys($modes))) {
+        $this->configuration = $this->defaultConfiguration();
+      }
+      $form['mode'] = [
+        '#type' => 'radios',
+        '#title' => $this->t('Mode'),
+        '#options' => $modes,
+        '#default_value' => $this->configuration['mode'],
+        '#required' => TRUE,
+        '#access' => !empty($modes),
+      ];
+    }
+    else {
+      $form['mode'] = [
+        '#type' => 'value',
+        '#value' => $this->configuration['mode'],
+      ];
+    }
+
     if (count($payment_method_types) > 1) {
       $form['payment_method_types'] = [
         '#type' => 'checkboxes',
@@ -277,7 +295,7 @@ abstract class PaymentGatewayBase extends PluginBase implements PaymentGatewayIn
    * {@inheritdoc}
    */
   public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
-    if (!$form_state->getErrors()) {
+    if (!$form_state->getErrors() && $form_state->isSubmitted()) {
+      $form['mode'] = [
+    if (count($modes) > 1) {
-      '#access' => !empty($modes),
-      '#access' => !empty($modes),
-    ];
+    if (count($modes) > 1) {
+      // Ajax sometimes mixes up with modes.
+      if (!in_array($this->configuration['mode'], array_keys($modes))) {
+        $this->configuration = $this->defaultConfiguration();
+      }
+      $form['mode'] = [
+        '#type' => 'radios',
+        '#title' => $this->t('Mode'),
+        '#options' => $modes,
+        '#default_value' => $this->configuration['mode'],
+        '#required' => TRUE,
+        '#access' => !empty($modes),
+      ];
+    }
+    else {
+      $form['mode'] = [
+        '#type' => 'value',
+        '#value' => $this->configuration['mode'],
+      ];
+    }
+
     if (count($payment_method_types) > 1) {
       $form['payment_method_types'] = [
         '#type' => 'checkboxes',
@@ -277,7 +295,7 @@ abstract class PaymentGatewayBase extends PluginBase implements PaymentGatewayIn
    * {@inheritdoc}
    */
   public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
-    if (!$form_state->getErrors()) {
+    if (!$form_state->getErrors() && $form_state->isSubmitted()) {
       $values = $form_state->getValue($form['#parents']);
       $values['payment_method_types'] = array_filter($values['payment_method_types']);
 

This looks like a fix unrelated to this issue. Removing it from the PR.
Can anyone explain what the problem was, so that we can spin it off into its own issue?

bojanz’s picture

Also extracted #2882136: Improve support for non-expiring payment methods. Manual payment gateways should not be creating or using payment methods.

vasike’s picture

@bojanz: i remember there was an issue about validation on change payment gateways (before submit) + customizing modes.

  • bojanz committed 753eabf on 8.x-2.x authored by vasike
    Issue #2828525 by vasike, bojanz: Implement manual payment gateways
    

  • bojanz committed 4c798e9 on 8.x-2.x
    Issue #2828525 followup: Replace payment_information with...
bojanz’s picture

Status: Needs review » Fixed

Did several iterations of the code, to reduce the size and make it more elegant.

Notable changes:
1) Payment methods are no longer used by this gateway. They were never supposed to be used in the first place.
2) Both manual and off-site gateways can now define a display_label, used at checkout.
3) Gateways can support voids without supporting authorizations (used instead of the initial Cancel code)
4) Payment instructions are integrated into the checkout completion message.

People who used the patch will need to delete the created payment gateway and any associated payment methods.
The associated payments should either be deleted or have their state names updated (completed -> received, canceled -> voided).

Utilvideo’s picture

Forgot....

Utilvideo’s picture

Can manual payment Live or Test? some how?

Londova’s picture

On order completion, the "Payment Instruction" is displayed on the screen but is NOT included in the email confirmation and is NOT saved into order details. Is this as intended or that need to be changed?

bojanz’s picture

@Londova
There's no reason to save it anywhere, it can be generated from scratch on each display.
It definitely makes sense to include it in the email, opened #2884497: Show payment instructions in the order receipt for that.

Agence Web CoherActio’s picture

Hi,

Would it be possible to push this functionality to a beta version of Commerce soon ?

Thanks

Laurent

bojanz’s picture

@Laurent_
An RC1 release should land this week.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

borisson_’s picture

I know that this might not show up on your radar @bojanz, because this issue is already closed. But I have a small problem related to this issue. It broke the Tests in commerce worldline; see #2890644: Fix test failures.


The problem seems to be that a non-js integration test doesn't have method to change the plugin trough the UI, making it post the configuration for the manual payment instead of my selected payment.

In facets, we have some similar form elements, where we change part of the form when the user selects a configuration option. One of those is the widgets.
Because that uses a button as well as ajax, we can post that button in the test - making it possible for non-js users/tests to submit the form with the correct information.

  $form['widget'] = [
      '#type' => 'radios',
      '#title' => $this->t('Widget'),
      '#description' => $this->t('The widget used for displaying this facet.'),
      '#options' => $widget_options,
      '#default_value' => $facet->getWidget()['type'],
      '#required' => TRUE,
      '#ajax' => [
        'trigger_as' => ['name' => 'widget_configure'],
        'callback' => '::buildAjaxWidgetConfigForm',
        'wrapper' => 'facets-widget-config-form',
        'method' => 'replace',
        'effect' => 'fade',
      ],
    ];
    $form['widget_config'] = [
      '#type' => 'container',
      '#attributes' => [
        'id' => 'facets-widget-config-form',
      ],
      '#tree' => TRUE,
    ];
    $form['widget_configure_button'] = [
      '#type' => 'submit',
      '#name' => 'widget_configure',
      '#value' => $this->t('Configure widget'),
      '#limit_validation_errors' => [['widget']],
      '#submit' => ['::submitAjaxWidgetConfigForm'],
      '#ajax' => [
        'callback' => '::buildAjaxWidgetConfigForm',
        'wrapper' => 'facets-widget-config-form',
      ],
      '#attributes' => ['class' => ['js-hide']],
    ];

I think that approach here would be a good idea as well. Otherwise, to have a valid configuration schema, I'd have to add the instructions to my own schema as well. This means that we'd have to follow very closely to any form / option changes to the manual form to make our own plugin function as expected.

    instructions:
      type: text_format
      label: 'Payment instructions'
      translatable: true

Would you like for me to open a new issue in the queue?

bojanz’s picture

FileSize
27.27 KB
zorax’s picture

Hello, Can you tell me if this module wiil be release soon ?
Do we need to patch the commerce module in dev version?
Doest it works with drupal 8.4 ?

Lukas von Blarer’s picture

This issue ist fixed.

GoempieK’s picture

I can see this issue is fixed, but where can we download the module?

Lukas von Blarer’s picture

This is in Commerce core in the commerce_payment module.