zenopay-sdk 0.0.1__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.
@@ -0,0 +1,130 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ *.manifest
31
+ *.spec
32
+
33
+ # Installer logs
34
+ pip-log.txt
35
+ pip-delete-this-directory.txt
36
+
37
+ # Unit test / coverage reports
38
+ htmlcov/
39
+ .tox/
40
+ .nox/
41
+ .coverage
42
+ .coverage.*
43
+ .cache
44
+ nosetests.xml
45
+ coverage.xml
46
+ *.cover
47
+ *.py,cover
48
+ .hypothesis/
49
+ .pytest_cache/
50
+ cover/
51
+
52
+ # Virtual environments
53
+ .env
54
+ .venv
55
+ env/
56
+ venv/
57
+ ENV/
58
+ env.bak/
59
+ venv.bak/
60
+
61
+ # IDEs and editors
62
+ .vscode/
63
+ .idea/
64
+ *.swp
65
+ *.swo
66
+ *~
67
+
68
+ # OS files
69
+ .DS_Store
70
+ .DS_Store?
71
+ ._*
72
+ .Spotlight-V100
73
+ .Trashes
74
+ ehthumbs.db
75
+ Thumbs.db
76
+
77
+ # Logs
78
+ *.log
79
+ logs/
80
+
81
+ # Documentation builds
82
+ docs/_build/
83
+ site/
84
+
85
+ # MyPy
86
+ .mypy_cache/
87
+ .dmypy.json
88
+ dmypy.json
89
+
90
+ # Pyre type checker
91
+ .pyre/
92
+
93
+ # pytype static type analyzer
94
+ .pytype/
95
+
96
+ # Cython debug symbols
97
+ cython_debug/
98
+
99
+ # Environment variables
100
+ .env.local
101
+ .env.development.local
102
+ .env.test.local
103
+ .env.production.local
104
+
105
+ # Secrets and config
106
+ config.ini
107
+ secrets.json
108
+ *.key
109
+ *.pem
110
+
111
+ # Temporary files
112
+ *.tmp
113
+ *.temp
114
+ tmp/
115
+ temp/
116
+
117
+ # Package files
118
+ *.tar.gz
119
+ *.zip
120
+
121
+ # Editor config
122
+ .editorconfig
123
+
124
+ # Local development
125
+ local_settings.py
126
+ .local
127
+
128
+ # Test outputs
129
+ test-results/
130
+ test-output/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Elusion Lab
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,387 @@
1
+ Metadata-Version: 2.4
2
+ Name: zenopay-sdk
3
+ Version: 0.0.1
4
+ Summary: A modern Python SDK for the ZenoPay payment API
5
+ Project-URL: Homepage, https://github.com/elusionhub/zenopay-python-sdk
6
+ Project-URL: Documentation, https://github.com/elusionhub/zenopay-python-sdk#readme
7
+ Project-URL: Repository, https://github.com/elusionhub/zenopay-python-sdk.git
8
+ Project-URL: Issues, https://github.com/elusionhub/zenopay-python-sdk/issues
9
+ Project-URL: Changelog, https://github.com/elusionhub/zenopay-python-sdk/blob/main/CHANGELOG.md
10
+ Author-email: Elution Hub <elusion.lab@gmail.com>
11
+ Maintainer-email: Elution Hub <elusion.lab@gmail.com>
12
+ License-Expression: MIT
13
+ License-File: LICENSE
14
+ Keywords: africa,api,mobile-money,payments,payments-gateway,sdk,tanzania,ussd,zenopay
15
+ Classifier: Development Status :: 4 - Beta
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: License :: OSI Approved :: MIT License
18
+ Classifier: Operating System :: OS Independent
19
+ Classifier: Programming Language :: Python :: 3
20
+ Classifier: Programming Language :: Python :: 3.8
21
+ Classifier: Programming Language :: Python :: 3.9
22
+ Classifier: Programming Language :: Python :: 3.10
23
+ Classifier: Programming Language :: Python :: 3.11
24
+ Classifier: Programming Language :: Python :: 3.12
25
+ Classifier: Topic :: Office/Business :: Financial :: Point-Of-Sale
26
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
27
+ Classifier: Typing :: Typed
28
+ Requires-Python: >=3.8
29
+ Requires-Dist: httpx>=0.25.0
30
+ Requires-Dist: pydantic>=2.0.0
31
+ Requires-Dist: python-dotenv>=1.0.0
32
+ Requires-Dist: typing-extensions>=4.0.0; python_version < '3.11'
33
+ Provides-Extra: dev
34
+ Requires-Dist: black>=23.0.0; extra == 'dev'
35
+ Requires-Dist: flake8>=6.0.0; extra == 'dev'
36
+ Requires-Dist: mypy>=1.0.0; extra == 'dev'
37
+ Requires-Dist: pre-commit>=3.0.0; extra == 'dev'
38
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
39
+ Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
40
+ Requires-Dist: pytest-mock>=3.10.0; extra == 'dev'
41
+ Requires-Dist: pytest>=7.0.0; extra == 'dev'
42
+ Requires-Dist: respx>=0.20.0; extra == 'dev'
43
+ Provides-Extra: docs
44
+ Requires-Dist: mkdocs-material>=9.0.0; extra == 'docs'
45
+ Requires-Dist: mkdocs>=1.5.0; extra == 'docs'
46
+ Requires-Dist: mkdocstrings[python]>=0.20.0; extra == 'docs'
47
+ Provides-Extra: server
48
+ Requires-Dist: fastapi>=0.68.0; extra == 'server'
49
+ Requires-Dist: flask>=2.0.0; extra == 'server'
50
+ Requires-Dist: uvicorn>=0.15.0; extra == 'server'
51
+ Description-Content-Type: text/markdown
52
+
53
+ # ZenoPay Python SDK
54
+
55
+ Modern Python SDK for ZenoPay payment API with async/sync support and webhook handling.
56
+
57
+ ## Installation
58
+
59
+ ```bash
60
+ pip install zenopay-sdk
61
+ ```
62
+
63
+ ## Quick Start
64
+
65
+ ```python
66
+ from elusion.zenopay import ZenoPay
67
+ from elusion.zenopay.models.order import NewOrder
68
+
69
+ # Initialize client
70
+ client = ZenoPay(account_id="your_account_id")
71
+
72
+ # Create order (sync)
73
+ with client:
74
+ order = NewOrder(
75
+ buyer_email="customer@example.com",
76
+ buyer_name="John Doe",
77
+ buyer_phone="0700000000",
78
+ amount=1000
79
+ )
80
+ response = client.orders.sync.create(order)
81
+ print(f"Order ID: {response.data.order_id}")
82
+ ```
83
+
84
+ ## Configuration
85
+
86
+ ### Environment Variables
87
+
88
+ ```bash
89
+ export ZENOPAY_ACCOUNT_ID="your_account_id"
90
+ export ZENOPAY_API_KEY="your_api_key" # Optional
91
+ export ZENOPAY_SECRET_KEY="your_secret_key" # Optional
92
+ ```
93
+
94
+ ### Code Configuration
95
+
96
+ ```python
97
+ client = ZenoPay(
98
+ account_id="your_account_id",
99
+ api_key="your_api_key",
100
+ secret_key="your_secret_key",
101
+ timeout=30.0
102
+ )
103
+ ```
104
+
105
+ ## API Usage
106
+
107
+ ### Synchronous Operations
108
+
109
+ ```python
110
+ # Create order
111
+ with client:
112
+ order_data = {
113
+ "buyer_email": "test@example.com",
114
+ "buyer_name": "Test User",
115
+ "buyer_phone": "0700000000",
116
+ "amount": 5000,
117
+ "webhook_url": "https://yoursite.com/webhook"
118
+ }
119
+ response = client.orders.sync.create(order_data)
120
+ order_id = response.data.order_id
121
+
122
+ # Check status
123
+ with client:
124
+ status = client.orders.sync.get_status(order_id)
125
+ print(f"Payment status: {status.data.payment_status}")
126
+
127
+ # Check if paid
128
+ with client:
129
+ is_paid = client.orders.sync.check_payment(order_id)
130
+ print(f"Paid: {is_paid}")
131
+
132
+ # Wait for payment
133
+ with client:
134
+ try:
135
+ completed = client.orders.sync.wait_for_payment(order_id, timeout=300)
136
+ print("Payment completed!")
137
+ except TimeoutError:
138
+ print("Payment timeout")
139
+ ```
140
+
141
+ ### Asynchronous Operations
142
+
143
+ ```python
144
+ import asyncio
145
+
146
+ async def create_payment():
147
+ async with client:
148
+ order_data = {
149
+ "buyer_email": "test@example.com",
150
+ "buyer_name": "Test User",
151
+ "buyer_phone": "0700000000",
152
+ "amount": 5000
153
+ }
154
+
155
+ # Create order
156
+ response = await client.orders.create(order_data)
157
+ order_id = response.data.order_id
158
+
159
+ # Check status
160
+ status = await client.orders.get_status(order_id)
161
+ print(f"Status: {status.data.payment_status}")
162
+
163
+ # Wait for completion
164
+ try:
165
+ completed = await client.orders.wait_for_payment(order_id)
166
+ print("Payment completed!")
167
+ except TimeoutError:
168
+ print("Payment timeout")
169
+
170
+ asyncio.run(create_payment())
171
+ ```
172
+
173
+ ## Webhook Handling
174
+
175
+ ### Basic Setup
176
+
177
+ ```python
178
+ # Setup handlers
179
+ def payment_completed(event):
180
+ order_id = event.payload.order_id
181
+ reference = event.payload.reference
182
+ print(f"Payment completed: {order_id} - {reference}")
183
+
184
+ def payment_failed(event):
185
+ order_id = event.payload.order_id
186
+ print(f"Payment failed: {order_id}")
187
+
188
+ # Register handlers
189
+ client.webhooks.on_payment_completed(payment_completed)
190
+ client.webhooks.on_payment_failed(payment_failed)
191
+
192
+ # Process webhook
193
+ webhook_data = '{"order_id":"123","payment_status":"COMPLETED","reference":"REF123"}'
194
+ response = client.webhooks.process_webhook_request(webhook_data)
195
+ ```
196
+
197
+ ### Flask Integration
198
+
199
+ ```python
200
+ from flask import Flask, request, jsonify
201
+
202
+ app = Flask(__name__)
203
+ client = ZenoPay(account_id="your_account_id")
204
+
205
+ def handle_completed_payment(event):
206
+ order_id = event.payload.order_id
207
+ # Update database, send emails, etc.
208
+ print(f"Order {order_id} completed")
209
+
210
+ client.webhooks.on_payment_completed(handle_completed_payment)
211
+
212
+ @app.route('/zenopay/webhook', methods=['POST'])
213
+ def webhook():
214
+ raw_data = request.data.decode('utf-8')
215
+ response = client.webhooks.process_webhook_request(raw_data)
216
+ return jsonify({'status': response.status})
217
+
218
+ if __name__ == '__main__':
219
+ app.run()
220
+ ```
221
+
222
+ ### FastAPI Integration
223
+
224
+ ```python
225
+ from fastapi import FastAPI, Request
226
+
227
+ app = FastAPI()
228
+ client = ZenoPay(account_id="your_account_id")
229
+
230
+ def handle_completed_payment(event):
231
+ order_id = event.payload.order_id
232
+ print(f"Order {order_id} completed")
233
+
234
+ client.webhooks.on_payment_completed(handle_completed_payment)
235
+
236
+ @app.post("/zenopay/webhook")
237
+ async def webhook(request: Request):
238
+ raw_data = await request.body()
239
+ raw_data_str = raw_data.decode('utf-8')
240
+ response = client.webhooks.process_webhook_request(raw_data_str)
241
+ return {'status': response.status}
242
+ ```
243
+
244
+ ## Error Handling
245
+
246
+ ```python
247
+ from elusion.zenopay.exceptions import (
248
+ ZenoPayError,
249
+ ZenoPayValidationError,
250
+ ZenoPayNetworkError
251
+ )
252
+
253
+ try:
254
+ with client:
255
+ response = client.orders.sync.create(order_data)
256
+ except ZenoPayValidationError as e:
257
+ print(f"Validation error: {e.message}")
258
+ print(f"Details: {e.validation_errors}")
259
+ except ZenoPayNetworkError as e:
260
+ print(f"Network error: {e.message}")
261
+ except ZenoPayError as e:
262
+ print(f"General error: {e.message}")
263
+ ```
264
+
265
+ ## Order Models
266
+
267
+ ### Creating Orders
268
+
269
+ ```python
270
+ from elusion.zenopay.models.order import NewOrder
271
+
272
+ # Using model
273
+ order = NewOrder(
274
+ buyer_email="customer@example.com",
275
+ buyer_name="John Doe",
276
+ buyer_phone="0700000000",
277
+ amount=1000,
278
+ webhook_url="https://yoursite.com/webhook",
279
+ metadata={
280
+ "product_id": "12345",
281
+ "campaign": "summer_sale"
282
+ }
283
+ )
284
+
285
+ # Using dictionary
286
+ order_data = {
287
+ "buyer_email": "customer@example.com",
288
+ "buyer_name": "John Doe",
289
+ "buyer_phone": "0700000000",
290
+ "amount": 1000
291
+ }
292
+ ```
293
+
294
+ ### Response Models
295
+
296
+ ```python
297
+ # Order creation response
298
+ response = client.orders.sync.create(order)
299
+ print(f"Order ID: {response.data.order_id}")
300
+ print(f"Status: {response.data.status}")
301
+ print(f"Message: {response.data.message}")
302
+
303
+ # Status check response
304
+ status = client.orders.sync.get_status(order_id)
305
+ print(f"Payment Status: {status.data.payment_status}")
306
+ print(f"Order ID: {status.data.order_id}")
307
+ ```
308
+
309
+ ## API Reference
310
+
311
+ ### Order Operations
312
+
313
+ | Method | Sync | Async | Description |
314
+ | ---------------- | --------------------------------------- | ---------------------------------------- | -------------------------- |
315
+ | Create Order | `client.orders.sync.create()` | `await client.orders.create()` | Create new payment order |
316
+ | Get Status | `client.orders.sync.get_status()` | `await client.orders.get_status()` | Check order payment status |
317
+ | Check Payment | `client.orders.sync.check_payment()` | `await client.orders.check_payment()` | Returns boolean if paid |
318
+ | Wait for Payment | `client.orders.sync.wait_for_payment()` | `await client.orders.wait_for_payment()` | Poll until completed |
319
+
320
+ ### Webhook Events
321
+
322
+ | Event | Handler Method | Description |
323
+ | --------- | ---------------------------------------- | ------------------ |
324
+ | COMPLETED | `client.webhooks.on_payment_completed()` | Payment successful |
325
+ | FAILED | `client.webhooks.on_payment_failed()` | Payment failed |
326
+ | PENDING | `client.webhooks.on_payment_pending()` | Payment initiated |
327
+ | CANCELLED | `client.webhooks.on_payment_cancelled()` | Payment cancelled |
328
+
329
+ ## Testing
330
+
331
+ ```python
332
+ # Create test webhook
333
+ test_event = client.webhooks.create_test_webhook("test-order-123", "COMPLETED")
334
+ response = client.webhooks.handle_webhook(test_event)
335
+ print(f"Test response: {response.status}")
336
+ ```
337
+
338
+ ## Best Practices
339
+
340
+ ### Context Managers
341
+
342
+ Always use context managers for proper resource cleanup:
343
+
344
+ ```python
345
+ # Sync
346
+ with client:
347
+ response = client.orders.sync.create(order)
348
+
349
+ # Async
350
+ async with client:
351
+ response = await client.orders.create(order)
352
+ ```
353
+
354
+ ### Error Handling
355
+
356
+ Handle specific exceptions for better error management:
357
+
358
+ ```python
359
+ try:
360
+ with client:
361
+ response = client.orders.sync.create(order)
362
+ except ZenoPayValidationError:
363
+ # Handle validation errors
364
+ pass
365
+ except ZenoPayNetworkError:
366
+ # Handle network issues
367
+ pass
368
+ ```
369
+
370
+ ### Environment Configuration
371
+
372
+ Use environment variables for sensitive configuration:
373
+
374
+ ```python
375
+ # Don't hardcode credentials
376
+ client = ZenoPay(account_id=os.getenv('ZENOPAY_ACCOUNT_ID'))
377
+ ```
378
+
379
+ ## Support
380
+
381
+ - **GitHub**: [zenopay-python-sdk](https://github.com/elusionhub/zenopay-python-sdk)
382
+ - **Issues**: [Report bugs](https://github.com/elusionhub/zenopay-python-sdk/issues)
383
+ - **Email**: elusion.lab@gmail.com
384
+
385
+ ## License
386
+
387
+ MIT License - see [LICENSE](LICENSE) file for details.