pypaystack2 3.2.1__tar.gz → 3.4.0__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 (86) hide show
  1. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/PKG-INFO +4 -7
  2. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/README.md +0 -2
  3. pypaystack2-3.4.0/pyproject.toml +61 -0
  4. pypaystack2-3.2.1/pyproject.toml → pypaystack2-3.4.0/pyproject.toml.orig +11 -11
  5. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/__init__.py +9 -11
  6. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/_metadata.py +1 -1
  7. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/base_clients.py +15 -15
  8. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/enums.py +33 -0
  9. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/fees_calculation_mixin.py +21 -7
  10. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/main_clients.py +137 -32
  11. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/models/__init__.py +2 -0
  12. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/models/payload_models.py +19 -7
  13. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/models/response_models.py +29 -3
  14. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/__init__.py +13 -12
  15. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/__init__.py +4 -4
  16. pypaystack2-3.4.0/src/pypaystack2/sub_clients/async_clients/orders.py +191 -0
  17. pypaystack2-3.4.0/src/pypaystack2/sub_clients/async_clients/preauthorizations.py +318 -0
  18. pypaystack2-3.4.0/src/pypaystack2/sub_clients/async_clients/storefronts.py +399 -0
  19. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/virtual_terminals.py +1 -0
  20. pypaystack2-3.4.0/src/pypaystack2/sub_clients/async_clients/webhook_events.py +202 -0
  21. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/__init__.py +4 -4
  22. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/dedicated_accounts.py +1 -1
  23. pypaystack2-3.4.0/src/pypaystack2/sub_clients/sync_clients/orders.py +191 -0
  24. pypaystack2-3.4.0/src/pypaystack2/sub_clients/sync_clients/preauthorizations.py +314 -0
  25. pypaystack2-3.4.0/src/pypaystack2/sub_clients/sync_clients/storefronts.py +395 -0
  26. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/virtual_terminals.py +3 -1
  27. pypaystack2-3.4.0/src/pypaystack2/sub_clients/sync_clients/webhook_events.py +197 -0
  28. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/webhook/cli.py +4 -3
  29. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/webhook/logging_config.py +1 -1
  30. pypaystack2-3.4.0/src/pypaystack2/webhook/models.py +6 -0
  31. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/webhook/webhook_proxy_server.py +11 -3
  32. pypaystack2-3.2.1/src/pypaystack2/webhook/enums.py +0 -28
  33. pypaystack2-3.2.1/src/pypaystack2/webhook/models.py +0 -45
  34. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/cli.py +0 -0
  35. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/exceptions.py +0 -0
  36. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/py.typed +0 -0
  37. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/apple_pay.py +0 -0
  38. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/bulk_charges.py +0 -0
  39. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/charge.py +0 -0
  40. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/customers.py +0 -0
  41. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/dedicated_accounts.py +0 -0
  42. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/direct_debits.py +0 -0
  43. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/disputes.py +0 -0
  44. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/integration.py +0 -0
  45. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/miscellaneous.py +0 -0
  46. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/payment_pages.py +0 -0
  47. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/payment_requests.py +0 -0
  48. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/plans.py +0 -0
  49. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/products.py +0 -0
  50. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/refunds.py +0 -0
  51. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/settlements.py +0 -0
  52. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/splits.py +0 -0
  53. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/subaccounts.py +0 -0
  54. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/subscriptions.py +0 -0
  55. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/terminals.py +0 -0
  56. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/transactions.py +0 -0
  57. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/transfer_recipients.py +0 -0
  58. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/transfers.py +0 -0
  59. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/transfers_control.py +0 -0
  60. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/verification.py +0 -0
  61. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/apple_pay.py +0 -0
  62. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/bulk_charges.py +0 -0
  63. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/charge.py +0 -0
  64. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/customers.py +0 -0
  65. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/direct_debits.py +0 -0
  66. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/disputes.py +0 -0
  67. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/integration.py +0 -0
  68. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/miscellaneous.py +0 -0
  69. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/payment_pages.py +0 -0
  70. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/payment_requests.py +0 -0
  71. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/plans.py +0 -0
  72. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/products.py +0 -0
  73. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/refunds.py +0 -0
  74. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/settlements.py +0 -0
  75. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/splits.py +0 -0
  76. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/subaccounts.py +0 -0
  77. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/subscriptions.py +0 -0
  78. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/terminals.py +0 -0
  79. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/transactions.py +0 -0
  80. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/transfer_recipients.py +0 -0
  81. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/transfers.py +0 -0
  82. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/transfers_control.py +0 -0
  83. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/verification.py +0 -0
  84. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/types.py +0 -0
  85. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/utils.py +0 -0
  86. {pypaystack2-3.2.1 → pypaystack2-3.4.0}/src/pypaystack2/webhook/__init__.py +0 -0
