lingo: handle empty payload in ReturnView (#42581)
This commit is contained in:
parent
ea0657f565
commit
bda15dbcef
|
@ -562,8 +562,9 @@ class PaymentView(View):
|
|||
payment = get_eopayment_object(request, payment_backend)
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.info(u'received payment response: %r', backend_response)
|
||||
extra_info = kwargs.pop('payment_extra_info', {})
|
||||
try:
|
||||
payment_response = payment.response(backend_response)
|
||||
payment_response = payment.response(backend_response, **extra_info)
|
||||
except eopayment.PaymentException as e:
|
||||
logger.error(u'failed to process payment response: %s', e,
|
||||
extra={'eopayment_raw_response': repr(backend_response)})
|
||||
|
@ -686,23 +687,36 @@ class ReturnView(PaymentView):
|
|||
return super(ReturnView, self).dispatch(*args, **kwargs)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
if not request.environ['QUERY_STRING']:
|
||||
return HttpResponseBadRequest('Missing query string')
|
||||
return self.handle_return(request, request.environ['QUERY_STRING'], **kwargs)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
return self.handle_return(request, force_text(request.body) or request.environ['QUERY_STRING'], **kwargs)
|
||||
|
||||
def handle_return(self, request, backend_response, **kwargs):
|
||||
payment_extra_info = {'redirect': True}
|
||||
|
||||
transaction = None
|
||||
transaction_id = kwargs.get('transaction_signature')
|
||||
if transaction_id:
|
||||
try:
|
||||
transaction_id = signing_loads(transaction_id)
|
||||
except signing.BadSignature:
|
||||
transaction_id = None
|
||||
|
||||
if transaction_id:
|
||||
# retrieve info about previously known state
|
||||
try:
|
||||
current_transaction = Transaction.objects.get(pk=transaction_id)
|
||||
except Transaction.DoesNotExist:
|
||||
pass
|
||||
else:
|
||||
payment_extra_info['order_id_hint'] = current_transaction.order_id
|
||||
payment_extra_info['order_status_hint'] = current_transaction.status
|
||||
|
||||
try:
|
||||
transaction = self.handle_response(request, backend_response, **kwargs)
|
||||
transaction = self.handle_response(
|
||||
request, backend_response, payment_extra_info=payment_extra_info, **kwargs
|
||||
)
|
||||
except UnsignedPaymentException as e:
|
||||
# some payment backends do not sign return URLs, don't mark this as
|
||||
# an error, they will provide a notification to the callback
|
||||
|
@ -710,7 +724,6 @@ class ReturnView(PaymentView):
|
|||
if transaction_id:
|
||||
return HttpResponseRedirect(get_payment_status_view(transaction_id))
|
||||
return HttpResponseRedirect(get_basket_url())
|
||||
|
||||
except PaymentException as e:
|
||||
messages.error(request, _('We are sorry but the payment service '
|
||||
'failed to provide a correct answer.'))
|
||||
|
|
|
@ -825,6 +825,45 @@ def test_payment_callback_no_regie(app, basket_page, regie, user, with_payment_b
|
|||
assert data['amount'] == '11.50'
|
||||
|
||||
|
||||
@pytest.mark.parametrize('with_payment_backend', [False, True])
|
||||
def test_payment_return_without_query_string(app, basket_page, regie, user, with_payment_backend):
|
||||
page = Page(title='xxx', slug='index', template_name='standard')
|
||||
page.save()
|
||||
item = BasketItem.objects.create(user=user, regie=regie,
|
||||
subject='test_item', amount='10.5',
|
||||
source_url='http://example.org/testitem/')
|
||||
resp = login(app).get(basket_page.get_online_url())
|
||||
resp = resp.form.submit()
|
||||
assert resp.status_code == 302
|
||||
location = resp.location
|
||||
parsed = urlparse.urlparse(location)
|
||||
qs = urlparse.parse_qs(parsed.query)
|
||||
return_url = qs['return_url'][0]
|
||||
transaction_id = qs['transaction_id'][0]
|
||||
data = {'transaction_id': transaction_id, 'signed': True,
|
||||
'amount': qs['amount'][0], 'ok': True}
|
||||
|
||||
# payment status is obtained through callback
|
||||
callback_url = get_url(with_payment_backend, 'lingo-callback', regie)
|
||||
with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as request:
|
||||
get_resp = app.get(callback_url, params=data)
|
||||
transaction = Transaction.objects.get(order_id=transaction_id)
|
||||
assert transaction.status == 3
|
||||
|
||||
# then return view is called without any data, which should be expected by the backend
|
||||
with mock.patch.object(eopayment.dummy.Payment, 'response', autospec=True) as mock_response:
|
||||
mock_response.return_value = eopayment.common.PaymentResponse(result=transaction.status,
|
||||
order_id=transaction.order_id)
|
||||
get_resp = app.get(return_url)
|
||||
mock_response.assert_called_once_with(
|
||||
mock.ANY, '', redirect=True, order_id_hint=transaction.order_id,
|
||||
order_status_hint=transaction.status
|
||||
)
|
||||
assert get_resp.status_code == 302
|
||||
resp = app.get(get_resp['Location'])
|
||||
assert 'Your payment has been succesfully registered.' in resp.text
|
||||
|
||||
|
||||
@pytest.mark.parametrize('with_payment_backend', [False, True])
|
||||
def test_nonexisting_transaction(app, regie, user, with_payment_backend):
|
||||
app = login(app)
|
||||
|
|
Loading…
Reference in New Issue