Problem/Motivation

When I place an order from my Drupal site, I can see the transaction in the Up2Pay backoffice (called Vision Air), and there is a data called Reference Commande (Order reference in english) which is supposed to map the transaction with an entity from the merchant (Drupal in our case) site.
The entity referenced here is the Payment, which is totally understandable, as an order could have several payment, but I would like to have the two informations : order id AND payment id.

Steps to reproduce

Place an order and pay it using Paybox gateway payment, check in Vision Air backoffice (available for Up2Pay, not sure for anoter Paybox solution).
Check the Commande Reference column

Proposed resolution

Alter request() implementation in src/Plugin/Commerce/PaymentGateway/Paybox.php to use both order id and payment id, and separate them with a separator.
A good idea would be to have this separator part of the payment gateway config. We would have the possibility to choose wheter we want order id, payment id, or both, and then select a separator if both.

Remaining tasks

User interface changes

API changes

Data model changes

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

OwilliwO created an issue. See original summary.

owilliwo’s picture

Title: Send order ID and payment ID to Paybox/Up2Pay » Send order ID and/or payment ID to Paybox/Up2Pay (admin choice)

anthonychoosit made their first commit to this issue’s fork.

adelgado12’s picture

Status: Active » Needs review
owilliwo’s picture

I've been looking further in the code, and this PBX_CMD is sent back to Drupal through a callback, to validate or not the payment entity once payment is processed on Paybox side. To do so, payment ID is mandatory.
It's a bit more complicated than I expected at first, as we need to handle this return in 3 different parts.

I've tried to serialize() or json_encode() an array to send both payment and order ids, then extract the data using unserialize() or json_decode(), but it's not working for now.
I'm able to load the payment entity on the callback, but it's the signature check which is failing..

\Drupal\commerce_paybox_payment\Plugin\Commerce\PaymentGateway\Paybox::onReturn

    if (!$payment instanceof PaymentInterface) {
      \Drupal::logger('commerce_paybox_payment')->debug('Check instanceof PaymentInterface failed');
      throw new PaymentGatewayException('Payment cannot be found');
    }

Exception message should be more explicit also.

If anybody has an advice.
I'll keep trying on my side.

owilliwo’s picture

OK, it seems that signature is not checkable or so based on some special characters. So I've restricted the separator option to - and _ only.
Seems OK so far.

My concern is on the API side.
payment_return.access_checker service and the API controller: they both get the Ref data from the request, but as payment has not been loaded at this point, I'm wondering how I'd be able to load the gateway config to know how to process this Ref data ?
Any lead ?

Also, di you have an example of where/how this API part code is used ?

adelgado12’s picture

I took the method 'GetPaymentID' on AccessCheck Service to get payment id from ref request.
It works fine on my test, payment is correctly loaded.
What bothers me, that the way to get payment gateway configuration.
I load the different gateways available and take the first 'paybox' plugin, but if we have many payment gateway using paybox plugin with different configuration, that will be a problem. But i'm not sure that a case which oftens happens

owilliwo’s picture

That's one way to get this plugin config. But as you said, it would be safe only if there is only one Paybox payment gateway.

What about this : storing these two options in a global config for commerce_paybox_payment module, by modifying a bit the plugin config form build and submit methods.

  • Pro: it would be accessible even if we don't know about current payment.
  • Con: if user decides to set up 2 paybox gateways or more, they would all have the same config for this PBX_CMD / Ref mapping & separator setting.
owilliwo’s picture

OK, I ve just pushed a another commit to make mapping and separator config global, using config_factory.
So you don't get to load all paybox gateway to get config in the accessChecker.

Though, I still have some questions :

  • why do you need to set the Ref at the end of the \Drupal\commerce_paybox_payment\Access\PaymentReturnAccessCheck::access method() ?
  • what about the \Drupal\commerce_paybox_payment\Controller\PaymentController::return() method ? It's still getting the payment id directly from "Ref", without any processing..

I think the better way would be to have a service PbxCmdRefHelper or similar, providing two methods:

  • one to build PBX_CMD value to post it
  • one to process Ref value from request

We could use this service in both 3 classes :

  • \Drupal\commerce_paybox_payment\Plugin\Commerce\PaymentGateway\Paybox
  • \Drupal\commerce_paybox_payment\Access\PaymentReturnAccessCheck
  • \Drupal\commerce_paybox_payment\Controller\PaymentController
adelgado12’s picture

yes, good idea for the service that may be used by controller, access check and payment gateway and global config
In case on server return, we don't pass by onreturn method in payment gateway, common service will avoid duplicate lines codes.
Maybe, we should add note in readme to explain if user want to have many paybox payment gateway (it won"t happen very often but in case). the different payment gateways have to use same separator

owilliwo’s picture

Service is provided and instanciated in the 3 classes as we were discussing last week.
I've also add a mention about global config for entity mapping and separator, in the README file.

adelgado12’s picture

Thank a lot @owilliwo

I have test payment with two separator, each by web return and api return and it works in all time :)

If it's ok to you too, i think we can merge ;

owilliwo’s picture

Status: Needs review » Reviewed & tested by the community

OK for me.
All the tests I've been running manually were also OK.

adelgado12’s picture

Status: Reviewed & tested by the community » Patch (to be ported)
owilliwo’s picture

Hey !
Not that I want to re-open this issue, but I've figured out a way to get the payment id without having to get a global config for the separator and so..
To implement a manual payment from admin UI, I've created routes for Paybox callback, including both order and payment as parameters.
Something like that could be applied to the gateway method onReturn and onCancel. Not sure though, as I'm not sure of the route those two methods "answer" ?
And also for the IPN return callback (definitely, as it is a custom route)

Any thoughts ?

adelgado12’s picture

Hello, I would like to be sure I understand.
The initial goal was to send the order ID to Paybox to have it in the interface in addition to the payment ID. I don't see how we can retrieve the payment id if it is not sent or it is sent via another variable than `PXB_CMD`?

owilliwo’s picture

Actually, I think I was missing something.
Routes that are using onReturn and onCancel methods (also onNotify) are not custom routes, and payment ID is definitely not including as route parameters. So my last idea is not applicable in that case. Just nevermind ;)

---------

Though, there is one thing I read in the Drupal Commerce doc, making me wondering: why are you creating the payment entity before going to the offsite payment form.
It is definitely not recommended by Drupal Commerce documentation : https://docs.drupalcommerce.org/commerce2/developer-guide/payments/creat...

Maybe we should open a new issue/thread to discuss that matter instead of polluting this one, which is closed.

adelgado12’s picture

Status: Patch (to be ported) » Fixed

Status: Fixed » Closed (fixed)

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