@@ -1,19 +1,18 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pypaystack2
3
- Version: 3.2.1
3
+ Version: 3.4.0
4
4
  Summary: A developer-friendly client library for Paystack
5
5
  Keywords: paystack-python,pypaystack,paystack,paystackapi
6
6
  Author: Gbenga Adeyi
7
7
  Author-email: Gbenga Adeyi <adeyigbenga005@gmail.com>
8
8
  License-Expression: MIT
9
- Classifier: License :: OSI Approved :: MIT License
10
9
  Classifier: Programming Language :: Python
11
10
  Classifier: Programming Language :: Python :: 3
12
11
  Requires-Dist: httpx>=0.28.1
13
- Requires-Dist: pydantic>=2.12.5
14
- Requires-Dist: fastapi[standard]>=0.123.10 ; extra == 'webhook'
12
+ Requires-Dist: pydantic>=2.14.0
13
+ Requires-Dist: fastapi[standard]>=0.143.0 ; extra == 'webhook'
15
14
  Requires-Dist: ngrok>=1.4.0 ; extra == 'webhook'
16
- Requires-Dist: python-dotenv>=1.2.1 ; extra == 'webhook'
15
+ Requires-Dist: python-dotenv>=1.2.4 ; extra == 'webhook'
17
16
  Requires-Python: >=3.11
18
17
  Provides-Extra: webhook
19
18
  Description-Content-Type: text/markdown
