-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
Return to payment step if payment failed. #817
Return to payment step if payment failed. #817
Conversation
); | ||
|
||
// Complete checkout if payment success | ||
if ($status->isSuccess()) { |
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.
@makasim Should we consider pending payment as a "success" payment here?
Because PayPal payment doesn't go through imminently (wait for IPN), I don't know does Payum mark those payment as success or pending.
Thank you.
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.
I would treat pending here as success too. because if user redirected to payment step again and his first payment accepter (the one which is pending) he would end up with two payments.
I think the event class has to be
I would not pass it, but maybe cannot proceed without it? I dont know. |
To add to to that, I think that the Cart should not be cleared to soon during the PurchaseStep. See public function forwardAction(ProcessContextInterface $context)
{
$token = $this->getHttpRequestVerifier()->verify($this->getRequest());
$this->getHttpRequestVerifier()->invalidate($token);
$this->getCartProvider()->abandonCart();
$status = new StatusRequest($token);
$this->getPayum()->getPayment($token->getPaymentName())->execute($status); the getCartProvider()->abandonCart() should only occur if the payment has been successful IMHO. |
Like said in #811, it should be configurable. Vespolina, in its early stages, tried to resolve this by using a workflow framework at the core of the step process. There could be a more offical way by using the strategy pattern or something (similar to this finally), but simpler to hook in, and normalized. This way, there is no hardcoded default checkout process flow, just a default strategy provided by sylius. |
@docteurklein This is how it works now, SyliusFlowBundle allows various different flows (including non-linear processes), what we are evaluating here is the default, most common checkout flow. In my projects I sometimes had 2-3 different checkout flows, built using the same steps, provided by Sylius. Of course, they have to appear in some logical order if one steps requires some information which is provided in other step. If you look at - https://github.com/Sylius/Sylius/blob/master/src/Sylius/Bundle/CoreBundle/Checkout/CheckoutProcessScenario.php#L46 - It's kind of process builder (ala forms), you can construct the flow dynamically ... and so on. It's pretty flexible, not sure if we can call it workflow framework, but it is something similar. We use it for both checkout & installer. What we could do is to make it easier to configure this, maybe we could load the steps from configuration file. Right now if you want to change the flow, you have to override this class. |
@docteurklein if it has to be configurable, the better would be to use the service tag system, to dynamically register steps. Then we would call on each class a getPosition method, that whould return an int, somehow ordering the classes. That would be easy to insert a step into a basic workflow. |
Steps are registered via tags, just like form types so I think some kind of configuration file where you define various flows using these step names would be awesome. Instead of the requirement to create new process class. |
oh sorry, that's indeed the kind of customisation I was talking about. Sorry for the noise. |
@kayue @makasim @pjedrzejewski Please check this PR now. I am ready to push this forward until it is merged. |
PurchaseStep specs are on my todo list. |
@@ -0,0 +1,35 @@ | |||
<?php | |||
|
|||
namespace Sylius\Bundle\CoreBundle\EventListener; |
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.
Missing license.
Skipping those few comments it's 👍 =) |
{ | ||
$status = $event->getArgument('status'); | ||
|
||
if ($status->isSuccess() || $status->isPending()) { |
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.
This introduce dependency on StatusRequestInterface
from payum. So maybe this listener has to be moved to sylius payum bundle?
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.
or maybe we can just pass PaymentInterface
constant and you it in if
statement
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.
No, as this would add dependency on CartBundle
for PayumBundle
which is not needed, also CoreBundle
already depends on PayumBundle
so it's ok with this dependency.
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.
Plus redirect to sylius_checkout_payment
, which is core again.
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.
then it`s ok
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.
I disagree. Here is what I have in mind:
- We add
PRE_PURCHASE
andPOST_PURCHASE
events inSyliusCheckoutEvents
(not in sylius_payum_*) - We pass $payment to it (which is actually already done)
- Then we keep this listener in
CoreBundle
and look at the status of the payment ($payment = $event->getSubject()
)
So that everything is clean, and we don't mix core and payum. What do you think?
also some methods missed docblocks |
@makasim That was intentional. cc @pjedrzejewski |
in general this approach looks good to me |
Thanks guys, will fix comments, polish and fix specs... |
<service id="sylius.listener.purchase" class="%sylius.listener.purchase.class%"> | ||
<argument type="service" id="sylius.cart_provider" /> | ||
<argument type="service" id="router" /> | ||
<tag name="kernel.event_listener" event="sylius.payum.post_purchase_step" method="onPostPurchaseStep" /> |
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.
why not event subscriber? asking just out of curiosity
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.
I inherited this code, so it was nobrainer. But as we dont change the events listener is registered for at runtime, I do not see any advantage of subscriber. Do you?
Fixed comments. Ready for 2nd review. Will fix specs now... |
|
||
namespace Sylius\Bundle\PayumBundle\Checkout; | ||
|
||
final class SyliusCheckoutEvents |
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.
There is already a SyliusCheckoutEvents in CoreBundle, I think you should use it instead of creating a new one. Purchase step is not specific to payum, only its implementation is. So the event (which is dispatched with payum or with anything else) should live in Core.
I'm lost in this amount of comments and new github UI. Kinda weird. :/ |
Fixed specs, reabasing... |
Am I missing something or this will go through the finalize step again if the payment fails? I am wondering about the implications of that... |
Rebased. Ready for final review. @pjedrzejewski Hehum, yes, I think it will. |
} | ||
|
||
$event->setResponse(new RedirectResponse( | ||
$this->router->generate('sylius_checkout_payment') |
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.
should the route name be configurable?
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.
Maybe. @pjedrzejewski @stloyd @winzou ?
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.
Yeah, but let's do it when I'll rework the flow bundle a bit. :)
@pjedrzejewski Good to be merged? |
Let's wait for travis and I want to test it myself to verify there is no harm in going through finalize step more than once. Sounds suspicious to me. :) |
@pjedrzejewski if there is an issue then we should fix it, but going twice (or even more) through the finalize step must not be an issue. |
@winzou That's my point, it should be fine, but we need to check it. |
@pjedrzejewski Piiing :) |
Ping @pjedrzejewski |
@umpirsky This needs to be rebased. |
I tested it and it works fine, just please rebase it and we're good to merge. |
@pjedrzejewski @stloyd Rebased. |
Waiting for travis. |
Return to payment step if payment failed.
Thanks guys! 👍 |
@pjedrzejewski Thanks for merging it. Please check my other PRs when you find some time. |
@umpirsky @pjedrzejewski the flash message should not be set in the same method as the abandon cart, because we cannot reuse it if we don't want flashes... Can you trigger it separately? (set the method to public and add it to listen an event from the config) |
@winzou Have sense. Will do it in separate PR. Thanks. |
Related to #811.