3

I'm trying to truncate Django-Oscar's checkout flow. Assuming we start in basket/cart, the default flow looks like this:

  1. User clicks on "Proceed to checkout" button
  2. PaymentMethodView is called
  3. 'payment-details' page loads
  4. User clicks on "Continue"
  5. Oscar's 'preview' loads. User clicks on "Place order" and purchases the item
  6. User is sent to Oscar's 'thank-you' page and receives an email confirmation

I want this instead:

  1. "Proceed to checkout" button is replaced with PayPal Checkout Express client-side checkout.js button
  2. User clicks on PayPal button and pays
  3. User is sent to Oscar's 'thank-you' page and receives an email confirmation

The problem is this: the PayPal button works and payments come through successfully every time but, Oscar alternately sends the user to the 'payment-details' page and the 'thank-you' page after payment. To be clear:

  1. User buys an item, and is sent to 'thank-you' page and gets an email
  2. User buys another item, is sent to 'payment-details' page and does not get an email, and Oscar does not register the purchase even though the payment comes through
  3. User buys a third item and experiences Oscar's response in step 1
  4. User buys a fourth item and experiences Oscar's response in step 2
  5. And so ad infinitum

All urls, views, and models, worked perfectly up to this point. The only thing I'd done at this point was replace the "Proceed to checkout" button with PayPal's button.

I then removed the PayPal button, and restored the "Proceed to checkout" button, but with one edit. The button looks like this: <a href="{% url 'checkout:index' %}" class="...">{% trans "Proceed to checkout" %}</a>.

I replaced 'checkout:index' with 'checkout:preview' to see if I could skip the 'payment-details' page. The alternating situation continued. Oscar sent users to the 'preview' page first, and on the next turn it sent users to the 'payment-details' page.

I also tried overriding PaymentMethodView:

from oscar.apps.checkout.views import PaymentMethodView as BasePaymentMethodView
from django.shortcuts import redirect

class PaymentMethodView(BasePaymentMethodView):

    def get_success_response(self):
        return redirect('thank-you')

The alternating between the 'payment-details' and 'thank-you' pages remained.

I'm out of ideas. What could have have gone wrong?

nusantara
  • 1,109
  • 1
  • 15
  • 38
  • So you have overridden the `checkout.views.IndexView` right? Can you show your (redacted) source for that? Also, it might be worth looking into that your `basket` (whose `id` is used for `order_number`) is not being handled properly (freeze / unfreeze / reset) after payment success / failure. Can't say anything unless you show your `PaymentDetailsView` or your `IndexView` customizations. – shad0w_wa1k3r Apr 17 '18 at 08:48
  • @AshishNitinPatil I didn't override IndexView and PaymentDetailsView. I did play with PaymentDetailsView for just a tiny bit but I put it back to default. I'll look into the basket and see how it goes. Thanks! – nusantara Apr 17 '18 at 09:57
  • Strange, then I'm not sure how you are handling the almost single-page checkout. Anyway, the basket issue will definitely throw an error, so, unless you are seeing errors, you shouldn't really worry about that. – shad0w_wa1k3r Apr 17 '18 at 10:04

1 Answers1

2

The checkout views make use of skip_conditions and pre_conditions properties to determine which view to show, and all views implement a get_pre_conditions() and get_skip_conditions() method which you can use to change the default behaviour. So probably some of these pre_conditions is not met after purchasing an item.

There also is a PassedSkipCondition and FailedPreCondition exception which you can use for redirection.

I will show you how I handle a similar situation. The below method is from my custom PaymentDetailsView, where I override skip_unless_payment_is_required. My webshop has a manual pickup options, where the customer can place an order but only pays upon pickup. So I raise a PassedSkipCondition exception to force the customer over to the preview page.

def skip_unless_payment_is_required(self, request):
    # Check to see if payment is actually required for this order.
    shipping_address = self.get_shipping_address(request.basket)
    shipping_method = self.get_shipping_method(request.basket, shipping_address)

    if shipping_method:
        shipping_charge = shipping_method.calculate(request.basket)

        # CUSTOMER WILL MANUALLY PICKUP ITEMS, SO SKIP PAYMENT DETAILS PAGE!
        if shipping_method.code == 'MANUAL_PICKUP':
            raise exceptions.PassedSkipCondition(url=reverse('checkout:preview'))

    else:
        ... 
dentemm
  • 6,231
  • 3
  • 31
  • 43