Projet

Général

Profil

0001-lingo-refuse-payment-if-an-item-cannot-be-trigged-58.patch

Thomas Noël, 29 octobre 2021 15:10

Télécharger (30,7 ko)

Voir les différences:

Subject: [PATCH] lingo: refuse payment if an item cannot be trigged (#58210)

 combo/apps/lingo/models.py  |   9 ++
 combo/apps/lingo/views.py   |   6 +
 tests/test_lingo_payment.py | 212 ++++++++++++++++++++++++++----------
 3 files changed, 172 insertions(+), 55 deletions(-)
combo/apps/lingo/models.py
650 650
                    transaction.poll_backend()
651 651
        return qs
652 652

  
653
    def is_notifiable(self, status='paid'):
654
        if not self.source_url:
655
            return True
656
        url = self.source_url + 'jump/trigger/%s' % status
657
        req = requests.get(url, remote_service='auto', timeout=5)
658
        if req.status_code == 404:
659
            return False
660
        return True
661

  
653 662
    def notify(self, status):
654 663
        if not self.source_url:
655 664
            return
combo/apps/lingo/views.py
393 393
            if item.regie != regie:
394 394
                messages.error(request, _('Invalid grouping for basket items.'))
395 395
                return HttpResponseRedirect(next_url)
396

  
397
        for item in items:
398
            if not item.is_notifiable():
399
                messages.error(request, _('At least one item is not linked to a payable form.'))
400
                return HttpResponseRedirect(next_url)
401

  
396 402
        user = request.user if request.user.is_authenticated else None
397 403
        transaction = Transaction()
398 404
        if user:
tests/test_lingo_payment.py
177 177
    assert json.loads(resp.text).get('data')[0]['id'] == Regie.objects.get(is_default=True).slug
178 178

  
179 179

  
180
def test_payment_min_amount(app, basket_page, regie, user):
180
@mock.patch('combo.utils.requests_wrapper.RequestsSession.request')
181
def test_payment_min_amount(mock_trigger_request, app, basket_page, regie, user):
182
    mock_response = mock.Mock()
183
    mock_response.status_code = 403
184
    mock_trigger_request.return_value = mock_response
181 185
    items = {
182 186
        'item1': {'amount': '1.5', 'source_url': '/item/1'},
183 187
        'item2': {'amount': '2.4', 'source_url': '/item/2'},
......
189 193
    resp = login(app).get('/test_basket_cell/')
190 194
    resp = resp.form.submit()
191 195
    assert resp.status_code == 302
196
    assert mock_trigger_request.call_count == 0
192 197

  
193 198

  
194
def test_transaction_manual_validation(app, basket_page, user, monkeypatch):
199
@mock.patch('combo.utils.requests_wrapper.RequestsSession.request')
200
def test_transaction_manual_validation(mock_trigger_request, app, basket_page, user, monkeypatch):
201
    mock_response = mock.Mock()
202
    mock_response.status_code = 403
203
    mock_trigger_request.return_value = mock_response
195 204
    pb = PaymentBackend.objects.create(
196 205
        label='test1',
197 206
        slug='test1',
......
206 215
        transaction_options={'manual_validation': True},
207 216
        can_pay_only_one_basket_item=False,
208 217
    )
209
    BasketItem.objects.create(user=user, regie=regie, subject='item1', amount='1.5', source_url='/item/1')
218
    BasketItem.objects.create(
219
        user=user, regie=regie, subject='item1', amount='1.5', source_url='http://example.org/item/1/'
220
    )
210 221

  
211 222
    with mock.patch('eopayment.Payment') as MockPayment:
212 223
        MockPayment.return_value.request.return_value = (9876, 3, {})
213 224
        resp = login(app).get('/test_basket_cell/')
214 225
        resp = resp.form.submit()
215 226
        assert MockPayment.return_value.request.call_args[1]['manual_validation'] is True
227
    assert mock_trigger_request.call_count == 1
228
    assert mock_trigger_request.call_args[0][0] == 'GET'
229
    assert mock_trigger_request.call_args[0][1].startswith('http://example.org/item/1/jump/trigger/paid')
216 230

  
217 231

  
232
@mock.patch('combo.utils.requests_wrapper.RequestsSession.request')
218 233
@pytest.mark.parametrize('with_payment_backend', [False, True])
219
def test_successfull_items_payment(app, basket_page, regie, user, with_payment_backend):
234
def test_successfull_items_payment(mock_trigger_request, app, basket_page, regie, user, with_payment_backend):
235
    mock_response = mock.Mock()
236
    mock_response.status_code = 403
237
    mock_trigger_request.return_value = mock_response
220 238
    items = {
221
        'item1': {'amount': '10.5', 'source_url': 'http://example.org/item/1'},
222
        'item2': {'amount': '42', 'source_url': 'http://example.org/item/2'},
223
        'item3': {'amount': '100', 'source_url': 'http://example.org/item/3'},
224
        'item4': {'amount': '354', 'source_url': 'http://example.org/item/4'},
239
        'item1': {'amount': '10.5', 'source_url': 'http://example.org/item/1/'},
240
        'item2': {'amount': '42', 'source_url': 'http://example.org/item/2/'},
241
        'item3': {'amount': '100', 'source_url': 'http://example.org/item/3/'},
242
        'item4': {'amount': '354', 'source_url': 'http://example.org/item/4/'},
225 243
    }
226 244
    b_items = []
227 245
    for subject, details in items.items():
......
230 248

  
231 249
    resp = login(app).get('/test_basket_cell/')
232 250
    resp = resp.form.submit()
251
    assert mock_trigger_request.call_count == 4  # source_url/jump/trigger/paid items had been verified
233 252
    assert resp.status_code == 302
234 253
    location = resp.location
235 254
    assert 'dummy-payment' in location
......
264 283
    )
265 284
    other_regie.save()
266 285

  
267
    data = {'display_name': 'test amount', 'url': 'http://example.com'}
286
    data = {'display_name': 'test amount', 'url': 'http://example.com/form/42/'}
268 287
    url = '%s?NameId=%s&orig=wcs' % (reverse('api-add-basket-item'), user_name_id)
269 288
    url = sign_url(url, key)
270 289
    resp = app.post_json(url, params=data, status=400)
......
494 513

  
495 514

  
496 515
def test_add_basket_item_without_display_name(app, user_name_id, regie):
497
    data = {'amount': '42', 'url': 'http://example.com'}
516
    data = {'amount': '42', 'url': 'http://example.com/form/id/'}
498 517
    url = '%s?NameId=%s&orig=wcs' % (reverse('api-add-basket-item'), user_name_id)
499 518
    url = sign_url(url, settings.LINGO_API_SIGN_KEY)
500 519
    resp = app.post_json(url, params=data, status=400)
501 520
    assert 'missing display_name parameter' in resp.text
502 521

  
503 522

  
504
def test_cant_pay_if_different_capture_date(app, basket_page, regie, user):
523
@mock.patch('combo.utils.requests_wrapper.RequestsSession.request')
524
def test_cant_pay_if_different_capture_date(mock_trigger_request, app, basket_page, regie, user):
505 525
    capture1 = (timezone.now() + timedelta(days=1)).date()
506 526
    capture2 = (timezone.now() + timedelta(days=2)).date()
507 527
    items = {
508 528
        'item1': {
509 529
            'amount': '10.5',
510 530
            'capture_date': capture1.isoformat(),
511
            'source_url': 'http://example.org/item/1',
531
            'source_url': 'http://example.org/item/1/',
512 532
        },
513 533
        'item2': {
514 534
            'amount': '42',
515 535
            'capture_date': capture2.isoformat(),
516
            'source_url': 'http://example.org/item/2',
536
            'source_url': 'http://example.org/item/2/',
517 537
        },
518 538
    }
519 539
    b_items = []
......
527 547
    assert urllib.parse.urlparse(resp.location).path == '/test_basket_cell/'
528 548
    resp = resp.follow()
529 549
    assert "Invalid grouping for basket items: different capture dates." in resp.text
550
    assert mock_trigger_request.call_count == 0
530 551

  
531 552

  
532
def test_pay_single_basket_item(app, key, regie, user_name_id, john_doe):
553
@mock.patch('combo.utils.requests_wrapper.RequestsSession.request')
554
def test_pay_single_basket_item(mock_trigger_request, app, key, regie, user_name_id, john_doe):
533 555
    page = Page(title='xxx', slug='index', template_name='standard')
534 556
    page.save()
535 557
    cell = LingoBasketCell(page=page, placeholder='content', order=0)
536 558
    cell.save()
537 559

  
538 560
    amount = 12
539
    data = {'amount': amount, 'display_name': 'test amount', 'url': 'http://example.com'}
561
    data = {'amount': amount, 'display_name': 'test amount', 'url': 'http://example.com/form/42/'}
540 562
    url = '%s?NameId=%s&orig=wcs' % (reverse('api-add-basket-item'), user_name_id)
541 563
    url = sign_url(url, key)
542 564
    resp = app.post_json(url, params=data)
......
547 569

  
548 570
    # check that payment is possible unconnected
549 571
    app.get(payment_url, status=302)
572
    assert mock_trigger_request.call_count == 1
550 573

  
551 574
    # and connected with another user (john.doe != admin)
552 575
    login(app, username='john.doe', password='john.doe')
553 576
    app.get(payment_url, status=302)
577
    assert mock_trigger_request.call_count == 2
554 578

  
555 579
    # forbid payment to regie with extra_fees_ws_url
556 580
    regie.extra_fees_ws_url = 'http://example.com/extra-fees'
......
563 587
    regie.extra_fees_ws_url = ''
564 588
    regie.save()
565 589

  
590
    # forbid payment if payment trigger is impossible (404)
591
    app.reset()
592
    login(app)
593
    mock_trigger_request.reset_mock()
594
    mock_response = mock.Mock()
595
    mock_response.status_code = 404
596
    mock_trigger_request.return_value = mock_response
597
    resp = app.get(payment_url, status=302)
598
    assert mock_trigger_request.call_count == 1
599
    assert mock_trigger_request.call_args[0][0] == 'GET'
600
    assert mock_trigger_request.call_args[0][1].startswith('http://example.com/form/42/jump/trigger/paid')
601
    assert 'At least one item is not linked to a payable form.' in app.session['_messages']
602

  
603
    # now launch a good payment
604
    mock_trigger_request.reset_mock()
605
    mock_response = mock.Mock()
606
    mock_response.status_code = 403
607
    mock_trigger_request.return_value = mock_response
566 608
    assert not Transaction.objects.filter(user__username='admin', status=0).exists()
567 609
    resp = app.get(payment_url, params={'next_url': 'http://example.net/form/id/'})
610
    assert mock_trigger_request.call_count == 1
611
    assert mock_trigger_request.call_args[0][0] == 'GET'
612
    assert mock_trigger_request.call_args[0][1].startswith('http://example.com/form/42/jump/trigger/paid')
568 613
    assert Transaction.objects.filter(user__username='admin', status=0).exists()
569 614

  
570 615
    # make sure the redirection is done to the payment backend
......
583 628
    assert Transaction.objects.filter(user__username='admin', status=eopayment.PAID).exists()
584 629

  
585 630

  
586
def test_pay_single_basket_item_another_user(app, key, regie, user_name_id, john_doe):
631
@mock.patch('combo.utils.requests_wrapper.RequestsSession.request')
632
def test_pay_single_basket_item_another_user(mock_trigger_request, app, key, regie, user_name_id, john_doe):
587 633
    page = Page(title='xxx', slug='index', template_name='standard')
588 634
    page.save()
589 635
    cell = LingoBasketCell(page=page, placeholder='content', order=0)
590 636
    cell.save()
591 637

  
592 638
    amount = 12
593
    data = {'amount': amount, 'display_name': 'test amount', 'url': 'http://example.com'}
639
    data = {'amount': amount, 'display_name': 'test amount', 'url': 'http://example.com/form/id/'}
594 640
    url = '%s?NameId=%s&orig=wcs' % (reverse('api-add-basket-item'), user_name_id)
595 641
    url = sign_url(url, key)
596 642
    resp = app.post_json(url, params=data)
......
603 649

  
604 650
    assert not Transaction.objects.filter(user__username='john.doe', status=0).exists()
605 651
    resp = app.get(payment_url, params={'next_url': 'http://example.net/form/id/'})
652
    assert mock_trigger_request.call_count == 1
606 653
    assert Transaction.objects.filter(user__username='john.doe', status=0).exists()
607 654

  
608 655
    # make sure the redirection is done to the payment backend
......
621 668
    assert Transaction.objects.filter(user__username='john.doe', status=eopayment.PAID).exists()
622 669

  
623 670

  
624
def test_pay_multiple_regies(app, key, regie, user_name_id):
671
@mock.patch('combo.utils.requests_wrapper.RequestsSession.request')
672
def test_pay_multiple_regies(mocked_trigger_request, app, key, regie, user_name_id):
625 673
    test_add_amount_to_basket(app, key, regie, user_name_id)
626 674

  
627 675
    page = Page(title='xxx', slug='test_basket_cell', template_name='standard')
......
630 678
    cell.save()
631 679

  
632 680
    resp = login(app).get(page.get_online_url())
681
    assert mocked_trigger_request.call_count == 0
633 682
    resp = resp.forms[0].submit()
683
    assert mocked_trigger_request.call_count == 6  # trigger/paid verification, first regie
634 684
    assert resp.location.startswith('http://dummy-payment.demo.entrouvert.com/')
635 685
    qs = urllib.parse.parse_qs(urllib.parse.urlparse(resp.location).query)
636 686
    assert qs['amount'] == ['234.46']
637 687

  
638 688
    resp = login(app).get(page.get_online_url())
689
    mocked_trigger_request.reset_mock()
639 690
    resp = resp.forms[1].submit()
691
    assert mocked_trigger_request.call_count == 1  # trigger/paid verification, other regie
640 692
    qs = urllib.parse.parse_qs(urllib.parse.urlparse(resp.location).query)
641 693
    assert qs['amount'] == ['22.23']
642 694

  
......
658 710
def test_cancel_basket_item(app, key, regie, user_name_id):
659 711
    url = '%s?NameId=%s&orig=wcs' % (reverse('api-add-basket-item'), user_name_id)
660 712
    url = sign_url(url, key)
661
    data = {'amount': 42, 'display_name': 'test amount', 'url': 'http://example.com/', 'notify': 'true'}
713
    data = {
714
        'amount': 42,
715
        'display_name': 'test amount',
716
        'url': 'http://example.com/form/id/',
717
        'notify': 'true',
718
    }
662 719
    resp = app.post_json(url, params=data)
663 720
    assert resp.status_code == 200
664 721
    assert json.loads(resp.text)['result'] == 'success'
......
723 780
        url = sign_url(url, key)
724 781
        data = {'basket_item_id': basket_item_id, 'notify': 'true'}
725 782
        resp = app.post_json(url, params=data)
726
        assert request.call_args[0] == ('POST', 'http://example.com/jump/trigger/cancelled')
783
        assert request.call_args[0] == ('POST', 'http://example.com/form/id/jump/trigger/cancelled')
727 784
        assert not BasketItem.objects.filter(amount=42, cancellation_date__isnull=True).exists()
728 785
        assert BasketItem.objects.filter(amount=21, cancellation_date__isnull=True).exists()
729 786

  
......
807 864
    page = Page(title='xxx', slug='index', template_name='standard')
808 865
    page.save()
809 866
    BasketItem.objects.create(
810
        user=user, regie=regie, subject='test_item', amount='10.5', source_url='http://example.org/testitem/'
867
        user=user, regie=regie, subject='test_item', amount='10.5', source_url='http://example.org/test/id/'
811 868
    )
812 869
    resp = login(app).get(basket_page.get_online_url())
813
    resp = resp.form.submit()
870
    with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as trigger_request:
871
        resp = resp.form.submit()
872
        assert trigger_request.call_count == 1
814 873
    assert resp.status_code == 302
815 874
    location = resp.location
816 875
    parsed = urllib.parse.urlparse(location)
......
824 883
    with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as request:
825 884
        get_resp = app.get(callback_url, params=data)
826 885
        url = request.call_args[0][1]
827
        assert url.startswith('http://example.org/testitem/jump/trigger/paid')
886
        assert url.startswith('http://example.org/test/id/jump/trigger/paid')
828 887
    assert get_resp.status_code == 200
829 888
    assert Transaction.objects.get(order_id=transaction_id).status == 3
830 889

  
831 890
    BasketItem.objects.create(
832
        user=user, regie=regie, subject='test_item', amount='11.5', source_url='http://example.org/testitem/'
891
        user=user, regie=regie, subject='test_item', amount='11.5', source_url='http://example.org/test/id/'
833 892
    )
834 893
    resp = login(app).get(basket_page.get_online_url())
835
    resp = resp.form.submit()
894
    with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as trigger_request:
895
        resp = resp.form.submit()
896
        assert trigger_request.call_count == 1
836 897
    assert resp.status_code == 302
837 898
    location = resp.location
838 899
    parsed = urllib.parse.urlparse(location)
......
858 919
@pytest.mark.parametrize('with_payment_backend', [False, True])
859 920
def test_payment_callback_no_regie(app, basket_page, regie, user, with_payment_backend):
860 921
    BasketItem.objects.create(
861
        user=user, regie=regie, subject='test_item', amount='10.5', source_url='http://example.org/testitem/'
922
        user=user, regie=regie, subject='test_item', amount='10.5', source_url='http://example.org/test/1/'
862 923
    )
863 924
    resp = login(app).get(basket_page.get_online_url())
864
    resp = resp.form.submit()
925
    with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as trigger_request:
926
        resp = resp.form.submit()
927
        assert trigger_request.call_count == 1
928
        assert trigger_request.call_args[0][0] == 'GET'
929
        assert trigger_request.call_args[0][1].startswith('http://example.org/test/1/jump/trigger/paid')
865 930
    assert resp.status_code == 302
866 931
    location = resp.location
867 932
    parsed = urllib.parse.urlparse(location)
......
874 939
    callback_url = get_url(with_payment_backend, 'lingo-callback', regie)
875 940
    with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as request:
876 941
        get_resp = app.get(callback_url, params=data)
942
        assert request.call_args[0][0] == 'POST'
877 943
        url = request.call_args[0][1]
878
        assert url.startswith('http://example.org/testitem/jump/trigger/paid')
944
        assert url.startswith('http://example.org/test/1/jump/trigger/paid')
879 945
    assert get_resp.status_code == 200
880 946
    assert Transaction.objects.get(order_id=transaction_id).status == 3
881 947

  
882 948
    BasketItem.objects.create(
883
        user=user, regie=regie, subject='test_item', amount='11.5', source_url='http://example.org/testitem/'
949
        user=user, regie=regie, subject='test_item', amount='11.5', source_url='http://example.org/test/2/'
884 950
    )
885 951
    resp = login(app).get(basket_page.get_online_url())
886
    resp = resp.form.submit()
952
    with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as trigger_request:
953
        resp = resp.form.submit()
954
        assert trigger_request.call_count == 1
955
        assert trigger_request.call_args[0][0] == 'GET'
956
        assert trigger_request.call_args[0][1].startswith('http://example.org/test/2/jump/trigger/paid')
887 957
    assert resp.status_code == 302
888 958
    location = resp.location
889 959
    parsed = urllib.parse.urlparse(location)
......
898 968
    page = Page(title='xxx', slug='index', template_name='standard')
899 969
    page.save()
900 970
    BasketItem.objects.create(
901
        user=user, regie=regie, subject='test_item', amount='10.5', source_url='http://example.org/testitem/'
971
        user=user, regie=regie, subject='test_item', amount='10.5', source_url='http://example.org/test/3/'
902 972
    )
903 973
    resp = login(app).get(basket_page.get_online_url())
904
    resp = resp.form.submit()
974
    with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as trigger_request:
975
        resp = resp.form.submit()
976
        assert trigger_request.call_count == 1
977
        assert trigger_request.call_args[0][0] == 'GET'
978
        assert trigger_request.call_args[0][1].startswith('http://example.org/test/3/jump/trigger/paid')
905 979
    assert resp.status_code == 302
906 980
    location = resp.location
907 981
    parsed = urllib.parse.urlparse(location)
......
948 1022
@pytest.mark.parametrize('with_payment_backend', [False, True])
949 1023
def test_payment_callback_waiting(app, basket_page, regie, user, with_payment_backend):
950 1024
    item = BasketItem.objects.create(
951
        user=user, regie=regie, subject='test_item', amount='10.5', source_url='http://example.org/testitem/'
1025
        user=user, regie=regie, subject='test_item', amount='10.5', source_url='http://example.org/test/4/'
952 1026
    )
953 1027
    resp = login(app).get(basket_page.get_online_url())
954
    resp = resp.form.submit()
1028
    with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as trigger_request:
1029
        resp = resp.form.submit()
1030
        assert trigger_request.call_count == 1
1031
        assert trigger_request.call_args[0][0] == 'GET'
1032
        assert trigger_request.call_args[0][1].startswith('http://example.org/test/4/jump/trigger/paid')
955 1033
    assert resp.status_code == 302
956 1034
    location = resp.location
957 1035
    parsed = urllib.parse.urlparse(location)
......
975 1053
        resp = app.get(callback_url, params=data)
976 1054
        assert resp.status_code == 200
977 1055
        url = request.call_args[0][1]
978
        assert url.startswith('http://example.org/testitem/jump/trigger/paid')
1056
        assert url.startswith('http://example.org/test/4/jump/trigger/paid')
979 1057

  
980 1058
    assert Transaction.objects.get(order_id=transaction_id).status == eopayment.PAID
981 1059
    assert BasketItem.objects.get(id=item.id).payment_date
......
985 1063
@pytest.mark.parametrize('with_payment_backend', [False, True])
986 1064
def test_payment_no_callback_just_return(caplog, app, basket_page, regie, user, with_payment_backend):
987 1065
    BasketItem.objects.create(
988
        user=user, regie=regie, subject='test_item', amount='10.5', source_url='http://example.org/testitem/'
1066
        user=user, regie=regie, subject='test_item', amount='10.5', source_url='http://example.org/test/5/'
989 1067
    )
990 1068
    resp = login(app).get(basket_page.get_online_url())
991
    resp = resp.form.submit()
1069
    with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as trigger_request:
1070
        resp = resp.form.submit()
1071
        assert trigger_request.call_count == 1
1072
        assert trigger_request.call_args[0][0] == 'GET'
1073
        assert trigger_request.call_args[0][1].startswith('http://example.org/test/5/jump/trigger/paid')
992 1074
    assert resp.status_code == 302
993 1075
    location = resp.location
994 1076
    parsed = urllib.parse.urlparse(location)
......
1024 1106
    with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as request:
1025 1107
        get_resp = app.post(return_url, params=data)
1026 1108
        url = request.call_args[0][1]
1027
        assert url.startswith('http://example.org/testitem/jump/trigger/paid')
1109
        assert url.startswith('http://example.org/test/5/jump/trigger/paid')
1028 1110
    # redirect to payment status
1029 1111
    assert get_resp.status_code == 302
1030 1112
    assert urllib.parse.urlparse(get_resp.url).path.startswith('/lingo/payment-status')
......
1382 1464
@pytest.mark.parametrize('with_payment_backend', [False, True])
1383 1465
def test_payment_callback_error(app, basket_page, regie, user, with_payment_backend):
1384 1466
    item = BasketItem.objects.create(
1385
        user=user, regie=regie, subject='test_item', amount='10.5', source_url='http://example.org/testitem/'
1467
        user=user, regie=regie, subject='test_item', amount='10.5', source_url='http://example.org/test/6/'
1386 1468
    )
1387 1469
    resp = login(app).get(basket_page.get_online_url())
1388
    resp = resp.form.submit()
1470
    with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as trigger_request:
1471
        resp = resp.form.submit()
1472
        assert trigger_request.call_count == 1
1473
        assert trigger_request.call_args[0][0] == 'GET'
1474
        assert trigger_request.call_args[0][1].startswith('http://example.org/test/6/jump/trigger/paid')
1389 1475
    assert resp.status_code == 302
1390 1476
    location = resp.location
1391 1477
    parsed = urllib.parse.urlparse(location)
......
1407 1493
        request.return_value = mock_response
1408 1494
        get_resp = app.get(callback_url, params=data)
1409 1495
        url = request.call_args[0][1]
1410
        assert url.startswith('http://example.org/testitem/jump/trigger/paid')
1496
        assert url.startswith('http://example.org/test/6/jump/trigger/paid')
1411 1497
    assert get_resp.status_code == 200
1412 1498
    assert Transaction.objects.get(order_id=transaction_id).status == 3
1413 1499
    assert BasketItem.objects.get(id=item.id).payment_date
......
1430 1516
        request.return_value = mock_response
1431 1517
        appconfig.notify_payments()
1432 1518
        url = request.call_args[0][1]
1433
        assert url.startswith('http://example.org/testitem/jump/trigger/paid')
1519
        assert url.startswith('http://example.org/test/6/jump/trigger/paid')
1434 1520
    assert BasketItem.objects.get(id=item.id).payment_date
1435 1521
    assert BasketItem.objects.get(id=item.id).notification_date
1436 1522

  
......
1448 1534
@pytest.mark.parametrize("authenticated", [True, False])
1449 1535
def test_payment_no_basket(app, user_name_id, regie, authenticated):
1450 1536
    url = reverse('api-add-basket-item')
1451
    source_url = 'http://example.org/item/1'
1537
    source_url = 'http://example.org/item/1/'
1452 1538
    data = {'amount': 10, 'display_name': 'test item', 'url': source_url}
1453 1539
    if authenticated:
1454 1540
        data['NameId'] = user_name_id
......
1484 1570
    # amount ok, redirection to payment backend
1485 1571
    item.amount = Decimal('10.00')
1486 1572
    item.save()
1487
    resp = app.get(payment_url)
1573
    with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as trigger_request:
1574
        resp = app.get(payment_url)
1575
        assert trigger_request.call_count == 1
1576
        assert trigger_request.call_args[0][0] == 'GET'
1577
        assert trigger_request.call_args[0][1].startswith('http://example.org/item/1/jump/trigger/paid')
1488 1578
    assert resp.location.startswith('http://dummy-payment.demo.entrouvert.com/')
1489 1579
    qs = urllib.parse.parse_qs(urllib.parse.urlparse(resp.location).query)
1490 1580
    assert qs['amount'] == ['10.00']
......
1494 1584
        assert 'email' not in qs
1495 1585

  
1496 1586
    # mail can be specified here for anonymous user
1497
    resp = app.get(
1498
        payment_url,
1499
        params={
1500
            'email': 'foo@localhost',
1501
        },
1502
    )
1587
    with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as trigger_request:
1588
        resp = app.get(
1589
            payment_url,
1590
            params={
1591
                'email': 'foo@localhost',
1592
            },
1593
        )
1594
        assert trigger_request.call_count == 1
1595
        assert trigger_request.call_args[0][0] == 'GET'
1596
        assert trigger_request.call_args[0][1].startswith('http://example.org/item/1/jump/trigger/paid')
1503 1597
    assert resp.location.startswith('http://dummy-payment.demo.entrouvert.com/')
1504 1598
    qs = urllib.parse.parse_qs(urllib.parse.urlparse(resp.location).query)
1505 1599
    assert qs['amount'] == ['10.00']
......
1612 1706

  
1613 1707
def test_request_payment_exception(app, basket_page, regie, user):
1614 1708
    BasketItem.objects.create(
1615
        user=user, regie=regie, subject='test_item', amount='10.5', source_url='http://example.org/testitem/'
1709
        user=user, regie=regie, subject='test_item', amount='10.5', source_url='http://example.org/test/7/'
1616 1710
    )
1617 1711

  
1618 1712
    with mock.patch('eopayment.dummy.Payment.request', autospec=True) as mock_request:
1619 1713
        mock_request.side_effect = eopayment.PaymentException
1620 1714
        resp = login(app).get(basket_page.get_online_url())
1621
        resp = resp.form.submit().follow()
1715
        with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as trigger_request:
1716
            resp = resp.form.submit().follow()
1717
            assert trigger_request.call_count == 1
1718
            assert trigger_request.call_args[0][0] == 'GET'
1719
            assert trigger_request.call_args[0][1].startswith('http://example.org/test/7/jump/trigger/paid')
1622 1720
        assert 'Failed to initiate payment request' in resp.text
1623 1721

  
1624 1722

  
1625 1723
@pytest.mark.parametrize('transaction_date', [None, datetime(2020, 1, 1, 12, 00, 00, tzinfo=utc)])
1626 1724
def test_bank_transaction_date(app, key, regie, user, john_doe, caplog, transaction_date):
1627 1725
    amount = 12
1628
    data = {'amount': amount, 'display_name': 'test amount', 'url': 'http://example.com/'}
1726
    data = {'amount': amount, 'display_name': 'test amount', 'url': 'http://example.com/form/id/'}
1629 1727
    url = reverse('api-add-basket-item') + '?orig=wcs'
1630 1728
    url = sign_url(url, key)
1631 1729
    resp = app.post_json(url, params=data)
......
1633 1731
    assert BasketItem.objects.filter(regie=regie, amount=amount, payment_date__isnull=True).exists()
1634 1732

  
1635 1733
    payment_url = resp.json['payment_url']
1636
    resp = app.get(payment_url, params={'next_url': 'http://example.net/form/id/'})
1734
    with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as trigger_request:
1735
        resp = app.get(payment_url, params={'next_url': 'http://example.net/form/id/'})
1736
        assert trigger_request.call_count == 1
1737
        assert trigger_request.call_args[0][0] == 'GET'
1738
        assert trigger_request.call_args[0][1].startswith('http://example.com/form/id/jump/trigger/paid')
1637 1739

  
1638 1740
    assert Transaction.objects.count() == 1
1639 1741
    transaction = Transaction.objects.get()
......
1689 1791
                assert json.loads(post.call_args[1]['data'])['bank_transaction_date'] == '2020-01-02T12:00:00'
1690 1792
            else:
1691 1793
                assert json.loads(post.call_args[1]['data'])['bank_transaction_date'] == '2020-01-01T12:00:00'
1692
            assert post.call_args[0][0] == 'http://example.com/jump/trigger/paid'
1794
            assert post.call_args[0][0] == 'http://example.com/form/id/jump/trigger/paid'
1693 1795
    transaction.refresh_from_db()
1694 1796
    if transaction_date is None:
1695 1797
        transaction.refresh_from_db()
1696
-