Metadata-Version: 2.4
Name: edahab
Version: 2.0.2
Summary: Python client for the eDahab payment API
Author: eDahab Python client contributors
License: MIT
Keywords: edahab,payment,api,somalia
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Typing :: Typed
Requires-Python: >=3.9
Description-Content-Type: text/markdown

<p align="center">
  <img src="https://edahab.net/eDahab.png" alt="eDahab logo" width="120" />
</p>

<h1 align="center">edahab (Python SDK)</h1>

<p align="center">
  Full Python SDK for the official <a href="https://docs.edahab.net/api-introduction">eDahab API</a>.
</p>

<p align="center">
  <a href="https://pypi.org/project/edahab/">PyPI</a> •
  <a href="./n8n-nodes-edahab/README.md">n8n Node Docs</a> •
  <a href="https://docs.edahab.net/status">Status Codes</a>
</p>

---

## Table of Contents

- [1) Product separation](#1-product-separation)
- [2) Install](#2-install)
- [3) Quick start](#3-quick-start)
- [4) Credentials and configuration](#4-credentials-and-configuration)
- [5) API reference (module-level functions)](#5-api-reference-module-level-functions)
- [6) API reference (EdahabClient)](#6-api-reference-edahabclient)
- [7) Result objects](#7-result-objects)
- [8) Exceptions](#8-exceptions)
- [9) Status codes](#9-status-codes)
- [10) Troubleshooting](#12-troubleshooting)
- [11) Exports](#13-exports)
- [12) Official docs links](#14-official-docs-links)

---

## 1) Product separation

This repository has **two separate deliverables**:

- **Python SDK** (this package): `edahab` (published on PyPI)
- **n8n node package**: see `n8n-nodes-edahab/README.md` (published on npm)

They are independent in packaging and release process.

---

## 2) Install

Install from PyPI:

```bash
pip install edahab
```

Install from local source:

```bash
pip install .
```

Editable install for development:

```bash
pip install -e .
```

---

## 3) Quick start

```python
from edahab import configure, pay, verify_invoice, is_invoice_paid

configure("your-api-key", "your-api-secret")

invoice = pay(
    customer="65",
    amount=1,
    agent="5555",
    currency="USD",  # required
)

print(invoice.invoice_id, invoice.invoice_status)
print("paid?", is_invoice_paid(invoice.invoice_status))

if invoice.invoice_id:
    status = verify_invoice(invoice_id=invoice.invoice_id)
    print("verified:", status.invoice_status)
```

> Every payment call requires `currency` and only accepts `USD` or `SLSH`.

---

## 4) Credentials and configuration

### Environment variables

- `EDAHAB_API_KEY`
- `EDAHAB_API_SECRET`

### `configure(api_key, api_secret, *, base_url=..., timeout=..., open_url=...)`

Sets a shared default client used by `pay`, `verify_invoice`, and `send_credit`.

### `configure_from_env(...)`

Same as `configure`, but reads from env vars.

### `get_client()`

Returns configured client or raises `RuntimeError` if not configured.

### `clear_configuration()`

Clears configured default client (mostly useful in tests).

---

## 5) API reference (module-level functions)

### `pay(api_key=None, api_secret=None, *, customer, amount, agent, currency) -> IssueInvoiceResult`

Creates purchase invoice (`Issueinvoice`).

- If `api_key` and `api_secret` are omitted, uses configured default client.
- If either key is provided alone, raises `ValueError`.

Example:

```python
from edahab import pay

res = pay(
    "your-api-key",
    "your-api-secret",
    customer="65",
    amount=1,
    agent="5555",
    currency="USD",
)
```

### `verify_invoice(api_key=None, api_secret=None, *, invoice_id) -> CheckInvoiceStatusResult`

Checks status via `CheckInvoiceStatus`.

### `send_credit(api_key=None, api_secret=None, *, to, amount, reference, currency) -> AgentPaymentResult`

Sends merchant-balance credit (`agentPayment`).

### `is_invoice_paid(invoice_status) -> bool`

Returns `True` only for `"Paid"`.

### `normalize_currency(currency) -> str`

Normalizes and validates currency:

- accepts case-insensitive input
- returns canonical `"USD"` / `"SLSH"`
- raises `ValueError` on invalid input

### `generate_request_hash(serialized_body, api_secret) -> str`

Computes SHA-256 hex of `serialized_body + api_secret`.

### `serialize_body(payload: dict) -> str`

Compacts JSON with stable sorting:

- `separators=(",", ":")`
- `sort_keys=True`

### `describe_status_code(code) -> str | None`

Human description for invoice `StatusCode`.

---

## 6) API reference (EdahabClient)

### Constructor

`EdahabClient(api_key, api_secret, *, base_url="https://edahab.net/api/api/", timeout=30.0, open_url=None)`

### Alternate constructor

`EdahabClient.from_env(...)`

### Property

`client.api_key`

### Methods

#### `issue_invoice(edahab_number, amount, agent_code, *, currency, raise_on_api_error=True)`

- endpoint: `Issueinvoice`
- returns: `IssueInvoiceResult`

#### `pay(*, customer, amount, agent, currency, raise_on_api_error=True)`

Alias for `issue_invoice`.

#### `agent_payment(phone_number, transaction_amount, transaction_id, *, currency)`

- endpoint: `agentPayment`
- returns: `AgentPaymentResult`

#### `send_credit(*, to, amount, reference, currency)`

Alias for `agent_payment`.

#### `check_invoice_status(invoice_id, *, raise_on_api_error=True)`

- endpoint: `CheckInvoiceStatus`
- returns: `CheckInvoiceStatusResult`

#### `verify(invoice_id, *, raise_on_api_error=True)`

Alias for `check_invoice_status`.

### Error behavior

- invoice endpoints can raise based on `StatusCode` if `raise_on_api_error=True`
- credit endpoint currently returns parsed payload without status-code raising

---

## 7) Result objects

### `IssueInvoiceResult`

- `invoice_status`
- `transaction_id`
- `invoice_id`
- `status_code`
- `request_id`
- `status_description`
- `validation_errors`
- `raw`

### `CheckInvoiceStatusResult`

Same field shape as `IssueInvoiceResult`.

### `AgentPaymentResult`

- `transaction_status`
- `transaction_message` (handles API typo `TransactionMesage`)
- `phone_number`
- `transaction_id`
- `currency`
- `raw`

---

## 8) Exceptions

- `EdahabError` (base)
- `EdahabHTTPError` (`status_code`, `url`, `body`)
- `EdahabDecodeError`
- `EdahabCredentialError`
- `EdahabValidationError` (`validation_errors`)
- `EdahabAPIStatusError` (`status_code`, `status_description`, `raw_response`)

Example:

```python
from edahab import (
    EdahabClient,
    EdahabCredentialError,
    EdahabValidationError,
    EdahabAPIStatusError,
    EdahabHTTPError,
)

client = EdahabClient("your-api-key", "your-api-secret")

try:
    client.issue_invoice("65", 1, "5555", currency="USD")
except EdahabCredentialError:
    print("invalid key/secret/hash")
except EdahabValidationError as e:
    print(e.validation_errors)
except EdahabAPIStatusError as e:
    print(e.status_code, e.raw_response)
except EdahabHTTPError as e:
    print(e.status_code, e.body)
```

---

## 9) Status codes

`StatusCode` enum:

- `SUCCESS = 0`
- `API_ERROR = 1`
- `INVALID_JSON = 2`
- `VALIDATION_ERROR = 3`
- `INVALID_API_CREDENTIALS = 4`
- `INSUFFICIENT_CUSTOMER_BALANCE = 5`
- `INVOICE_NOT_FOUND = 6`
- `INVALID = 7`

Use `STATUS_DESCRIPTIONS` or `describe_status_code()` for labels.

## 10) Troubleshooting

- **`RuntimeError: No default client configured`**
  Call `configure(...)` or `configure_from_env()` first.

- **`ValueError: currency must be 'USD' or 'SLSH'`**
  Pass valid currency; use `normalize_currency()`.

- **`HTTP 400` at upload to PyPI**
  You are likely re-uploading an existing release file; bump version.

- **`StatusCode=4` from API**
  Check key/secret pair and hash generation body consistency.

---

## 11) Exports

`configure`, `configure_from_env`, `get_client`, `clear_configuration`, `pay`, `verify_invoice`, `send_credit`, `is_invoice_paid`, `normalize_currency`, `generate_request_hash`, `serialize_body`, `describe_status_code`, `EdahabClient`, `DEFAULT_BASE_URL`, `StatusCode`, `STATUS_DESCRIPTIONS`, `IssueInvoiceResult`, `CheckInvoiceStatusResult`, `AgentPaymentResult`, `EdahabError`, `EdahabHTTPError`, `EdahabDecodeError`, `EdahabCredentialError`, `EdahabValidationError`, `EdahabAPIStatusError`.

---

## 12) Official docs links

- [API introduction](https://docs.edahab.net/api-introduction)
- [Purchase / Issueinvoice](https://docs.edahab.net/purchase)
- [Credit payment / agentPayment](https://docs.edahab.net/credit-invoice)
- [Verify invoice / CheckInvoiceStatus](https://docs.edahab.net/verify-invoice)
- [Status codes](https://docs.edahab.net/status)
