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.
- zenopay_sdk-0.0.1/.gitignore +130 -0
- zenopay_sdk-0.0.1/LICENSE +21 -0
- zenopay_sdk-0.0.1/PKG-INFO +387 -0
- zenopay_sdk-0.0.1/README.md +335 -0
- zenopay_sdk-0.0.1/pyproject.toml +176 -0
- zenopay_sdk-0.0.1/src/elusion/__init__.py +3 -0
- zenopay_sdk-0.0.1/src/elusion/zenopay/__init__.py +42 -0
- zenopay_sdk-0.0.1/src/elusion/zenopay/client.py +207 -0
- zenopay_sdk-0.0.1/src/elusion/zenopay/config.py +116 -0
- zenopay_sdk-0.0.1/src/elusion/zenopay/exceptions.py +227 -0
- zenopay_sdk-0.0.1/src/elusion/zenopay/http/__init__.py +5 -0
- zenopay_sdk-0.0.1/src/elusion/zenopay/http/client.py +320 -0
- zenopay_sdk-0.0.1/src/elusion/zenopay/models/__init__.py +43 -0
- zenopay_sdk-0.0.1/src/elusion/zenopay/models/common.py +93 -0
- zenopay_sdk-0.0.1/src/elusion/zenopay/models/order.py +251 -0
- zenopay_sdk-0.0.1/src/elusion/zenopay/models/payment.py +304 -0
- zenopay_sdk-0.0.1/src/elusion/zenopay/models/webhook.py +122 -0
- zenopay_sdk-0.0.1/src/elusion/zenopay/services/__init__.py +7 -0
- zenopay_sdk-0.0.1/src/elusion/zenopay/services/base.py +175 -0
- zenopay_sdk-0.0.1/src/elusion/zenopay/services/orders.py +135 -0
- zenopay_sdk-0.0.1/src/elusion/zenopay/services/webhooks.py +188 -0
- zenopay_sdk-0.0.1/src/elusion/zenopay/utils/__init__.py +9 -0
- zenopay_sdk-0.0.1/src/elusion/zenopay/utils/helpers.py +35 -0
@@ -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.
|