python-payway 0.0.8__tar.gz → 0.0.10__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_payway-0.0.8/python_payway.egg-info → python_payway-0.0.10}/PKG-INFO +37 -1
- {python_payway-0.0.8 → python_payway-0.0.10}/README.md +36 -0
- {python_payway-0.0.8 → python_payway-0.0.10}/payway/client.py +2 -2
- {python_payway-0.0.8 → python_payway-0.0.10}/payway/constants.py +1 -3
- {python_payway-0.0.8 → python_payway-0.0.10}/payway/customers.py +3 -3
- {python_payway-0.0.8 → python_payway-0.0.10}/payway/model.py +14 -3
- python_payway-0.0.10/payway/transactions.py +43 -0
- {python_payway-0.0.8 → python_payway-0.0.10}/pyproject.toml +1 -1
- {python_payway-0.0.8 → python_payway-0.0.10/python_payway.egg-info}/PKG-INFO +37 -1
- {python_payway-0.0.8 → python_payway-0.0.10}/tests/test_client.py +23 -0
- {python_payway-0.0.8 → python_payway-0.0.10}/tests/test_customers.py +14 -0
- python_payway-0.0.10/tests/test_transactions.py +66 -0
- python_payway-0.0.8/payway/transactions.py +0 -18
- python_payway-0.0.8/tests/test_transactions.py +0 -32
- {python_payway-0.0.8 → python_payway-0.0.10}/LICENSE +0 -0
- {python_payway-0.0.8 → python_payway-0.0.10}/payway/__init__.py +0 -0
- {python_payway-0.0.8 → python_payway-0.0.10}/payway/exceptions.py +0 -0
- {python_payway-0.0.8 → python_payway-0.0.10}/payway/test_utils.py +0 -0
- {python_payway-0.0.8 → python_payway-0.0.10}/payway/utils.py +0 -0
- {python_payway-0.0.8 → python_payway-0.0.10}/python_payway.egg-info/SOURCES.txt +0 -0
- {python_payway-0.0.8 → python_payway-0.0.10}/python_payway.egg-info/dependency_links.txt +0 -0
- {python_payway-0.0.8 → python_payway-0.0.10}/python_payway.egg-info/requires.txt +0 -0
- {python_payway-0.0.8 → python_payway-0.0.10}/python_payway.egg-info/top_level.txt +0 -0
- {python_payway-0.0.8 → python_payway-0.0.10}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-payway
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.10
|
|
4
4
|
Summary: Python client for working with Westpac's PayWay REST API
|
|
5
5
|
Author-email: Ben Napper <reppan197@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -201,6 +201,27 @@ Poll a transaction using the `get_transaction` method.
|
|
|
201
201
|
transaction, errors = client.get_transaction(transaction.transaction_id)
|
|
202
202
|
```
|
|
203
203
|
|
|
204
|
+
## Search transactions
|
|
205
|
+
|
|
206
|
+
PayWay has no plain `GET /transactions` resource, only three search paths. Each returns a
|
|
207
|
+
paginated list (20 per page, most recent first) with `next`/`prev` links.
|
|
208
|
+
|
|
209
|
+
```python
|
|
210
|
+
response = client.search_transactions_by_customer(customer_number)
|
|
211
|
+
response = client.search_transactions_by_receipt(receipt_number)
|
|
212
|
+
response = client.search_transactions_by_order(order_number)
|
|
213
|
+
|
|
214
|
+
transactions = response["data"]
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Pass `page` to fetch a later page, using the number from the `next`/`prev` links:
|
|
218
|
+
|
|
219
|
+
```python
|
|
220
|
+
response = client.search_transactions_by_customer(customer_number, page=2)
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
`list_customers()` takes the same `page` argument.
|
|
224
|
+
|
|
204
225
|
## Process and capture a pre-authorisation
|
|
205
226
|
|
|
206
227
|
To process a credit card pre-authorisation using a credit card stored against a customer use `preAuth` as the `transaction_type` along with the customer's PayWay number, amount and currency.
|
|
@@ -260,6 +281,21 @@ PayWay API documentation <https://www.payway.com.au/docs/rest.html>
|
|
|
260
281
|
It is recommended to use PayWay's Trusted Frame <https://www.payway.com.au/docs/rest.html#trusted-frame>
|
|
261
282
|
when creating a single use token of a card or bank account so your PCI-compliance scope is reduced.
|
|
262
283
|
|
|
284
|
+
## Keeping the raw response
|
|
285
|
+
|
|
286
|
+
Models parsed from a PayWay response keep that response verbatim on `raw`:
|
|
287
|
+
|
|
288
|
+
```python
|
|
289
|
+
transaction, errors = client.process_payment(payment)
|
|
290
|
+
transaction.raw # exactly what PayWay returned
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
Parsing is lossy — keys PayWay sends that the dataclass does not declare are dropped,
|
|
294
|
+
absent keys become `None`, and a few are renamed (`maskedCardNumber` is parsed into
|
|
295
|
+
`card_number`). Store `raw` rather than `to_dict()` if you are persisting responses for
|
|
296
|
+
auditing, reconciliation or dispute resolution. Models you construct yourself, such as a
|
|
297
|
+
`PayWayPayment` you are about to send, leave `raw` as `None`.
|
|
298
|
+
|
|
263
299
|
## Fraud
|
|
264
300
|
|
|
265
301
|
Please follow PayWay's advice about reducing your risk of fraudulent transactions. <https://www.payway.com.au/docs/card-testing.html#card-testing>
|
|
@@ -178,6 +178,27 @@ Poll a transaction using the `get_transaction` method.
|
|
|
178
178
|
transaction, errors = client.get_transaction(transaction.transaction_id)
|
|
179
179
|
```
|
|
180
180
|
|
|
181
|
+
## Search transactions
|
|
182
|
+
|
|
183
|
+
PayWay has no plain `GET /transactions` resource, only three search paths. Each returns a
|
|
184
|
+
paginated list (20 per page, most recent first) with `next`/`prev` links.
|
|
185
|
+
|
|
186
|
+
```python
|
|
187
|
+
response = client.search_transactions_by_customer(customer_number)
|
|
188
|
+
response = client.search_transactions_by_receipt(receipt_number)
|
|
189
|
+
response = client.search_transactions_by_order(order_number)
|
|
190
|
+
|
|
191
|
+
transactions = response["data"]
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Pass `page` to fetch a later page, using the number from the `next`/`prev` links:
|
|
195
|
+
|
|
196
|
+
```python
|
|
197
|
+
response = client.search_transactions_by_customer(customer_number, page=2)
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
`list_customers()` takes the same `page` argument.
|
|
201
|
+
|
|
181
202
|
## Process and capture a pre-authorisation
|
|
182
203
|
|
|
183
204
|
To process a credit card pre-authorisation using a credit card stored against a customer use `preAuth` as the `transaction_type` along with the customer's PayWay number, amount and currency.
|
|
@@ -237,6 +258,21 @@ PayWay API documentation <https://www.payway.com.au/docs/rest.html>
|
|
|
237
258
|
It is recommended to use PayWay's Trusted Frame <https://www.payway.com.au/docs/rest.html#trusted-frame>
|
|
238
259
|
when creating a single use token of a card or bank account so your PCI-compliance scope is reduced.
|
|
239
260
|
|
|
261
|
+
## Keeping the raw response
|
|
262
|
+
|
|
263
|
+
Models parsed from a PayWay response keep that response verbatim on `raw`:
|
|
264
|
+
|
|
265
|
+
```python
|
|
266
|
+
transaction, errors = client.process_payment(payment)
|
|
267
|
+
transaction.raw # exactly what PayWay returned
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
Parsing is lossy — keys PayWay sends that the dataclass does not declare are dropped,
|
|
271
|
+
absent keys become `None`, and a few are renamed (`maskedCardNumber` is parsed into
|
|
272
|
+
`card_number`). Store `raw` rather than `to_dict()` if you are persisting responses for
|
|
273
|
+
auditing, reconciliation or dispute resolution. Models you construct yourself, such as a
|
|
274
|
+
`PayWayPayment` you are about to send, leave `raw` as `None`.
|
|
275
|
+
|
|
240
276
|
## Fraud
|
|
241
277
|
|
|
242
278
|
Please follow PayWay's advice about reducing your risk of fraudulent transactions. <https://www.payway.com.au/docs/card-testing.html#card-testing>
|
|
@@ -15,7 +15,7 @@ from payway.constants import (
|
|
|
15
15
|
CUSTOMER_URL,
|
|
16
16
|
PAYWAY_ERROR_RESPONSE_CODES,
|
|
17
17
|
RETRYABLE_STATUS_CODES,
|
|
18
|
-
|
|
18
|
+
TOKEN_URL,
|
|
19
19
|
TRANSACTION_URL,
|
|
20
20
|
VALID_PAYMENT_METHOD_CHOICES,
|
|
21
21
|
PaymentMethod,
|
|
@@ -190,7 +190,7 @@ class Client(CustomerRequest, TransactionRequest):
|
|
|
190
190
|
data["paymentMethod"] = BANK_ACCOUNT_PAYMENT_CHOICE
|
|
191
191
|
logger.info("Sending Create Token request to PayWay.")
|
|
192
192
|
response = self.post_request(
|
|
193
|
-
|
|
193
|
+
TOKEN_URL,
|
|
194
194
|
data,
|
|
195
195
|
auth=(self.publishable_api_key, ""),
|
|
196
196
|
idempotency_key=idempotency_key,
|
|
@@ -10,11 +10,9 @@ class PaymentMethod(StrEnum):
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
PAYWAY_API_URL = "https://api.payway.com.au/rest/v1"
|
|
13
|
-
TOKEN_URL = PAYWAY_API_URL + "/single-use-tokens
|
|
13
|
+
TOKEN_URL = PAYWAY_API_URL + "/single-use-tokens"
|
|
14
14
|
TRANSACTION_URL = PAYWAY_API_URL + "/transactions"
|
|
15
15
|
CUSTOMER_URL = PAYWAY_API_URL + "/customers"
|
|
16
|
-
OWN_BANK_ACCOUNTS_URL = PAYWAY_API_URL + "/your-bank-accounts"
|
|
17
|
-
TOKEN_NO_REDIRECT = PAYWAY_API_URL + "/single-use-tokens"
|
|
18
16
|
TRANSACTION_APPROVED = "0"
|
|
19
17
|
|
|
20
18
|
SUMMARY_CODES = {
|
|
@@ -98,10 +98,10 @@ class CustomerRequest:
|
|
|
98
98
|
)
|
|
99
99
|
|
|
100
100
|
@json_list("list_customers")
|
|
101
|
-
def list_customers(self) -> requests.Response:
|
|
101
|
+
def list_customers(self, page: int | None = None) -> requests.Response:
|
|
102
102
|
"""
|
|
103
103
|
List all customers in PayWay
|
|
104
104
|
Returns paginated list of customerNumber, customerName
|
|
105
|
+
:param page: page number, taken from the `next`/`prev` links of a previous response
|
|
105
106
|
"""
|
|
106
|
-
|
|
107
|
-
return self.session_no_headers.get(CUSTOMER_URL)
|
|
107
|
+
return self.session_no_headers.get(CUSTOMER_URL, params={"page": page})
|
|
@@ -15,9 +15,16 @@ class PayWayModel:
|
|
|
15
15
|
alias: PayWay key when it is not the camelCase of the field name
|
|
16
16
|
exclude: omit the field from to_dict output
|
|
17
17
|
from_dict: callable applied to a non-None raw value when parsing
|
|
18
|
+
|
|
19
|
+
Instances built by from_dict keep the response body they were parsed from
|
|
20
|
+
on ``raw``, unchanged. Parsing is lossy - undeclared PayWay keys are dropped,
|
|
21
|
+
absent ones become None, and aliases rename them - so callers persisting a
|
|
22
|
+
response for auditing or dispute resolution should store ``raw``, not
|
|
23
|
+
``to_dict()``. Models you build yourself leave it None.
|
|
18
24
|
"""
|
|
19
25
|
|
|
20
26
|
__dataclass_fields__: ClassVar[dict[str, Any]]
|
|
27
|
+
raw: dict[str, Any] | None = None
|
|
21
28
|
|
|
22
29
|
def to_dict(self) -> dict[str, Any]:
|
|
23
30
|
result = {}
|
|
@@ -39,7 +46,9 @@ class PayWayModel:
|
|
|
39
46
|
if converter is not None and value is not None:
|
|
40
47
|
value = converter(value)
|
|
41
48
|
kwargs[f.name] = value
|
|
42
|
-
|
|
49
|
+
instance = cls(**kwargs)
|
|
50
|
+
instance.raw = data
|
|
51
|
+
return instance
|
|
43
52
|
|
|
44
53
|
|
|
45
54
|
@dataclass
|
|
@@ -65,8 +74,10 @@ class PayWayCard(PayWayModel):
|
|
|
65
74
|
|
|
66
75
|
@classmethod
|
|
67
76
|
def from_dict(cls, data: dict[str, Any]) -> PayWayCard:
|
|
68
|
-
|
|
69
|
-
|
|
77
|
+
card = super().from_dict({**data, "cardNumber": data.get("maskedCardNumber") or data.get("cardNumber")})
|
|
78
|
+
# Keep PayWay's own body, not the copy rewritten for the alias above.
|
|
79
|
+
card.raw = data
|
|
80
|
+
return card
|
|
70
81
|
|
|
71
82
|
|
|
72
83
|
@dataclass
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
import requests
|
|
6
|
+
|
|
7
|
+
from payway.constants import TRANSACTION_URL
|
|
8
|
+
from payway.utils import json_list
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class TransactionRequest:
|
|
12
|
+
session = requests.Session()
|
|
13
|
+
session_no_headers = requests.Session()
|
|
14
|
+
|
|
15
|
+
def _search(self, path: str, params: dict[str, Any]) -> requests.Response:
|
|
16
|
+
return self.session_no_headers.get(f"{TRANSACTION_URL}/{path}", params=params)
|
|
17
|
+
|
|
18
|
+
@json_list("search_transactions_by_customer")
|
|
19
|
+
def search_transactions_by_customer(self, customer_number: int | str, page: int | None = None) -> requests.Response:
|
|
20
|
+
"""
|
|
21
|
+
Returns a paginated list of transactions for a PayWay customer, most recent first
|
|
22
|
+
:param customer_number: PayWay customer number
|
|
23
|
+
:param page: page number, taken from the `next`/`prev` links of a previous response
|
|
24
|
+
"""
|
|
25
|
+
return self._search("search-customer", {"customerNumber": customer_number, "page": page})
|
|
26
|
+
|
|
27
|
+
@json_list("search_transactions_by_receipt")
|
|
28
|
+
def search_transactions_by_receipt(self, receipt_number: int | str, page: int | None = None) -> requests.Response:
|
|
29
|
+
"""
|
|
30
|
+
Returns a paginated list of transactions with the given receipt number, most recent first
|
|
31
|
+
:param receipt_number: PayWay receipt number
|
|
32
|
+
:param page: page number, taken from the `next`/`prev` links of a previous response
|
|
33
|
+
"""
|
|
34
|
+
return self._search("search-receipt", {"receiptNumber": receipt_number, "page": page})
|
|
35
|
+
|
|
36
|
+
@json_list("search_transactions_by_order")
|
|
37
|
+
def search_transactions_by_order(self, order_number: str, page: int | None = None) -> requests.Response:
|
|
38
|
+
"""
|
|
39
|
+
Returns a paginated list of transactions with the given order number, most recent first
|
|
40
|
+
:param order_number: your order number, supplied when the transaction was created
|
|
41
|
+
:param page: page number, taken from the `next`/`prev` links of a previous response
|
|
42
|
+
"""
|
|
43
|
+
return self._search("search-order", {"orderNumber": order_number, "page": page})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-payway
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.10
|
|
4
4
|
Summary: Python client for working with Westpac's PayWay REST API
|
|
5
5
|
Author-email: Ben Napper <reppan197@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -201,6 +201,27 @@ Poll a transaction using the `get_transaction` method.
|
|
|
201
201
|
transaction, errors = client.get_transaction(transaction.transaction_id)
|
|
202
202
|
```
|
|
203
203
|
|
|
204
|
+
## Search transactions
|
|
205
|
+
|
|
206
|
+
PayWay has no plain `GET /transactions` resource, only three search paths. Each returns a
|
|
207
|
+
paginated list (20 per page, most recent first) with `next`/`prev` links.
|
|
208
|
+
|
|
209
|
+
```python
|
|
210
|
+
response = client.search_transactions_by_customer(customer_number)
|
|
211
|
+
response = client.search_transactions_by_receipt(receipt_number)
|
|
212
|
+
response = client.search_transactions_by_order(order_number)
|
|
213
|
+
|
|
214
|
+
transactions = response["data"]
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Pass `page` to fetch a later page, using the number from the `next`/`prev` links:
|
|
218
|
+
|
|
219
|
+
```python
|
|
220
|
+
response = client.search_transactions_by_customer(customer_number, page=2)
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
`list_customers()` takes the same `page` argument.
|
|
224
|
+
|
|
204
225
|
## Process and capture a pre-authorisation
|
|
205
226
|
|
|
206
227
|
To process a credit card pre-authorisation using a credit card stored against a customer use `preAuth` as the `transaction_type` along with the customer's PayWay number, amount and currency.
|
|
@@ -260,6 +281,21 @@ PayWay API documentation <https://www.payway.com.au/docs/rest.html>
|
|
|
260
281
|
It is recommended to use PayWay's Trusted Frame <https://www.payway.com.au/docs/rest.html#trusted-frame>
|
|
261
282
|
when creating a single use token of a card or bank account so your PCI-compliance scope is reduced.
|
|
262
283
|
|
|
284
|
+
## Keeping the raw response
|
|
285
|
+
|
|
286
|
+
Models parsed from a PayWay response keep that response verbatim on `raw`:
|
|
287
|
+
|
|
288
|
+
```python
|
|
289
|
+
transaction, errors = client.process_payment(payment)
|
|
290
|
+
transaction.raw # exactly what PayWay returned
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
Parsing is lossy — keys PayWay sends that the dataclass does not declare are dropped,
|
|
294
|
+
absent keys become `None`, and a few are renamed (`maskedCardNumber` is parsed into
|
|
295
|
+
`card_number`). Store `raw` rather than `to_dict()` if you are persisting responses for
|
|
296
|
+
auditing, reconciliation or dispute resolution. Models you construct yourself, such as a
|
|
297
|
+
`PayWayPayment` you are about to send, leave `raw` as `None`.
|
|
298
|
+
|
|
263
299
|
## Fraud
|
|
264
300
|
|
|
265
301
|
Please follow PayWay's advice about reducing your risk of fraudulent transactions. <https://www.payway.com.au/docs/card-testing.html#card-testing>
|
|
@@ -179,6 +179,29 @@ class TestClient(unittest.TestCase):
|
|
|
179
179
|
self.assertEqual(transaction.status, "approved")
|
|
180
180
|
self.assertEqual(transaction.response_code, "11")
|
|
181
181
|
|
|
182
|
+
@patch("requests.post")
|
|
183
|
+
def test_process_payment_keeps_the_raw_response(self, mock_post) -> None:
|
|
184
|
+
"""
|
|
185
|
+
Parsing drops keys PayWay sent, so ``raw`` keeps the body verbatim for
|
|
186
|
+
callers that persist responses for auditing or dispute resolution.
|
|
187
|
+
"""
|
|
188
|
+
response = load_json_file("tests/data/transaction.json")
|
|
189
|
+
mock_post.return_value.status_code = 200
|
|
190
|
+
mock_post.return_value.json.return_value = response
|
|
191
|
+
payment = copy.deepcopy(self.payment)
|
|
192
|
+
payment.customer_number = "1"
|
|
193
|
+
payment.token = "2bcec36f-7b02-43db-b3ec-bfb65acfe272"
|
|
194
|
+
payment.order_number = "5200"
|
|
195
|
+
payment.merchant_id = self.client.merchant_id
|
|
196
|
+
|
|
197
|
+
transaction, _ = self.client.process_payment(payment)
|
|
198
|
+
|
|
199
|
+
self.assertEqual(transaction.raw, response)
|
|
200
|
+
# cardScheme and cardType are not modelled, so only raw still has them.
|
|
201
|
+
self.assertEqual(transaction.raw["creditCard"]["cardScheme"], "visa")
|
|
202
|
+
self.assertNotIn("cardScheme", transaction.to_dict()["creditCard"])
|
|
203
|
+
self.assertEqual(transaction.card.raw, response["creditCard"])
|
|
204
|
+
|
|
182
205
|
@patch("requests.post")
|
|
183
206
|
def test_process_payment_with_idempotency_key(self, mock_post) -> None:
|
|
184
207
|
"""
|
|
@@ -211,6 +211,20 @@ class TestCustomerRequest(unittest.TestCase):
|
|
|
211
211
|
mock_get.return_value.status_code = 200
|
|
212
212
|
mock_get.return_value.json.return_value = load_json_file("tests/data/customers.json")
|
|
213
213
|
response = self.client.list_customers()
|
|
214
|
+
mock_get.assert_called_once_with(
|
|
215
|
+
"https://api.payway.com.au/rest/v1/customers",
|
|
216
|
+
params={"page": None},
|
|
217
|
+
)
|
|
214
218
|
self.assertEqual(response.__class__, dict)
|
|
215
219
|
self.assertIsNotNone(response)
|
|
216
220
|
self.assertIsNotNone(response.get("data"))
|
|
221
|
+
|
|
222
|
+
@patch("requests.Session.get")
|
|
223
|
+
def test_list_customers_with_page(self, mock_get) -> None:
|
|
224
|
+
mock_get.return_value.status_code = 200
|
|
225
|
+
mock_get.return_value.json.return_value = load_json_file("tests/data/customers.json")
|
|
226
|
+
self.client.list_customers(page=3)
|
|
227
|
+
mock_get.assert_called_once_with(
|
|
228
|
+
"https://api.payway.com.au/rest/v1/customers",
|
|
229
|
+
params={"page": 3},
|
|
230
|
+
)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import unittest
|
|
4
|
+
from unittest.mock import patch
|
|
5
|
+
|
|
6
|
+
from payway.client import Client
|
|
7
|
+
from payway.test_utils import load_json_file
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class TestTransactionRequest(unittest.TestCase):
|
|
11
|
+
@classmethod
|
|
12
|
+
def setUpClass(cls) -> None:
|
|
13
|
+
merchant_id = "TEST"
|
|
14
|
+
bank_account_id = "0000000A"
|
|
15
|
+
publishable_api_key = "TPUBLISHABLE-API-KEY"
|
|
16
|
+
secret_api_key = "TPUBLISHABLE-SECRET"
|
|
17
|
+
|
|
18
|
+
cls.client = Client(
|
|
19
|
+
merchant_id=merchant_id,
|
|
20
|
+
bank_account_id=bank_account_id,
|
|
21
|
+
publishable_api_key=publishable_api_key,
|
|
22
|
+
secret_api_key=secret_api_key,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
@patch("requests.Session.get")
|
|
26
|
+
def test_search_transactions_by_customer(self, mock_get) -> None:
|
|
27
|
+
mock_get.return_value.status_code = 200
|
|
28
|
+
mock_get.return_value.json.return_value = load_json_file("tests/data/transactions.json")
|
|
29
|
+
response = self.client.search_transactions_by_customer(1)
|
|
30
|
+
mock_get.assert_called_once_with(
|
|
31
|
+
"https://api.payway.com.au/rest/v1/transactions/search-customer",
|
|
32
|
+
params={"customerNumber": 1, "page": None},
|
|
33
|
+
)
|
|
34
|
+
self.assertIsNotNone(response["data"])
|
|
35
|
+
|
|
36
|
+
@patch("requests.Session.get")
|
|
37
|
+
def test_search_transactions_by_customer_with_page(self, mock_get) -> None:
|
|
38
|
+
mock_get.return_value.status_code = 200
|
|
39
|
+
mock_get.return_value.json.return_value = load_json_file("tests/data/transactions.json")
|
|
40
|
+
self.client.search_transactions_by_customer(1, page=2)
|
|
41
|
+
mock_get.assert_called_once_with(
|
|
42
|
+
"https://api.payway.com.au/rest/v1/transactions/search-customer",
|
|
43
|
+
params={"customerNumber": 1, "page": 2},
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
@patch("requests.Session.get")
|
|
47
|
+
def test_search_transactions_by_receipt(self, mock_get) -> None:
|
|
48
|
+
mock_get.return_value.status_code = 200
|
|
49
|
+
mock_get.return_value.json.return_value = load_json_file("tests/data/transactions.json")
|
|
50
|
+
response = self.client.search_transactions_by_receipt("1234567")
|
|
51
|
+
mock_get.assert_called_once_with(
|
|
52
|
+
"https://api.payway.com.au/rest/v1/transactions/search-receipt",
|
|
53
|
+
params={"receiptNumber": "1234567", "page": None},
|
|
54
|
+
)
|
|
55
|
+
self.assertIsNotNone(response["data"])
|
|
56
|
+
|
|
57
|
+
@patch("requests.Session.get")
|
|
58
|
+
def test_search_transactions_by_order(self, mock_get) -> None:
|
|
59
|
+
mock_get.return_value.status_code = 200
|
|
60
|
+
mock_get.return_value.json.return_value = load_json_file("tests/data/transactions.json")
|
|
61
|
+
response = self.client.search_transactions_by_order("ORDER-1")
|
|
62
|
+
mock_get.assert_called_once_with(
|
|
63
|
+
"https://api.payway.com.au/rest/v1/transactions/search-order",
|
|
64
|
+
params={"orderNumber": "ORDER-1", "page": None},
|
|
65
|
+
)
|
|
66
|
+
self.assertIsNotNone(response["data"])
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import requests
|
|
4
|
-
|
|
5
|
-
from payway.constants import TRANSACTION_URL
|
|
6
|
-
from payway.utils import json_list
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class TransactionRequest:
|
|
10
|
-
session = requests.Session()
|
|
11
|
-
session_no_headers = requests.Session()
|
|
12
|
-
|
|
13
|
-
@json_list("search_transactions")
|
|
14
|
-
def search_transactions(self, query: str) -> requests.Response:
|
|
15
|
-
"""
|
|
16
|
-
Returns a list of transactions
|
|
17
|
-
"""
|
|
18
|
-
return self.session_no_headers.get(TRANSACTION_URL + query)
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import unittest
|
|
4
|
-
from unittest.mock import patch
|
|
5
|
-
|
|
6
|
-
from payway.client import Client
|
|
7
|
-
from payway.test_utils import load_json_file
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class TestTransactionRequest(unittest.TestCase):
|
|
11
|
-
@classmethod
|
|
12
|
-
def setUpClass(cls) -> None:
|
|
13
|
-
merchant_id = "TEST"
|
|
14
|
-
bank_account_id = "0000000A"
|
|
15
|
-
publishable_api_key = "TPUBLISHABLE-API-KEY"
|
|
16
|
-
secret_api_key = "TPUBLISHABLE-SECRET"
|
|
17
|
-
|
|
18
|
-
cls.client = Client(
|
|
19
|
-
merchant_id=merchant_id,
|
|
20
|
-
bank_account_id=bank_account_id,
|
|
21
|
-
publishable_api_key=publishable_api_key,
|
|
22
|
-
secret_api_key=secret_api_key,
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
@patch("requests.Session.get")
|
|
26
|
-
def test_search_transactions(self, mock_get) -> None:
|
|
27
|
-
mock_get.return_value.status_code = 200
|
|
28
|
-
mock_get.return_value.json.return_value = load_json_file("tests/data/transactions.json")
|
|
29
|
-
query = "/search-customer?customerNumber=1"
|
|
30
|
-
response = self.client.search_transactions(query)
|
|
31
|
-
transactions = response["data"]
|
|
32
|
-
self.assertIsNotNone(transactions)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|