lingo: add support for payment services returning 'WAITING' as status (#19362)

This commit is contained in:
Frédéric Péters 2018-01-31 15:25:13 +01:00
parent 8ddf947e59
commit 60915c7d6d
4 changed files with 70 additions and 0 deletions

View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.8 on 2018-01-31 14:24
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('lingo', '0030_transaction_to_be_paid_remote_items'),
]
operations = [
migrations.AddField(
model_name='basketitem',
name='waiting_date',
field=models.DateTimeField(null=True),
),
]

View File

@ -217,6 +217,7 @@ class BasketItem(models.Model):
user_cancellable = models.BooleanField(default=True)
creation_date = models.DateTimeField(auto_now_add=True)
cancellation_date = models.DateTimeField(null=True)
waiting_date = models.DateTimeField(null=True)
payment_date = models.DateTimeField(null=True)
notification_date = models.DateTimeField(null=True)
@ -228,6 +229,7 @@ class BasketItem(models.Model):
return cls.objects.filter(
user=user,
payment_date__isnull=True,
waiting_date__isnull=True,
cancellation_date__isnull=True)
def notify(self, status):

View File

@ -436,6 +436,17 @@ class CallbackView(View):
if not transaction.regie == regie:
return HttpResponseBadRequest('Invalid payment regie')
if payment_response.result == eopayment.WAITING:
# mark basket items as waiting for payment confirmation
transaction.items.all().update(waiting_date=timezone.now())
return HttpResponse()
if payment_response.result == eopayment.CANCELLED:
# mark basket items as no longer waiting so the user can restart a
# payment.
transaction.items.all().update(waiting_date=None)
return HttpResponse()
if payment_response.result not in (eopayment.PAID, eopayment.ACCEPTED):
return HttpResponse()

View File

@ -445,6 +445,43 @@ def test_nonexisting_transaction(regie, user):
get_resp = client.get(callback_url, data)
assert get_resp.status_code == 404
def test_payment_callback_waiting(regie, user):
item = BasketItem.objects.create(user=user, regie=regie,
subject='test_item', amount='10.5',
source_url='http://example.org/testitem/')
login()
resp = client.post(reverse('lingo-pay'), {'regie': regie.pk})
assert resp.status_code == 302
location = resp.get('location')
parsed = urlparse.urlparse(location)
qs = urlparse.parse_qs(parsed.query)
transaction_id = qs['transaction_id'][0]
data = {'transaction_id': transaction_id, 'signed': True,
'amount': qs['amount'][0], 'waiting': True}
assert data['amount'] == '10.50'
# callback with WAITING state
callback_url = reverse('lingo-callback', kwargs={'regie_pk': regie.id})
resp = client.get(callback_url, data)
assert resp.status_code == 200
assert Transaction.objects.get(order_id=transaction_id).status == eopayment.WAITING
assert BasketItem.objects.get(id=item.id).waiting_date
assert not BasketItem.objects.get(id=item.id).payment_date
assert BasketItem.get_items_to_be_paid(user).count() == 0
# callback with PAID state
data = {'transaction_id': transaction_id, 'signed': True,
'amount': qs['amount'][0], 'ok': True}
with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as request:
resp = client.get(callback_url, data)
assert resp.status_code == 200
url = request.call_args[0][1]
assert url.startswith('http://example.org/testitem/jump/trigger/paid')
assert Transaction.objects.get(order_id=transaction_id).status == eopayment.PAID
assert BasketItem.objects.get(id=item.id).payment_date
assert BasketItem.get_items_to_be_paid(user).count() == 0
def test_transaction_expiration():
t1 = Transaction(status=0)
t1.save()