0001-lingo-handle-single-basket-item-payment-25725.patch
combo/apps/lingo/urls.py | ||
---|---|---|
21 | 21 |
from .views import (RegiesApiView, AddBasketItemApiView, PayView, CallbackView, |
22 | 22 |
ReturnView, ItemDownloadView, ItemView, CancelItemView, |
23 | 23 |
RemoveBasketItemApiView, ValidateTransactionApiView, |
24 |
CancelTransactionApiView, SelfInvoiceView) |
|
24 |
CancelTransactionApiView, SelfInvoiceView, BasketItemPayView)
|
|
25 | 25 |
from .manager_views import (RegieListView, RegieCreateView, RegieUpdateView, |
26 | 26 |
RegieDeleteView, TransactionListView, download_transactions_csv) |
27 | 27 | |
... | ... | |
56 | 56 |
ItemDownloadView.as_view(), name='download-item-pdf'), |
57 | 57 |
url(r'^lingo/item/(?P<regie_id>[\w,-]+)/(?P<item_crypto_id>[\w,-]+)/$', |
58 | 58 |
ItemView.as_view(), name='view-item'), |
59 |
url(r'^lingo/item/(?P<item_id>\d+)/pay$', |
|
60 |
BasketItemPayView.as_view(), name='basket-item-pay-view'), |
|
59 | 61 |
url(r'^lingo/self-invoice/(?P<cell_id>\w+)/$', SelfInvoiceView.as_view(), |
60 | 62 |
name='lingo-self-invoice'), |
61 | 63 |
] |
combo/apps/lingo/views.py | ||
---|---|---|
165 | 165 |
item.regie.compute_extra_fees(user=item.user) |
166 | 166 | |
167 | 167 |
response = HttpResponse(content_type='application/json') |
168 |
response.write(json.dumps({'result': 'success', 'id': str(item.id)})) |
|
168 |
payment_url = reverse('basket-item-pay-view', kwargs={'item_id': item.id}) |
|
169 |
response.write(json.dumps({'result': 'success', 'id': str(item.id), |
|
170 |
'payment_url': request.build_absolute_uri(payment_url)})) |
|
169 | 171 |
return response |
170 | 172 | |
171 | 173 | |
... | ... | |
391 | 393 |
return self.handle_payment(request, regie, items, remote_items, next_url, email) |
392 | 394 | |
393 | 395 | |
396 |
class BasketItemPayView(PayMixin, View): |
|
397 |
def get(self, request, *args, **kwargs): |
|
398 |
next_url = request.GET.get('next_url') or '/' |
|
399 |
if not (request.user and request.user.is_authenticated()): |
|
400 |
return HttpResponseForbidden(_('No item payment allowed for anonymous users.')) |
|
401 | ||
402 |
item = BasketItem.objects.get(pk=kwargs['item_id']) |
|
403 |
regie = item.regie |
|
404 |
if regie.extra_fees_ws_url: |
|
405 |
return HttpResponseForbidden(_('No item payment allowed as extra fees set.')) |
|
406 | ||
407 |
if item.user != request.user: |
|
408 |
return HttpResponseForbidden(_('Wrong item: payment not allowed.')) |
|
409 | ||
410 |
return self.handle_payment(request, regie, [item], [], next_url) |
|
411 | ||
412 | ||
394 | 413 |
class PaymentException(Exception): |
395 | 414 |
pass |
396 | 415 |
tests/test_lingo_payment.py | ||
---|---|---|
199 | 199 |
url = '%s?email=%s&orig=wcs' % (reverse('api-add-basket-item'), user_email) |
200 | 200 |
url = sign_url(url, settings.LINGO_API_SIGN_KEY) |
201 | 201 |
resp = app.post_json(url, params=data) |
202 |
item = BasketItem.objects.get(amount=Decimal('22.23')) |
|
202 | 203 |
assert resp.status_code == 200 |
203 |
assert json.loads(resp.content)['result'] == 'success' |
|
204 |
response = json.loads(resp.content) |
|
205 |
assert response['result'] == 'success' |
|
206 |
assert response['payment_url'].endswith('/lingo/item/%s/pay' % item.id) |
|
204 | 207 |
assert BasketItem.objects.filter(amount=Decimal('22.23')).exists() |
205 | 208 |
assert BasketItem.objects.filter(amount=Decimal('22.23'))[0].regie_id == other_regie.id |
206 | 209 | |
... | ... | |
230 | 233 |
resp = app.post_json(url, params=data, status=400) |
231 | 234 |
assert resp.text == 'Unknown regie' |
232 | 235 | |
236 |
def test_pay_single_basket_item(app, key, regie, user, john_doe): |
|
237 |
page = Page(title='xxx', slug='index', template_name='standard') |
|
238 |
page.save() |
|
239 |
cell = LingoBasketCell(page=page, placeholder='content', order=0) |
|
240 |
cell.save() |
|
241 | ||
242 |
amount = 12 |
|
243 |
data = {'amount': amount, 'display_name': 'test amount', |
|
244 |
'url': 'http://example.com'} |
|
245 |
url = '%s?email=%s&orig=wcs' % (reverse('api-add-basket-item'), user.email) |
|
246 |
url = sign_url(url, key) |
|
247 |
resp = app.post_json(url, params=data) |
|
248 |
payment_url = json.loads(resp.content)['payment_url'] |
|
249 |
resp = app.get(payment_url, status=403) |
|
250 |
assert 'No item payment allowed for anonymous users.' in resp.text |
|
251 | ||
252 |
login(app, username='john.doe', password='john.doe') |
|
253 |
resp = app.get(payment_url, status=403) |
|
254 |
assert 'Wrong item: payment not allowed.' in resp.text |
|
255 | ||
256 |
regie.extra_fees_ws_url = 'http://example.com/extra-fees' |
|
257 |
regie.save() |
|
258 | ||
259 |
app.reset() |
|
260 |
login(app) |
|
261 |
resp = app.get(payment_url, status=403) |
|
262 |
assert 'No item payment allowed as extra fees set.' in resp.text |
|
263 | ||
264 |
regie.extra_fees_ws_url = '' |
|
265 |
regie.save() |
|
266 |
# set next_url to check if redirection is done after payment |
|
267 |
resp = app.get(payment_url, params={'next_url': 'http://example.net/form/id/'}) |
|
268 |
assert resp.location.startswith('http://dummy-payment.demo.entrouvert.com/') |
|
269 |
qs = urlparse.parse_qs(urlparse.urlparse(resp.location).query) |
|
270 |
assert qs['amount'] == ['12.00'] |
|
271 | ||
272 |
data = {'transaction_id': qs['transaction_id'][0], 'ok': True, |
|
273 |
'amount': qs['amount'][0], 'signed': True} |
|
274 | ||
275 |
resp = app.get(qs['return_url'][0], params=data) |
|
276 |
assert resp.location == 'http://example.net/form/id/' |
|
277 | ||
233 | 278 |
def test_pay_multiple_regies(app, key, regie, user): |
234 | 279 |
test_add_amount_to_basket(app, key, regie, user) |
235 | 280 | |
236 |
- |