usdpay 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.
- usdpay-1.0.0/.github/workflows/ci.yml +55 -0
- usdpay-1.0.0/.github/workflows/release.yml +42 -0
- usdpay-1.0.0/.gitignore +17 -0
- usdpay-1.0.0/CHANGELOG.md +12 -0
- usdpay-1.0.0/LICENSE +21 -0
- usdpay-1.0.0/PKG-INFO +205 -0
- usdpay-1.0.0/README.md +172 -0
- usdpay-1.0.0/RELEASE_REPORT.md +19 -0
- usdpay-1.0.0/pyproject.toml +73 -0
- usdpay-1.0.0/src/usdpay/__init__.py +13 -0
- usdpay-1.0.0/src/usdpay/client.py +266 -0
- usdpay-1.0.0/src/usdpay/exceptions.py +26 -0
- usdpay-1.0.0/src/usdpay/py.typed +1 -0
- usdpay-1.0.0/src/usdpay/transport.py +109 -0
- usdpay-1.0.0/src/usdpay/webhook.py +40 -0
- usdpay-1.0.0/tests/test_client.py +225 -0
- usdpay-1.0.0/tests/test_transport.py +117 -0
- usdpay-1.0.0/tests/test_webhook.py +33 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
strategy:
|
|
16
|
+
fail-fast: false
|
|
17
|
+
matrix:
|
|
18
|
+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
- uses: actions/setup-python@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: ${{ matrix.python-version }}
|
|
24
|
+
cache: pip
|
|
25
|
+
- name: Install test dependencies
|
|
26
|
+
run: python -m pip install --upgrade pip pytest ruff
|
|
27
|
+
- name: Lint
|
|
28
|
+
run: ruff check .
|
|
29
|
+
- name: Test
|
|
30
|
+
run: pytest
|
|
31
|
+
|
|
32
|
+
package:
|
|
33
|
+
runs-on: ubuntu-latest
|
|
34
|
+
steps:
|
|
35
|
+
- uses: actions/checkout@v4
|
|
36
|
+
- uses: actions/setup-python@v5
|
|
37
|
+
with:
|
|
38
|
+
python-version: "3.14"
|
|
39
|
+
cache: pip
|
|
40
|
+
- name: Install build tools
|
|
41
|
+
run: python -m pip install --upgrade pip build twine
|
|
42
|
+
- name: Build distributions
|
|
43
|
+
run: python -m build
|
|
44
|
+
- name: Check distributions
|
|
45
|
+
run: python -m twine check dist/*
|
|
46
|
+
- name: Test clean wheel install
|
|
47
|
+
run: |
|
|
48
|
+
python -m venv /tmp/usdpay-wheel-test
|
|
49
|
+
/tmp/usdpay-wheel-test/bin/python -m pip install --no-deps dist/usdpay-1.0.0-py3-none-any.whl
|
|
50
|
+
/tmp/usdpay-wheel-test/bin/python -c "from usdpay import UsdpayClient, UsdpayApiError, verify_webhook_signature; assert UsdpayClient and UsdpayApiError and verify_webhook_signature"
|
|
51
|
+
- uses: actions/upload-artifact@v4
|
|
52
|
+
with:
|
|
53
|
+
name: distributions
|
|
54
|
+
path: dist/
|
|
55
|
+
if-no-files-found: error
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
- uses: actions/setup-python@v5
|
|
16
|
+
with:
|
|
17
|
+
python-version: "3.14"
|
|
18
|
+
- name: Build and validate distributions
|
|
19
|
+
run: |
|
|
20
|
+
python -m pip install --upgrade pip build twine
|
|
21
|
+
python -m build
|
|
22
|
+
python -m twine check dist/*
|
|
23
|
+
- uses: actions/upload-artifact@v4
|
|
24
|
+
with:
|
|
25
|
+
name: distributions
|
|
26
|
+
path: dist/
|
|
27
|
+
if-no-files-found: error
|
|
28
|
+
|
|
29
|
+
publish:
|
|
30
|
+
needs: build
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
environment: pypi
|
|
33
|
+
permissions:
|
|
34
|
+
contents: read
|
|
35
|
+
id-token: write
|
|
36
|
+
steps:
|
|
37
|
+
- uses: actions/download-artifact@v4
|
|
38
|
+
with:
|
|
39
|
+
name: distributions
|
|
40
|
+
path: dist/
|
|
41
|
+
- name: Publish distributions to PyPI
|
|
42
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
usdpay-1.0.0/.gitignore
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 1.0.0
|
|
4
|
+
|
|
5
|
+
- Initial public release.
|
|
6
|
+
- Create USDPAY invoices.
|
|
7
|
+
- Retrieve invoice details.
|
|
8
|
+
- List invoices.
|
|
9
|
+
- Idempotency-Key support.
|
|
10
|
+
- Structured API errors.
|
|
11
|
+
- HMAC-SHA256 webhook signature verification.
|
|
12
|
+
- Inline Python type hints.
|
usdpay-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 PIXELTIDE LLC
|
|
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.
|
usdpay-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: usdpay
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Python SDK for accepting USDT payments directly to your wallet with automatic payment verification and webhooks.
|
|
5
|
+
Project-URL: Homepage, https://usdpay.me/
|
|
6
|
+
Project-URL: Documentation, https://usdpay.me/docs/payments
|
|
7
|
+
Project-URL: Webhooks, https://usdpay.me/webhooks
|
|
8
|
+
Project-URL: Security, https://usdpay.me/security
|
|
9
|
+
Project-URL: Support, https://usdpay.me/contact
|
|
10
|
+
Project-URL: Source, https://github.com/probizi/usdpay-python
|
|
11
|
+
Project-URL: Issues, https://github.com/probizi/usdpay-python/issues
|
|
12
|
+
Author: USDPAY
|
|
13
|
+
License-Expression: MIT
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Keywords: bep20,bsc,crypto-payments,payment-api,payment-gateway,payments,ton,trc20,tron,usdpay,usdt,usdt-api,webhook
|
|
16
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
17
|
+
Classifier: Intended Audience :: Developers
|
|
18
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
25
|
+
Classifier: Typing :: Typed
|
|
26
|
+
Requires-Python: >=3.10
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: build<2,>=1.2; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest<10,>=8; extra == 'dev'
|
|
30
|
+
Requires-Dist: ruff<1,>=0.9; extra == 'dev'
|
|
31
|
+
Requires-Dist: twine<7,>=6; extra == 'dev'
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
34
|
+
# USDPAY Python SDK
|
|
35
|
+
|
|
36
|
+
Official Python SDK for USDPAY.
|
|
37
|
+
|
|
38
|
+
Accept USDT directly to your wallet. USDPAY verifies the payment on-chain and notifies your application automatically with signed webhooks.
|
|
39
|
+
|
|
40
|
+
## Requirements
|
|
41
|
+
|
|
42
|
+
- Python 3.10 or newer
|
|
43
|
+
- A USDPAY store secret key for authenticated methods
|
|
44
|
+
- A server-side application; never expose the secret key in browser or mobile code
|
|
45
|
+
|
|
46
|
+
## Installation
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pip install usdpay
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Quick Start
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
import os
|
|
56
|
+
|
|
57
|
+
from usdpay import UsdpayClient
|
|
58
|
+
|
|
59
|
+
client = UsdpayClient(
|
|
60
|
+
secret_key=os.environ["USDPAY_SECRET"]
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
result = client.create_invoice(
|
|
64
|
+
{
|
|
65
|
+
"amount": "49.00",
|
|
66
|
+
"orderId": "ORDER-1042",
|
|
67
|
+
"network": "TRC20",
|
|
68
|
+
"callbackUrl": "https://merchant.example/usdpay/webhook",
|
|
69
|
+
"returnUrl": "https://merchant.example/orders/1042",
|
|
70
|
+
},
|
|
71
|
+
idempotency_key="ORDER-1042-create",
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
print(result["invoice"]["checkoutUrl"])
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Create an Invoice
|
|
78
|
+
|
|
79
|
+
`create_invoice()` sends `POST /api/invoices`. JSON field names match the REST API exactly.
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
result = client.create_invoice(
|
|
83
|
+
{
|
|
84
|
+
"amount": "49.00",
|
|
85
|
+
"orderId": "ORDER-1042",
|
|
86
|
+
"network": "TRC20",
|
|
87
|
+
"expiresInMinutes": 30,
|
|
88
|
+
"callbackUrl": "https://merchant.example/usdpay/webhook",
|
|
89
|
+
"returnUrl": "https://merchant.example/orders/1042",
|
|
90
|
+
},
|
|
91
|
+
idempotency_key="ORDER-1042-create",
|
|
92
|
+
)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Omit `network` to let the customer choose an enabled network in the hosted checkout.
|
|
96
|
+
|
|
97
|
+
## Get an Invoice
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
result = client.get_invoice("inv_7Fq2xK9")
|
|
101
|
+
print(result["invoice"]["status"])
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The production API exposes this status endpoint to anyone who has the unguessable invoice ID. The SDK therefore does not send your Bearer key with `get_invoice()`.
|
|
105
|
+
|
|
106
|
+
## List Invoices
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
result = client.list_invoices()
|
|
110
|
+
for invoice in result["invoices"]:
|
|
111
|
+
print(invoice["id"], invoice["status"])
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
`list_invoices()` is authenticated and returns invoices for the store selected by the secret key. The current API does not define filtering or pagination parameters, so the SDK does not invent any.
|
|
115
|
+
|
|
116
|
+
## Fiat Order Amounts
|
|
117
|
+
|
|
118
|
+
Keep monetary values as decimal strings. USDPAY performs the currency conversion; the SDK does not use floating-point math or calculate FX rates.
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
result = client.create_invoice(
|
|
122
|
+
{
|
|
123
|
+
"amount": "49.00",
|
|
124
|
+
"currency": "EUR",
|
|
125
|
+
"orderId": "ORDER-1042",
|
|
126
|
+
"callbackUrl": "https://merchant.example/usdpay/webhook",
|
|
127
|
+
},
|
|
128
|
+
idempotency_key="ORDER-1042-create",
|
|
129
|
+
)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Idempotency
|
|
133
|
+
|
|
134
|
+
Pass one stable `idempotency_key` for a logical create operation. If a timeout, `429`, or retryable `5xx` occurs, retry with the same key. Do not generate a new key for each attempt.
|
|
135
|
+
|
|
136
|
+
USDPAY accepts 1–160 letters, digits, dots, underscores, colons, or hyphens. The SDK validates the key but does not automatically retry requests.
|
|
137
|
+
|
|
138
|
+
## Verify Webhooks
|
|
139
|
+
|
|
140
|
+
Verify the signature against the exact raw request body before parsing JSON.
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
import os
|
|
144
|
+
|
|
145
|
+
from usdpay import verify_webhook_signature
|
|
146
|
+
|
|
147
|
+
raw_body = request_body_bytes
|
|
148
|
+
signature = request_headers.get("X-USDPAY-Signature", "")
|
|
149
|
+
|
|
150
|
+
if not verify_webhook_signature(
|
|
151
|
+
raw_body,
|
|
152
|
+
signature,
|
|
153
|
+
os.environ["USDPAY_WEBHOOK_SECRET"],
|
|
154
|
+
):
|
|
155
|
+
# Return HTTP 401.
|
|
156
|
+
...
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
The signature format is `sha256=<hex HMAC-SHA256>`. Store `X-USDPAY-Idempotency-Key` under a unique database constraint before fulfilling an order, and acknowledge an already processed delivery with a `2xx` response.
|
|
160
|
+
|
|
161
|
+
## Error Handling
|
|
162
|
+
|
|
163
|
+
```python
|
|
164
|
+
from usdpay import UsdpayApiError
|
|
165
|
+
|
|
166
|
+
try:
|
|
167
|
+
client.create_invoice(
|
|
168
|
+
{"amount": "49.00", "orderId": "ORDER-1042"},
|
|
169
|
+
idempotency_key="ORDER-1042-create",
|
|
170
|
+
)
|
|
171
|
+
except UsdpayApiError as exc:
|
|
172
|
+
print(exc.status)
|
|
173
|
+
print(exc.code)
|
|
174
|
+
print(exc.retry_after)
|
|
175
|
+
print(exc.request_id)
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
`UsdpayApiError` covers HTTP failures, timeouts, network failures, and malformed JSON. Its public attributes are:
|
|
179
|
+
|
|
180
|
+
- `status`: HTTP status, or `0` when no HTTP response was received
|
|
181
|
+
- `code`: stable API or SDK error code
|
|
182
|
+
- `details`: redacted response object when available
|
|
183
|
+
- `retry_after`: parsed `Retry-After` seconds or HTTP-date
|
|
184
|
+
- `request_id`: response request identifier for support
|
|
185
|
+
|
|
186
|
+
## Security
|
|
187
|
+
|
|
188
|
+
- Keep `USDPAY_SECRET` and the webhook signing secret on your server.
|
|
189
|
+
- The default transport accepts HTTPS only and uses Python's verified system trust store with hostname verification.
|
|
190
|
+
- Requests have finite connect and response timeouts; configure them with `connect_timeout` and `timeout`.
|
|
191
|
+
- The client does not follow redirects or make network calls when imported.
|
|
192
|
+
- Secrets are not included in `repr(client)`, public exception messages, or exception details.
|
|
193
|
+
- Never disable TLS verification.
|
|
194
|
+
|
|
195
|
+
## Documentation
|
|
196
|
+
|
|
197
|
+
- [Official website](https://usdpay.me/)
|
|
198
|
+
- [Payment API documentation](https://usdpay.me/docs/payments)
|
|
199
|
+
- [Webhook documentation](https://usdpay.me/webhooks)
|
|
200
|
+
- [Security](https://usdpay.me/security)
|
|
201
|
+
- [Support](https://usdpay.me/contact)
|
|
202
|
+
|
|
203
|
+
## License
|
|
204
|
+
|
|
205
|
+
[MIT](LICENSE) © 2026 PIXELTIDE LLC.
|
usdpay-1.0.0/README.md
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# USDPAY Python SDK
|
|
2
|
+
|
|
3
|
+
Official Python SDK for USDPAY.
|
|
4
|
+
|
|
5
|
+
Accept USDT directly to your wallet. USDPAY verifies the payment on-chain and notifies your application automatically with signed webhooks.
|
|
6
|
+
|
|
7
|
+
## Requirements
|
|
8
|
+
|
|
9
|
+
- Python 3.10 or newer
|
|
10
|
+
- A USDPAY store secret key for authenticated methods
|
|
11
|
+
- A server-side application; never expose the secret key in browser or mobile code
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pip install usdpay
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
import os
|
|
23
|
+
|
|
24
|
+
from usdpay import UsdpayClient
|
|
25
|
+
|
|
26
|
+
client = UsdpayClient(
|
|
27
|
+
secret_key=os.environ["USDPAY_SECRET"]
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
result = client.create_invoice(
|
|
31
|
+
{
|
|
32
|
+
"amount": "49.00",
|
|
33
|
+
"orderId": "ORDER-1042",
|
|
34
|
+
"network": "TRC20",
|
|
35
|
+
"callbackUrl": "https://merchant.example/usdpay/webhook",
|
|
36
|
+
"returnUrl": "https://merchant.example/orders/1042",
|
|
37
|
+
},
|
|
38
|
+
idempotency_key="ORDER-1042-create",
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
print(result["invoice"]["checkoutUrl"])
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Create an Invoice
|
|
45
|
+
|
|
46
|
+
`create_invoice()` sends `POST /api/invoices`. JSON field names match the REST API exactly.
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
result = client.create_invoice(
|
|
50
|
+
{
|
|
51
|
+
"amount": "49.00",
|
|
52
|
+
"orderId": "ORDER-1042",
|
|
53
|
+
"network": "TRC20",
|
|
54
|
+
"expiresInMinutes": 30,
|
|
55
|
+
"callbackUrl": "https://merchant.example/usdpay/webhook",
|
|
56
|
+
"returnUrl": "https://merchant.example/orders/1042",
|
|
57
|
+
},
|
|
58
|
+
idempotency_key="ORDER-1042-create",
|
|
59
|
+
)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Omit `network` to let the customer choose an enabled network in the hosted checkout.
|
|
63
|
+
|
|
64
|
+
## Get an Invoice
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
result = client.get_invoice("inv_7Fq2xK9")
|
|
68
|
+
print(result["invoice"]["status"])
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The production API exposes this status endpoint to anyone who has the unguessable invoice ID. The SDK therefore does not send your Bearer key with `get_invoice()`.
|
|
72
|
+
|
|
73
|
+
## List Invoices
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
result = client.list_invoices()
|
|
77
|
+
for invoice in result["invoices"]:
|
|
78
|
+
print(invoice["id"], invoice["status"])
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`list_invoices()` is authenticated and returns invoices for the store selected by the secret key. The current API does not define filtering or pagination parameters, so the SDK does not invent any.
|
|
82
|
+
|
|
83
|
+
## Fiat Order Amounts
|
|
84
|
+
|
|
85
|
+
Keep monetary values as decimal strings. USDPAY performs the currency conversion; the SDK does not use floating-point math or calculate FX rates.
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
result = client.create_invoice(
|
|
89
|
+
{
|
|
90
|
+
"amount": "49.00",
|
|
91
|
+
"currency": "EUR",
|
|
92
|
+
"orderId": "ORDER-1042",
|
|
93
|
+
"callbackUrl": "https://merchant.example/usdpay/webhook",
|
|
94
|
+
},
|
|
95
|
+
idempotency_key="ORDER-1042-create",
|
|
96
|
+
)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Idempotency
|
|
100
|
+
|
|
101
|
+
Pass one stable `idempotency_key` for a logical create operation. If a timeout, `429`, or retryable `5xx` occurs, retry with the same key. Do not generate a new key for each attempt.
|
|
102
|
+
|
|
103
|
+
USDPAY accepts 1–160 letters, digits, dots, underscores, colons, or hyphens. The SDK validates the key but does not automatically retry requests.
|
|
104
|
+
|
|
105
|
+
## Verify Webhooks
|
|
106
|
+
|
|
107
|
+
Verify the signature against the exact raw request body before parsing JSON.
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
import os
|
|
111
|
+
|
|
112
|
+
from usdpay import verify_webhook_signature
|
|
113
|
+
|
|
114
|
+
raw_body = request_body_bytes
|
|
115
|
+
signature = request_headers.get("X-USDPAY-Signature", "")
|
|
116
|
+
|
|
117
|
+
if not verify_webhook_signature(
|
|
118
|
+
raw_body,
|
|
119
|
+
signature,
|
|
120
|
+
os.environ["USDPAY_WEBHOOK_SECRET"],
|
|
121
|
+
):
|
|
122
|
+
# Return HTTP 401.
|
|
123
|
+
...
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
The signature format is `sha256=<hex HMAC-SHA256>`. Store `X-USDPAY-Idempotency-Key` under a unique database constraint before fulfilling an order, and acknowledge an already processed delivery with a `2xx` response.
|
|
127
|
+
|
|
128
|
+
## Error Handling
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
from usdpay import UsdpayApiError
|
|
132
|
+
|
|
133
|
+
try:
|
|
134
|
+
client.create_invoice(
|
|
135
|
+
{"amount": "49.00", "orderId": "ORDER-1042"},
|
|
136
|
+
idempotency_key="ORDER-1042-create",
|
|
137
|
+
)
|
|
138
|
+
except UsdpayApiError as exc:
|
|
139
|
+
print(exc.status)
|
|
140
|
+
print(exc.code)
|
|
141
|
+
print(exc.retry_after)
|
|
142
|
+
print(exc.request_id)
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
`UsdpayApiError` covers HTTP failures, timeouts, network failures, and malformed JSON. Its public attributes are:
|
|
146
|
+
|
|
147
|
+
- `status`: HTTP status, or `0` when no HTTP response was received
|
|
148
|
+
- `code`: stable API or SDK error code
|
|
149
|
+
- `details`: redacted response object when available
|
|
150
|
+
- `retry_after`: parsed `Retry-After` seconds or HTTP-date
|
|
151
|
+
- `request_id`: response request identifier for support
|
|
152
|
+
|
|
153
|
+
## Security
|
|
154
|
+
|
|
155
|
+
- Keep `USDPAY_SECRET` and the webhook signing secret on your server.
|
|
156
|
+
- The default transport accepts HTTPS only and uses Python's verified system trust store with hostname verification.
|
|
157
|
+
- Requests have finite connect and response timeouts; configure them with `connect_timeout` and `timeout`.
|
|
158
|
+
- The client does not follow redirects or make network calls when imported.
|
|
159
|
+
- Secrets are not included in `repr(client)`, public exception messages, or exception details.
|
|
160
|
+
- Never disable TLS verification.
|
|
161
|
+
|
|
162
|
+
## Documentation
|
|
163
|
+
|
|
164
|
+
- [Official website](https://usdpay.me/)
|
|
165
|
+
- [Payment API documentation](https://usdpay.me/docs/payments)
|
|
166
|
+
- [Webhook documentation](https://usdpay.me/webhooks)
|
|
167
|
+
- [Security](https://usdpay.me/security)
|
|
168
|
+
- [Support](https://usdpay.me/contact)
|
|
169
|
+
|
|
170
|
+
## License
|
|
171
|
+
|
|
172
|
+
[MIT](LICENSE) © 2026 PIXELTIDE LLC.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Release report — 1.0.0
|
|
2
|
+
|
|
3
|
+
This report is completed from local and GitHub Actions results before publishing the release.
|
|
4
|
+
|
|
5
|
+
| Check | Status |
|
|
6
|
+
| --- | --- |
|
|
7
|
+
| Python 3.10 | PASS — 21 tests |
|
|
8
|
+
| Python 3.11 | PASS — 21 tests |
|
|
9
|
+
| Python 3.12 | PASS — 21 tests |
|
|
10
|
+
| Python 3.13 | PASS — 21 tests |
|
|
11
|
+
| Python 3.14 | PASS — 21 tests |
|
|
12
|
+
| pytest | PASS |
|
|
13
|
+
| ruff | PASS |
|
|
14
|
+
| build | PASS — sdist and universal wheel |
|
|
15
|
+
| twine check | PASS |
|
|
16
|
+
| wheel install | PASS — clean virtual environment, no dependencies |
|
|
17
|
+
| secret scan | PASS — Gitleaks and targeted patterns |
|
|
18
|
+
|
|
19
|
+
Publication requires a PyPI Pending Trusted Publisher for project `usdpay`, owner `probizi`, repository `usdpay-python`, workflow `release.yml`, and environment `pypi`.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling>=1.27,<1.32"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "usdpay"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "Python SDK for accepting USDT payments directly to your wallet with automatic payment verification and webhooks."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "USDPAY" }
|
|
14
|
+
]
|
|
15
|
+
keywords = [
|
|
16
|
+
"usdpay",
|
|
17
|
+
"usdt",
|
|
18
|
+
"payments",
|
|
19
|
+
"payment-gateway",
|
|
20
|
+
"crypto-payments",
|
|
21
|
+
"payment-api",
|
|
22
|
+
"usdt-api",
|
|
23
|
+
"webhook",
|
|
24
|
+
"tron",
|
|
25
|
+
"trc20",
|
|
26
|
+
"ton",
|
|
27
|
+
"bep20",
|
|
28
|
+
"bsc"
|
|
29
|
+
]
|
|
30
|
+
classifiers = [
|
|
31
|
+
"Development Status :: 5 - Production/Stable",
|
|
32
|
+
"Intended Audience :: Developers",
|
|
33
|
+
"License :: OSI Approved :: MIT License",
|
|
34
|
+
"Programming Language :: Python :: 3",
|
|
35
|
+
"Programming Language :: Python :: 3.10",
|
|
36
|
+
"Programming Language :: Python :: 3.11",
|
|
37
|
+
"Programming Language :: Python :: 3.12",
|
|
38
|
+
"Programming Language :: Python :: 3.13",
|
|
39
|
+
"Programming Language :: Python :: 3.14",
|
|
40
|
+
"Typing :: Typed"
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
[project.urls]
|
|
44
|
+
Homepage = "https://usdpay.me/"
|
|
45
|
+
Documentation = "https://usdpay.me/docs/payments"
|
|
46
|
+
Webhooks = "https://usdpay.me/webhooks"
|
|
47
|
+
Security = "https://usdpay.me/security"
|
|
48
|
+
Support = "https://usdpay.me/contact"
|
|
49
|
+
Source = "https://github.com/probizi/usdpay-python"
|
|
50
|
+
Issues = "https://github.com/probizi/usdpay-python/issues"
|
|
51
|
+
|
|
52
|
+
[project.optional-dependencies]
|
|
53
|
+
dev = [
|
|
54
|
+
"build>=1.2,<2",
|
|
55
|
+
"pytest>=8,<10",
|
|
56
|
+
"ruff>=0.9,<1",
|
|
57
|
+
"twine>=6,<7"
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
[tool.hatch.build.targets.wheel]
|
|
61
|
+
packages = ["src/usdpay"]
|
|
62
|
+
|
|
63
|
+
[tool.pytest.ini_options]
|
|
64
|
+
addopts = "-ra"
|
|
65
|
+
pythonpath = ["src"]
|
|
66
|
+
testpaths = ["tests"]
|
|
67
|
+
|
|
68
|
+
[tool.ruff]
|
|
69
|
+
line-length = 100
|
|
70
|
+
target-version = "py310"
|
|
71
|
+
|
|
72
|
+
[tool.ruff.lint]
|
|
73
|
+
select = ["E", "F", "I", "UP", "B", "SIM"]
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""Official Python SDK for the USDPAY Payments API."""
|
|
2
|
+
|
|
3
|
+
from .client import UsdpayClient
|
|
4
|
+
from .exceptions import UsdpayApiError
|
|
5
|
+
from .webhook import verify_webhook_signature
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"UsdpayClient",
|
|
9
|
+
"UsdpayApiError",
|
|
10
|
+
"verify_webhook_signature",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
__version__ = "1.0.0"
|