diff options
author | Patryk Zawadzki <patrys@room-303.com> | 2013-11-06 15:23:30 +0100 |
---|---|---|
committer | Patryk Zawadzki <patrys@room-303.com> | 2013-11-06 15:23:30 +0100 |
commit | b7cf5500116329c48076efb3651a0f636d352c40 (patch) | |
tree | b650b1df6b57f9b24f8e8f75e0de53a7155604a7 | |
parent | 540c988db786d5b11eb2540ee190dea747042774 (diff) | |
download | django-payments-taler-b7cf5500116329c48076efb3651a0f636d352c40.tar.gz django-payments-taler-b7cf5500116329c48076efb3651a0f636d352c40.tar.bz2 django-payments-taler-b7cf5500116329c48076efb3651a0f636d352c40.zip |
Make tests more robust
Make sure PayPal serializes properly, allow Travis CI to run the tests.
-rw-r--r-- | doc/modules.rst | 2 | ||||
-rw-r--r-- | payments/dotpay/__init__.py | 4 | ||||
-rw-r--r-- | payments/dotpay/forms.py | 3 | ||||
-rw-r--r-- | payments/dotpay/tests.py | 4 | ||||
-rw-r--r-- | payments/dummy/__init__.py | 8 | ||||
-rw-r--r-- | payments/paypal-card/__init__.py | 37 | ||||
-rw-r--r-- | payments/paypal/__init__.py | 17 | ||||
-rw-r--r-- | payments/paypal/tests.py | 43 | ||||
-rw-r--r-- | payments/tests.py | 5 | ||||
-rw-r--r-- | payments/wallet/__init__.py | 10 | ||||
-rw-r--r-- | payments/wallet/forms.py | 7 | ||||
-rw-r--r-- | payments/wallet/tests.py | 89 | ||||
-rwxr-xr-x[-rw-r--r--] | setup.py | 8 | ||||
-rw-r--r-- | test_settings.py | 2 |
14 files changed, 123 insertions, 116 deletions
diff --git a/doc/modules.rst b/doc/modules.rst index 1328601..1b9500a 100644 --- a/doc/modules.rst +++ b/doc/modules.rst @@ -98,7 +98,7 @@ To specify the `postback URL` at the Merchant Settings page use direct url to `p E.g: ``https://example.com/payments/process/wallet`` -Paypal +PayPal ------ .. class:: payments.paypal.PaypalProvider(client_id, secret[, endpoint='https://api.paypal.com']) diff --git a/payments/dotpay/__init__.py b/payments/dotpay/__init__.py index 2b42132..16337aa 100644 --- a/payments/dotpay/__init__.py +++ b/payments/dotpay/__init__.py @@ -1,9 +1,7 @@ from django.http import HttpResponse, HttpResponseForbidden from .forms import ProcessPaymentForm -from .. import BasicProvider, get_payment_model - -Payment = get_payment_model() +from .. import BasicProvider class DotpayProvider(BasicProvider): diff --git a/payments/dotpay/forms.py b/payments/dotpay/forms.py index cfe24e4..54dfa45 100644 --- a/payments/dotpay/forms.py +++ b/payments/dotpay/forms.py @@ -2,9 +2,6 @@ import hashlib from django import forms -from .. import get_payment_model - -Payment = get_payment_model() NO_MORE_CONFIRMATION = 0 NEW = 1 diff --git a/payments/dotpay/tests.py b/payments/dotpay/tests.py index 7b5aecb..4f6443c 100644 --- a/payments/dotpay/tests.py +++ b/payments/dotpay/tests.py @@ -1,8 +1,8 @@ -from mock import MagicMock import hashlib +from unittest import TestCase from django.http import HttpResponse, HttpResponseForbidden -from django.test import TestCase +from mock import MagicMock from .forms import ACCEPTED from . import DotpayProvider diff --git a/payments/dummy/__init__.py b/payments/dummy/__init__.py index 04550b3..505b4f6 100644 --- a/payments/dummy/__init__.py +++ b/payments/dummy/__init__.py @@ -7,16 +7,8 @@ from .. import BasicProvider, RedirectNeeded class DummyProvider(BasicProvider): ''' Dummy payment provider - - url: - return URL, user will be bounced to this address after payment is - processed ''' - def __init__(self, *args, **kwargs): - self._url = kwargs.pop('url') - super(DummyProvider, self).__init__(*args, **kwargs) - def get_form(self, data=None): form = DummyForm(data=data, hidden_inputs=False, provider=self, payment=self.payment) diff --git a/payments/paypal-card/__init__.py b/payments/paypal-card/__init__.py deleted file mode 100644 index a780f5c..0000000 --- a/payments/paypal-card/__init__.py +++ /dev/null @@ -1,37 +0,0 @@ -from django.http import HttpResponseForbidden - -from ..paypal import PaypalProvider -from ..forms import PaymentForm -from .. import get_payment_model, RedirectNeeded - -Payment = get_payment_model() - - -class PaypalCardProvider(PaypalProvider): - ''' - paypal.com credit card payment provider - ''' - def get_form(self, data=None): - if self.payment.status == 'waiting': - self.payment.change_status('input') - form = PaymentForm(data, provider=self, payment=self.payment) - if form.is_valid(): - raise RedirectNeeded(self.payment.get_success_url()) - return form - - def get_product_data(self, extra_data): - data = self.get_transactions_data() - year = extra_data['expiration'].year - month = extra_data['expiration'].month - credit_card = {'number': extra_data['number'], - 'type': extra_data['type'], - 'expire_month': month, - 'expire_year': year} - if 'cvv2' in extra_data and extra_data['cvv2']: - credit_card['cvv2'] = extra_data['cvv2'] - data['payer'] = {'payment_method': 'credit_card', - 'funding_instruments': [{'credit_card': credit_card}]} - return data - - def process_data(self, request): - return HttpResponseForbidden('FAILED') diff --git a/payments/paypal/__init__.py b/payments/paypal/__init__.py index 2c51471..27d2afb 100644 --- a/payments/paypal/__init__.py +++ b/payments/paypal/__init__.py @@ -8,9 +8,7 @@ from django.shortcuts import redirect from django.utils import simplejson, timezone from .forms import PaymentForm -from .. import BasicProvider, RedirectNeeded, get_payment_model - -Payment = get_payment_model() +from .. import BasicProvider, RedirectNeeded class UnauthorizedRequest(Exception): @@ -83,15 +81,16 @@ class PaypalProvider(BasicProvider): def get_transactions_data(self): items = list(self.payment.get_purchased_items()) sub_total = self.payment.total - self.payment.delivery - data = {'intent': 'sale', - 'transactions': [{ + data = { + 'intent': 'sale', + 'transactions': [{ 'amount': { - 'total': self.payment.total, + 'total': str(self.payment.total), 'currency': self.payment.currency, 'details': { - 'subtotal': sub_total, - 'tax': self.payment.tax, - 'shipping': self.payment.delivery}}, + 'subtotal': str(sub_total), + 'tax': str(self.payment.tax), + 'shipping': str(self.payment.delivery)}}, 'item_list': {'items': items}, 'description': self.payment.description}]} return data diff --git a/payments/paypal/tests.py b/payments/paypal/tests.py new file mode 100644 index 0000000..c6f4e0d --- /dev/null +++ b/payments/paypal/tests.py @@ -0,0 +1,43 @@ +from decimal import Decimal +from unittest import TestCase + +from django.utils import simplejson +from mock import MagicMock + +from . import PaypalProvider + + +CLIENT_ID = 'abc123' +PAYMENT_TOKEN = '5a4dae68-2715-4b1e-8bb2-2c2dbe9255f6' +SECRET = '123abc' +VARIANT = 'wallet' + + +class Payment(MagicMock): + + id = 1 + description = 'payment' + currency = 'USD' + delivery = Decimal(10) + status = 'waiting' + tax = Decimal(10) + token = PAYMENT_TOKEN + total = Decimal(100) + variant = VARIANT + + def change_status(self, status): + self.status = status + + def get_failure_url(self): + return 'http://cancel.com' + + def get_success_url(self): + return 'http://success.com' + + +class TestPaypalProvider(TestCase): + + def test_payload_serializable(self): + payment = Payment() + provider = PaypalProvider(payment, secret=SECRET, client_id=CLIENT_ID) + simplejson.dumps(provider.get_product_data()) diff --git a/payments/tests.py b/payments/tests.py index 41be8e4..79ca32f 100644 --- a/payments/tests.py +++ b/payments/tests.py @@ -1,4 +1,7 @@ from .dotpay.tests import TestDotpayProvider +from .paypal.tests import TestPaypalProvider from .wallet.tests import TestGoogleWalletProvider -__all__ = ['TestDotpayProvider', 'TestGoogleWalletProvider'] + +__all__ = ['TestDotpayProvider', 'TestGoogleWalletProvider', + 'TestPaypalProvider'] diff --git a/payments/wallet/__init__.py b/payments/wallet/__init__.py index a401e8a..93d412f 100644 --- a/payments/wallet/__init__.py +++ b/payments/wallet/__init__.py @@ -5,9 +5,7 @@ from django.http import HttpResponseForbidden, HttpResponse import jwt from .forms import PaymentForm, ProcessPaymentForm -from .. import get_payment_model, BasicProvider - -Payment = get_payment_model() +from .. import BasicProvider class GoogleWalletProvider(BasicProvider): @@ -32,9 +30,9 @@ class GoogleWalletProvider(BasicProvider): 'iat': current_time, 'exp': exp_time, 'request': { - "currencyCode": self.payment.currency, - "price": str(self.payment.total), - 'name': self.payment.description or "Total payment", + 'currencyCode': self.payment.currency, + 'price': str(self.payment.total), + 'name': self.payment.description or 'Total payment', 'sellerData': self.payment.token}} return jwt.encode(jwt_info, self.seller_secret) diff --git a/payments/wallet/forms.py b/payments/wallet/forms.py index c6f5904..9d11487 100644 --- a/payments/wallet/forms.py +++ b/payments/wallet/forms.py @@ -23,10 +23,9 @@ class ProcessPaymentForm(forms.Form): self.payment = payment def clean_jwt(self): - cleaned_jwt = super(ProcessPaymentForm, self).clean().get('jwt') - + payload = super(ProcessPaymentForm, self).clean().get('jwt') try: - jwt_data = jwt.decode(str(cleaned_jwt), + jwt_data = jwt.decode(payload.encode('utf-8'), self.provider.seller_secret) except jwt.DecodeError: raise forms.ValidationError('Incorrect response') @@ -41,7 +40,7 @@ class ProcessPaymentForm(forms.Form): raise forms.ValidationError('Incorrect payment token') self.order_id = jwt_data['response']['orderId'] - return cleaned_jwt + return payload def save(self): self.payment.transaction_id = self.order_id diff --git a/payments/wallet/tests.py b/payments/wallet/tests.py index 42c0af0..51af2ee 100644 --- a/payments/wallet/tests.py +++ b/payments/wallet/tests.py @@ -1,44 +1,42 @@ -from mock import MagicMock +from decimal import Decimal +from unittest import TestCase from django.http import HttpResponse, HttpResponseForbidden -from django.test import TestCase import jwt +from mock import MagicMock from . import GoogleWalletProvider -VARIANT = 'wallet' - -PAYMENT_TOKEN = "5a4dae68-2715-4b1e-8bb2-2c2dbe9255f6" - +PAYMENT_TOKEN = '5a4dae68-2715-4b1e-8bb2-2c2dbe9255f6' SELLER_ID = 'abc123' SELLER_SECRET = '123abc' +VARIANT = 'wallet' + JWT_DATA = { - "iss": "Google", - "aud": SELLER_ID, - "typ": "google/payments/inapp/item/v1/postback/buy", - "iat": "1309988959", - "exp": "1409988959", - "request": { - "name": "Test Order #12", - "price": "22.50", - "currencyCode": "USD", - "sellerData": PAYMENT_TOKEN - }, - "response": { - "orderId": "1234567890" - } -} + 'iss': 'Google', + 'aud': SELLER_ID, + 'typ': 'google/payments/inapp/item/v1/postback/buy', + 'iat': '1309988959', + 'exp': '1409988959', + 'request': { + 'name': 'Test Order #12', + 'price': '22.50', + 'currencyCode': 'USD', + 'sellerData': PAYMENT_TOKEN}, + 'response': { + 'orderId': '1234567890'}} class Payment(MagicMock): id = 1 - variant = VARIANT currency = 'USD' - total = 100 - token = PAYMENT_TOKEN + description = 'payment' status = 'waiting' + token = PAYMENT_TOKEN + total = Decimal(100) + variant = VARIANT def change_status(self, status): self.status = status @@ -52,42 +50,53 @@ class Payment(MagicMock): class TestGoogleWalletProvider(TestCase): - def setUp(self): - self.payment = Payment() - self.request = MagicMock() - self.request.POST = {'jwt': jwt.encode(JWT_DATA, SELLER_SECRET)} - def test_process_data(self): """ GoogleWalletProvider.process_data() returns a correct HTTP response """ - provider = GoogleWalletProvider(self.payment, seller_id=SELLER_ID, + payment = Payment() + request = MagicMock() + request.POST = {'jwt': jwt.encode(JWT_DATA, SELLER_SECRET)} + provider = GoogleWalletProvider(payment, seller_id=SELLER_ID, seller_secret=SELLER_SECRET) - response = provider.process_data(self.request) + response = provider.process_data(request) self.assertEqual(type(response), HttpResponse) - self.assertEqual(self.payment.status, 'confirmed') + self.assertEqual(payment.status, 'confirmed') def test_incorrect_process_data(self): """ GoogleWalletProvider.process_data() checks POST data """ - data = JWT_DATA - data['aud'] = 'wrong seller id' - self.request.POST = {'jwt': jwt.encode(data, SELLER_SECRET)} - provider = GoogleWalletProvider(self.payment, seller_id=SELLER_ID, + data = dict(JWT_DATA, aud='wrong seller id') + payment = Payment() + request = MagicMock() + payload = jwt.encode(data, SELLER_SECRET) + request.POST = {'jwt': payload} + provider = GoogleWalletProvider(payment, seller_id=SELLER_ID, seller_secret=SELLER_SECRET) - response = provider.process_data(self.request) + response = provider.process_data(request) self.assertEqual(type(response), HttpResponseForbidden) def test_provider_request_payment_token(self): + request = MagicMock() + request.POST = {'jwt': jwt.encode(JWT_DATA, SELLER_SECRET)} provider = GoogleWalletProvider(payment=None, seller_id=SELLER_ID, seller_secret=SELLER_SECRET) - token = provider.get_token_from_request(self.request) + token = provider.get_token_from_request(request) self.assertEqual(token, PAYMENT_TOKEN) def test_provider_invalid_request(self): - self.request.POST = {'jwt': 'wrong jwt data'} + request = MagicMock() + request.POST = {'jwt': 'wrong jwt data'} provider = GoogleWalletProvider(payment=None, seller_id=SELLER_ID, seller_secret=SELLER_SECRET) - token = provider.get_token_from_request(self.request) + token = provider.get_token_from_request(request) self.assertFalse(token) + + def test_jwt_encoder(self): + payment = Payment() + provider = GoogleWalletProvider(payment, seller_id=SELLER_ID, + seller_secret=SELLER_SECRET) + payload = provider.get_jwt_data() + data = jwt.decode(payload, SELLER_SECRET) + self.assertEqual(data['request']['price'], '100') @@ -1,12 +1,15 @@ #!/usr/bin/env python from setuptools import setup, find_packages +import os + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'test_settings') setup( name='django-payments', author='Mirumee Software', author_email='hello@mirumee.com', description='Universal payment handling for Django', - version='0.3.4.4', + version='0.3.5', url='http://github.com/mirumee/django-payments', packages=find_packages(), classifiers=[ @@ -22,6 +25,7 @@ setup( 'Framework :: Django', 'Topic :: Software Development :: Libraries :: Application Frameworks', 'Topic :: Software Development :: Libraries :: Python Modules'], - install_requires=['requests>=1.2.0', 'pycrypto', 'PyJWT'], + install_requires=['Django>=1.5', 'requests>=1.2.0', 'pycrypto', 'PyJWT'], include_package_data=True, + test_suite='payments.tests', zip_safe=False) diff --git a/test_settings.py b/test_settings.py new file mode 100644 index 0000000..362a3c0 --- /dev/null +++ b/test_settings.py @@ -0,0 +1,2 @@ +SECRET_KEY = 'NOTREALLY' +PAYMENT_BASE_URL = 'http://example.com/' |