pypaystack2 3.3.0__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.3.0 → pypaystack2-3.4.0}/PKG-INFO +4 -6
  2. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/README.md +0 -2
  3. pypaystack2-3.4.0/pyproject.toml +61 -0
  4. pypaystack2-3.3.0/pyproject.toml → pypaystack2-3.4.0/pyproject.toml.orig +11 -10
  5. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/__init__.py +9 -11
  6. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/_metadata.py +1 -1
  7. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/base_clients.py +15 -15
  8. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/enums.py +33 -0
  9. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/main_clients.py +52 -43
  10. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/models/response_models.py +26 -1
  11. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/__init__.py +13 -12
  12. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/__init__.py +4 -4
  13. pypaystack2-3.4.0/src/pypaystack2/sub_clients/async_clients/webhook_events.py +202 -0
  14. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/__init__.py +4 -4
  15. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/virtual_terminals.py +2 -1
  16. pypaystack2-3.4.0/src/pypaystack2/sub_clients/sync_clients/webhook_events.py +197 -0
  17. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/webhook/cli.py +4 -3
  18. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/webhook/logging_config.py +1 -1
  19. pypaystack2-3.4.0/src/pypaystack2/webhook/models.py +6 -0
  20. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/webhook/webhook_proxy_server.py +11 -3
  21. pypaystack2-3.3.0/src/pypaystack2/webhook/enums.py +0 -28
  22. pypaystack2-3.3.0/src/pypaystack2/webhook/models.py +0 -45
  23. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/cli.py +0 -0
  24. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/exceptions.py +0 -0
  25. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/fees_calculation_mixin.py +0 -0
  26. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/models/__init__.py +0 -0
  27. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/models/payload_models.py +0 -0
  28. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/py.typed +0 -0
  29. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/apple_pay.py +0 -0
  30. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/bulk_charges.py +0 -0
  31. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/charge.py +0 -0
  32. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/customers.py +0 -0
  33. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/dedicated_accounts.py +0 -0
  34. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/direct_debits.py +0 -0
  35. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/disputes.py +0 -0
  36. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/integration.py +0 -0
  37. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/miscellaneous.py +0 -0
  38. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/orders.py +0 -0
  39. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/payment_pages.py +0 -0
  40. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/payment_requests.py +0 -0
  41. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/plans.py +0 -0
  42. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/preauthorizations.py +0 -0
  43. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/products.py +0 -0
  44. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/refunds.py +0 -0
  45. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/settlements.py +0 -0
  46. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/splits.py +0 -0
  47. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/storefronts.py +0 -0
  48. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/subaccounts.py +0 -0
  49. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/subscriptions.py +0 -0
  50. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/terminals.py +0 -0
  51. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/transactions.py +0 -0
  52. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/transfer_recipients.py +0 -0
  53. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/transfers.py +0 -0
  54. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/transfers_control.py +0 -0
  55. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/verification.py +0 -0
  56. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/async_clients/virtual_terminals.py +0 -0
  57. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/apple_pay.py +0 -0
  58. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/bulk_charges.py +0 -0
  59. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/charge.py +0 -0
  60. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/customers.py +0 -0
  61. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/dedicated_accounts.py +0 -0
  62. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/direct_debits.py +0 -0
  63. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/disputes.py +0 -0
  64. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/integration.py +0 -0
  65. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/miscellaneous.py +0 -0
  66. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/orders.py +0 -0
  67. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/payment_pages.py +0 -0
  68. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/payment_requests.py +0 -0
  69. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/plans.py +0 -0
  70. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/preauthorizations.py +0 -0
  71. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/products.py +0 -0
  72. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/refunds.py +0 -0
  73. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/settlements.py +0 -0
  74. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/splits.py +0 -0
  75. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/storefronts.py +0 -0
  76. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/subaccounts.py +0 -0
  77. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/subscriptions.py +0 -0
  78. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/terminals.py +0 -0
  79. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/transactions.py +0 -0
  80. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/transfer_recipients.py +0 -0
  81. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/transfers.py +0 -0
  82. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/transfers_control.py +0 -0
  83. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/sub_clients/sync_clients/verification.py +0 -0
  84. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/types.py +0 -0
  85. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/utils.py +0 -0
  86. {pypaystack2-3.3.0 → pypaystack2-3.4.0}/src/pypaystack2/webhook/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pypaystack2
