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

Return to payment step if payment failed. #817

Merged
merged 4 commits into from
Jan 30, 2014

Conversation

kayue
Copy link
Contributor

@kayue kayue commented Jan 11, 2014

Related to #811.

);

// Complete checkout if payment success
if ($status->isSuccess()) {
Copy link
Contributor Author

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.

Copy link
Contributor

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.

@makasim
Copy link
Contributor

makasim commented Jan 14, 2014

Since other checkout events are all using GenericEvent, in order to be able to set Response to the event, so I guess I have to create a new event Sylius\Bundle\PayumBundle\Event\ResponseEvent that extend GenericEvent.

I think the event class has to be PurchaseCompleteEvent and has to be stored in core bundle. ResponseEvent in payum names looks weird.

Should we pass PurchaseStep ($this) as a argument to the event, so people can call $step->complete() in event listener?

I would not pass it, but maybe cannot proceed without it? I dont know.

@kepeket
Copy link

kepeket commented Jan 24, 2014

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.

@docteurklein
Copy link
Contributor

Like said in #811, it should be configurable.
There are so much possible flows we can't even think about, but that sylius users will have to implement :)

Vespolina, in its early stages, tried to resolve this by using a workflow framework at the core of the step process.
Currently, every user could override some parts of the steps by extending or replacing the PurchaseStep service.

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.

@pjedrzejewski
Copy link
Member

@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.

@kepeket
Copy link

kepeket commented Jan 24, 2014

@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.

@pjedrzejewski
Copy link
Member

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.

@docteurklein
Copy link
Contributor

oh sorry, that's indeed the kind of customisation I was talking about. Sorry for the noise.

@umpirsky
Copy link
Contributor

@kayue @makasim @pjedrzejewski Please check this PR now. I am ready to push this forward until it is merged.

@umpirsky
Copy link
Contributor

PurchaseStep specs are on my todo list.

@@ -0,0 +1,35 @@
<?php

namespace Sylius\Bundle\CoreBundle\EventListener;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing license.

@stloyd
Copy link
Contributor

stloyd commented Jan 28, 2014

Skipping those few comments it's 👍 =)

{
$status = $event->getArgument('status');

if ($status->isSuccess() || $status->isPending()) {
Copy link
Contributor

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?

Copy link
Contributor

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

Copy link
Contributor

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.

Copy link
Contributor

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.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then it`s ok

Copy link
Contributor

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 and POST_PURCHASE events in SyliusCheckoutEvents (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?

@makasim
Copy link
Contributor

makasim commented Jan 28, 2014

also some methods missed docblocks

@umpirsky
Copy link
Contributor

@makasim That was intentional. cc @pjedrzejewski

@makasim
Copy link
Contributor

makasim commented Jan 28, 2014

in general this approach looks good to me

@umpirsky
Copy link
Contributor

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" />
Copy link
Contributor

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

Copy link
Contributor

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?

@umpirsky
Copy link
Contributor

Fixed comments. Ready for 2nd review. Will fix specs now...


namespace Sylius\Bundle\PayumBundle\Checkout;

final class SyliusCheckoutEvents
Copy link
Contributor

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.

@pjedrzejewski
Copy link
Member

I'm lost in this amount of comments and new github UI. Kinda weird. :/

@umpirsky
Copy link
Contributor

Fixed specs, reabasing...

@pjedrzejewski
Copy link
Member

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...

@umpirsky
Copy link
Contributor

Rebased. Ready for final review.

@pjedrzejewski Hehum, yes, I think it will.

}

$event->setResponse(new RedirectResponse(
$this->router->generate('sylius_checkout_payment')
Copy link
Contributor

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?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

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. :)

@umpirsky
Copy link
Contributor

@pjedrzejewski Good to be merged?

@pjedrzejewski
Copy link
Member

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. :)

@winzou
Copy link
Contributor

winzou commented Jan 29, 2014

@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.

@pjedrzejewski
Copy link
Member

@winzou That's my point, it should be fine, but we need to check it.

@umpirsky
Copy link
Contributor

@pjedrzejewski Piiing :)

@kayue
Copy link
Contributor Author

kayue commented Jan 30, 2014

Ping @pjedrzejewski

@stloyd
Copy link
Contributor

stloyd commented Jan 30, 2014

@umpirsky This needs to be rebased.

@pjedrzejewski
Copy link
Member

I tested it and it works fine, just please rebase it and we're good to merge.

@umpirsky
Copy link
Contributor

@pjedrzejewski @stloyd Rebased.

@pjedrzejewski
Copy link
Member

Waiting for travis.

pjedrzejewski pushed a commit that referenced this pull request Jan 30, 2014
Return to payment step if payment failed.
@pjedrzejewski pjedrzejewski merged commit b689f5d into Sylius:master Jan 30, 2014
@pjedrzejewski
Copy link
Member

Thanks guys! 👍

@umpirsky umpirsky deleted the feature/failure-payment-flow branch January 30, 2014 23:05
@umpirsky
Copy link
Contributor

@pjedrzejewski Thanks for merging it. Please check my other PRs when you find some time.

@winzou
Copy link
Contributor

winzou commented Jan 31, 2014

@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)

@umpirsky
Copy link
Contributor

@winzou Have sense. Will do it in separate PR. Thanks.

@umpirsky
Copy link
Contributor

@winzou @pjedrzejewski #953

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement Minor issues and PRs improving the current solutions (optimizations, typo fixes, etc.).
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

10 participants