pysibs 0.1.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.
- pysibs-0.1.0/.gitignore +35 -0
- pysibs-0.1.0/CHANGELOG.md +24 -0
- pysibs-0.1.0/LICENSE +21 -0
- pysibs-0.1.0/PKG-INFO +237 -0
- pysibs-0.1.0/README.md +196 -0
- pysibs-0.1.0/pyproject.toml +118 -0
- pysibs-0.1.0/pysibs/__init__.py +86 -0
- pysibs-0.1.0/pysibs/_http.py +181 -0
- pysibs-0.1.0/pysibs/_payloads.py +217 -0
- pysibs-0.1.0/pysibs/_version.py +5 -0
- pysibs-0.1.0/pysibs/async_client.py +200 -0
- pysibs-0.1.0/pysibs/client.py +204 -0
- pysibs-0.1.0/pysibs/config.py +134 -0
- pysibs-0.1.0/pysibs/enums.py +114 -0
- pysibs-0.1.0/pysibs/exceptions.py +77 -0
- pysibs-0.1.0/pysibs/idempotency.py +49 -0
- pysibs-0.1.0/pysibs/models.py +111 -0
- pysibs-0.1.0/pysibs/money.py +94 -0
- pysibs-0.1.0/pysibs/py.typed +0 -0
- pysibs-0.1.0/pysibs/validators.py +72 -0
- pysibs-0.1.0/pysibs/webhooks.py +149 -0
- pysibs-0.1.0/tests/__init__.py +0 -0
- pysibs-0.1.0/tests/conftest.py +34 -0
- pysibs-0.1.0/tests/integration/__init__.py +0 -0
- pysibs-0.1.0/tests/integration/test_sandbox_payments.py +41 -0
- pysibs-0.1.0/tests/unit/__init__.py +0 -0
- pysibs-0.1.0/tests/unit/test_client.py +270 -0
- pysibs-0.1.0/tests/unit/test_config.py +71 -0
- pysibs-0.1.0/tests/unit/test_exceptions.py +17 -0
- pysibs-0.1.0/tests/unit/test_money.py +63 -0
- pysibs-0.1.0/tests/unit/test_status_mapping.py +29 -0
- pysibs-0.1.0/tests/unit/test_validators.py +54 -0
- pysibs-0.1.0/tests/unit/test_webhooks.py +119 -0
pysibs-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Byte-compiled / optimized
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# Distribution / packaging
|
|
7
|
+
build/
|
|
8
|
+
dist/
|
|
9
|
+
*.egg-info/
|
|
10
|
+
.eggs/
|
|
11
|
+
wheels/
|
|
12
|
+
|
|
13
|
+
# Test / coverage
|
|
14
|
+
.pytest_cache/
|
|
15
|
+
.coverage
|
|
16
|
+
.coverage.*
|
|
17
|
+
htmlcov/
|
|
18
|
+
coverage.xml
|
|
19
|
+
.mypy_cache/
|
|
20
|
+
.ruff_cache/
|
|
21
|
+
|
|
22
|
+
# Virtual environments
|
|
23
|
+
.venv/
|
|
24
|
+
venv/
|
|
25
|
+
env/
|
|
26
|
+
|
|
27
|
+
# Secrets / local config
|
|
28
|
+
.env
|
|
29
|
+
.env.*
|
|
30
|
+
!.env.example
|
|
31
|
+
|
|
32
|
+
# Editors / OS
|
|
33
|
+
.idea/
|
|
34
|
+
.vscode/
|
|
35
|
+
.DS_Store
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. This project adheres to
|
|
4
|
+
[Semantic Versioning](https://semver.org/) and the format is based on
|
|
5
|
+
[Keep a Changelog](https://keepachangelog.com/).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [0.1.0] - 2026-06-19
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- Initial `SIBSClient` (synchronous) and `AsyncSIBSClient` (asynchronous).
|
|
13
|
+
- `create_payment`, `get_payment_status`, `refund_payment`, `capture_payment` and
|
|
14
|
+
`cancel_payment`.
|
|
15
|
+
- `from_env()` constructor reading `SIBS_*` environment variables.
|
|
16
|
+
- Typed Pydantic models with normalized `PaymentStatus` and preserved `raw_response`.
|
|
17
|
+
- `Decimal`-based money handling that rejects `float`.
|
|
18
|
+
- Webhook parsing (`parse_webhook`) and configurable signature verification
|
|
19
|
+
(`verify_webhook_signature`, `hmac_sha256_verifier`).
|
|
20
|
+
- Full exception hierarchy under `SIBSError`; raw `httpx` errors never leak.
|
|
21
|
+
- Documentation, examples (Django/FastAPI), CI and PyPI publish workflows.
|
|
22
|
+
|
|
23
|
+
[Unreleased]: https://github.com/robertruben98/pysibs/compare/v0.1.0...HEAD
|
|
24
|
+
[0.1.0]: https://github.com/robertruben98/pysibs/releases/tag/v0.1.0
|
pysibs-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Robert Ruben
|
|
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.
|
pysibs-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pysibs
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A modern Python SDK for SIBS Gateway payment integrations.
|
|
5
|
+
Project-URL: Homepage, https://github.com/robertruben98/pysibs
|
|
6
|
+
Project-URL: Repository, https://github.com/robertruben98/pysibs
|
|
7
|
+
Project-URL: Issues, https://github.com/robertruben98/pysibs/issues
|
|
8
|
+
Project-URL: Documentation, https://github.com/robertruben98/pysibs#readme
|
|
9
|
+
Author: Robert Benitez
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: fintech,mbway,multibanco,payment-gateway,payments,python-sdk,sibs
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Office/Business :: Financial
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Classifier: Typing :: Typed
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Requires-Dist: httpx>=0.27.0
|
|
25
|
+
Requires-Dist: pydantic>=2.0.0
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: build; extra == 'dev'
|
|
28
|
+
Requires-Dist: mypy; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest-asyncio; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest-cov; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: respx>=0.21; extra == 'dev'
|
|
33
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
34
|
+
Requires-Dist: twine; extra == 'dev'
|
|
35
|
+
Provides-Extra: examples
|
|
36
|
+
Requires-Dist: django; extra == 'examples'
|
|
37
|
+
Requires-Dist: fastapi; extra == 'examples'
|
|
38
|
+
Requires-Dist: python-dotenv; extra == 'examples'
|
|
39
|
+
Requires-Dist: uvicorn; extra == 'examples'
|
|
40
|
+
Description-Content-Type: text/markdown
|
|
41
|
+
|
|
42
|
+
# PySIBS
|
|
43
|
+
|
|
44
|
+
A modern, typed, developer-friendly Python SDK for [SIBS Gateway](https://www.sibsapimarket.com/) payment integrations.
|
|
45
|
+
|
|
46
|
+
PySIBS provides a clean API for payments, refunds, captures, cancellations, status
|
|
47
|
+
checks and webhook verification. It is framework-agnostic and works in Django,
|
|
48
|
+
FastAPI, Flask, Celery, CLI scripts — anywhere Python runs.
|
|
49
|
+
|
|
50
|
+
> **Project status: Alpha.** The public API surface is intentionally small and
|
|
51
|
+
> stable, but endpoint/field details are still being validated against SIBS' official
|
|
52
|
+
> documentation. Every response exposes a `raw_response` so you are never blocked by a
|
|
53
|
+
> field PySIBS has not yet normalized. See [Caveats](#caveats--unverified-details).
|
|
54
|
+
|
|
55
|
+
## Features
|
|
56
|
+
|
|
57
|
+
- Synchronous (`SIBSClient`) and asynchronous (`AsyncSIBSClient`) clients
|
|
58
|
+
- Create payments, check status, refund, capture and cancel
|
|
59
|
+
- Typed Pydantic models with normalized statuses (`PaymentStatus`)
|
|
60
|
+
- Safe money handling with `Decimal` (floats are rejected)
|
|
61
|
+
- Webhook parsing and configurable signature verification
|
|
62
|
+
- A clear exception hierarchy — raw `httpx` errors never leak out
|
|
63
|
+
- Fully typed (`py.typed`), `ruff` + `mypy --strict` clean
|
|
64
|
+
|
|
65
|
+
## Installation
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
pip install pysibs
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Requires Python 3.10+.
|
|
72
|
+
|
|
73
|
+
## Configuration
|
|
74
|
+
|
|
75
|
+
Construct a client directly:
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
from pysibs import SIBSClient
|
|
79
|
+
|
|
80
|
+
client = SIBSClient(
|
|
81
|
+
api_key="your_api_key",
|
|
82
|
+
terminal_id="your_terminal_id",
|
|
83
|
+
environment="sandbox", # or "production"
|
|
84
|
+
)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
…or from environment variables (`SIBS_API_KEY`, `SIBS_TERMINAL_ID`,
|
|
88
|
+
`SIBS_ENVIRONMENT`, and optionally `SIBS_CLIENT_ID`, `SIBS_WEBHOOK_SECRET`):
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
client = SIBSClient.from_env()
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The **core library never reads `.env`** — only the bundled examples do, via
|
|
95
|
+
`python-dotenv`. See [`.env.example`](.env.example).
|
|
96
|
+
|
|
97
|
+
## Create a payment
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
payment = client.create_payment(
|
|
101
|
+
amount="10.00", # str, int or Decimal — never float
|
|
102
|
+
currency="EUR",
|
|
103
|
+
merchant_transaction_id="ORDER-123",
|
|
104
|
+
return_url="https://example.com/payment/success",
|
|
105
|
+
cancel_url="https://example.com/payment/cancel",
|
|
106
|
+
payment_methods=["CARD", "MBWAY", "MULTIBANCO"],
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
print(payment.id)
|
|
110
|
+
print(payment.status) # normalized PaymentStatus
|
|
111
|
+
print(payment.redirect_url)
|
|
112
|
+
print(payment.raw_response) # untouched SIBS response
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Check payment status
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
status = client.get_payment_status("payment_123")
|
|
119
|
+
print(status.status) # normalized PaymentStatus
|
|
120
|
+
print(status.raw_status) # original value from SIBS
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Refunds
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
# Full refund
|
|
127
|
+
client.refund_payment(payment_id="payment_123")
|
|
128
|
+
|
|
129
|
+
# Partial refund
|
|
130
|
+
client.refund_payment(payment_id="payment_123", amount="10.00", merchant_refund_id="REF-1001")
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Capture & cancel
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
client.capture_payment(payment_id="payment_123", amount="25.50")
|
|
137
|
+
client.cancel_payment("payment_123")
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Async usage
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
from pysibs import AsyncSIBSClient
|
|
144
|
+
|
|
145
|
+
async with AsyncSIBSClient.from_env() as client:
|
|
146
|
+
payment = await client.create_payment(amount="10.00", merchant_transaction_id="ORDER-1")
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Webhooks
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
from pysibs import parse_webhook, verify_webhook_signature
|
|
153
|
+
|
|
154
|
+
event = parse_webhook(raw_body) # bytes, str or dict
|
|
155
|
+
print(event.payment_id, event.status, event.raw_payload)
|
|
156
|
+
|
|
157
|
+
is_valid = verify_webhook_signature(
|
|
158
|
+
payload=raw_body,
|
|
159
|
+
signature=request.headers.get("X-SIBS-Signature"),
|
|
160
|
+
secret="webhook_secret",
|
|
161
|
+
)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
SIBS' webhook signing scheme is not uniformly documented and may differ per
|
|
165
|
+
product/environment. `verify_webhook_signature` defaults to HMAC-SHA256, but you can
|
|
166
|
+
pass a custom `verifier` callable that matches whatever SIBS actually uses for your
|
|
167
|
+
integration. **Always confirm the scheme against the official documentation.**
|
|
168
|
+
|
|
169
|
+
## Error handling
|
|
170
|
+
|
|
171
|
+
All exceptions inherit from `SIBSError`:
|
|
172
|
+
|
|
173
|
+
| Exception | Raised when |
|
|
174
|
+
| --- | --- |
|
|
175
|
+
| `SIBSConfigurationError` | The client is misconfigured (missing credentials, bad environment). |
|
|
176
|
+
| `SIBSValidationError` | Input fails local validation (e.g. a float amount, empty id). |
|
|
177
|
+
| `SIBSAuthenticationError` | SIBS rejects credentials (HTTP 401/403). |
|
|
178
|
+
| `SIBSAPIError` | Other API errors (carries `status_code` and `response_body`). |
|
|
179
|
+
| `SIBSTimeoutError` | The request times out (or HTTP 408). |
|
|
180
|
+
| `SIBSConnectionError` | SIBS cannot be reached (DNS/TCP/TLS). |
|
|
181
|
+
| `SIBSInvalidWebhookSignature` | A webhook signature fails verification. |
|
|
182
|
+
|
|
183
|
+
```python
|
|
184
|
+
from pysibs import SIBSError, SIBSAuthenticationError
|
|
185
|
+
|
|
186
|
+
try:
|
|
187
|
+
client.create_payment(amount="10.00", merchant_transaction_id="ORDER-1")
|
|
188
|
+
except SIBSAuthenticationError:
|
|
189
|
+
... # bad credentials
|
|
190
|
+
except SIBSError as exc:
|
|
191
|
+
... # any other PySIBS failure
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## PCI DSS note
|
|
195
|
+
|
|
196
|
+
This SDK does not store or process cardholder data by itself. However, some SIBS
|
|
197
|
+
server-to-server card payment flows may require the merchant environment to be PCI DSS
|
|
198
|
+
compliant. Always validate your integration scope with SIBS and your PCI advisor.
|
|
199
|
+
|
|
200
|
+
PySIBS deliberately:
|
|
201
|
+
|
|
202
|
+
- never stores PAN or CVV,
|
|
203
|
+
- never logs `Authorization` headers or credentials,
|
|
204
|
+
- ships no examples containing real card data.
|
|
205
|
+
|
|
206
|
+
## Caveats — unverified details
|
|
207
|
+
|
|
208
|
+
SIBS' public documentation does not pin down every endpoint, field name and signing
|
|
209
|
+
detail unambiguously, and they can vary by product/environment. Where there was
|
|
210
|
+
ambiguity, PySIBS:
|
|
211
|
+
|
|
212
|
+
1. keeps the wire format isolated in `pysibs/_payloads.py` and base URLs in
|
|
213
|
+
`pysibs/config.py`, so they are trivial to adjust in one place;
|
|
214
|
+
2. preserves the full `raw_response` / `raw_payload` on every model;
|
|
215
|
+
3. never sends undocumented headers (e.g. idempotency — see `pysibs/idempotency.py`).
|
|
216
|
+
|
|
217
|
+
Before going to production, verify the endpoints, payloads and webhook signature
|
|
218
|
+
scheme against the current official SIBS documentation.
|
|
219
|
+
|
|
220
|
+
## Python compatibility
|
|
221
|
+
|
|
222
|
+
Tested on CPython 3.10, 3.11, 3.12 and 3.13.
|
|
223
|
+
|
|
224
|
+
## Roadmap
|
|
225
|
+
|
|
226
|
+
- `0.1.0` — `SIBSClient`/`AsyncSIBSClient`, create/status/refund/capture/cancel,
|
|
227
|
+
webhook parsing + verification, typed models, docs.
|
|
228
|
+
- `0.2.0` — richer payment-method specific models (MB WAY, MULTIBANCO references).
|
|
229
|
+
- `1.0.0` — stable API once the SIBS contract is fully confirmed end-to-end.
|
|
230
|
+
|
|
231
|
+
## Contributing
|
|
232
|
+
|
|
233
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md). Security issues: see [SECURITY.md](SECURITY.md).
|
|
234
|
+
|
|
235
|
+
## License
|
|
236
|
+
|
|
237
|
+
[MIT](LICENSE) © Robert Benitez
|
pysibs-0.1.0/README.md
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# PySIBS
|
|
2
|
+
|
|
3
|
+
A modern, typed, developer-friendly Python SDK for [SIBS Gateway](https://www.sibsapimarket.com/) payment integrations.
|
|
4
|
+
|
|
5
|
+
PySIBS provides a clean API for payments, refunds, captures, cancellations, status
|
|
6
|
+
checks and webhook verification. It is framework-agnostic and works in Django,
|
|
7
|
+
FastAPI, Flask, Celery, CLI scripts — anywhere Python runs.
|
|
8
|
+
|
|
9
|
+
> **Project status: Alpha.** The public API surface is intentionally small and
|
|
10
|
+
> stable, but endpoint/field details are still being validated against SIBS' official
|
|
11
|
+
> documentation. Every response exposes a `raw_response` so you are never blocked by a
|
|
12
|
+
> field PySIBS has not yet normalized. See [Caveats](#caveats--unverified-details).
|
|
13
|
+
|
|
14
|
+
## Features
|
|
15
|
+
|
|
16
|
+
- Synchronous (`SIBSClient`) and asynchronous (`AsyncSIBSClient`) clients
|
|
17
|
+
- Create payments, check status, refund, capture and cancel
|
|
18
|
+
- Typed Pydantic models with normalized statuses (`PaymentStatus`)
|
|
19
|
+
- Safe money handling with `Decimal` (floats are rejected)
|
|
20
|
+
- Webhook parsing and configurable signature verification
|
|
21
|
+
- A clear exception hierarchy — raw `httpx` errors never leak out
|
|
22
|
+
- Fully typed (`py.typed`), `ruff` + `mypy --strict` clean
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install pysibs
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Requires Python 3.10+.
|
|
31
|
+
|
|
32
|
+
## Configuration
|
|
33
|
+
|
|
34
|
+
Construct a client directly:
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
from pysibs import SIBSClient
|
|
38
|
+
|
|
39
|
+
client = SIBSClient(
|
|
40
|
+
api_key="your_api_key",
|
|
41
|
+
terminal_id="your_terminal_id",
|
|
42
|
+
environment="sandbox", # or "production"
|
|
43
|
+
)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
…or from environment variables (`SIBS_API_KEY`, `SIBS_TERMINAL_ID`,
|
|
47
|
+
`SIBS_ENVIRONMENT`, and optionally `SIBS_CLIENT_ID`, `SIBS_WEBHOOK_SECRET`):
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
client = SIBSClient.from_env()
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The **core library never reads `.env`** — only the bundled examples do, via
|
|
54
|
+
`python-dotenv`. See [`.env.example`](.env.example).
|
|
55
|
+
|
|
56
|
+
## Create a payment
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
payment = client.create_payment(
|
|
60
|
+
amount="10.00", # str, int or Decimal — never float
|
|
61
|
+
currency="EUR",
|
|
62
|
+
merchant_transaction_id="ORDER-123",
|
|
63
|
+
return_url="https://example.com/payment/success",
|
|
64
|
+
cancel_url="https://example.com/payment/cancel",
|
|
65
|
+
payment_methods=["CARD", "MBWAY", "MULTIBANCO"],
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
print(payment.id)
|
|
69
|
+
print(payment.status) # normalized PaymentStatus
|
|
70
|
+
print(payment.redirect_url)
|
|
71
|
+
print(payment.raw_response) # untouched SIBS response
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Check payment status
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
status = client.get_payment_status("payment_123")
|
|
78
|
+
print(status.status) # normalized PaymentStatus
|
|
79
|
+
print(status.raw_status) # original value from SIBS
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Refunds
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
# Full refund
|
|
86
|
+
client.refund_payment(payment_id="payment_123")
|
|
87
|
+
|
|
88
|
+
# Partial refund
|
|
89
|
+
client.refund_payment(payment_id="payment_123", amount="10.00", merchant_refund_id="REF-1001")
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Capture & cancel
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
client.capture_payment(payment_id="payment_123", amount="25.50")
|
|
96
|
+
client.cancel_payment("payment_123")
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Async usage
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
from pysibs import AsyncSIBSClient
|
|
103
|
+
|
|
104
|
+
async with AsyncSIBSClient.from_env() as client:
|
|
105
|
+
payment = await client.create_payment(amount="10.00", merchant_transaction_id="ORDER-1")
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Webhooks
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
from pysibs import parse_webhook, verify_webhook_signature
|
|
112
|
+
|
|
113
|
+
event = parse_webhook(raw_body) # bytes, str or dict
|
|
114
|
+
print(event.payment_id, event.status, event.raw_payload)
|
|
115
|
+
|
|
116
|
+
is_valid = verify_webhook_signature(
|
|
117
|
+
payload=raw_body,
|
|
118
|
+
signature=request.headers.get("X-SIBS-Signature"),
|
|
119
|
+
secret="webhook_secret",
|
|
120
|
+
)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
SIBS' webhook signing scheme is not uniformly documented and may differ per
|
|
124
|
+
product/environment. `verify_webhook_signature` defaults to HMAC-SHA256, but you can
|
|
125
|
+
pass a custom `verifier` callable that matches whatever SIBS actually uses for your
|
|
126
|
+
integration. **Always confirm the scheme against the official documentation.**
|
|
127
|
+
|
|
128
|
+
## Error handling
|
|
129
|
+
|
|
130
|
+
All exceptions inherit from `SIBSError`:
|
|
131
|
+
|
|
132
|
+
| Exception | Raised when |
|
|
133
|
+
| --- | --- |
|
|
134
|
+
| `SIBSConfigurationError` | The client is misconfigured (missing credentials, bad environment). |
|
|
135
|
+
| `SIBSValidationError` | Input fails local validation (e.g. a float amount, empty id). |
|
|
136
|
+
| `SIBSAuthenticationError` | SIBS rejects credentials (HTTP 401/403). |
|
|
137
|
+
| `SIBSAPIError` | Other API errors (carries `status_code` and `response_body`). |
|
|
138
|
+
| `SIBSTimeoutError` | The request times out (or HTTP 408). |
|
|
139
|
+
| `SIBSConnectionError` | SIBS cannot be reached (DNS/TCP/TLS). |
|
|
140
|
+
| `SIBSInvalidWebhookSignature` | A webhook signature fails verification. |
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
from pysibs import SIBSError, SIBSAuthenticationError
|
|
144
|
+
|
|
145
|
+
try:
|
|
146
|
+
client.create_payment(amount="10.00", merchant_transaction_id="ORDER-1")
|
|
147
|
+
except SIBSAuthenticationError:
|
|
148
|
+
... # bad credentials
|
|
149
|
+
except SIBSError as exc:
|
|
150
|
+
... # any other PySIBS failure
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## PCI DSS note
|
|
154
|
+
|
|
155
|
+
This SDK does not store or process cardholder data by itself. However, some SIBS
|
|
156
|
+
server-to-server card payment flows may require the merchant environment to be PCI DSS
|
|
157
|
+
compliant. Always validate your integration scope with SIBS and your PCI advisor.
|
|
158
|
+
|
|
159
|
+
PySIBS deliberately:
|
|
160
|
+
|
|
161
|
+
- never stores PAN or CVV,
|
|
162
|
+
- never logs `Authorization` headers or credentials,
|
|
163
|
+
- ships no examples containing real card data.
|
|
164
|
+
|
|
165
|
+
## Caveats — unverified details
|
|
166
|
+
|
|
167
|
+
SIBS' public documentation does not pin down every endpoint, field name and signing
|
|
168
|
+
detail unambiguously, and they can vary by product/environment. Where there was
|
|
169
|
+
ambiguity, PySIBS:
|
|
170
|
+
|
|
171
|
+
1. keeps the wire format isolated in `pysibs/_payloads.py` and base URLs in
|
|
172
|
+
`pysibs/config.py`, so they are trivial to adjust in one place;
|
|
173
|
+
2. preserves the full `raw_response` / `raw_payload` on every model;
|
|
174
|
+
3. never sends undocumented headers (e.g. idempotency — see `pysibs/idempotency.py`).
|
|
175
|
+
|
|
176
|
+
Before going to production, verify the endpoints, payloads and webhook signature
|
|
177
|
+
scheme against the current official SIBS documentation.
|
|
178
|
+
|
|
179
|
+
## Python compatibility
|
|
180
|
+
|
|
181
|
+
Tested on CPython 3.10, 3.11, 3.12 and 3.13.
|
|
182
|
+
|
|
183
|
+
## Roadmap
|
|
184
|
+
|
|
185
|
+
- `0.1.0` — `SIBSClient`/`AsyncSIBSClient`, create/status/refund/capture/cancel,
|
|
186
|
+
webhook parsing + verification, typed models, docs.
|
|
187
|
+
- `0.2.0` — richer payment-method specific models (MB WAY, MULTIBANCO references).
|
|
188
|
+
- `1.0.0` — stable API once the SIBS contract is fully confirmed end-to-end.
|
|
189
|
+
|
|
190
|
+
## Contributing
|
|
191
|
+
|
|
192
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md). Security issues: see [SECURITY.md](SECURITY.md).
|
|
193
|
+
|
|
194
|
+
## License
|
|
195
|
+
|
|
196
|
+
[MIT](LICENSE) © Robert Benitez
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "pysibs"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "A modern Python SDK for SIBS Gateway payment integrations."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
license = "MIT"
|
|
8
|
+
license-files = ["LICENSE"]
|
|
9
|
+
authors = [{ name = "Robert Benitez" }]
|
|
10
|
+
keywords = [
|
|
11
|
+
"sibs",
|
|
12
|
+
"payments",
|
|
13
|
+
"payment-gateway",
|
|
14
|
+
"mbway",
|
|
15
|
+
"multibanco",
|
|
16
|
+
"fintech",
|
|
17
|
+
"python-sdk",
|
|
18
|
+
]
|
|
19
|
+
classifiers = [
|
|
20
|
+
"Development Status :: 3 - Alpha",
|
|
21
|
+
"Intended Audience :: Developers",
|
|
22
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
23
|
+
"Topic :: Office/Business :: Financial",
|
|
24
|
+
"Programming Language :: Python :: 3",
|
|
25
|
+
"Programming Language :: Python :: 3.10",
|
|
26
|
+
"Programming Language :: Python :: 3.11",
|
|
27
|
+
"Programming Language :: Python :: 3.12",
|
|
28
|
+
"Programming Language :: Python :: 3.13",
|
|
29
|
+
"Typing :: Typed",
|
|
30
|
+
]
|
|
31
|
+
dependencies = [
|
|
32
|
+
"httpx>=0.27.0",
|
|
33
|
+
"pydantic>=2.0.0",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[project.optional-dependencies]
|
|
37
|
+
dev = [
|
|
38
|
+
"pytest>=8.0",
|
|
39
|
+
"pytest-cov",
|
|
40
|
+
"pytest-asyncio",
|
|
41
|
+
"respx>=0.21",
|
|
42
|
+
"ruff",
|
|
43
|
+
"mypy",
|
|
44
|
+
"build",
|
|
45
|
+
"twine",
|
|
46
|
+
]
|
|
47
|
+
examples = [
|
|
48
|
+
"python-dotenv",
|
|
49
|
+
"fastapi",
|
|
50
|
+
"uvicorn",
|
|
51
|
+
"django",
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
[project.urls]
|
|
55
|
+
Homepage = "https://github.com/robertruben98/pysibs"
|
|
56
|
+
Repository = "https://github.com/robertruben98/pysibs"
|
|
57
|
+
Issues = "https://github.com/robertruben98/pysibs/issues"
|
|
58
|
+
Documentation = "https://github.com/robertruben98/pysibs#readme"
|
|
59
|
+
|
|
60
|
+
[build-system]
|
|
61
|
+
requires = ["hatchling"]
|
|
62
|
+
build-backend = "hatchling.build"
|
|
63
|
+
|
|
64
|
+
[tool.hatch.build.targets.wheel]
|
|
65
|
+
packages = ["pysibs"]
|
|
66
|
+
|
|
67
|
+
[tool.hatch.build.targets.sdist]
|
|
68
|
+
include = [
|
|
69
|
+
"/pysibs",
|
|
70
|
+
"/tests",
|
|
71
|
+
"/README.md",
|
|
72
|
+
"/LICENSE",
|
|
73
|
+
"/CHANGELOG.md",
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
[tool.ruff]
|
|
77
|
+
line-length = 100
|
|
78
|
+
target-version = "py310"
|
|
79
|
+
|
|
80
|
+
[tool.ruff.lint]
|
|
81
|
+
select = ["E", "F", "I", "UP", "B", "W", "C4", "SIM"]
|
|
82
|
+
ignore = ["B008"]
|
|
83
|
+
|
|
84
|
+
[tool.ruff.lint.per-file-ignores]
|
|
85
|
+
"tests/*" = ["B011"]
|
|
86
|
+
|
|
87
|
+
[tool.mypy]
|
|
88
|
+
python_version = "3.10"
|
|
89
|
+
strict = true
|
|
90
|
+
warn_unused_ignores = true
|
|
91
|
+
warn_redundant_casts = true
|
|
92
|
+
disallow_untyped_defs = true
|
|
93
|
+
plugins = ["pydantic.mypy"]
|
|
94
|
+
|
|
95
|
+
[[tool.mypy.overrides]]
|
|
96
|
+
module = ["respx.*"]
|
|
97
|
+
ignore_missing_imports = true
|
|
98
|
+
|
|
99
|
+
[tool.pytest.ini_options]
|
|
100
|
+
testpaths = ["tests"]
|
|
101
|
+
asyncio_mode = "auto"
|
|
102
|
+
markers = [
|
|
103
|
+
"integration: integration tests that hit a real SIBS sandbox (disabled by default)",
|
|
104
|
+
]
|
|
105
|
+
addopts = "-m 'not integration'"
|
|
106
|
+
|
|
107
|
+
[tool.coverage.run]
|
|
108
|
+
source = ["pysibs"]
|
|
109
|
+
branch = true
|
|
110
|
+
|
|
111
|
+
[tool.coverage.report]
|
|
112
|
+
show_missing = true
|
|
113
|
+
exclude_lines = [
|
|
114
|
+
"pragma: no cover",
|
|
115
|
+
"if TYPE_CHECKING:",
|
|
116
|
+
"raise NotImplementedError",
|
|
117
|
+
"\\.\\.\\.",
|
|
118
|
+
]
|