3
- Version: 3.3.0
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
@@ -9,10 +9,10 @@ License-Expression: MIT
9
9
  Classifier: Programming Language :: Python
10
10
  Classifier: Programming Language :: Python :: 3
11
11
  Requires-Dist: httpx>=0.28.1
12
- Requires-Dist: pydantic>=2.12.5
13
- 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'
14
14
  Requires-Dist: ngrok>=1.4.0 ; extra == 'webhook'
15
- Requires-Dist: python-dotenv>=1.2.1 ; extra == 'webhook'
15
+ Requires-Dist: python-dotenv>=1.2.4 ; extra == 'webhook'
16
16
  Requires-Python: >=3.11
17
17
  Provides-Extra: webhook
18
18
  Description-Content-Type: text/markdown
@@ -26,8 +26,6 @@ Description-Content-Type: text/markdown
26
26
  PyPaystack2 is an Open Source Python client library for integrating [Paystack](https://paystack.com/) into your python
27
27
  projects. It aims at being developer friendly and easy to use.
28
28
 
29
- **Version 3 is here now**
30
-
31
29
  ## Features
32
30
 
33
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.3.0"
3
+ version = "3.4.0"
4
4
  description = "A developer-friendly client library for Paystack"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -14,10 +14,10 @@ classifiers = [
14
14
  ]
15
15
 
16
16
 
17
- requires-python = ">= 3.11"
17
+ requires-python = ">=3.11"
18
18
  dependencies = [
19
19
  "httpx>=0.28.1",
20
- "pydantic>=2.12.5",
20
+ "pydantic>=2.14.0",
21
21
  ]
22
22
 
23
23
  [project.scripts]
@@ -25,13 +25,13 @@ pypaystack2 = "pypaystack2.cli:cli_app"
25
25
 
26
26
  [project.optional-dependencies]
27
27
  webhook = [
28
- "fastapi[standard]>=0.123.10",
28
+ "fastapi[standard]>=0.143.0",
29
29
  "ngrok>=1.4.0",
30
- "python-dotenv>=1.2.1",
30
+ "python-dotenv>=1.2.4",
31
31
  ]
32
32
 
33
33
  [build-system]
34
- requires = ["uv_build>=0.11.19,<0.12.0"]
34
+ requires = ["uv_build>=0.13.0,<0.14.0"]
35
35
  build-backend = "uv_build"
36
36
 
37
37
  [dependency-groups]
@@ -42,18 +42,19 @@ dev = [
42
42
  { include-group = "coverage" },
43
43
  ]
44
44
  format = [
45
- "ruff>=0.14.8",
45
+ "ruff>=0.17.0",
46
46
  ]
47
47
  test = [
48
- "python-dotenv>=1.2.1",
49
- "tomli>=2.3.0",
48
+ "python-dotenv>=1.2.4",
49
+ "tomli>=2.5.0",
50
50
  ]
51
51
  coverage = []
52
52
  doc = [
53
- "mike>=2.1.3",
53
+ "mike>=2.2.0",
54
54
  "mkdocs>=1.6.1",
55
55
  "mkdocs-glightbox>=0.5.2",
56
56
  "mkdocs-material>=9.7.0",
57
57
  "mkdocstrings>=1.0.0",
58
58
  "mkdocstrings-python>=2.0.1",
59
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.3.0"
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"
@@ -1,70 +1,73 @@
1
- from pypaystack2.sub_clients.async_clients.storefronts import AsyncStorefrontClient
2
- from pypaystack2.sub_clients.async_clients.orders import AsyncOrderClient
3
- from pypaystack2.sub_clients.async_clients.preauthorizations import (
4
- AsyncPreauthorizationClient,
5
- )
6
- from pypaystack2.sub_clients.sync_clients.preauthorizations import (
7
- PreauthorizationClient,
8
- )
9
- from pypaystack2.sub_clients.sync_clients.orders import OrderClient
10
- from pypaystack2.sub_clients.sync_clients.storefronts import StorefrontClient
11
1
  from http import HTTPMethod
12
- from pypaystack2.types import PaystackDataModel
13
- from pypaystack2.sub_clients.async_clients.direct_debits import AsyncDirectDebitClient
14
- from pypaystack2.sub_clients.sync_clients.direct_debits import DirectDebitClient
15
- from pypaystack2.sub_clients.async_clients.virtual_terminals import (
16
- AsyncVirtualTerminalClient,
17
- )
18
- from pypaystack2.sub_clients.sync_clients.virtual_terminals import VirtualTerminalClient
2
+
19
3
  from pypaystack2.base_clients import BaseAPIClient, BaseAsyncAPIClient
20
4
  from pypaystack2.sub_clients import (
21
5
  ApplePayClient,
22
- BulkChargeClient,
23
- ChargeClient,
24
- IntegrationClient,
25
- CustomerClient,
26
- DedicatedAccountClient,
27
- DisputeClient,
28
- PaymentRequestClient,
29
- MiscellaneousClient,
30
- PaymentPageClient,
31
- PlanClient,
32
- ProductClient,
33
- RefundClient,
34
- SettlementClient,
35
- TransactionSplitClient,
36
- SubAccountClient,
37
- SubscriptionClient,
38
- TerminalClient,
39
- TransactionClient,
40
- TransferRecipientClient,
41
- TransferClient,
42
- TransferControlClient,
43
- VerificationClient,
44
6
  AsyncApplePayClient,
45
7
  AsyncBulkChargeClient,
46
8
  AsyncChargeClient,
47
- AsyncIntegrationClient,
48
9
  AsyncCustomerClient,
49
10
  AsyncDedicatedAccountClient,
50
11
  AsyncDisputeClient,
51
- AsyncPaymentRequestClient,
12
+ AsyncIntegrationClient,
52
13
  AsyncMiscellaneousClient,
53
14
  AsyncPaymentPageClient,
15
+ AsyncPaymentRequestClient,
54
16
  AsyncPlanClient,
55
17
  AsyncProductClient,
56
18
  AsyncRefundClient,
57
19
  AsyncSettlementClient,
58
- AsyncTransactionSplitClient,
59
20
  AsyncSubAccountClient,
60
21
  AsyncSubscriptionClient,
61
22
  AsyncTerminalClient,
62
23
  AsyncTransactionClient,
63
- AsyncTransferRecipientClient,
24
+ AsyncTransactionSplitClient,
64
25
  AsyncTransferClient,
65
26
  AsyncTransferControlClient,
27
+ AsyncTransferRecipientClient,
66
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,
67
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,
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
68
71
 
69
72
 
70
73
  class PaystackClient(BaseAPIClient):
@@ -130,6 +133,8 @@ class PaystackClient(BaseAPIClient):
130
133
  Order API e.g. `OrderClient.create`.
131
134
  preauthorizations: A binding to `PreauthorizationClient` providing methods for interacting with Paystack's
132
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`.
133
138
  """
134
139
 
135
140
  def __init__(self, secret_key: str | None = None):
@@ -190,6 +195,7 @@ class PaystackClient(BaseAPIClient):
190
195
  self.storefronts = StorefrontClient(secret_key=self._secret_key)
191
196
  self.orders = OrderClient(secret_key=self._secret_key)
192
197
  self.preauthorizations = PreauthorizationClient(secret_key=self._secret_key)
198
+ self.webhook_events = WebhookEventClient(secret_key=self._secret_key)
193
199
 
194
200
  def get_capitec_pay_transaction(
195
201
  self,
@@ -287,6 +293,8 @@ class AsyncPaystackClient(BaseAsyncAPIClient):
287
293
  Order API e.g. `AsyncOrderClient.create`.
288
294
  preauthorizations: A binding to `AsyncPreauthorizationClient` providing methods for interacting with Paystack's
289
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`.
290
298
 
291
299
  """
292
300
 
@@ -326,6 +334,7 @@ class AsyncPaystackClient(BaseAsyncAPIClient):
326
334
  self.preauthorizations = AsyncPreauthorizationClient(
327
335
  secret_key=self._secret_key
328
336
  )
337
+ self.webhook_events = AsyncWebhookEventClient(secret_key=self._secret_key)
329
338
 
330
339
  async def get_capitec_pay_transaction(
331
340
  self,
@@ -2,7 +2,7 @@ from datetime import datetime, timedelta
2
2
  from http import HTTPStatus
3
3
  from typing import Any, Generic, Literal, Optional, Union
4
4
 
5
- from pydantic import BaseModel
5
+ from pydantic import BaseModel, Field
6
6
 
7
7
  from pypaystack2.enums import (
8
8
  BulkChargeStatus,
@@ -13,6 +13,8 @@ from pypaystack2.enums import (
13
13
  Interval,
14
14
  RiskAction,
15
15
  SupportedCountryRelationshipType,
16
+ WebhookEventType,
17
+ WebhookDeliveryStatus,
16
18
  )
17
19
  from pypaystack2.models.payload_models import LineItem, Tax
18
20
  from pypaystack2.types import D, PaystackResponseData, T
@@ -858,3 +860,26 @@ class SupportedCountryBank(BaseModel):
858
860
  class AccountNumberPattern(BaseModel):
859
861
  exact_match: bool
860
862
  pattern: str
863
+
864
+
865
+ class WebhookPayload(BaseModel):
866
+ event: WebhookEventType
867
+ data: dict[str, Any]
868
+
869
+
870
+ class WebhookEvent(BaseModel):
871
+ id: str = Field(alias="_id")
872
+ domain: Domain
873
+ category: str
874
+ event_name: WebhookEventType
875
+ category_row_id: int
876
+ status: WebhookDeliveryStatus
877
+ status_detail: str
878
+ response_code: int
879
+ trial_count: int
880
+ created_at: datetime
881
+ updated_at: datetime
882
+ webhook_url: str | None = None
883
+ webhook_url_code: str | None = None
884
+ event_payload: WebhookPayload | str | None = None
885
+ merchant_response_body: dict[str, Any] | str | None = None
@@ -1,4 +1,3 @@
1
- # ruff: noqa: F401
2
1
  from pypaystack2.sub_clients.async_clients import (
3
2
  AsyncApplePayClient,
4
3
  AsyncBulkChargeClient,
@@ -14,15 +13,16 @@ from pypaystack2.sub_clients.async_clients import (
14
13
  AsyncProductClient,
15
14
  AsyncRefundClient,
16
15
  AsyncSettlementClient,
17
- AsyncTransactionSplitClient,
18
16
  AsyncSubAccountClient,
19
17
  AsyncSubscriptionClient,
20
18
  AsyncTerminalClient,
21
19
  AsyncTransactionClient,
22
- AsyncTransferRecipientClient,
20
+ AsyncTransactionSplitClient,
23
21
  AsyncTransferClient,
24
22
  AsyncTransferControlClient,
23
+ AsyncTransferRecipientClient,
25
24
  AsyncVerificationClient,
25
+ AsyncWebhookEventClient,
26
26
  )
27
27
  from pypaystack2.sub_clients.sync_clients import (
28
28
  ApplePayClient,
@@ -39,19 +39,20 @@ from pypaystack2.sub_clients.sync_clients import (
39
39
  ProductClient,
40
40
  RefundClient,
41
41
  SettlementClient,
42
- TransactionSplitClient,
43
42
  SubAccountClient,
44
43
  SubscriptionClient,
45
44
  TerminalClient,
46
45
  TransactionClient,
47
- TransferRecipientClient,
46
+ TransactionSplitClient,
48
47
  TransferClient,
49
48
  TransferControlClient,
49
+ TransferRecipientClient,
50
50
  VerificationClient,
51
+ WebhookEventClient,
51
52
  )
52
53
 
53
54
  __all__ = [
54
- # Async Clients
55
+ "ApplePayClient",
55
56
  "AsyncApplePayClient",
56
57
  "AsyncBulkChargeClient",
57
58
  "AsyncChargeClient",
@@ -66,17 +67,16 @@ __all__ = [
66
67
  "AsyncProductClient",
67
68
  "AsyncRefundClient",
68
69
  "AsyncSettlementClient",
69
- "AsyncTransactionSplitClient",
70
70
  "AsyncSubAccountClient",
71
71
  "AsyncSubscriptionClient",
72
72
  "AsyncTerminalClient",
73
73
  "AsyncTransactionClient",
74
- "AsyncTransferRecipientClient",
74
+ "AsyncTransactionSplitClient",
75
75
  "AsyncTransferClient",
76
76
  "AsyncTransferControlClient",
77
+ "AsyncTransferRecipientClient",
77
78
  "AsyncVerificationClient",
78
- # Sync Clients
79
- "ApplePayClient",
79
+ "AsyncWebhookEventClient",
80
80
  "BulkChargeClient",
81
81
  "ChargeClient",
82
82
  "CustomerClient",
@@ -90,13 +90,14 @@ __all__ = [
90
90
  "ProductClient",
91
91
  "RefundClient",
92
92
  "SettlementClient",
93
- "TransactionSplitClient",
94
93
  "SubAccountClient",
95
94
  "SubscriptionClient",
96
95
  "TerminalClient",
97
96
  "TransactionClient",
98
- "TransferRecipientClient",
97
+ "TransactionSplitClient",
99
98
  "TransferClient",
100
99
  "TransferControlClient",
100
+ "TransferRecipientClient",
101
101
  "VerificationClient",
102
+ "WebhookEventClient",
102
103
  ]
@@ -1,4 +1,3 @@
1
- # ruff: noqa: F401
2
1
  from pypaystack2.sub_clients.async_clients.apple_pay import AsyncApplePayClient
3
2
  from pypaystack2.sub_clients.async_clients.bulk_charges import AsyncBulkChargeClient
4
3
  from pypaystack2.sub_clients.async_clients.charge import AsyncChargeClient
@@ -30,7 +29,7 @@ from pypaystack2.sub_clients.async_clients.transfers_control import (
30
29
  AsyncTransferControlClient,
31
30
  )
32
31
  from pypaystack2.sub_clients.async_clients.verification import AsyncVerificationClient
33
-
32
+ from pypaystack2.sub_clients.async_clients.webhook_events import AsyncWebhookEventClient
34
33
 
35
34
  __all__ = [
36
35
  "AsyncApplePayClient",
@@ -47,13 +46,14 @@ __all__ = [
47
46
  "AsyncProductClient",
48
47
  "AsyncRefundClient",
49
48
  "AsyncSettlementClient",
50
- "AsyncTransactionSplitClient",
51
49
  "AsyncSubAccountClient",
52
50
  "AsyncSubscriptionClient",
53
51
  "AsyncTerminalClient",
54
52
  "AsyncTransactionClient",
55
- "AsyncTransferRecipientClient",
53
+ "AsyncTransactionSplitClient",
56
54
  "AsyncTransferClient",
57
55
  "AsyncTransferControlClient",
56
+ "AsyncTransferRecipientClient",
58
57
  "AsyncVerificationClient",
58
+ "AsyncWebhookEventClient",
59
59
  ]