Skip to content

Commit 95d896a

Browse files
Release 5.0.0
1 parent 882199a commit 95d896a

25 files changed

Lines changed: 288 additions & 69 deletions

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Library facilitates your interaction with various services such as transactions,
2121
pip3 install --upgrade wallee
2222
```
2323

24-
### pip3 install from source via github
24+
### pip3 install from source via GitHub
2525

2626
```sh
2727
pip3 install git+http://github.com/wallee-payment/python-sdk.git
@@ -49,7 +49,6 @@ You can also optionally set `default_headers` to set some headers that will be s
4949
```python
5050
from wallee import Configuration
5151
from wallee.api import TransactionServiceApi, TransactionPaymentPageServiceApi
52-
from wallee.models import LineItem, LineItemType, TransactionCreate
5352

5453
space_id = 405
5554

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
import setuptools
44

5-
with open("README.md", "r") as fh:
5+
with open("README.md", "r", encoding="utf8") as fh:
66
long_description = fh.read()
77

88
NAME = "wallee"
9-
VERSION = "4.2.0"
9+
VERSION = "5.0.0"
1010

1111
REQUIRES = [
1212
"certifi >= 14.05.14",

test/constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
SPACE_ID = 405
1717

18+
1819
def get_transaction_create():
1920
return TransactionCreate(
2021
line_items=[

test/test_refund.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,18 @@ def test_refund(self):
8484
"State must be SUCCESSFUL",
8585
)
8686

87+
def test_read_not_found(self):
88+
"""read_not_found() should read not found refund as none"""
89+
90+
NOT_FOUND_REFUND_ID = 0
91+
92+
refund_read = self.refund_service.read(
93+
space_id=SPACE_ID, id=NOT_FOUND_REFUND_ID)
94+
95+
self.assertIsNone(refund_read, "Return data must be None.")
96+
8797
def test_read(self):
88-
"""read() should should fetch refund details"""
98+
"""read() should fetch refund details"""
8999

90100
transaction = self.transaction_service.create(
91101
space_id=SPACE_ID, transaction=get_transaction_create())
@@ -121,6 +131,8 @@ def test_read(self):
121131
read_refund = self.refund_service.read(
122132
space_id=SPACE_ID, id=refund.id)
123133

134+
self.assertIsNotNone(read_refund, "Return data must not be None.")
135+
124136
self.assertEqual(
125137
refund.id,
126138
read_refund.id,
@@ -164,7 +176,7 @@ def test_search(self):
164176
criteria = EntityQuery(
165177
filter=EntityQueryFilter(
166178
field_name="id",
167-
value=transaction_completion.id,
179+
value=refund.id,
168180
type=EntityQueryFilterType.LEAF,
169181
operator=CriteriaOperator.EQUALS
170182
)
@@ -173,6 +185,7 @@ def test_search(self):
173185
refunds_found = self.refund_service.search(
174186
SPACE_ID, query=criteria)
175187

188+
self.assertEqual(1, len(refunds_found))
176189
for ref in refunds_found:
177190
self.assertEqual(
178191
refund.id,

test/test_transaction_completion_service.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
TransactionCompletionState
2727
)
2828

29+
2930
class TransactionCompletionServiceTest(unittest.TestCase):
3031
"""TransactionCompletionServiceApi tests"""
3132

@@ -126,6 +127,8 @@ def test_read(self):
126127
transaction_read = self.transaction_completion_service.read(
127128
space_id=SPACE_ID, id=transaction_completion.id)
128129

130+
self.assertIsNotNone(transaction_read, "Return data must not be None.")
131+
129132
self.assertEqual(transaction_completion.id,
130133
transaction_read.id, "Transaction ids must match", )
131134

test/test_transaction_service.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,16 @@ def test_fetch_payment_methods(self):
155155
self.assertTrue(len(payment_methods) > 0,
156156
"Payment methods should be configured for a given transaction in test space", )
157157

158+
def test_read_not_found(self):
159+
"""read_not_found() should read not found transaction as none"""
160+
161+
NOT_FOUND_TRANSACTION_ID = 0
162+
163+
transaction_read = self.transaction_service.read(
164+
space_id=SPACE_ID, id=NOT_FOUND_TRANSACTION_ID)
165+
166+
self.assertIsNone(transaction_read, "Return data must be None.")
167+
158168
def test_read(self):
159169
"""read() should read transaction details"""
160170

@@ -164,6 +174,8 @@ def test_read(self):
164174
transaction_read = self.transaction_service.read(
165175
space_id=SPACE_ID, id=transaction.id)
166176

177+
self.assertIsNotNone(transaction_read, "Return data must not be None.")
178+
167179
self.assertEqual(transaction.id, transaction_read.id,
168180
"Transaction ids should match")
169181

@@ -195,6 +207,8 @@ def test_read_with_credentials(self):
195207
transaction_read = self.transaction_service.read_with_credentials(
196208
credentials=creds)
197209

210+
self.assertIsNotNone(transaction_read, "Return data must not be None.")
211+
198212
self.assertEqual(transaction.id, transaction_read.id,
199213
"Transaction ids should match")
200214

@@ -239,7 +253,7 @@ def test_process_without_user_interaction(self):
239253
space_id=SPACE_ID, id=transaction.id)
240254

241255
self.assertEqual(
242-
transaction.id, transaction_processed.id, "Transaction ids mush match"
256+
transaction.id, transaction_processed.id, "Transaction ids must match"
243257
)
244258

245259
def test_fetch_one_click_tokens_with_credentials_no_tokens(self):
@@ -318,6 +332,8 @@ def test_process_one_click_token_and_redirect_with_credentials(self):
318332
transaction2_read = self.transaction_service.read(
319333
space_id=SPACE_ID, id=transaction2.id)
320334

335+
self.assertIsNotNone(transaction2_read, "Return data must not be None.")
336+
321337
self.assertEqual(
322338
TransactionState.AUTHORIZED,
323339
transaction2_read.state,
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import unittest
2+
from unittest.mock import patch
3+
4+
from constants import (
5+
API_CONFIG
6+
)
7+
from wallee.api import (
8+
WebhookEncryptionServiceApi
9+
)
10+
from wallee.models import (
11+
WebhookEncryptionPublicKey
12+
)
13+
14+
CONTENT_TO_VERIFY = ('{"entityId":11,"eventId":35,"listenerEntityId":1472041829003,'
15+
'"listenerEntityTechnicalName":"Transaction","spaceId":1,"state":"PROCESSING",'
16+
'"timestamp":"2023-12-19T13:43:35+0000","webhookListenerId":2}')
17+
18+
SIGNATURE_HEADER = ("algorithm=SHA256withECDSA, keyId=ab3b774e-770e-4644-9b51-885d71f973e5, "
19+
"signature=MEYCIQCTzbMrMsOAC6T57T9kQTb1iGZVg2R7n6pY9A4ML4P31gIhAIOoav8cG8x0jpRWQztqSJIC8gXWKq+4DuENEySvmMYf")
20+
21+
PUBLIC_KEY_ID = "ab3b774e-770e-4644-9b51-885d71f973e5"
22+
23+
VALID_ENCODED_PUBLIC_KEY = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEdWq7ZBGsjUzhBO3e6mzUBLpjpV3TQw1bL1rk3ocjn5C5qne7TY0OBBhiWgaPtWlvUcqASz903vtfeSTQma+SBA=="
24+
25+
26+
class WebhookEncryptionServiceTest(unittest.TestCase):
27+
"""WebhookEncryptionServiceApi tests"""
28+
29+
def setUp(self):
30+
self.webhook_encryption_service = WebhookEncryptionServiceApi(API_CONFIG)
31+
32+
def tearDown(self):
33+
pass
34+
35+
@patch('wallee.api.WebhookEncryptionServiceApi.read')
36+
def test_validate_valid_content_and_signature(self, mock_webhook_encryption_service_read):
37+
"""validate_valid_content_and_signature() should validate correct content and signature"""
38+
39+
mock_webhook_encryption_service_read.return_value = (
40+
WebhookEncryptionPublicKey(id=1, public_key=VALID_ENCODED_PUBLIC_KEY))
41+
42+
is_content_valid = self.webhook_encryption_service.is_content_valid(SIGNATURE_HEADER, CONTENT_TO_VERIFY)
43+
44+
mock_webhook_encryption_service_read.assert_called_once()
45+
self.assertIsNotNone(is_content_valid, "Return webhook encryption validation marker must not be None.")
46+
self.assertTrue(is_content_valid, "The webhook encryption content and signature must be valid.")
47+
48+
@patch('wallee.api.WebhookEncryptionServiceApi.read')
49+
def test_read_webhook_encryption_not_found(self, mock_webhook_encryption_service_read):
50+
"""read_webhook_encryption_not_found() should fail when webhook encryption public key is none """
51+
52+
mock_webhook_encryption_service_read.return_value = None
53+
54+
with self.assertRaises(ValueError) as context:
55+
self.webhook_encryption_service.is_content_valid(SIGNATURE_HEADER, CONTENT_TO_VERIFY)
56+
57+
self.assertEqual(str(context.exception), f"Could not find public key with id {PUBLIC_KEY_ID}")
58+
59+
mock_webhook_encryption_service_read.assert_called_once()
60+
61+
@patch('wallee.api.WebhookEncryptionServiceApi.read')
62+
def test_validate_invalid_signature_header(self, mock_webhook_encryption_service_read):
63+
"""validate_invalid_signature_header() should fail when signature header is invalid """
64+
65+
mock_webhook_encryption_service_read.return_value = (
66+
WebhookEncryptionPublicKey(id=1, public_key=VALID_ENCODED_PUBLIC_KEY))
67+
68+
invalid_signature_header = "algorithm=SHA256withECDSA, keyId=ab3b774e-770e-4644-9b51-885d71f973e5"
69+
70+
with self.assertRaises(ValueError) as context:
71+
self.webhook_encryption_service.is_content_valid(invalid_signature_header, CONTENT_TO_VERIFY)
72+
73+
self.assertEqual(str(context.exception), "Invalid webhook signature header. Expected format: "
74+
"'algorithm=<algorithm>, keyId=<keyId>, signature=<signature>'")
75+
76+
77+
if __name__ == "__main__":
78+
unittest.main(failfast=True)

wallee/api/charge_flow_service_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ def fetch_charge_flow_payment_page_url_with_http_info(self, space_id, id, **kwar
419419
body_params = None
420420
# HTTP header `Accept`
421421
header_params['Accept'] = self.api_client.select_header_accept(
422-
['application/json', 'text/plain;charset=utf-8'])
422+
['text/plain;charset=utf-8', 'application/json'])
423423

424424
# Authentication setting
425425
auth_settings = []

wallee/api/human_user_service_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ def export_with_http_info(self, request, **kwargs):
395395
body_params = params['request']
396396
# HTTP header `Accept`
397397
header_params['Accept'] = self.api_client.select_header_accept(
398-
['application/json;charset=utf-8', 'text/csv'])
398+
['text/csv', 'application/json;charset=utf-8'])
399399

400400
# HTTP header `Content-Type`
401401
header_params['Content-Type'] = self.api_client.select_header_content_type(

wallee/api/refund_comment_service_api.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ def create(self, space_id, entity, **kwargs):
135135
136136
:param async_req bool
137137
:param int space_id: (required)
138-
:param RefundCommentCreate entity: (required)
138+
:param RefundCommentCreate entity: The comment object which should be created. (required)
139139
:return: RefundComment
140140
If the method is called asynchronously,
141141
returns the request thread.
@@ -161,7 +161,7 @@ def create_with_http_info(self, space_id, entity, **kwargs):
161161
162162
:param async_req bool
163163
:param int space_id: (required)
164-
:param RefundCommentCreate entity: (required)
164+
:param RefundCommentCreate entity: The comment object which should be created. (required)
165165
:return: RefundComment
166166
If the method is called asynchronously,
167167
returns the request thread.
@@ -309,15 +309,15 @@ def delete_with_http_info(self, space_id, id, **kwargs):
309309
query_params = []
310310
if 'space_id' in params:
311311
query_params.append(('spaceId', params['space_id']))
312-
if 'id' in params:
313-
query_params.append(('id', params['id']))
314312

315313
header_params = {}
316314

317315
form_params = []
318316
local_var_files = {}
319317

320318
body_params = None
319+
if 'id' in params:
320+
body_params = params['id']
321321
# HTTP header `Accept`
322322
header_params['Accept'] = self.api_client.select_header_accept(
323323
['application/json;charset=utf-8'])
@@ -357,7 +357,7 @@ def pin(self, space_id, id, **kwargs):
357357
358358
:param async_req bool
359359
:param int space_id: (required)
360-
:param int id: (required)
360+
:param int id: The id of the comment to pin to the top. (required)
361361
:return: None
362362
If the method is called asynchronously,
363363
returns the request thread.
@@ -383,7 +383,7 @@ def pin_with_http_info(self, space_id, id, **kwargs):
383383
384384
:param async_req bool
385385
:param int space_id: (required)
386-
:param int id: (required)
386+
:param int id: The id of the comment to pin to the top. (required)
387387
:return: None
388388
If the method is called asynchronously,
389389
returns the request thread.
@@ -468,7 +468,7 @@ def read(self, space_id, id, **kwargs):
468468
469469
:param async_req bool
470470
:param int space_id: (required)
471-
:param int id: (required)
471+
:param int id: The id of the comment which should be returned. (required)
472472
:return: RefundComment
473473
If the method is called asynchronously,
474474
returns the request thread.
@@ -494,7 +494,7 @@ def read_with_http_info(self, space_id, id, **kwargs):
494494
495495
:param async_req bool
496496
:param int space_id: (required)
497-
:param int id: (required)
497+
:param int id: The id of the comment which should be returned. (required)
498498
:return: RefundComment
499499
If the method is called asynchronously,
500500
returns the request thread.
@@ -579,7 +579,7 @@ def unpin(self, space_id, id, **kwargs):
579579
580580
:param async_req bool
581581
:param int space_id: (required)
582-
:param int id: (required)
582+
:param int id: The id of the comment to unpin. (required)
583583
:return: None
584584
If the method is called asynchronously,
585585
returns the request thread.
@@ -605,7 +605,7 @@ def unpin_with_http_info(self, space_id, id, **kwargs):
605605
606606
:param async_req bool
607607
:param int space_id: (required)
608-
:param int id: (required)
608+
:param int id: The id of the comment to unpin. (required)
609609
:return: None
610610
If the method is called asynchronously,
611611
returns the request thread.
@@ -690,7 +690,7 @@ def update(self, space_id, entity, **kwargs):
690690
691691
:param async_req bool
692692
:param int space_id: (required)
693-
:param RefundCommentActive entity: (required)
693+
:param RefundCommentActive entity: The comment object with the properties which should be updated. (required)
694694
:return: RefundComment
695695
If the method is called asynchronously,
696696
returns the request thread.
@@ -716,7 +716,7 @@ def update_with_http_info(self, space_id, entity, **kwargs):
716716
717717
:param async_req bool
718718
:param int space_id: (required)
719-
:param RefundCommentActive entity: (required)
719+
:param RefundCommentActive entity: The comment object with the properties which should be updated. (required)
720720
:return: RefundComment
721721
If the method is called asynchronously,
722722
returns the request thread.

0 commit comments

Comments
 (0)