Commit f89ac74a by Jim Abramson

Merge pull request #57 from edx/jsa/xcom-211-2

Move payment processor list endpoint to api/
parents 541d5b35 4e7f0f73
......@@ -64,3 +64,11 @@ class OrderSerializer(serializers.Serializer):
lines = LinesSerializer(many=True)
billing_address = BillingAddressSerializer(allow_null=True)
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,
from ecommerce.extensions.api.views import OrdersThrottle, FulfillmentMixin, OrderListCreateAPIView
from ecommerce.extensions.fulfillment.status import LINE, ORDER
from ecommerce.extensions.order.utils import OrderNumberGenerator
from ecommerce.extensions.payment.processors import BasePaymentProcessor
from ecommerce.tests.mixins import UserMixin
......@@ -432,3 +433,42 @@ class ListOrderViewTests(AccessTokenMixin, ThrottlingMixin, UserMixin, TestCase)
factories.create_order(user=other_user)
response = self.client.get(self.path, HTTP_AUTHORIZATION=self.token)
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(
urlpatterns = patterns(
'',
url(r'^processors/$', views.PaymentProcessorsView.as_view(), name='payment_processors'),
url(r'^orders/', include(ORDER_URLS, namespace='orders'))
)
......@@ -5,7 +5,7 @@ from django.conf import settings
from django.http import Http404
from oscar.core.loading import get_class, get_classes, get_model
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.response import Response
......@@ -301,3 +301,14 @@ class FulfillOrderView(FulfillmentMixin, UpdateAPIView):
serializer = self.get_serializer(order)
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 @@
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):
"""Serializes a transaction. """
txn_type = serializers.CharField(max_length=128)
......
""" Tests of the Payment Views. """
import json
from django.core.urlresolvers import reverse
from django.test import TestCase
from django.test.utils import override_settings
......@@ -10,7 +8,6 @@ from oscar.core.loading import get_model
from ecommerce.extensions.payment.constants import ProcessorConstants as PC
from ecommerce.extensions.payment.processors import BasePaymentProcessor
from ecommerce.extensions.fulfillment.status import ORDER
from ecommerce.tests.mixins import UserMixin
ShippingEventType = get_model('order', 'ShippingEventType')
......@@ -84,34 +81,6 @@ class DummySuccessProcessor(BasePaymentProcessor):
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
@override_settings(
FULFILLMENT_MODULES=['ecommerce.extensions.fulfillment.tests.test_api.FakeFulfillmentModule', ]
......
......@@ -5,6 +5,5 @@ from ecommerce.extensions.payment import views
urlpatterns = patterns(
'',
url(r'processors/$', views.ProcessorListView.as_view(), name='processor_list'),
url(r'/cybersource/callback/$', views.CybersourceResponseView.as_view(), name='cybersource_callback'),
)
......@@ -4,26 +4,12 @@ from django.http import HttpResponse
from django.views.generic import View
from oscar.apps.checkout.mixins import OrderPlacementMixin
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.fulfillment.status import ORDER
from ecommerce.extensions.fulfillment.mixins import FulfillmentMixin
from ecommerce.extensions.payment.constants import ProcessorConstants as PC
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):
......
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