Commit 4e7f0f73 by jsa

Move payment processor list endpoint to api/

XCOM-211
parent 541d5b35
...@@ -64,3 +64,11 @@ class OrderSerializer(serializers.Serializer): ...@@ -64,3 +64,11 @@ class OrderSerializer(serializers.Serializer):
lines = LinesSerializer(many=True) lines = LinesSerializer(many=True)
billing_address = BillingAddressSerializer(allow_null=True) billing_address = BillingAddressSerializer(allow_null=True)
payment_processor = serializers.CharField(max_length=32) payment_processor = serializers.CharField(max_length=32)
class PaymentProcessorSerializer(serializers.Serializer):
""" Serializer to use with instances of processors.BasePaymentProcessor """
def to_representation(self, instance):
""" Serialize instances as a string instead of a mapping object. """
return instance.NAME
...@@ -26,6 +26,7 @@ from ecommerce.extensions.api.tests.test_authentication import AccessTokenMixin, ...@@ -26,6 +26,7 @@ from ecommerce.extensions.api.tests.test_authentication import AccessTokenMixin,
from ecommerce.extensions.api.views import OrdersThrottle, FulfillmentMixin, OrderListCreateAPIView from ecommerce.extensions.api.views import OrdersThrottle, FulfillmentMixin, OrderListCreateAPIView
from ecommerce.extensions.fulfillment.status import LINE, ORDER from ecommerce.extensions.fulfillment.status import LINE, ORDER
from ecommerce.extensions.order.utils import OrderNumberGenerator from ecommerce.extensions.order.utils import OrderNumberGenerator
from ecommerce.extensions.payment.processors import BasePaymentProcessor
from ecommerce.tests.mixins import UserMixin from ecommerce.tests.mixins import UserMixin
...@@ -432,3 +433,42 @@ class ListOrderViewTests(AccessTokenMixin, ThrottlingMixin, UserMixin, TestCase) ...@@ -432,3 +433,42 @@ class ListOrderViewTests(AccessTokenMixin, ThrottlingMixin, UserMixin, TestCase)
factories.create_order(user=other_user) factories.create_order(user=other_user)
response = self.client.get(self.path, HTTP_AUTHORIZATION=self.token) response = self.client.get(self.path, HTTP_AUTHORIZATION=self.token)
self.assert_empty_result_response(response) self.assert_empty_result_response(response)
class DummyProcessor1(BasePaymentProcessor): # pylint: disable=abstract-method
NAME = "dummy-1"
class DummyProcessor2(BasePaymentProcessor): # pylint: disable=abstract-method
NAME = "dummy-2"
class PaymentProcessorsViewTestCase(TestCase, UserMixin):
""" Ensures correct behavior of the payment processors list view."""
def setUp(self):
self.token = self.generate_jwt_token_header(self.create_user())
def assert_processor_list_matches(self, expected):
""" DRY helper. """
response = self.client.get(reverse('payment_processors'), HTTP_AUTHORIZATION=self.token)
self.assertEqual(response.status_code, 200)
self.assertSetEqual(set(json.loads(response.content)), set(expected))
def test_permission(self):
"""Ensure authentication is required to access the view. """
response = self.client.get(reverse('payment_processors'))
self.assertEqual(response.status_code, 401)
@override_settings(PAYMENT_PROCESSORS=['ecommerce.extensions.api.tests.test_views.DummyProcessor1'])
def test_get_one(self):
"""Ensure a single payment processor in settings is handled correctly."""
self.assert_processor_list_matches(['dummy-1'])
@override_settings(PAYMENT_PROCESSORS=[
'ecommerce.extensions.api.tests.test_views.DummyProcessor1',
'ecommerce.extensions.api.tests.test_views.DummyProcessor2',
])
def test_get_many(self):
"""Ensure multiple processors in settings are handled correctly."""
self.assert_processor_list_matches(['dummy-1', 'dummy-2'])
...@@ -22,5 +22,6 @@ ORDER_URLS = patterns( ...@@ -22,5 +22,6 @@ ORDER_URLS = patterns(
urlpatterns = patterns( urlpatterns = patterns(
'', '',
url(r'^processors/$', views.PaymentProcessorsView.as_view(), name='payment_processors'),
url(r'^orders/', include(ORDER_URLS, namespace='orders')) url(r'^orders/', include(ORDER_URLS, namespace='orders'))
) )
...@@ -5,7 +5,7 @@ from django.conf import settings ...@@ -5,7 +5,7 @@ from django.conf import settings
from django.http import Http404 from django.http import Http404
from oscar.core.loading import get_class, get_classes, get_model from oscar.core.loading import get_class, get_classes, get_model
from rest_framework import status from rest_framework import status
from rest_framework.generics import UpdateAPIView, RetrieveAPIView, ListCreateAPIView from rest_framework.generics import UpdateAPIView, RetrieveAPIView, ListCreateAPIView, ListAPIView
from rest_framework.permissions import IsAuthenticated, DjangoModelPermissions from rest_framework.permissions import IsAuthenticated, DjangoModelPermissions
from rest_framework.response import Response from rest_framework.response import Response
...@@ -301,3 +301,14 @@ class FulfillOrderView(FulfillmentMixin, UpdateAPIView): ...@@ -301,3 +301,14 @@ class FulfillOrderView(FulfillmentMixin, UpdateAPIView):
serializer = self.get_serializer(order) serializer = self.get_serializer(order)
return Response(serializer.data) return Response(serializer.data)
class PaymentProcessorsView(ListAPIView):
""" View that lists the available payment processors. """
pagination_class = None
permission_classes = (IsAuthenticated,)
serializer_class = serializers.PaymentProcessorSerializer
def get_queryset(self):
""" Fetch the list of payment processor classes based on django settings."""
return [get_processor_class(path) for path in settings.PAYMENT_PROCESSORS]
...@@ -3,14 +3,6 @@ ...@@ -3,14 +3,6 @@
from rest_framework import serializers from rest_framework import serializers
class ProcessorSerializer(serializers.Serializer):
""" Serializer to use with instances of processors.BasePaymentProcessor """
def to_representation(self, instance):
""" Serialize instances as a string instead of a mapping object. """
return instance.NAME
class TransactionSerializer(serializers.Serializer): class TransactionSerializer(serializers.Serializer):
"""Serializes a transaction. """ """Serializes a transaction. """
txn_type = serializers.CharField(max_length=128) txn_type = serializers.CharField(max_length=128)
......
""" Tests of the Payment Views. """ """ Tests of the Payment Views. """
import json
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.test import TestCase from django.test import TestCase
from django.test.utils import override_settings from django.test.utils import override_settings
...@@ -10,7 +8,6 @@ from oscar.core.loading import get_model ...@@ -10,7 +8,6 @@ from oscar.core.loading import get_model
from ecommerce.extensions.payment.constants import ProcessorConstants as PC from ecommerce.extensions.payment.constants import ProcessorConstants as PC
from ecommerce.extensions.payment.processors import BasePaymentProcessor from ecommerce.extensions.payment.processors import BasePaymentProcessor
from ecommerce.extensions.fulfillment.status import ORDER from ecommerce.extensions.fulfillment.status import ORDER
from ecommerce.tests.mixins import UserMixin
ShippingEventType = get_model('order', 'ShippingEventType') ShippingEventType = get_model('order', 'ShippingEventType')
...@@ -84,34 +81,6 @@ class DummySuccessProcessor(BasePaymentProcessor): ...@@ -84,34 +81,6 @@ class DummySuccessProcessor(BasePaymentProcessor):
return {PC.SUCCESS: True, PC.ORDER_NUMBER: ORDER_NUMBER} return {PC.SUCCESS: True, PC.ORDER_NUMBER: ORDER_NUMBER}
class ProcessorListViewTestCase(TestCase, UserMixin):
""" Ensures correct behavior of the payment processors list view."""
def setUp(self):
self.token = self.generate_jwt_token_header(self.create_user())
def assert_processor_list_matches(self, expected):
""" DRY helper. """
response = self.client.get(reverse('processor_list'), HTTP_AUTHORIZATION=self.token)
self.assertEqual(response.status_code, 200)
self.assertSetEqual(set(json.loads(response.content)), set(expected))
def test_permission(self):
"""Ensure authentication is required to access the view. """
response = self.client.get(reverse('processor_list'))
self.assertEqual(response.status_code, 401)
@override_settings(PAYMENT_PROCESSORS=[SUCCESS_PROCESSOR])
def test_get_one(self):
"""Ensure a single payment processor in settings is handled correctly."""
self.assert_processor_list_matches(['DummySuccessProcessor'])
@override_settings(PAYMENT_PROCESSORS=[SUCCESS_PROCESSOR, FAILURE_PROCESSOR])
def test_get_many(self):
"""Ensure multiple processors in settings are handled correctly."""
self.assert_processor_list_matches(['DummySuccessProcessor', 'DummyFailureProcessor'])
# Reuse the fake fulfillment module provided by the test_api tests # Reuse the fake fulfillment module provided by the test_api tests
@override_settings( @override_settings(
FULFILLMENT_MODULES=['ecommerce.extensions.fulfillment.tests.test_api.FakeFulfillmentModule', ] FULFILLMENT_MODULES=['ecommerce.extensions.fulfillment.tests.test_api.FakeFulfillmentModule', ]
......
...@@ -5,6 +5,5 @@ from ecommerce.extensions.payment import views ...@@ -5,6 +5,5 @@ from ecommerce.extensions.payment import views
urlpatterns = patterns( urlpatterns = patterns(
'', '',
url(r'processors/$', views.ProcessorListView.as_view(), name='processor_list'),
url(r'/cybersource/callback/$', views.CybersourceResponseView.as_view(), name='cybersource_callback'), url(r'/cybersource/callback/$', views.CybersourceResponseView.as_view(), name='cybersource_callback'),
) )
...@@ -4,26 +4,12 @@ from django.http import HttpResponse ...@@ -4,26 +4,12 @@ from django.http import HttpResponse
from django.views.generic import View from django.views.generic import View
from oscar.apps.checkout.mixins import OrderPlacementMixin from oscar.apps.checkout.mixins import OrderPlacementMixin
from oscar.apps.payment.models import SourceType from oscar.apps.payment.models import SourceType
from rest_framework.generics import ListAPIView
from rest_framework.permissions import IsAuthenticated
from ecommerce.extensions.order.models import Order from ecommerce.extensions.order.models import Order
from ecommerce.extensions.fulfillment.status import ORDER from ecommerce.extensions.fulfillment.status import ORDER
from ecommerce.extensions.fulfillment.mixins import FulfillmentMixin from ecommerce.extensions.fulfillment.mixins import FulfillmentMixin
from ecommerce.extensions.payment.constants import ProcessorConstants as PC from ecommerce.extensions.payment.constants import ProcessorConstants as PC
from ecommerce.extensions.payment.helpers import get_processor_class from ecommerce.extensions.payment.helpers import get_processor_class
from ecommerce.extensions.payment.serializers import ProcessorSerializer
class ProcessorListView(ListAPIView):
""" View that lists the available payment processors. """
pagination_class = None
permission_classes = (IsAuthenticated,)
serializer_class = ProcessorSerializer
def get_queryset(self):
""" Fetch the list of payment processor classes based on django settings."""
return [get_processor_class(path) for path in settings.PAYMENT_PROCESSORS]
class CybersourceResponseView(View, OrderPlacementMixin, FulfillmentMixin): class CybersourceResponseView(View, OrderPlacementMixin, FulfillmentMixin):
......
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