Commit b5264bd5 by Joyce Zhu

Implement new checkout error page (moved from LMS)

Replaces LMS commerce error page.

SOL-1946
parent 46a3964a
...@@ -6,11 +6,13 @@ from oscar.core.loading import get_class ...@@ -6,11 +6,13 @@ from oscar.core.loading import get_class
class CheckoutApplication(app.CheckoutApplication): class CheckoutApplication(app.CheckoutApplication):
free_checkout = get_class('checkout.views', 'FreeCheckoutView') free_checkout = get_class('checkout.views', 'FreeCheckoutView')
cancel_checkout = get_class('checkout.views', 'CancelCheckoutView') cancel_checkout = get_class('checkout.views', 'CancelCheckoutView')
checkout_error = get_class('checkout.views', 'CheckoutErrorView')
def get_urls(self): def get_urls(self):
urls = [ urls = [
url(r'^free-checkout/$', self.free_checkout.as_view(), name='free-checkout'), url(r'^free-checkout/$', self.free_checkout.as_view(), name='free-checkout'),
url(r'^cancel-checkout/$', self.cancel_checkout.as_view(), name='cancel-checkout'), url(r'^cancel-checkout/$', self.cancel_checkout.as_view(), name='cancel-checkout'),
url(r'^error/', self.checkout_error.as_view(), name='error'),
url(r'^$', self.index_view.as_view(), name='index'), url(r'^$', self.index_view.as_view(), name='index'),
......
...@@ -88,3 +88,37 @@ class CancelCheckoutViewTests(TestCase): ...@@ -88,3 +88,37 @@ class CancelCheckoutViewTests(TestCase):
self.assertEqual( self.assertEqual(
response.context['payment_support_email'], self.request.site.siteconfiguration.payment_support_email response.context['payment_support_email'], self.request.site.siteconfiguration.payment_support_email
) )
class CheckoutErrorViewTests(TestCase):
""" CheckoutErrorView view tests. """
path = reverse('checkout:error')
def setUp(self):
super(CheckoutErrorViewTests, self).setUp()
self.user = self.create_user()
self.client.login(username=self.user.username, password=self.password)
@httpretty.activate
def test_get_returns_payment_support_email_in_context(self):
"""
Verify that after receiving a GET response, the view returns a payment support email in its context.
"""
response = self.client.get(self.path)
self.assertEqual(response.status_code, 200)
self.assertEqual(
response.context['payment_support_email'], self.request.site.siteconfiguration.payment_support_email
)
@httpretty.activate
def test_post_returns_payment_support_email_in_context(self):
"""
Verify that after receiving a POST response, the view returns a payment support email in its context.
"""
post_data = {'decision': 'CANCEL', 'reason_code': '200', 'signed_field_names': 'dummy'}
response = self.client.post(self.path, data=post_data)
self.assertEqual(response.status_code, 200)
self.assertEqual(
response.context['payment_support_email'], self.request.site.siteconfiguration.payment_support_email
)
...@@ -56,20 +56,23 @@ class FreeCheckoutView(EdxOrderPlacementMixin, RedirectView): ...@@ -56,20 +56,23 @@ class FreeCheckoutView(EdxOrderPlacementMixin, RedirectView):
class CancelCheckoutView(TemplateView): class CancelCheckoutView(TemplateView):
""" Displays a cancellation message when the customer cancels checkout on the payment processor page. """ """
Displays a cancellation message when the customer cancels checkout on the
payment processor page.
"""
template_name = 'checkout/cancel_checkout.html' template_name = 'checkout/cancel_checkout.html'
@method_decorator(csrf_exempt) @method_decorator(csrf_exempt)
def dispatch(self, *args, **kwargs): def dispatch(self, *args, **kwargs):
""" """
Request needs to be csrf_exempt so CyberSource can POST back to page. Request needs to be csrf_exempt to handle POST back from external payment processor.
""" """
return super(CancelCheckoutView, self).dispatch(*args, **kwargs) return super(CancelCheckoutView, self).dispatch(*args, **kwargs)
def post(self, request, *args, **kwargs): # pylint: disable=unused-argument def post(self, request, *args, **kwargs): # pylint: disable=unused-argument
""" """
Handle CyberSource's post back. Allow POST responses from payment processors and just render the cancel page..
""" """
context = self.get_context_data(**kwargs) context = self.get_context_data(**kwargs)
return self.render_to_response(context) return self.render_to_response(context)
...@@ -80,3 +83,30 @@ class CancelCheckoutView(TemplateView): ...@@ -80,3 +83,30 @@ class CancelCheckoutView(TemplateView):
'payment_support_email': self.request.site.siteconfiguration.payment_support_email, 'payment_support_email': self.request.site.siteconfiguration.payment_support_email,
}) })
return context return context
class CheckoutErrorView(TemplateView):
""" Displays an error page when checkout does not complete successfully. """
template_name = 'checkout/error.html'
@method_decorator(csrf_exempt)
def dispatch(self, *args, **kwargs):
"""
Request needs to be csrf_exempt to handle POST back from external payment processor.
"""
return super(CheckoutErrorView, self).dispatch(*args, **kwargs)
def post(self, request, *args, **kwargs): # pylint: disable=unused-argument
"""
Allow POST responses from payment processors and just render the error page.
"""
context = self.get_context_data(**kwargs)
return self.render_to_response(context)
def get_context_data(self, **kwargs):
context = super(CheckoutErrorView, self).get_context_data(**kwargs)
context.update({
'payment_support_email': self.request.site.siteconfiguration.payment_support_email,
})
return context
...@@ -69,7 +69,7 @@ class Paypal(BasePaymentProcessor): ...@@ -69,7 +69,7 @@ class Paypal(BasePaymentProcessor):
@property @property
def error_url(self): def error_url(self):
return get_lms_url(self.configuration['error_path']) return get_ecommerce_url(self.configuration['error_path'])
def get_transaction_parameters(self, basket, request=None): def get_transaction_parameters(self, basket, request=None):
""" """
......
...@@ -106,7 +106,7 @@ PAYMENT_PROCESSORS = ( ...@@ -106,7 +106,7 @@ PAYMENT_PROCESSORS = (
PAYMENT_PROCESSOR_RECEIPT_PATH = '/commerce/checkout/receipt/' PAYMENT_PROCESSOR_RECEIPT_PATH = '/commerce/checkout/receipt/'
PAYMENT_PROCESSOR_CANCEL_PATH = '/checkout/cancel-checkout/' PAYMENT_PROCESSOR_CANCEL_PATH = '/checkout/cancel-checkout/'
PAYMENT_PROCESSOR_ERROR_PATH = '/commerce/checkout/error/' PAYMENT_PROCESSOR_ERROR_PATH = '/checkout/error/'
PAYMENT_PROCESSOR_CONFIG = { PAYMENT_PROCESSOR_CONFIG = {
'edx': { 'edx': {
......
{% extends 'edx/base.html' %}
{% load i18n %}
{% load staticfiles %}
{% block title %}
{% trans "Checkout Error" %}
{% endblock title %}
{% block navbar %}
{% include 'edx/partials/_student_navbar.html' %}
{% endblock navbar %}
{% block content %}
<div class="container content-wrapper receipt-cancel-error">
<h1>{% trans "Checkout Error" %}</h1>
<p>{% blocktrans %} An error has occurred with your payment. <b>You have not been charged.</b>
{% endblocktrans %}</p>
<p>{% with "<a class='nav-link' href='mailto:"|add:payment_support_email|add:"'>"|safe as start_link %}
{% blocktrans with end_link="</a>"|safe %}
Please try to submit your payment again. If this problem persists, contact {{ start_link }}
{{ payment_support_email }}{{ end_link }}.
{% endblocktrans %}
{% endwith %}</p>
</div>
{% endblock content %}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment