python-payway 0.0.9__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.
Files changed (22) hide show
  1. {python_payway-0.0.9/python_payway.egg-info → python_payway-0.0.10}/PKG-INFO +16 -1
  2. {python_payway-0.0.9 → python_payway-0.0.10}/README.md +15 -0
  3. {python_payway-0.0.9 → python_payway-0.0.10}/payway/model.py +14 -3
  4. {python_payway-0.0.9 → python_payway-0.0.10}/pyproject.toml +1 -1
  5. {python_payway-0.0.9 → python_payway-0.0.10/python_payway.egg-info}/PKG-INFO +16 -1
  6. {python_payway-0.0.9 → python_payway-0.0.10}/tests/test_client.py +23 -0
  7. {python_payway-0.0.9 → python_payway-0.0.10}/LICENSE +0 -0
  8. {python_payway-0.0.9 → python_payway-0.0.10}/payway/__init__.py +0 -0
  9. {python_payway-0.0.9 → python_payway-0.0.10}/payway/client.py +0 -0
  10. {python_payway-0.0.9 → python_payway-0.0.10}/payway/constants.py +0 -0
  11. {python_payway-0.0.9 → python_payway-0.0.10}/payway/customers.py +0 -0
  12. {python_payway-0.0.9 → python_payway-0.0.10}/payway/exceptions.py +0 -0
  13. {python_payway-0.0.9 → python_payway-0.0.10}/payway/test_utils.py +0 -0
  14. {python_payway-0.0.9 → python_payway-0.0.10}/payway/transactions.py +0 -0
  15. {python_payway-0.0.9 → python_payway-0.0.10}/payway/utils.py +0 -0
  16. {python_payway-0.0.9 → python_payway-0.0.10}/python_payway.egg-info/SOURCES.txt +0 -0
  17. {python_payway-0.0.9 → python_payway-0.0.10}/python_payway.egg-info/dependency_links.txt +0 -0
  18. {python_payway-0.0.9 → python_payway-0.0.10}/python_payway.egg-info/requires.txt +0 -0
  19. {python_payway-0.0.9 → python_payway-0.0.10}/python_payway.egg-info/top_level.txt +0 -0
  20. {python_payway-0.0.9 → python_payway-0.0.10}/setup.cfg +0 -0
  21. {python_payway-0.0.9 → python_payway-0.0.10}/tests/test_customers.py +0 -0
  22. {python_payway-0.0.9 → python_payway-0.0.10}/tests/test_transactions.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-payway
3
- Version: 0.0.9
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
@@ -281,6 +281,21 @@ PayWay API documentation <https://www.payway.com.au/docs/rest.html>
281
281
  It is recommended to use PayWay's Trusted Frame <https://www.payway.com.au/docs/rest.html#trusted-frame>
282
282
  when creating a single use token of a card or bank account so your PCI-compliance scope is reduced.
283
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
+
284
299
  ## Fraud
285
300
 
286
301
  Please follow PayWay's advice about reducing your risk of fraudulent transactions. <https://www.payway.com.au/docs/card-testing.html#card-testing>
@@ -258,6 +258,21 @@ PayWay API documentation <https://www.payway.com.au/docs/rest.html>
258
258
  It is recommended to use PayWay's Trusted Frame <https://www.payway.com.au/docs/rest.html#trusted-frame>
259
259
  when creating a single use token of a card or bank account so your PCI-compliance scope is reduced.
260
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
+
261
276
  ## Fraud
262
277
 
263
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,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
- return cls(**kwargs)
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
- data = {**data, "cardNumber": data.get("maskedCardNumber") or data.get("cardNumber")}
69
- return super().from_dict(data)
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "python-payway"
7
- version = "0.0.9"
7
+ version = "0.0.10"
8
8
  description = "Python client for working with Westpac's PayWay REST API"
9
9
  authors = [
10
10
  { name = "Ben Napper", email = "reppan197@gmail.com" }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-payway
3
- Version: 0.0.9
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
@@ -281,6 +281,21 @@ PayWay API documentation <https://www.payway.com.au/docs/rest.html>
281
281
  It is recommended to use PayWay's Trusted Frame <https://www.payway.com.au/docs/rest.html#trusted-frame>
282
282
  when creating a single use token of a card or bank account so your PCI-compliance scope is reduced.
283
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
+
284
299
  ## Fraud
285
300
 
286
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
  """
File without changes
File without changes