ethio-receipt-verify 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.
- ethio_receipt_verify-0.1.0/.gitignore +41 -0
- ethio_receipt_verify-0.1.0/PKG-INFO +409 -0
- ethio_receipt_verify-0.1.0/README.md +380 -0
- ethio_receipt_verify-0.1.0/ethio_receipt_verify/__init__.py +52 -0
- ethio_receipt_verify-0.1.0/ethio_receipt_verify/banks/__init__.py +28 -0
- ethio_receipt_verify-0.1.0/ethio_receipt_verify/banks/awash.py +48 -0
- ethio_receipt_verify-0.1.0/ethio_receipt_verify/banks/base.py +29 -0
- ethio_receipt_verify-0.1.0/ethio_receipt_verify/banks/boa.py +89 -0
- ethio_receipt_verify-0.1.0/ethio_receipt_verify/banks/cbe.py +103 -0
- ethio_receipt_verify-0.1.0/ethio_receipt_verify/banks/cbebirr.py +46 -0
- ethio_receipt_verify-0.1.0/ethio_receipt_verify/banks/dashen.py +43 -0
- ethio_receipt_verify-0.1.0/ethio_receipt_verify/banks/kaafiebirr.py +21 -0
- ethio_receipt_verify-0.1.0/ethio_receipt_verify/banks/mpesa.py +65 -0
- ethio_receipt_verify-0.1.0/ethio_receipt_verify/banks/siinqee.py +20 -0
- ethio_receipt_verify-0.1.0/ethio_receipt_verify/banks/telebirr.py +88 -0
- ethio_receipt_verify-0.1.0/ethio_receipt_verify/banks/zemen.py +48 -0
- ethio_receipt_verify-0.1.0/ethio_receipt_verify/cli.py +251 -0
- ethio_receipt_verify-0.1.0/ethio_receipt_verify/client.py +416 -0
- ethio_receipt_verify-0.1.0/ethio_receipt_verify/client_types.py +415 -0
- ethio_receipt_verify-0.1.0/ethio_receipt_verify/errors.py +14 -0
- ethio_receipt_verify-0.1.0/ethio_receipt_verify/registry.py +28 -0
- ethio_receipt_verify-0.1.0/ethio_receipt_verify/result.py +48 -0
- ethio_receipt_verify-0.1.0/pyproject.toml +53 -0
- ethio_receipt_verify-0.1.0/tests/__init__.py +0 -0
- ethio_receipt_verify-0.1.0/tests/test_banks.py +220 -0
- ethio_receipt_verify-0.1.0/tests/test_client.py +485 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
|
2
|
+
|
|
3
|
+
# dependencies
|
|
4
|
+
/node_modules
|
|
5
|
+
/.pnp
|
|
6
|
+
.pnp.*
|
|
7
|
+
.yarn/*
|
|
8
|
+
!.yarn/patches
|
|
9
|
+
!.yarn/plugins
|
|
10
|
+
!.yarn/releases
|
|
11
|
+
!.yarn/versions
|
|
12
|
+
|
|
13
|
+
# testing
|
|
14
|
+
/coverage
|
|
15
|
+
|
|
16
|
+
# next.js
|
|
17
|
+
/.next/
|
|
18
|
+
/out/
|
|
19
|
+
|
|
20
|
+
# production
|
|
21
|
+
/build
|
|
22
|
+
|
|
23
|
+
# misc
|
|
24
|
+
.DS_Store
|
|
25
|
+
*.pem
|
|
26
|
+
|
|
27
|
+
# debug
|
|
28
|
+
npm-debug.log*
|
|
29
|
+
yarn-debug.log*
|
|
30
|
+
yarn-error.log*
|
|
31
|
+
.pnpm-debug.log*
|
|
32
|
+
|
|
33
|
+
# env files (can opt-in for committing if needed)
|
|
34
|
+
.env*
|
|
35
|
+
|
|
36
|
+
# vercel
|
|
37
|
+
.vercel
|
|
38
|
+
|
|
39
|
+
# typescript
|
|
40
|
+
*.tsbuildinfo
|
|
41
|
+
next-env.d.ts
|
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ethio-receipt-verify
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Free, open-source Ethiopian bank/wallet receipt verification. Reverse-engineered public endpoints.
|
|
5
|
+
Project-URL: Homepage, https://github.com/1RB/cheki
|
|
6
|
+
Project-URL: Repository, https://github.com/1RB/cheki
|
|
7
|
+
Project-URL: Issues, https://github.com/1RB/cheki/issues
|
|
8
|
+
Author: 1RB
|
|
9
|
+
License: MIT
|
|
10
|
+
Keywords: bank,cbe,ethiopia,receipt,telebirr,verification
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Requires-Python: >=3.9
|
|
20
|
+
Requires-Dist: beautifulsoup4>=4.11.0
|
|
21
|
+
Requires-Dist: pdfplumber>=0.9.0
|
|
22
|
+
Requires-Dist: requests>=2.28.0
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
|
|
25
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
26
|
+
Requires-Dist: reportlab>=4.0.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: responses>=0.23.0; extra == 'dev'
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# ethio-receipt-verify (cheki Python SDK)
|
|
31
|
+
|
|
32
|
+
Free, open-source **Ethiopian bank/wallet receipt verification** for Python.
|
|
33
|
+
|
|
34
|
+
cheki verifies that a payment receipt is real by fetching it directly from the
|
|
35
|
+
bank's own public receipt endpoint — no API keys, no paywalls, no scraping with
|
|
36
|
+
Selenium. This SDK mirrors the [cheki](https://github.com/1RB/cheki) project's
|
|
37
|
+
other official SDKs (TypeScript, Go, PHP, Dart).
|
|
38
|
+
|
|
39
|
+
## Two modes
|
|
40
|
+
|
|
41
|
+
The SDK offers two complementary ways to verify receipts:
|
|
42
|
+
|
|
43
|
+
| Mode | When to use | How it works |
|
|
44
|
+
| --- | --- | --- |
|
|
45
|
+
| **API client** (recommended) | Production apps, servers, anything that wants reliability | Calls the hosted cheki REST API, which handles geo-blocking, QR decryption, PDF parsing, and bank-endpoint rotation for you. |
|
|
46
|
+
| **Direct verification** (advanced) | Self-hosting, no external dependency, research | Fetches bank endpoints *directly* from your machine. No round-trip to cheki, but geo-blocked banks (telebirr, M-Pesa) will fail outside Ethiopia. |
|
|
47
|
+
|
|
48
|
+
Both are importable from the top-level package:
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
from ethio_receipt_verify import ChekiClient, verify, supported_banks
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Quick start — API client
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
from ethio_receipt_verify import ChekiClient
|
|
60
|
+
|
|
61
|
+
cheki = ChekiClient() # uses https://cheki-pi.vercel.app by default
|
|
62
|
+
|
|
63
|
+
# CBE requires the receiving account number
|
|
64
|
+
result = cheki.verify("cbe", "FT26140P01YB", account_number="1000560536171")
|
|
65
|
+
|
|
66
|
+
if result.is_verified:
|
|
67
|
+
print(f"{result.sender_name} sent {result.amount} {result.currency}")
|
|
68
|
+
print(f"to {result.receiver_name} on {result.date}")
|
|
69
|
+
else:
|
|
70
|
+
print(f"Not verified: {result.error}")
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Batch verification
|
|
74
|
+
|
|
75
|
+
Verify up to 50 receipts in a single request:
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
results = cheki.verify_batch([
|
|
79
|
+
{"bank": "cbe", "reference": "FT26140P01YB", "accountNumber": "1000560536171"},
|
|
80
|
+
{"bank": "telebirr", "reference": "DET8FJGUJ4"},
|
|
81
|
+
{"bank": "dashen", "reference": "B22WDTI261620001"},
|
|
82
|
+
])
|
|
83
|
+
|
|
84
|
+
print(f"{results.verified}/{results.total} verified")
|
|
85
|
+
for r in results.results:
|
|
86
|
+
print(r.reference, r.is_verified, r.error)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Discover supported banks
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
for bank in cheki.get_banks():
|
|
93
|
+
print(f"{bank.code:<12} {bank.name} [{bank.status}]")
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Health check
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
health = cheki.get_health()
|
|
100
|
+
print(health.status) # "ok"
|
|
101
|
+
for check in health.checks:
|
|
102
|
+
print(f" {check.name}: {check.status} ({check.latency_ms}ms)")
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Context manager
|
|
106
|
+
|
|
107
|
+
`ChekiClient` reuses a connection pool and can be used as a context manager:
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
with ChekiClient(timeout=10, max_retries=5) as cheki:
|
|
111
|
+
result = cheki.verify("cbe", "FT26140P01YB", account_number="1000560536171")
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Quick start — Direct verification (advanced)
|
|
117
|
+
|
|
118
|
+
Direct verification fetches the bank endpoint from *your* machine. It needs no
|
|
119
|
+
cheki server but is subject to geo-blocking and bank-side changes.
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
from ethio_receipt_verify import verify, supported_banks
|
|
123
|
+
|
|
124
|
+
# CBE needs the full receiving account number
|
|
125
|
+
result = verify("cbe", "FT26140P01YB", account_number="1000560536171")
|
|
126
|
+
|
|
127
|
+
print(result.status) # VerificationStatus.VERIFIED
|
|
128
|
+
print(result.exists) # True
|
|
129
|
+
print(result.amount) # 20000.0
|
|
130
|
+
print(result.sender_name)
|
|
131
|
+
|
|
132
|
+
# telebirr / M-Pesa only work from Ethiopian IP addresses
|
|
133
|
+
print(supported_banks())
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Direct verification returns a `VerificationResult` (different from the API
|
|
137
|
+
client's `ClientVerifyResult`). See the [API reference](#api-reference) below.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Installation
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
pip install ethio-receipt-verify
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
From source (development):
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
git clone https://github.com/1RB/cheki.git
|
|
151
|
+
cd cheki/python
|
|
152
|
+
pip install -e ".[dev]"
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Dependencies: `requests`, `beautifulsoup4`, `pdfplumber` (the latter two are only
|
|
156
|
+
needed for direct verification of PDF/HTML receipts).
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## API reference
|
|
161
|
+
|
|
162
|
+
### `ChekiClient`
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
ChekiClient(
|
|
166
|
+
base_url="https://cheki-pi.vercel.app",
|
|
167
|
+
api_key=None,
|
|
168
|
+
timeout=30,
|
|
169
|
+
max_retries=3,
|
|
170
|
+
session=None,
|
|
171
|
+
user_agent=None,
|
|
172
|
+
)
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
| Parameter | Type | Default | Description |
|
|
176
|
+
| --- | --- | --- | --- |
|
|
177
|
+
| `base_url` | `str` | `https://cheki-pi.vercel.app` | cheki API root URL. |
|
|
178
|
+
| `api_key` | `str \| None` | `None` | Optional bearer token. The public API does not require one. |
|
|
179
|
+
| `timeout` | `float` | `30` | Per-request timeout in seconds. |
|
|
180
|
+
| `max_retries` | `int` | `3` | Retries on HTTP 408/429/5xx (in addition to the first attempt). |
|
|
181
|
+
| `session` | `requests.Session \| None` | `None` | Reuse a custom session (connection pool, proxies, etc.). |
|
|
182
|
+
| `user_agent` | `str \| None` | auto | `User-Agent` header value. |
|
|
183
|
+
|
|
184
|
+
#### Methods
|
|
185
|
+
|
|
186
|
+
##### `verify(bank, reference, account_number=None, phone_number=None, qr_data=None) -> ClientVerifyResult`
|
|
187
|
+
|
|
188
|
+
Verify a single receipt.
|
|
189
|
+
|
|
190
|
+
##### `verify_batch(receipts) -> ClientBatchResult`
|
|
191
|
+
|
|
192
|
+
Verify up to 50 receipts. Each receipt is a dict with `bank`, `reference`, and
|
|
193
|
+
optional `accountNumber` / `phoneNumber` / `qrData`. Results are returned in
|
|
194
|
+
input order with computed `total` / `verified` / `failed` counts.
|
|
195
|
+
|
|
196
|
+
##### `get_banks() -> list[ClientBankInfo]`
|
|
197
|
+
|
|
198
|
+
List supported banks/wallets.
|
|
199
|
+
|
|
200
|
+
##### `get_health() -> ClientHealthStatus`
|
|
201
|
+
|
|
202
|
+
Check service health (per-bank reachability).
|
|
203
|
+
|
|
204
|
+
##### `get_receipt_url(bank, reference, account_number=None) -> str`
|
|
205
|
+
|
|
206
|
+
Build a direct receipt-viewer URL (no network request).
|
|
207
|
+
|
|
208
|
+
##### `close()`
|
|
209
|
+
|
|
210
|
+
Close the underlying HTTP session.
|
|
211
|
+
|
|
212
|
+
### Response types
|
|
213
|
+
|
|
214
|
+
#### `ClientVerifyResult`
|
|
215
|
+
|
|
216
|
+
| Field | Type | Notes |
|
|
217
|
+
| --- | --- | --- |
|
|
218
|
+
| `success` | `bool` | HTTP-level success. |
|
|
219
|
+
| `verified` | `bool \| None` | Whether the receipt is legitimate. |
|
|
220
|
+
| `bank`, `bank_code`, `reference` | `str \| None` | Identifiers. |
|
|
221
|
+
| `source_url` | `str \| None` | Where the receipt was fetched from. |
|
|
222
|
+
| `sender_name`, `sender_account` | `str \| None` | Sender details. |
|
|
223
|
+
| `receiver_name`, `receiver_account` | `str \| None` | Receiver details. |
|
|
224
|
+
| `amount`, `currency` | `float \| None`, `str \| None` | Payment amount. |
|
|
225
|
+
| `date` | `str \| None` | Transaction date (as reported by the bank). |
|
|
226
|
+
| `branch`, `reason` | `str \| None` | Extra metadata. |
|
|
227
|
+
| `duration_ms` | `int \| None` | Server-side processing time. |
|
|
228
|
+
| `invoice_number`, `transaction_status` | `str \| None` | Wallet-specific. |
|
|
229
|
+
| `settled_amount`, `stamp_duty`, `discount_amount` | `float \| None` | Wallet fees. |
|
|
230
|
+
| `service_fee`, `service_fee_vat`, `total_paid` | `float \| None` | Wallet fees. |
|
|
231
|
+
| `amount_in_words`, `payment_mode`, `payment_channel` | `str \| None` | Wallet metadata. |
|
|
232
|
+
| `bank_account_number`, `bank_account_name` | `str \| None` | Wallet metadata. |
|
|
233
|
+
| `error` | `str \| None` | Error message on failure. |
|
|
234
|
+
| `fallback_url` | `str \| None` | Direct URL for geo-blocked banks. |
|
|
235
|
+
| `index` | `int \| None` | Position within a batch. |
|
|
236
|
+
| `raw` | `dict` | The unparsed API payload. |
|
|
237
|
+
|
|
238
|
+
Helper: `result.is_verified` → `True` when `success` and `verified` are both true.
|
|
239
|
+
|
|
240
|
+
#### `ClientBatchResult`
|
|
241
|
+
|
|
242
|
+
`success`, `total`, `verified`, `failed`, `results` (list of
|
|
243
|
+
`ClientVerifyResult`), `error`, `raw`.
|
|
244
|
+
|
|
245
|
+
#### `ClientBankInfo`
|
|
246
|
+
|
|
247
|
+
`code`, `name`, `swift`, `type`, `status`, `requires_account`,
|
|
248
|
+
`account_digits`, `requires_phone`, `endpoint`, `color`, `initials`, `raw`.
|
|
249
|
+
Helper: `bank.is_live`.
|
|
250
|
+
|
|
251
|
+
#### `ClientHealthStatus`
|
|
252
|
+
|
|
253
|
+
`success`, `status`, `version`, `timestamp`, `checks` (list of
|
|
254
|
+
`ClientHealthCheck`), `raw`. Helper: `health.is_ok`.
|
|
255
|
+
|
|
256
|
+
#### `ClientHealthCheck`
|
|
257
|
+
|
|
258
|
+
`name`, `status`, `latency_ms`, `raw`.
|
|
259
|
+
|
|
260
|
+
### Direct verification
|
|
261
|
+
|
|
262
|
+
#### `verify(bank, reference, **kwargs) -> VerificationResult`
|
|
263
|
+
|
|
264
|
+
Fetch and parse a receipt directly from the bank endpoint.
|
|
265
|
+
|
|
266
|
+
- `cbe`, `boa`: pass `account_number=` (full receiving account).
|
|
267
|
+
- `cbebirr`: pass `phone_number=` (payer phone, `2519XXXXXXXXX`).
|
|
268
|
+
|
|
269
|
+
Returns a `VerificationResult` with `status` (`VerificationStatus`), `exists`,
|
|
270
|
+
`amount`, `sender_name`, `receiver_name`, `transaction_date`, `source_url`, etc.
|
|
271
|
+
|
|
272
|
+
#### `supported_banks() -> dict[str, str]`
|
|
273
|
+
|
|
274
|
+
Map of bank code → human name for the banks with direct verifiers.
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## Error handling
|
|
279
|
+
|
|
280
|
+
### API client errors
|
|
281
|
+
|
|
282
|
+
All API client errors derive from `ChekiClientError`:
|
|
283
|
+
|
|
284
|
+
```python
|
|
285
|
+
from ethio_receipt_verify import (
|
|
286
|
+
ChekiClient, ChekiClientError, ChekiAPIError, ChekiNetworkError, ChekiTimeoutError,
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
cheki = ChekiClient()
|
|
290
|
+
try:
|
|
291
|
+
result = cheki.verify("cbe", "FT26140P01YB", account_number="1000560536171")
|
|
292
|
+
except ChekiTimeoutError as exc:
|
|
293
|
+
print("Request timed out:", exc)
|
|
294
|
+
except ChekiNetworkError as exc:
|
|
295
|
+
print("Network error:", exc)
|
|
296
|
+
except ChekiAPIError as exc:
|
|
297
|
+
print(f"API error (HTTP {exc.status_code}):", exc.message)
|
|
298
|
+
except ChekiClientError as exc:
|
|
299
|
+
print("Client error:", exc)
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
| Error | Meaning |
|
|
303
|
+
| --- | --- |
|
|
304
|
+
| `ChekiAPIError` | Non-2xx API response. Carries `status_code`, `message`, `body`. |
|
|
305
|
+
| `ChekiNetworkError` | Connection failure. |
|
|
306
|
+
| `ChekiTimeoutError` | Request timed out (subclass of `ChekiNetworkError`). |
|
|
307
|
+
|
|
308
|
+
> **Note:** a verification that *finds no receipt* is **not** an error — the API
|
|
309
|
+
> returns `success: false` with an `error` message in the `ClientVerifyResult`.
|
|
310
|
+
> Exceptions are reserved for transport/server failures.
|
|
311
|
+
|
|
312
|
+
### Direct verification errors
|
|
313
|
+
|
|
314
|
+
```python
|
|
315
|
+
from ethio_receipt_verify import verify
|
|
316
|
+
from ethio_receipt_verify.errors import (
|
|
317
|
+
VerificationError, ReceiptNotFoundError, UpstreamError, UnsupportedBankError,
|
|
318
|
+
)
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
| Error | Meaning |
|
|
322
|
+
| --- | --- |
|
|
323
|
+
| `UnsupportedBankError` | The bank code is not supported. |
|
|
324
|
+
| `ReceiptNotFoundError` | The bank returned a "not found" response. |
|
|
325
|
+
| `UpstreamError` | The bank endpoint is unreachable or returned an error. |
|
|
326
|
+
|
|
327
|
+
### Retries
|
|
328
|
+
|
|
329
|
+
`ChekiClient` automatically retries on HTTP `408`, `429`, and `5xx` using
|
|
330
|
+
exponential backoff with full jitter (up to `max_retries` extra attempts). A
|
|
331
|
+
`Retry-After` header, when present, is honored. Network and timeout errors are
|
|
332
|
+
also retried.
|
|
333
|
+
|
|
334
|
+
---
|
|
335
|
+
|
|
336
|
+
## CLI
|
|
337
|
+
|
|
338
|
+
Install the package to get the `ethio-verify` command:
|
|
339
|
+
|
|
340
|
+
```bash
|
|
341
|
+
# API client (recommended)
|
|
342
|
+
ethio-verify cbe FT26140P01YB --account 1000560536171 --api
|
|
343
|
+
ethio-verify telebirr DET8FJGUJ4 --api --json
|
|
344
|
+
|
|
345
|
+
# Direct verification (advanced)
|
|
346
|
+
ethio-verify cbe FT26140P01YB --account 1000560536171
|
|
347
|
+
|
|
348
|
+
# Service health & supported banks (via API)
|
|
349
|
+
ethio-verify --health
|
|
350
|
+
ethio-verify --list-banks --api
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### Flags
|
|
354
|
+
|
|
355
|
+
| Flag | Description |
|
|
356
|
+
| --- | --- |
|
|
357
|
+
| `bank` | Bank/wallet code (e.g. `cbe`, `telebirr`, `boa`, `mpesa`). |
|
|
358
|
+
| `reference` | Transaction reference number. |
|
|
359
|
+
| `--account` | Receiving account number (required for cbe, boa). |
|
|
360
|
+
| `--phone` | Payer phone number (required for cbebirr). |
|
|
361
|
+
| `--qr` | Raw QR payload (Bank of Abyssinia inter-bank receipts). |
|
|
362
|
+
| `--api` | Use the hosted cheki REST API instead of direct verification. |
|
|
363
|
+
| `--base-url` | cheki API base URL (default: `https://cheki-pi.vercel.app`). |
|
|
364
|
+
| `--api-key` | Optional bearer token. |
|
|
365
|
+
| `--timeout` | Per-request timeout in seconds (API mode, default: 30). |
|
|
366
|
+
| `--json` | Output raw JSON. |
|
|
367
|
+
| `--list-banks` | List supported banks and exit. |
|
|
368
|
+
| `--health` | Check cheki API health and exit (implies `--api`). |
|
|
369
|
+
|
|
370
|
+
---
|
|
371
|
+
|
|
372
|
+
## Configuration
|
|
373
|
+
|
|
374
|
+
### Custom base URL / self-hosting
|
|
375
|
+
|
|
376
|
+
```python
|
|
377
|
+
cheki = ChekiClient(base_url="https://cheki.my-server.com")
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
### Proxies & custom session
|
|
381
|
+
|
|
382
|
+
```python
|
|
383
|
+
import requests
|
|
384
|
+
|
|
385
|
+
session = requests.Session()
|
|
386
|
+
session.proxies = {"https": "http://proxy.local:8080"}
|
|
387
|
+
cheki = ChekiClient(session=session)
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### Timeouts & retries
|
|
391
|
+
|
|
392
|
+
```python
|
|
393
|
+
cheki = ChekiClient(timeout=10, max_retries=5)
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
## Supported banks
|
|
399
|
+
|
|
400
|
+
cbe, telebirr, boa, mpesa, dashen, zemen, cbebirr, siinqee, kaafiebirr (and
|
|
401
|
+
more — run `cheki.get_banks()` or `ethio-verify --list-banks --api` for the
|
|
402
|
+
current list). Availability depends on the bank endpoint's status and
|
|
403
|
+
geo-restrictions.
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
407
|
+
## License
|
|
408
|
+
|
|
409
|
+
MIT © [1RB](https://github.com/1RB)
|