distinguish machine and human payment return urls (#8350)

Tests added
This commit is contained in:
Serghei Mihai 2015-10-13 12:29:53 +02:00
parent 840f80b766
commit 7e6d3223f1
3 changed files with 114 additions and 8 deletions

View File

@ -19,7 +19,7 @@ from django.conf.urls import patterns, url, include
from combo.urls_utils import decorated_includes, manager_required
from .views import (RegiesApiView, AddBasketItemApiView, PayView, CallbackView,
ItemDownloadView, ItemView)
ReturnView, ItemDownloadView, ItemView)
from .manager_views import (RegieListView, RegieCreateView, RegieUpdateView,
RegieDeleteView)
@ -38,6 +38,7 @@ urlpatterns = patterns('',
name='api-add-basket-item'),
url('^lingo/pay$', PayView.as_view(), name='lingo-pay'),
url(r'^lingo/callback/(?P<regie_pk>\w+)/$', CallbackView.as_view(), name='lingo-callback'),
url(r'^lingo/return/(?P<regie_pk>\w+)/$', ReturnView.as_view(), name='lingo-return'),
url(r'^manage/lingo/', decorated_includes(manager_required,
include(lingo_manager_urls))),
url(r'^lingo/item/(?P<regie_id>[\w,-]+)/(?P<item_id>[\w,-]+)/pdf$',

View File

@ -141,11 +141,7 @@ class PayView(View):
reverse('lingo-callback', kwargs={'regie_pk': regie.id}))
(order_id, kind, data) = payment.request(total_amount,
email=request.user.email,
next_url=request.build_absolute_uri('/'),
accepturl=return_url,
declineurl=return_url,
exceptionurl=return_url,
cancelurl=return_url)
next_url=return_url)
transaction.order_id = order_id
transaction.save()
@ -178,7 +174,7 @@ class CallbackView(View):
assert transaction.regie == regie
if payment_response.result != eopayment.PAID:
return HttpResponseRedirect('/')
return HttpResponse()
for item in transaction.items.all():
item.payment_date = transaction.end_date
@ -192,7 +188,34 @@ class CallbackView(View):
for item in transaction.remote_items.split(','):
regie.pay_item(request, item)
return HttpResponseRedirect('/')
return HttpResponse()
class ReturnView(View):
def get(self, request, *args, **kwargs):
regie = Regie.objects.get(id=kwargs.get('regie_pk'))
payment = eopayment.Payment(regie.service, regie.service_options)
try:
payment_response = payment.response(request.environ['QUERY_STRING'])
except:
# if eopayment can't get response from query string redirect to
# homepage
return HttpResponseRedirect('/')
transaction = Transaction.objects.get(order_id=payment_response.order_id)
if transaction.items:
# redirect to first transaction local item view
return HttpResponseRedirect(reverse('view-item',
kwargs={'regie_id': regie.pk,
'item_id': transaction.items[0].id}))
if transaction.remote_items:
# redirect to first transaction remote item view
item = transaction.remote_items.split(',')[0]
return HttpResponseRedirect(reverse('view-item',
kwargs={'regie_id': regie.pk,
'item_id': item.id}))
class ItemDownloadView(View):

82
tests/test_payment.py Normal file
View File

@ -0,0 +1,82 @@
import pytest
from datetime import datetime, timedelta
import urlparse
from decimal import Decimal
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from django.core.wsgi import get_wsgi_application
from webtest import TestApp
from django.test import Client
from lingo.models import Regie, BasketItem, Transaction, RemoteItem
pytestmark = pytest.mark.django_db
client = Client()
@pytest.fixture
def regie():
try:
regie = Regie.objects.get(slug='test')
except Regie.DoesNotExist:
regie = Regie()
regie.label = 'Test'
regie.slug = 'test'
regie.description = 'test'
regie.payment_min_amount = Decimal(4.5)
regie.service = 'dummy'
regie.service_options = {'siret': '1234'}
regie.save()
return regie
@pytest.fixture
def user():
try:
user = User.objects.get(username='admin')
except User.DoesNotExist:
user = User.objects.create_user('admin', email=None, password='admin')
return user
def login(username='admin', password='admin'):
resp = client.post('/login/', {'username': username, 'password': password})
assert resp.status_code == 302
def test_payment_min_amount(regie, user):
items = {'item1': {'amount': '1.5', 'source_url': '/item/1'},
'item2': {'amount': '2.4', 'source_url': '/item/2'}
}
b_items = []
for subject, details in items.iteritems():
b_item = BasketItem.objects.create(user=user, regie=regie,
subject=subject, **details)
b_items.append(b_item.pk)
login()
resp = client.post(reverse('lingo-pay'), {'item': b_items, 'regie': regie.pk})
assert resp.status_code == 403
def test_successfull_items_payment(regie, user):
items = {'item1': {'amount': '10.5', 'source_url': '/item/1'},
'item2': {'amount': '42', 'source_url': '/item/2'},
'item3': {'amount': '100', 'source_url': '/item/3'},
'item4': {'amount': '354', 'source_url': '/item/4'}
}
b_items = []
for subject, details in items.iteritems():
b_item = BasketItem.objects.create(user=user, regie=regie,
subject=subject, **details)
b_items.append(b_item.pk)
login()
resp = client.post(reverse('lingo-pay'), {'item': b_items, 'regie': regie.pk})
assert resp.status_code == 302
location = resp.get('location')
assert 'dummy-payment' in location
parsed = urlparse.urlparse(location)
# get return_url and transaction id from location
qs = urlparse.parse_qs(parsed.query)
args = {'transaction_id': qs['transaction_id'][0], 'signed': True,
'ok': True, 'reason': 'Paid'}
# simulate backend callback call
resp = client.get(qs['return_url'][0], args)
assert resp.status_code == 200