@@ -27,8 +26,6 @@ Description-Content-Type: text/markdown
27
26
  PyPaystack2 is an Open Source Python client library for integrating [Paystack](https://paystack.com/) into your python
28
27
  projects. It aims at being developer friendly and easy to use.
29
28
 
30
- **Version 3 is here now**
31
-
32
29
  ## Features
33
30
 
34
31
  - 1st class support for type annotations.
@@ -7,8 +7,6 @@
7
7
  PyPaystack2 is an Open Source Python client library for integrating [Paystack](https://paystack.com/) into your python
8
8
  projects. It aims at being developer friendly and easy to use.
9
9
 
10
- **Version 3 is here now**
11
-
12
10
  ## Features
13
11
 
14
12
  - 1st class support for type annotations.
@@ -0,0 +1,61 @@
1
+ [project]
2
+ name = "pypaystack2"
3
+ version = "3.4.0"
4
+ description = "A developer-friendly client library for Paystack"
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ keywords = [
8
+ "paystack-python",
9
+ "pypaystack",
10
+ "paystack",
11
+ "paystackapi",
12
+ ]
13
+ classifiers = [
14
+ "Programming Language :: Python",
15
+ "Programming Language :: Python :: 3",
16
+ ]
17
+ requires-python = ">=3.11"
18
+ dependencies = [
19
+ "httpx>=0.28.1",
20
+ "pydantic>=2.14.0",
21
+ ]
22
+
23
+ [[project.authors]]
24
+ name = "Gbenga Adeyi"
25
+ email = "adeyigbenga005@gmail.com"
26
+
27
+ [project.scripts]
28
+ pypaystack2 = "pypaystack2.cli:cli_app"
29
+
30
+ [project.optional-dependencies]
31
+ webhook = [
32
+ "fastapi[standard]>=0.143.0",
33
+ "ngrok>=1.4.0",
34
+ "python-dotenv>=1.2.4",
35
+ ]
36
+
37
+ [build-system]
38
+ requires = ["uv_build>=0.13.0,<0.14.0"]
39
+ build-backend = "uv_build"
40
+
41
+ [dependency-groups]
42
+ dev = [
43
+ "pre-commit>=4.5.0",
44
+ { include-group = "format" },
45
+ { include-group = "test" },
46
+ { include-group = "coverage" },
47
+ ]
48
+ format = ["ruff>=0.17.0"]
49
+ test = [
50
+ "python-dotenv>=1.2.4",
51
+ "tomli>=2.5.0",
52
+ ]
53
+ coverage = []
54
+ doc = [
55
+ "mike>=2.2.0",
56
+ "mkdocs>=1.6.1",
57
+ "mkdocs-glightbox>=0.5.2",
58
+ "mkdocs-material>=9.7.0",
59
+ "mkdocstrings>=1.0.0",
60
+ "mkdocstrings-python>=2.0.1",
61
+ ]
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pypaystack2"
3
- version = "3.2.1"
3
+ version = "3.4.0"
4
4
  description = "A developer-friendly client library for Paystack"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -9,16 +9,15 @@ authors = [
9
9
  ]
10
10
  keywords = ["paystack-python", "pypaystack", "paystack", "paystackapi"]
11
11
  classifiers = [
12
- "License :: OSI Approved :: MIT License",
13
12
  "Programming Language :: Python",
14
13
  "Programming Language :: Python :: 3",
15
14
  ]
16
15
 
17
16
 
18
- requires-python = ">= 3.11"
17
+ requires-python = ">=3.11"
19
18
  dependencies = [
20
19
  "httpx>=0.28.1",
21
- "pydantic>=2.12.5",
20
+ "pydantic>=2.14.0",
22
21
  ]
23
22
 
24
23
  [project.scripts]
@@ -26,13 +25,13 @@ pypaystack2 = "pypaystack2.cli:cli_app"
26
25
 
27
26
  [project.optional-dependencies]
28
27
  webhook = [
29
- "fastapi[standard]>=0.123.10",
28
+ "fastapi[standard]>=0.143.0",
30
29
  "ngrok>=1.4.0",
31
- "python-dotenv>=1.2.1",
30
+ "python-dotenv>=1.2.4",
32
31
  ]
33
32
 
34
33
  [build-system]
35
- requires = ["uv_build>=0.9.10,<0.10.0"]
34
+ requires = ["uv_build>=0.13.0,<0.14.0"]
36
35
  build-backend = "uv_build"
37
36
 
38
37
  [dependency-groups]
@@ -43,18 +42,19 @@ dev = [
43
42
  { include-group = "coverage" },
44
43
  ]
45
44
  format = [
46
- "ruff>=0.14.8",
45
+ "ruff>=0.17.0",
47
46
  ]
48
47
  test = [
49
- "python-dotenv>=1.2.1",
50
- "tomli>=2.3.0",
48
+ "python-dotenv>=1.2.4",
49
+ "tomli>=2.5.0",
51
50
  ]
52
51
  coverage = []
53
52
  doc = [
54
- "mike>=2.1.3",
53
+ "mike>=2.2.0",
55
54
  "mkdocs>=1.6.1",
56
55
  "mkdocs-glightbox>=0.5.2",
57
56
  "mkdocs-material>=9.7.0",
58
57
  "mkdocstrings>=1.0.0",
59
58
  "mkdocstrings-python>=2.0.1",
60
59
  ]
60
+
@@ -36,23 +36,21 @@ Example usage:
36
36
  For more details, refer to the documentation.
37
37
  """
38
38
 
39
- # ruff: noqa: F401
40
39
  from pypaystack2._metadata import (
41
- __title__,
42
- __version__,
43
40
  __author__,
44
- __license__,
45
41
  __copyright__,
42
+ __license__,
43
+ __title__,
44
+ __version__,
46
45
  )
47
-
48
- from pypaystack2.main_clients import PaystackClient, AsyncPaystackClient
46
+ from pypaystack2.main_clients import AsyncPaystackClient, PaystackClient
49
47
 
50
48
  __all__ = [
51
- "__title__",
52
- "__version__",
49
+ "AsyncPaystackClient",
50
+ "PaystackClient",
53
51
  "__author__",
54
- "__license__",
55
52
  "__copyright__",
56
- "PaystackClient",
57
- "AsyncPaystackClient",
53
+ "__license__",
54
+ "__title__",
55
+ "__version__",
58
56
  ]
@@ -1,5 +1,5 @@
1
1
  __title__ = "pypaystack2"
2
- __version__ = "3.2.1"
2
+ __version__ = "3.4.0"
3
3
  __author__ = [{"name": "Gbenga Adeyi", "email": "adeyigbenga005@gmail.com"}]
4
4
  __license__ = "MIT"
5
5
  __copyright__ = "Copyright 2026."
@@ -8,7 +8,7 @@ from abc import ABC, abstractmethod
8
8
  from functools import reduce
9
9
  from http import HTTPMethod, HTTPStatus
10
10
  from json import JSONDecodeError
11
- from typing import Any, Type, cast
11
+ from typing import Any, cast
12
12
 
13
13
  import httpx
14
14
  from httpx import HTTPError
@@ -101,7 +101,7 @@ class AbstractAPIClient(FeesCalculationMixin, ABC):
101
101
  method: HTTPMethod,
102
102
  url: str,
103
103
  data: dict[str, Any] | list[Any] | None = None,
104
- response_data_model_class: Type[PaystackDataModel] | None = None,
104
+ response_data_model_class: type[PaystackDataModel] | None = None,
105
105
  raise_serialization_exception: bool = False,
106
106
  ) -> (
107
107
  Response[None] | Response[list[PaystackDataModel]] | Response[PaystackDataModel]
@@ -121,7 +121,7 @@ class AbstractAPIClient(FeesCalculationMixin, ABC):
121
121
  def _deserialize_response(
122
122
  self,
123
123
  raw_response: httpx.Response,
124
- response_data_model_class: Type[PaystackDataModel] | None = None,
124
+ response_data_model_class: type[PaystackDataModel] | None = None,
125
125
  raise_serialization_exception: bool = False,
126
126
  ) -> (
127
127
  Response[None] | Response[list[PaystackDataModel]] | Response[PaystackDataModel]
@@ -176,7 +176,7 @@ class AbstractAPIClient(FeesCalculationMixin, ABC):
176
176
  self,
177
177
  data: dict[str, Any] | list[Any],
178
178
  http_status_code: int,
179
- response_data_model_class: Type[PaystackDataModel] | None = None,
179
+ response_data_model_class: type[PaystackDataModel] | None = None,
180
180
  raise_serialization_exception: bool = False,
181
181
  ) -> PaystackDataModel | list[PaystackDataModel] | None:
182
182
  """Tries to convert the provided data to the provided pydantic instance, on failure to do so,
@@ -248,7 +248,7 @@ class BaseAPIClient(AbstractAPIClient):
248
248
  method: HTTPMethod,
249
249
  url: str,
250
250
  data: dict[str, Any] | list[Any] | None = None,
251
- response_data_model_class: Type[PaystackDataModel] | None = None,
251
+ response_data_model_class: type[PaystackDataModel] | None = None,
252
252
  raise_serialization_exception: bool = False,
253
253
  ) -> (
254
254
  Response[None] | Response[list[PaystackDataModel]] | Response[PaystackDataModel]
@@ -300,7 +300,7 @@ class BaseAsyncAPIClient(AbstractAPIClient):
300
300
  method: HTTPMethod,
301
301
  url: str,
302
302
  data: dict[str, Any] | list[Any] | None = None,
303
- response_data_model_class: Type[PaystackDataModel] | None = None,
303
+ response_data_model_class: type[PaystackDataModel] | None = None,
304
304
  raise_serialization_exception: bool = False,
305
305
  ) -> (
306
306
  Response[None] | Response[list[PaystackDataModel]] | Response[PaystackDataModel]
@@ -373,16 +373,11 @@ def add_to_payload(
373
373
  def append_query_params(query_params: list[tuple[str, Any]], url: str) -> str:
374
374
  """Adds more queries to url that already have query parameters in its suffix
375
375
 
376
- This function should only be used with urls that already have a
377
- query parameter suffixed to it because it makes that assumption
378
- that the url supplied is of the state ``http://example-url.com?firstQuery=1``
379
- and it adds more query parameters delimited by & to the end of the provided
380
- url ``http://example-url.com?firstQuery=1&otherQuery=2&...``
381
-
382
- Args:
376
+ Args:
383
377
  query_params: A list of other query parameters that should be appended to the url
384
- if it is not None. e.g ``[("page",2),("pagination",50),("currency",None)]`` ->
385
- ``url&page=2&pagination=50``
378
+ if it is not None. e.g `[("page",2),("pagination",50),("currency",None)]` ->
379
+ `url&page=2&pagination=50` if the url already has queries else
380
+ `url?page=2&pagination=50`
386
381
  url: The url to which additional query parameters are added.
387
382
 
388
383
  Returns:
@@ -393,4 +388,9 @@ def append_query_params(query_params: list[tuple[str, Any]], url: str) -> str:
393
388
  ]
394
389
  if len(params) == 0:
395
390
  return url
391
+ if "?" not in url:
392
+ first_query = params[0].replace("&", "", 1)
393
+ url = f"{url}?{first_query}"
394
+ params = params[1:]
395
+
396
396
  return url + reduce(add, params)
@@ -221,3 +221,36 @@ class SupportedCountryRelationshipType(StrEnum):
221
221
  INTEGRATION_FEATURE = "integration_feature"
222
222
  INTEGRATION_TYPE = "integration_type"
223
223
  PAYMENT_METHOD = "payment_method"
224
+
225
+
226
+ class WebhookEventType(StrEnum):
227
+ CHARGE_DISPUTE_CREATE = "charge.dispute.create"
228
+ CHARGE_DISPUTE_REMIND = "charge.dispute.remind"
229
+ CHARGE_DISPUTE_RESOLVE = "charge.dispute.resolve"
230
+ CHARGE_SUCCESS = "charge.success"
231
+ CUSTOMER_IDENTIFICATION_FAILED = "customeridentification.failed"
232
+ CUSTOMER_IDENTIFICATION_SUCCESS = "customeridentification.success"
233
+ DEDICATED_ACCOUNT_ASSIGN_FAILED = "dedicatedaccount.assign.failed"
234
+ DEDICATED_ACCOUNT_ASSIGN_SUCCESS = "dedicatedaccount.assign.success"
235
+ INVOICE_CREATE = "invoice.create"
236
+ INVOICE_PAYMENT_FAILED = "invoice.payment_failed"
237
+ INVOICE_UPDATE = "invoice.update"
238
+ PAYMENT_REQUEST_PENDING = "paymentrequest.pending"
239
+ PAYMENT_REQUEST_SUCCESS = "paymentrequet.success"
240
+ REFUND_FAILED = "refund.failed"
241
+ REFUND_PENDING = "refund.pending"
242
+ REFUND_PROCESSED = "refund.processed"
243
+ REFUND_PROCESSING = "refund.processing"
244
+ SUBSCRIPTION_CREATE = "subscription.create"
245
+ SUBSCRIPTION_DISABLE = "subscription.disable"
246
+ SUBSCRIPTION_EXPIRING_CARDS = "subscription.expiring_cards"
247
+ SUBSCRIPTION_NOT_RENEW = "subscription.not_renew"
248
+ TRANSFER_FAILED = "transfer.failed"
249
+ TRANSFER_SUCCESS = "transfer.success"
250
+ TRANSFER_REVERSED = "transfer.reversed"
251
+
252
+
253
+ class WebhookDeliveryStatus(StrEnum):
254
+ DELIVERED = "Delivered"
255
+ PENDING = "Pending"
256
+ FAILED = "Failed"
@@ -119,19 +119,33 @@ class FeesCalculationMixin:
119
119
  )
120
120
  options_model = options_validator_class.model_validate(options) # type: ignore
121
121
 
122
- if currency == Currency.NGN:
122
+ if currency == Currency.NGN and isinstance(
123
+ options_model, NigeriaServiceFeeOptions
124
+ ):
123
125
  return self._calculate_ngn_fee(amount, options_model)
124
- if currency == Currency.GHS:
126
+ if currency == Currency.GHS and isinstance(
127
+ options_model, GhanaServiceFeeOptions
128
+ ):
125
129
  return self._calculate_ghs_fee(amount, options_model)
126
- if currency == Currency.ZAR:
130
+ if currency == Currency.ZAR and isinstance(
131
+ options_model, SouthAfricaServiceFeeOptions
132
+ ):
127
133
  return self._calculate_zar_fee(amount, options_model)
128
- if currency == Currency.KES:
134
+ if currency == Currency.KES and isinstance(
135
+ options_model, KenyaServiceFeeOptions
136
+ ):
129
137
  return self._calculate_kes_fee(amount, options_model)
130
- if currency == Currency.XOF:
138
+ if currency == Currency.XOF and isinstance(
139
+ options_model, CoteDIvoreServiceFeeOptions
140
+ ):
131
141
  return self._calculate_xof_fee(amount, options_model)
132
- if currency == Currency.RWF:
142
+ if currency == Currency.RWF and isinstance(
143
+ options_model, RwandaServiceFeeOptions
144
+ ):
133
145
  return self._calculate_rwf_fee(amount, options_model)
134
- if currency == Currency.EGP:
146
+ if currency == Currency.EGP and isinstance(
147
+ options_model, EgyptServiceFeeOptions
148
+ ):
135
149
  return self._calculate_egp_fee(amount, options_model)
136
150
  raise ValueError(
137
151
  f"calculations not supported for the provided currency {currency}"
@@ -1,58 +1,73 @@
1
- from pypaystack2.sub_clients.async_clients.direct_debits import AsyncDirectDebitClient
2
- from pypaystack2.sub_clients.sync_clients.direct_debits import DirectDebitClient
3
- from pypaystack2.sub_clients.async_clients.virtual_terminals import (
4
- AsyncVirtualTerminalClient,
5
- )
6
- from pypaystack2.sub_clients.sync_clients.virtual_terminals import VirtualTerminalClient
1
+ from http import HTTPMethod
2
+
7
3
  from pypaystack2.base_clients import BaseAPIClient, BaseAsyncAPIClient
8
4
  from pypaystack2.sub_clients import (
9
5
  ApplePayClient,
10
- BulkChargeClient,
11
- ChargeClient,
12
- IntegrationClient,
13
- CustomerClient,
14
- DedicatedAccountClient,
15
- DisputeClient,
16
- PaymentRequestClient,
17
- MiscellaneousClient,
18
- PaymentPageClient,
19
- PlanClient,
20
- ProductClient,
21
- RefundClient,
22
- SettlementClient,
23
- TransactionSplitClient,
24
- SubAccountClient,
25
- SubscriptionClient,
26
- TerminalClient,
27
- TransactionClient,
28
- TransferRecipientClient,
29
- TransferClient,
30
- TransferControlClient,
31
- VerificationClient,
32
6
  AsyncApplePayClient,
33
7
  AsyncBulkChargeClient,
34
8
  AsyncChargeClient,
35
- AsyncIntegrationClient,
36
9
  AsyncCustomerClient,
37
10
  AsyncDedicatedAccountClient,
38
11
  AsyncDisputeClient,
39
- AsyncPaymentRequestClient,
12
+ AsyncIntegrationClient,
40
13
  AsyncMiscellaneousClient,
41
14
  AsyncPaymentPageClient,
15
+ AsyncPaymentRequestClient,
42
16
  AsyncPlanClient,
43
17
  AsyncProductClient,
44
18
  AsyncRefundClient,
45
19
  AsyncSettlementClient,
46
- AsyncTransactionSplitClient,
47
20
  AsyncSubAccountClient,
48
21
  AsyncSubscriptionClient,
49
22
  AsyncTerminalClient,
50
23
  AsyncTransactionClient,
51
- AsyncTransferRecipientClient,
24
+ AsyncTransactionSplitClient,
52
25
  AsyncTransferClient,
53
26
  AsyncTransferControlClient,
27
+ AsyncTransferRecipientClient,
54
28
  AsyncVerificationClient,
29
+ AsyncWebhookEventClient,
30
+ BulkChargeClient,
31
+ ChargeClient,
32
+ CustomerClient,
33
+ DedicatedAccountClient,
34
+ DisputeClient,
35
+ IntegrationClient,
36
+ MiscellaneousClient,
37
+ PaymentPageClient,
38
+ PaymentRequestClient,
39
+ PlanClient,
40
+ ProductClient,
41
+ RefundClient,
42
+ SettlementClient,
43
+ SubAccountClient,
44
+ SubscriptionClient,
45
+ TerminalClient,
46
+ TransactionClient,
47
+ TransactionSplitClient,
48
+ TransferClient,
49
+ TransferControlClient,
50
+ TransferRecipientClient,
51
+ VerificationClient,
52
+ WebhookEventClient,
53
+ )
54
+ from pypaystack2.sub_clients.async_clients.direct_debits import AsyncDirectDebitClient
55
+ from pypaystack2.sub_clients.async_clients.orders import AsyncOrderClient
56
+ from pypaystack2.sub_clients.async_clients.preauthorizations import (
57
+ AsyncPreauthorizationClient,
58
+ )
59
+ from pypaystack2.sub_clients.async_clients.storefronts import AsyncStorefrontClient
60
+ from pypaystack2.sub_clients.async_clients.virtual_terminals import (
61
+ AsyncVirtualTerminalClient,
62
+ )
63
+ from pypaystack2.sub_clients.sync_clients.direct_debits import DirectDebitClient
64
+ from pypaystack2.sub_clients.sync_clients.orders import OrderClient
65
+ from pypaystack2.sub_clients.sync_clients.preauthorizations import (
66
+ PreauthorizationClient,
55
67
  )
68
+ from pypaystack2.sub_clients.sync_clients.storefronts import StorefrontClient
69
+ from pypaystack2.sub_clients.sync_clients.virtual_terminals import VirtualTerminalClient
70
+ from pypaystack2.types import PaystackDataModel
56
71
 
57
72
 
58
73
  class PaystackClient(BaseAPIClient):
@@ -112,6 +127,14 @@ class PaystackClient(BaseAPIClient):
112
127
  Virtual Terminal API e.g. `VirtualTerminalClient.list`.
113
128
  direct_debits: A binding to `DirectDebitClient` providing methods for interacting with Paystack's
114
129
  Direct Debit API e.g. `DirectDebitClient.trigger_activation_charge`.
130
+ storefronts: A binding to `StorefrontClient` providing methods for interacting with Paystack's
131
+ Storefront API e.g. `StorefrontClient.create`.
132
+ orders: A binding to `OrderClient` providing methods for interacting with Paystack's
133
+ Order API e.g. `OrderClient.create`.
134
+ preauthorizations: A binding to `PreauthorizationClient` providing methods for interacting with Paystack's
135
+ Preauthorization API e.g. `PreauthorizationClient.initialize`.
136
+ webhook_events: A binding to `WebhookEventClient` providing methods for interacting with Paystack's
137
+ Webook events API e.g. `WebhookEventClient.all`.
115
138
  """
116
139
 
117
140
  def __init__(self, secret_key: str | None = None):
@@ -169,6 +192,42 @@ class PaystackClient(BaseAPIClient):
169
192
  )
170
193
  self.virtual_terminals = VirtualTerminalClient(secret_key=self._secret_key)
171
194
  self.direct_debits = DirectDebitClient(secret_key=self._secret_key)
195
+ self.storefronts = StorefrontClient(secret_key=self._secret_key)
196
+ self.orders = OrderClient(secret_key=self._secret_key)
197
+ self.preauthorizations = PreauthorizationClient(secret_key=self._secret_key)
198
+ self.webhook_events = WebhookEventClient(secret_key=self._secret_key)
199
+
200
+ def get_capitec_pay_transaction(
201
+ self,
202
+ reference: str,
203
+ alternate_model_class: type[PaystackDataModel] | None = None,
204
+ ):
205
+ """Check the status of a charge made with Capitec Pay.
206
+
207
+ Args:
208
+ reference: The transaction reference from the previously initiated charge request
209
+ alternate_model_class: A pydantic model class to use instead of the
210
+ default pydantic model used by the library to present the data in
211
+ the `Response.data`. The default behaviour of the library is to
212
+ set `Response.data` to `None` if it fails to serialize the data
213
+ returned from paystack with the model provided in the library.
214
+ Providing a pydantic model class via this parameter overrides
215
+ the library default model with the model class you provide.
216
+ This can come in handy when the models in the library do not
217
+ accurately represent the data returned, and you prefer working with the
218
+ data as a pydantic model instead of as a dict of the response returned
219
+ by paystack before it is serialized with pydantic models, The original
220
+ data can be accessed via `Response.raw`.
221
+
222
+ Returns:
223
+ A pydantic model containing the response gotten from paystack's server.
224
+ """
225
+ url = self._full_url(f"/capitec-pay/requery/{reference}")
226
+ return self._handle_request(
227
+ HTTPMethod.POST,
228
+ url,
229
+ response_data_model_class=alternate_model_class,
230
+ )
172
231
 
173
232
 
174
233
  class AsyncPaystackClient(BaseAsyncAPIClient):
@@ -228,6 +287,14 @@ class AsyncPaystackClient(BaseAsyncAPIClient):
228
287
  Virtual Terminal API e.g. `AsyncVirtualTerminalClient.list`.
229
288
  direct_debits: A binding to `AsyncDirectDebitClient` providing methods for interacting with Paystack's
230
289
  Direct Debit API e.g. `AsyncDirectDebitClient.trigger_activation_charge`.
290
+ storefronts: A binding to `AsyncStorefrontClient` providing methods for interacting with Paystack's
291
+ Storefront API e.g. `AsyncStorefrontClient.create`.
292
+ orders: A binding to `AsyncOrderClient` providing methods for interacting with Paystack's
293
+ Order API e.g. `AsyncOrderClient.create`.
294
+ preauthorizations: A binding to `AsyncPreauthorizationClient` providing methods for interacting with Paystack's
295
+ Preauthorization API e.g. `AsyncPreauthorizationClient.initialize`.
296
+ webhook_events: A binding to `AsyncWebhookEventClient` providing methods for interacting with Paystack's
297
+ Webook events API e.g. `AsyncWebhookEventClient.all`.
231
298
 
232
299
  """
233
300
 
@@ -262,3 +329,41 @@ class AsyncPaystackClient(BaseAsyncAPIClient):
262
329
  self.verification = AsyncVerificationClient(secret_key=self._secret_key)
263
330
  self.virtual_terminals = AsyncVirtualTerminalClient(secret_key=self._secret_key)
264
331
  self.direct_debits = AsyncDirectDebitClient(secret_key=self._secret_key)
332
+ self.storefronts = AsyncStorefrontClient(secret_key=self._secret_key)
333
+ self.orders = AsyncOrderClient(secret_key=self._secret_key)
334
+ self.preauthorizations = AsyncPreauthorizationClient(
335
+ secret_key=self._secret_key
336
+ )
337
+ self.webhook_events = AsyncWebhookEventClient(secret_key=self._secret_key)
338
+
339
+ async def get_capitec_pay_transaction(
340
+ self,
341
+ reference: str,
342
+ alternate_model_class: type[PaystackDataModel] | None = None,
343
+ ):
344
+ """Check the status of a charge made with Capitec Pay.
345
+
346
+ Args:
347
+ reference: The transaction reference from the previously initiated charge request
348
+ alternate_model_class: A pydantic model class to use instead of the
349
+ default pydantic model used by the library to present the data in
350
+ the `Response.data`. The default behaviour of the library is to
351
+ set `Response.data` to `None` if it fails to serialize the data
352
+ returned from paystack with the model provided in the library.
353
+ Providing a pydantic model class via this parameter overrides
354
+ the library default model with the model class you provide.
355
+ This can come in handy when the models in the library do not
356
+ accurately represent the data returned, and you prefer working with the
357
+ data as a pydantic model instead of as a dict of the response returned
358
+ by paystack before it is serialized with pydantic models, The original
359
+ data can be accessed via `Response.raw`.
360
+
361
+ Returns:
362
+ A pydantic model containing the response gotten from paystack's server.
363
+ """
364
+ url = self._full_url(f"/capitec-pay/requery/{reference}")
365
+ return await self._handle_request(
366
+ HTTPMethod.POST,
367
+ url,
368
+ response_data_model_class=alternate_model_class,
369
+ )
@@ -3,6 +3,7 @@ from pypaystack2.models.payload_models import (
3
3
  RefundAccount,
4
4
  BulkChargeInstruction,
5
5
  LineItem,
6
+ OrderLineItem,
6
7
  Tax,
7
8
  SplitAccount,
8
9
  Recipient,
@@ -90,6 +91,7 @@ __all__ = [
90
91
  # payload models
91
92
  "BulkChargeInstruction",
92
93
  "LineItem",
94
+ "OrderLineItem",
93
95
  "Tax",
94
96
  "SplitAccount",
95
97
  "Recipient",