0001-lingo-move-transaction-identifier-to-URL-path-39074.patch
combo/apps/lingo/urls.py | ||
---|---|---|
71 | 71 |
url(r'^lingo/callback-payment-backend/(?P<payment_backend_pk>\w+)/$', |
72 | 72 |
CallbackView.as_view(), name='lingo-callback-payment-backend'), |
73 | 73 |
url(r'^lingo/return/(?P<regie_pk>\w+)/$', ReturnView.as_view(), name='lingo-return'), |
74 |
url(r'^lingo/return-payment-backend/(?P<payment_backend_pk>\w+)/$', |
|
74 |
url(r'^lingo/return-payment-backend/(?P<payment_backend_pk>\w+)/(?P<transaction_signature>.+)/$',
|
|
75 | 75 |
ReturnView.as_view(), name='lingo-return-payment-backend'), |
76 | 76 |
url(r'^manage/lingo/', decorated_includes(manager_required, |
77 | 77 |
include(lingo_manager_urls))), |
combo/apps/lingo/views.py | ||
---|---|---|
54 | 54 |
if isinstance(regie_or_payment_backend, Regie): |
55 | 55 |
payment_backend = regie_or_payment_backend.payment_backend |
56 | 56 |
options = payment_backend.service_options |
57 |
normal_return_url = reverse( |
|
58 |
'lingo-return-payment-backend', |
|
59 |
kwargs={'payment_backend_pk': payment_backend.id} |
|
60 |
) |
|
61 |
if transaction_id: |
|
62 |
normal_return_url = "%s?lingo-transaction-id=%s" % (normal_return_url, signing.dumps(transaction_id)) |
|
63 | 57 |
options.update({ |
64 | 58 |
'automatic_return_url': request.build_absolute_uri( |
65 | 59 |
reverse('lingo-callback-payment-backend', |
66 | 60 |
kwargs={'payment_backend_pk': payment_backend.id})), |
67 |
'normal_return_url': request.build_absolute_uri(normal_return_url) |
|
68 | 61 |
}) |
62 | ||
63 |
if transaction_id: |
|
64 |
options['normal_return_url'] = request.build_absolute_uri( |
|
65 |
reverse('lingo-return-payment-backend', kwargs={ |
|
66 |
'payment_backend_pk': payment_backend.id, |
|
67 |
'transaction_signature': signing.dumps(transaction_id) |
|
68 |
}) |
|
69 |
) |
|
69 | 70 |
return eopayment.Payment(payment_backend.service, options) |
70 | 71 | |
71 | 72 | |
... | ... | |
642 | 643 | |
643 | 644 |
def handle_return(self, request, backend_response, **kwargs): |
644 | 645 |
transaction = None |
645 |
transaction_id = request.GET.get('lingo-transaction-id')
|
|
646 |
transaction_id = kwargs.get('transaction_signature')
|
|
646 | 647 |
if transaction_id: |
647 | 648 |
try: |
648 | 649 |
transaction_id = signing.loads(transaction_id) |
tests/test_lingo_payment.py | ||
---|---|---|
226 | 226 |
'ok': True, 'reason': 'Paid'} |
227 | 227 |
# make sure return url is the user return URL |
228 | 228 |
assert urlparse.urlparse(qs['return_url'][0]).path.startswith( |
229 |
reverse('lingo-return-payment-backend', |
|
230 |
kwargs={'payment_backend_pk': regie.payment_backend.id})) |
|
229 |
'/lingo/return-payment-backend/%s/' % regie.payment_backend.id) |
|
231 | 230 |
# simulate successful call to callback URL |
232 | 231 |
with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as request: |
233 | 232 |
resp = app.get(get_url(with_payment_backend, 'lingo-callback', regie), params=args) |
... | ... | |
642 | 641 |
parsed = urlparse.urlparse(location) |
643 | 642 |
qs = urlparse.parse_qs(parsed.query) |
644 | 643 |
transaction_id = qs['transaction_id'][0] |
644 |
return_url = qs['return_url'][0] |
|
645 | 645 |
data = {'transaction_id': transaction_id, 'signed': True, |
646 | 646 |
'amount': qs['amount'][0], 'ok': True} |
647 | 647 |
assert data['amount'] == '11.50' |
... | ... | |
653 | 653 |
assert Transaction.objects.get(order_id=transaction_id).status == 3 |
654 | 654 | |
655 | 655 |
# call return view |
656 |
return_url = get_url(with_payment_backend, 'lingo-return', regie) |
|
657 | 656 |
get_resp = app.get(return_url, params=data) |
658 | 657 |
assert get_resp.status_code == 302 |
659 | 658 |
resp = app.get(get_resp['Location']) |
... | ... | |
765 | 764 |
data = {'transaction_id': transaction_id, |
766 | 765 |
'amount': qs['amount'][0], 'ok': True} |
767 | 766 |
assert data['amount'] == '10.50' |
768 |
return_qs = urlparse.parse_qs(urlparse.urlparse(qs['return_url'][0]).query) |
|
769 |
lingo_transaction_id = return_qs['lingo-transaction-id'][0] |
|
767 |
return_url = qs['return_url'][0] |
|
770 | 768 | |
771 | 769 |
# call return with unsigned POST |
772 | 770 |
with check_log(caplog, 'received unsigned payment'): |
773 |
return_url = get_url(with_payment_backend, 'lingo-return', regie) |
|
774 | 771 |
with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as request: |
775 | 772 |
get_resp = app.post(return_url, params=data) |
776 | 773 |
assert request.call_count == 0 |
777 | 774 |
assert get_resp.status_code == 302 |
778 |
assert urlparse.urlparse(get_resp['location']).path == '/test_basket_cell/'
|
|
775 |
assert urlparse.urlparse(get_resp['location']).path == '/lingo/payment-status'
|
|
779 | 776 |
assert Transaction.objects.get(order_id=transaction_id).status == 0 # not paid |
780 | 777 | |
781 | 778 |
# call return with missing data |
... | ... | |
792 | 789 | |
793 | 790 |
# call return with signed POST |
794 | 791 |
data['signed'] = True |
795 |
return_url = get_url(with_payment_backend, 'lingo-return', regie) + \ |
|
796 |
'?lingo-transaction-id=%s' % lingo_transaction_id |
|
797 | 792 |
with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as request: |
798 | 793 |
get_resp = app.post(return_url, params=data) |
799 | 794 |
url = request.call_args[0][1] |
... | ... | |
1092 | 1087 |
# simulate bad responseform payment backend, no transaction id |
1093 | 1088 |
data = {'amount': qs['amount'][0], 'signed': True} |
1094 | 1089 |
return_url = qs['return_url'][0] |
1095 |
assert 'lingo-transaction-id' in return_url |
|
1096 | 1090 |
resp = app.get(return_url, params=data) |
1097 | 1091 |
assert_payment_status(resp.location) |
1098 | 1092 |
resp = resp.follow() |
... | ... | |
1108 | 1102 |
'amount': qs['amount'][0], 'signed': True |
1109 | 1103 |
} |
1110 | 1104 |
return_url = qs['return_url'][0] |
1111 |
assert 'lingo-transaction-id' in return_url |
|
1112 | 1105 |
resp = app.get(return_url, params=data) |
1113 | 1106 |
assert_payment_status(resp.location, transaction_id=item.transaction_set.last().pk) |
1114 | 1107 |
# check that item is paid |
tests/test_lingo_remote_regie.py | ||
---|---|---|
206 | 206 |
args = {'transaction_id': qs['transaction_id'][0], 'signed': True, |
207 | 207 |
'ok': True, 'reason': 'Paid'} |
208 | 208 |
# make sure return url is the user return URL |
209 |
assert urlparse.urlparse(qs['return_url'][0]).path.startswith( |
|
210 |
reverse('lingo-return-payment-backend', |
|
211 |
kwargs={'payment_backend_pk': remote_regie.payment_backend.id})) |
|
209 |
return_url = qs['return_url'][0] |
|
210 |
assert urlparse.urlparse(return_url).path.startswith('/lingo/return-payment-backend') |
|
212 | 211 |
# simulate successful return URL |
213 | 212 |
resp = app.get(qs['return_url'][0], params=args) |
214 | 213 |
# redirect to payment status |
... | ... | |
332 | 331 |
args = {'transaction_id': qs['transaction_id'][0], 'signed': True, |
333 | 332 |
'ok': True, 'reason': 'Paid'} |
334 | 333 |
# make sure return url is the user return URL |
335 |
assert urlparse.urlparse(qs['return_url'][0]).path.startswith(
|
|
336 |
reverse('lingo-return-payment-backend',
|
|
337 |
kwargs={'payment_backend_pk': remote_regie.payment_backend.id}))
|
|
334 |
return_url = qs['return_url'][0]
|
|
335 |
assert urlparse.urlparse(return_url).path.startswith(
|
|
336 |
'/lingo/return-payment-backend/%s/' % remote_regie.payment_backend.id)
|
|
338 | 337 |
# simulate payment failure |
339 | 338 |
mock_get.side_effect = ConnectionError('where is my hostname?') |
340 | 339 |
resp = app.get(qs['return_url'][0], params=args) |
341 |
- |