deliveryapi 1.0.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.
- deliveryapi-1.0.0/.gitignore +26 -0
- deliveryapi-1.0.0/PKG-INFO +162 -0
- deliveryapi-1.0.0/README.md +133 -0
- deliveryapi-1.0.0/pyproject.toml +60 -0
- deliveryapi-1.0.0/src/deliveryapi/__init__.py +84 -0
- deliveryapi-1.0.0/src/deliveryapi/_client.py +125 -0
- deliveryapi-1.0.0/src/deliveryapi/_exceptions.py +25 -0
- deliveryapi-1.0.0/src/deliveryapi/_http.py +110 -0
- deliveryapi-1.0.0/src/deliveryapi/_types.py +212 -0
- deliveryapi-1.0.0/src/deliveryapi/_webhook.py +100 -0
- deliveryapi-1.0.0/src/deliveryapi/py.typed +0 -0
- deliveryapi-1.0.0/src/deliveryapi/resources/__init__.py +0 -0
- deliveryapi-1.0.0/src/deliveryapi/resources/_base.py +13 -0
- deliveryapi-1.0.0/src/deliveryapi/resources/couriers.py +20 -0
- deliveryapi-1.0.0/src/deliveryapi/resources/subscriptions.py +101 -0
- deliveryapi-1.0.0/src/deliveryapi/resources/tracking.py +99 -0
- deliveryapi-1.0.0/src/deliveryapi/resources/webhooks.py +68 -0
- deliveryapi-1.0.0/tests/__init__.py +0 -0
- deliveryapi-1.0.0/tests/conftest.py +13 -0
- deliveryapi-1.0.0/tests/test_async.py +59 -0
- deliveryapi-1.0.0/tests/test_couriers.py +35 -0
- deliveryapi-1.0.0/tests/test_subscriptions.py +65 -0
- deliveryapi-1.0.0/tests/test_tracking.py +72 -0
- deliveryapi-1.0.0/tests/test_webhook_verify.py +93 -0
- deliveryapi-1.0.0/tests/test_webhooks.py +66 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Dependencies
|
|
2
|
+
node_modules/
|
|
3
|
+
|
|
4
|
+
# Build outputs
|
|
5
|
+
dist/
|
|
6
|
+
lib/
|
|
7
|
+
.output/
|
|
8
|
+
.nuxt/
|
|
9
|
+
.astro/
|
|
10
|
+
|
|
11
|
+
# Environment variables (민감정보)
|
|
12
|
+
.env
|
|
13
|
+
.env.*
|
|
14
|
+
!.env.example
|
|
15
|
+
|
|
16
|
+
# Firebase
|
|
17
|
+
.firebase/
|
|
18
|
+
**/serviceAccountKey*.json
|
|
19
|
+
**/serviceAccount*.json
|
|
20
|
+
|
|
21
|
+
# macOS
|
|
22
|
+
.DS_Store
|
|
23
|
+
|
|
24
|
+
# IDE
|
|
25
|
+
.vscode/
|
|
26
|
+
.idea/
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: deliveryapi
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Official Python SDK for the DeliveryAPI courier tracking platform
|
|
5
|
+
Project-URL: Homepage, https://deliveryapi.co.kr
|
|
6
|
+
Project-URL: Documentation, https://docs.deliveryapi.co.kr
|
|
7
|
+
Author-email: DeliveryAPI <support@deliveryapi.co.kr>
|
|
8
|
+
License: MIT
|
|
9
|
+
Keywords: courier,delivery,korea,sdk,tracking,webhook
|
|
10
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Typing :: Typed
|
|
19
|
+
Requires-Python: >=3.9
|
|
20
|
+
Requires-Dist: httpx>=0.27.0
|
|
21
|
+
Requires-Dist: typing-extensions>=4.0.0
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: mypy>=1.9; extra == 'dev'
|
|
24
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
25
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
26
|
+
Requires-Dist: respx>=0.21; extra == 'dev'
|
|
27
|
+
Requires-Dist: ruff>=0.4; extra == 'dev'
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# deliveryapi — Python SDK
|
|
31
|
+
|
|
32
|
+
Official Python SDK for the [DeliveryAPI](https://deliveryapi.co.kr) courier tracking and webhook platform.
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install deliveryapi
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Quick Start
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
from deliveryapi import DeliverySaasClient
|
|
44
|
+
|
|
45
|
+
client = DeliverySaasClient(
|
|
46
|
+
api_key="pk_live_...",
|
|
47
|
+
secret_key="sk_live_...",
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# Query a single tracking number
|
|
51
|
+
result = client.tracking.get_one("LOTTE", "1234567890")
|
|
52
|
+
item = result["results"][0]
|
|
53
|
+
if item["success"]:
|
|
54
|
+
print(item["data"]["deliveryStatus"]) # e.g. "IN_TRANSIT"
|
|
55
|
+
|
|
56
|
+
# Batch query
|
|
57
|
+
result = client.tracking.get([
|
|
58
|
+
{"courierCode": "LOTTE", "trackingNumber": "1234567890"},
|
|
59
|
+
{"courierCode": "cj", "trackingNumber": "9876543210"},
|
|
60
|
+
])
|
|
61
|
+
print(result["summary"])
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Async Support
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
import asyncio
|
|
68
|
+
from deliveryapi import AsyncDeliverySaasClient
|
|
69
|
+
|
|
70
|
+
async def main():
|
|
71
|
+
async with AsyncDeliverySaasClient(
|
|
72
|
+
api_key="pk_live_...",
|
|
73
|
+
secret_key="sk_live_...",
|
|
74
|
+
) as client:
|
|
75
|
+
result = await client.tracking.get_one("LOTTE", "1234567890")
|
|
76
|
+
print(result)
|
|
77
|
+
|
|
78
|
+
asyncio.run(main())
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Webhook Signature Verification
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from deliveryapi import verify_webhook_signature, WebhookSignatureError
|
|
85
|
+
|
|
86
|
+
# Flask example
|
|
87
|
+
@app.route("/webhook", methods=["POST"])
|
|
88
|
+
def handle_webhook():
|
|
89
|
+
try:
|
|
90
|
+
verify_webhook_signature(
|
|
91
|
+
payload=request.get_data(as_text=True),
|
|
92
|
+
signature=request.headers["X-Webhook-Signature"],
|
|
93
|
+
timestamp=request.headers["X-Webhook-Timestamp"],
|
|
94
|
+
secret="whsec_...",
|
|
95
|
+
)
|
|
96
|
+
except WebhookSignatureError:
|
|
97
|
+
return "Invalid signature", 400
|
|
98
|
+
|
|
99
|
+
event = request.json
|
|
100
|
+
print(event["data"]["currentStatus"])
|
|
101
|
+
return "", 200
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Error Handling
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from deliveryapi import (
|
|
108
|
+
DeliverySaasClient,
|
|
109
|
+
DeliverySaasError,
|
|
110
|
+
AuthenticationError,
|
|
111
|
+
RateLimitError,
|
|
112
|
+
NotFoundError,
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
client = DeliverySaasClient(api_key="pk_...", secret_key="sk_...")
|
|
116
|
+
|
|
117
|
+
try:
|
|
118
|
+
result = client.tracking.get_one("LOTTE", "1234567890")
|
|
119
|
+
except AuthenticationError:
|
|
120
|
+
print("Invalid API credentials")
|
|
121
|
+
except RateLimitError:
|
|
122
|
+
print("Rate limit exceeded — slow down requests")
|
|
123
|
+
except NotFoundError:
|
|
124
|
+
print("Resource not found")
|
|
125
|
+
except DeliverySaasError as e:
|
|
126
|
+
print(f"API error {e.status_code}: {e}")
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Webhook Management
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
# Register an endpoint
|
|
133
|
+
endpoint = client.webhooks.create({
|
|
134
|
+
"url": "https://my-server.com/webhook",
|
|
135
|
+
"name": "Production server",
|
|
136
|
+
})
|
|
137
|
+
print(endpoint["id"]) # e.g. "ep_..."
|
|
138
|
+
|
|
139
|
+
# Create a subscription
|
|
140
|
+
sub = client.subscriptions.create({
|
|
141
|
+
"courierCode": "LOTTE",
|
|
142
|
+
"trackingNumber": "1234567890",
|
|
143
|
+
"endpointId": endpoint["id"],
|
|
144
|
+
})
|
|
145
|
+
print(sub["id"]) # e.g. "sub_..."
|
|
146
|
+
|
|
147
|
+
# List and cancel
|
|
148
|
+
subs = client.subscriptions.list(status="active")
|
|
149
|
+
client.subscriptions.cancel(sub["id"])
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Supported Couriers
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
couriers = client.couriers.list()
|
|
156
|
+
for c in couriers["couriers"]:
|
|
157
|
+
print(c["id"], c["displayName"])
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## License
|
|
161
|
+
|
|
162
|
+
MIT
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# deliveryapi — Python SDK
|
|
2
|
+
|
|
3
|
+
Official Python SDK for the [DeliveryAPI](https://deliveryapi.co.kr) courier tracking and webhook platform.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install deliveryapi
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from deliveryapi import DeliverySaasClient
|
|
15
|
+
|
|
16
|
+
client = DeliverySaasClient(
|
|
17
|
+
api_key="pk_live_...",
|
|
18
|
+
secret_key="sk_live_...",
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
# Query a single tracking number
|
|
22
|
+
result = client.tracking.get_one("LOTTE", "1234567890")
|
|
23
|
+
item = result["results"][0]
|
|
24
|
+
if item["success"]:
|
|
25
|
+
print(item["data"]["deliveryStatus"]) # e.g. "IN_TRANSIT"
|
|
26
|
+
|
|
27
|
+
# Batch query
|
|
28
|
+
result = client.tracking.get([
|
|
29
|
+
{"courierCode": "LOTTE", "trackingNumber": "1234567890"},
|
|
30
|
+
{"courierCode": "cj", "trackingNumber": "9876543210"},
|
|
31
|
+
])
|
|
32
|
+
print(result["summary"])
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Async Support
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
import asyncio
|
|
39
|
+
from deliveryapi import AsyncDeliverySaasClient
|
|
40
|
+
|
|
41
|
+
async def main():
|
|
42
|
+
async with AsyncDeliverySaasClient(
|
|
43
|
+
api_key="pk_live_...",
|
|
44
|
+
secret_key="sk_live_...",
|
|
45
|
+
) as client:
|
|
46
|
+
result = await client.tracking.get_one("LOTTE", "1234567890")
|
|
47
|
+
print(result)
|
|
48
|
+
|
|
49
|
+
asyncio.run(main())
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Webhook Signature Verification
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
from deliveryapi import verify_webhook_signature, WebhookSignatureError
|
|
56
|
+
|
|
57
|
+
# Flask example
|
|
58
|
+
@app.route("/webhook", methods=["POST"])
|
|
59
|
+
def handle_webhook():
|
|
60
|
+
try:
|
|
61
|
+
verify_webhook_signature(
|
|
62
|
+
payload=request.get_data(as_text=True),
|
|
63
|
+
signature=request.headers["X-Webhook-Signature"],
|
|
64
|
+
timestamp=request.headers["X-Webhook-Timestamp"],
|
|
65
|
+
secret="whsec_...",
|
|
66
|
+
)
|
|
67
|
+
except WebhookSignatureError:
|
|
68
|
+
return "Invalid signature", 400
|
|
69
|
+
|
|
70
|
+
event = request.json
|
|
71
|
+
print(event["data"]["currentStatus"])
|
|
72
|
+
return "", 200
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Error Handling
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
from deliveryapi import (
|
|
79
|
+
DeliverySaasClient,
|
|
80
|
+
DeliverySaasError,
|
|
81
|
+
AuthenticationError,
|
|
82
|
+
RateLimitError,
|
|
83
|
+
NotFoundError,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
client = DeliverySaasClient(api_key="pk_...", secret_key="sk_...")
|
|
87
|
+
|
|
88
|
+
try:
|
|
89
|
+
result = client.tracking.get_one("LOTTE", "1234567890")
|
|
90
|
+
except AuthenticationError:
|
|
91
|
+
print("Invalid API credentials")
|
|
92
|
+
except RateLimitError:
|
|
93
|
+
print("Rate limit exceeded — slow down requests")
|
|
94
|
+
except NotFoundError:
|
|
95
|
+
print("Resource not found")
|
|
96
|
+
except DeliverySaasError as e:
|
|
97
|
+
print(f"API error {e.status_code}: {e}")
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Webhook Management
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
# Register an endpoint
|
|
104
|
+
endpoint = client.webhooks.create({
|
|
105
|
+
"url": "https://my-server.com/webhook",
|
|
106
|
+
"name": "Production server",
|
|
107
|
+
})
|
|
108
|
+
print(endpoint["id"]) # e.g. "ep_..."
|
|
109
|
+
|
|
110
|
+
# Create a subscription
|
|
111
|
+
sub = client.subscriptions.create({
|
|
112
|
+
"courierCode": "LOTTE",
|
|
113
|
+
"trackingNumber": "1234567890",
|
|
114
|
+
"endpointId": endpoint["id"],
|
|
115
|
+
})
|
|
116
|
+
print(sub["id"]) # e.g. "sub_..."
|
|
117
|
+
|
|
118
|
+
# List and cancel
|
|
119
|
+
subs = client.subscriptions.list(status="active")
|
|
120
|
+
client.subscriptions.cancel(sub["id"])
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Supported Couriers
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
couriers = client.couriers.list()
|
|
127
|
+
for c in couriers["couriers"]:
|
|
128
|
+
print(c["id"], c["displayName"])
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## License
|
|
132
|
+
|
|
133
|
+
MIT
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "deliveryapi"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "Official Python SDK for the DeliveryAPI courier tracking platform"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
|
+
keywords = ["delivery", "courier", "tracking", "webhook", "korea", "sdk"]
|
|
13
|
+
authors = [{ name = "DeliveryAPI", email = "support@deliveryapi.co.kr" }]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 5 - Production/Stable",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.9",
|
|
20
|
+
"Programming Language :: Python :: 3.10",
|
|
21
|
+
"Programming Language :: Python :: 3.11",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Typing :: Typed",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
dependencies = [
|
|
27
|
+
"httpx>=0.27.0",
|
|
28
|
+
"typing_extensions>=4.0.0",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[project.optional-dependencies]
|
|
32
|
+
dev = [
|
|
33
|
+
"pytest>=8.0",
|
|
34
|
+
"pytest-asyncio>=0.23",
|
|
35
|
+
"respx>=0.21",
|
|
36
|
+
"mypy>=1.9",
|
|
37
|
+
"ruff>=0.4",
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
[project.urls]
|
|
41
|
+
Homepage = "https://deliveryapi.co.kr"
|
|
42
|
+
Documentation = "https://docs.deliveryapi.co.kr"
|
|
43
|
+
|
|
44
|
+
[tool.hatch.build.targets.wheel]
|
|
45
|
+
packages = ["src/deliveryapi"]
|
|
46
|
+
|
|
47
|
+
[tool.ruff]
|
|
48
|
+
src = ["src"]
|
|
49
|
+
target-version = "py39"
|
|
50
|
+
|
|
51
|
+
[tool.ruff.lint]
|
|
52
|
+
select = ["E", "F", "I", "UP"]
|
|
53
|
+
|
|
54
|
+
[tool.mypy]
|
|
55
|
+
strict = true
|
|
56
|
+
mypy_path = "src"
|
|
57
|
+
|
|
58
|
+
[tool.pytest.ini_options]
|
|
59
|
+
asyncio_mode = "auto"
|
|
60
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""DeliverySaaS Python SDK.
|
|
2
|
+
|
|
3
|
+
Quick start::
|
|
4
|
+
|
|
5
|
+
from deliveryapi import DeliverySaasClient
|
|
6
|
+
|
|
7
|
+
client = DeliverySaasClient(api_key="pk_...", secret_key="sk_...")
|
|
8
|
+
result = client.tracking.get_one("LOTTE", "1234567890")
|
|
9
|
+
print(result["results"][0]["data"]["deliveryStatus"])
|
|
10
|
+
"""
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from ._client import AsyncDeliverySaasClient, DeliverySaasClient
|
|
14
|
+
from ._exceptions import (
|
|
15
|
+
AuthenticationError,
|
|
16
|
+
DeliverySaasError,
|
|
17
|
+
NotFoundError,
|
|
18
|
+
RateLimitError,
|
|
19
|
+
)
|
|
20
|
+
from ._types import (
|
|
21
|
+
CourierDeliveryStatus,
|
|
22
|
+
CourierInfo,
|
|
23
|
+
CourierListResult,
|
|
24
|
+
SubscriptionCreateInput,
|
|
25
|
+
SubscriptionListResult,
|
|
26
|
+
TrackingCacheInfo,
|
|
27
|
+
TrackingError,
|
|
28
|
+
TrackingErrorCode,
|
|
29
|
+
TrackingItem,
|
|
30
|
+
TrackingProgress,
|
|
31
|
+
TrackingResponse,
|
|
32
|
+
TrackingResult,
|
|
33
|
+
TrackingSummary,
|
|
34
|
+
TrackingSubscription,
|
|
35
|
+
UnifiedTrackingResponse,
|
|
36
|
+
WebhookCreateInput,
|
|
37
|
+
WebhookEndpoint,
|
|
38
|
+
WebhookListResult,
|
|
39
|
+
WebhookPayload,
|
|
40
|
+
WebhookPayloadData,
|
|
41
|
+
WebhookTestResult,
|
|
42
|
+
)
|
|
43
|
+
from ._webhook import WebhookSignatureError, verify_webhook_signature
|
|
44
|
+
|
|
45
|
+
__version__ = "1.0.0"
|
|
46
|
+
|
|
47
|
+
__all__ = [
|
|
48
|
+
# Clients
|
|
49
|
+
"DeliverySaasClient",
|
|
50
|
+
"AsyncDeliverySaasClient",
|
|
51
|
+
# Exceptions
|
|
52
|
+
"DeliverySaasError",
|
|
53
|
+
"AuthenticationError",
|
|
54
|
+
"RateLimitError",
|
|
55
|
+
"NotFoundError",
|
|
56
|
+
# Webhook utils
|
|
57
|
+
"verify_webhook_signature",
|
|
58
|
+
"WebhookSignatureError",
|
|
59
|
+
# Types — tracking
|
|
60
|
+
"CourierDeliveryStatus",
|
|
61
|
+
"TrackingItem",
|
|
62
|
+
"TrackingProgress",
|
|
63
|
+
"TrackingResult",
|
|
64
|
+
"TrackingError",
|
|
65
|
+
"TrackingErrorCode",
|
|
66
|
+
"TrackingCacheInfo",
|
|
67
|
+
"TrackingSummary",
|
|
68
|
+
"TrackingResponse",
|
|
69
|
+
"UnifiedTrackingResponse",
|
|
70
|
+
# Types — couriers
|
|
71
|
+
"CourierInfo",
|
|
72
|
+
"CourierListResult",
|
|
73
|
+
# Types — webhooks
|
|
74
|
+
"WebhookCreateInput",
|
|
75
|
+
"WebhookEndpoint",
|
|
76
|
+
"WebhookListResult",
|
|
77
|
+
"WebhookTestResult",
|
|
78
|
+
"WebhookPayload",
|
|
79
|
+
"WebhookPayloadData",
|
|
80
|
+
# Types — subscriptions
|
|
81
|
+
"SubscriptionCreateInput",
|
|
82
|
+
"TrackingSubscription",
|
|
83
|
+
"SubscriptionListResult",
|
|
84
|
+
]
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"""Main client classes for the DeliverySaaS API."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from ._http import DEFAULT_BASE_URL, DEFAULT_TIMEOUT, AsyncHttpClient, HttpClient
|
|
5
|
+
from .resources.couriers import AsyncCouriersResource, CouriersResource
|
|
6
|
+
from .resources.subscriptions import AsyncSubscriptionsResource, SubscriptionsResource
|
|
7
|
+
from .resources.tracking import AsyncTrackingResource, TrackingResource
|
|
8
|
+
from .resources.webhooks import AsyncWebhooksResource, WebhooksResource
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class DeliverySaasClient:
|
|
12
|
+
"""Synchronous DeliverySaaS API client.
|
|
13
|
+
|
|
14
|
+
Args:
|
|
15
|
+
api_key: Your API key (``pk_live_...`` or ``pk_test_...``).
|
|
16
|
+
secret_key: Your secret key (``sk_live_...`` or ``sk_test_...``).
|
|
17
|
+
base_url: Override the API base URL (useful for local emulator).
|
|
18
|
+
timeout: HTTP request timeout in seconds (default: 30).
|
|
19
|
+
|
|
20
|
+
Example::
|
|
21
|
+
|
|
22
|
+
from deliveryapi import DeliverySaasClient
|
|
23
|
+
|
|
24
|
+
client = DeliverySaasClient(
|
|
25
|
+
api_key="pk_live_...",
|
|
26
|
+
secret_key="sk_live_...",
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
# List supported couriers
|
|
30
|
+
couriers = client.couriers.list()
|
|
31
|
+
|
|
32
|
+
# Query tracking status
|
|
33
|
+
result = client.tracking.get_one("LOTTE", "1234567890")
|
|
34
|
+
|
|
35
|
+
# Manage webhook endpoints
|
|
36
|
+
endpoint = client.webhooks.create({"url": "https://my.server/webhook"})
|
|
37
|
+
|
|
38
|
+
# Create a subscription
|
|
39
|
+
sub = client.subscriptions.create({
|
|
40
|
+
"courierCode": "LOTTE",
|
|
41
|
+
"trackingNumber": "1234567890",
|
|
42
|
+
"endpointId": endpoint["id"],
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
Context manager::
|
|
46
|
+
|
|
47
|
+
with DeliverySaasClient(api_key="...", secret_key="...") as client:
|
|
48
|
+
result = client.tracking.get_one("LOTTE", "1234567890")
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
def __init__(
|
|
52
|
+
self,
|
|
53
|
+
*,
|
|
54
|
+
api_key: str,
|
|
55
|
+
secret_key: str,
|
|
56
|
+
base_url: str = DEFAULT_BASE_URL,
|
|
57
|
+
timeout: float = DEFAULT_TIMEOUT,
|
|
58
|
+
) -> None:
|
|
59
|
+
http = HttpClient(api_key, secret_key, base_url, timeout)
|
|
60
|
+
self.tracking = TrackingResource(http)
|
|
61
|
+
self.couriers = CouriersResource(http)
|
|
62
|
+
self.webhooks = WebhooksResource(http)
|
|
63
|
+
self.subscriptions = SubscriptionsResource(http)
|
|
64
|
+
self._http = http
|
|
65
|
+
|
|
66
|
+
def close(self) -> None:
|
|
67
|
+
"""Close the underlying HTTP connection pool."""
|
|
68
|
+
self._http.close()
|
|
69
|
+
|
|
70
|
+
def __enter__(self) -> DeliverySaasClient:
|
|
71
|
+
return self
|
|
72
|
+
|
|
73
|
+
def __exit__(self, *args: object) -> None:
|
|
74
|
+
self.close()
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class AsyncDeliverySaasClient:
|
|
78
|
+
"""Async DeliverySaaS API client (requires asyncio).
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
api_key: Your API key (``pk_live_...`` or ``pk_test_...``).
|
|
82
|
+
secret_key: Your secret key (``sk_live_...`` or ``sk_test_...``).
|
|
83
|
+
base_url: Override the API base URL (useful for local emulator).
|
|
84
|
+
timeout: HTTP request timeout in seconds (default: 30).
|
|
85
|
+
|
|
86
|
+
Example::
|
|
87
|
+
|
|
88
|
+
import asyncio
|
|
89
|
+
from deliveryapi import AsyncDeliverySaasClient
|
|
90
|
+
|
|
91
|
+
async def main():
|
|
92
|
+
async with AsyncDeliverySaasClient(
|
|
93
|
+
api_key="pk_live_...",
|
|
94
|
+
secret_key="sk_live_...",
|
|
95
|
+
) as client:
|
|
96
|
+
result = await client.tracking.get_one("LOTTE", "1234567890")
|
|
97
|
+
print(result)
|
|
98
|
+
|
|
99
|
+
asyncio.run(main())
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
def __init__(
|
|
103
|
+
self,
|
|
104
|
+
*,
|
|
105
|
+
api_key: str,
|
|
106
|
+
secret_key: str,
|
|
107
|
+
base_url: str = DEFAULT_BASE_URL,
|
|
108
|
+
timeout: float = DEFAULT_TIMEOUT,
|
|
109
|
+
) -> None:
|
|
110
|
+
http = AsyncHttpClient(api_key, secret_key, base_url, timeout)
|
|
111
|
+
self.tracking = AsyncTrackingResource(http)
|
|
112
|
+
self.couriers = AsyncCouriersResource(http)
|
|
113
|
+
self.webhooks = AsyncWebhooksResource(http)
|
|
114
|
+
self.subscriptions = AsyncSubscriptionsResource(http)
|
|
115
|
+
self._http = http
|
|
116
|
+
|
|
117
|
+
async def aclose(self) -> None:
|
|
118
|
+
"""Close the underlying async HTTP connection pool."""
|
|
119
|
+
await self._http.aclose()
|
|
120
|
+
|
|
121
|
+
async def __aenter__(self) -> AsyncDeliverySaasClient:
|
|
122
|
+
return self
|
|
123
|
+
|
|
124
|
+
async def __aexit__(self, *args: object) -> None:
|
|
125
|
+
await self.aclose()
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class DeliverySaasError(Exception):
|
|
5
|
+
"""Base exception for all DeliverySaaS API errors."""
|
|
6
|
+
|
|
7
|
+
def __init__(self, message: str, status_code: int, code: str | None = None) -> None:
|
|
8
|
+
super().__init__(message)
|
|
9
|
+
self.status_code = status_code
|
|
10
|
+
self.code = code
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class AuthenticationError(DeliverySaasError):
|
|
14
|
+
def __init__(self, message: str = "Invalid API key or secret key") -> None:
|
|
15
|
+
super().__init__(message, 401, "AUTHENTICATION_ERROR")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class RateLimitError(DeliverySaasError):
|
|
19
|
+
def __init__(self, message: str = "Rate limit exceeded") -> None:
|
|
20
|
+
super().__init__(message, 429, "RATE_LIMIT_ERROR")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class NotFoundError(DeliverySaasError):
|
|
24
|
+
def __init__(self, message: str = "Resource not found") -> None:
|
|
25
|
+
super().__init__(message, 404, "NOT_FOUND")
|