Metadata-Version: 2.4
Name: pesapal-python
Version: 1.0.0
Summary: Python SDK for the Pesapal API v3 (authentication, orders, transaction status, refunds, cancellations) with an optional Selenium mobile-money helper.
Author: Pesapal SDK Contributors
License: MIT
Project-URL: Homepage, https://github.com/robin-001/pesapal-py
Project-URL: Documentation, https://github.com/robin-001/pesapal-py#readme
Project-URL: Source, https://github.com/robin-001/pesapal-py
Project-URL: Bug Tracker, https://github.com/robin-001/pesapal-py/issues
Keywords: pesapal,payments,mobile money,uganda,kenya,api
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
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: Topic :: Office/Business :: Financial
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.25
Requires-Dist: python-dotenv>=1.0
Provides-Extra: mobilemoney
Requires-Dist: selenium>=4.10; extra == "mobilemoney"
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: responses>=0.23; extra == "dev"
Requires-Dist: build; extra == "dev"
Requires-Dist: twine; extra == "dev"
Dynamic: license-file

# pesapal-python

A lightweight Python SDK for the [Pesapal API v3](https://developer.pesapal.com/),
covering authentication, order submission, transaction status, refunds and
cancellations, plus an optional Selenium helper to trigger the mobile-money
STK push from the hosted payment page.

## Features

- **Authenticate** and transparently cache/refresh the bearer token.
- **Register IPN** URLs and list them (needed to obtain a `notification_id`).
- **Submit orders** and get back the `redirect_url` / `order_tracking_id`.
- **Initiate mobile money** payment by driving the hosted iframe (optional).
- **Get transaction status** for an order.
- **Refund** completed transactions.
- **Cancel** pending orders.

## Installation

```bash
pip install pesapal-python
```

To use the Selenium mobile-money helper (requires Google Chrome + chromedriver):

```bash
pip install "pesapal-python[mobilemoney]"
```

## Configuration via `.env`

Copy `.env.example` to `.env` and fill in your credentials:

```dotenv
PESAPAL_CONSUMER_KEY=xxx
PESAPAL_CONSUMER_SECRET=xxx=
PESAPAL_PRODUCTION_BASE_URL=https://pay.pesapal.com/v3
PESAPAL_SANDBOX_BASE_URL=https://cybqa.pesapal.com/pesapalv3
```

Then build the client straight from the environment:

```python
from pesapal import PesapalClient

client = PesapalClient.from_env(sandbox=True)  # loads .env automatically
```

`from_env` reads `PESAPAL_CONSUMER_KEY` / `PESAPAL_CONSUMER_SECRET` and picks the
base URL from `PESAPAL_SANDBOX_BASE_URL` or `PESAPAL_PRODUCTION_BASE_URL`
depending on `sandbox`, falling back to the built-in defaults.

## Quick start

```python
from pesapal import PesapalClient, OrderRequest, BillingAddress

client = PesapalClient(
    consumer_key="YOUR_CONSUMER_KEY",
    consumer_secret="YOUR_CONSUMER_SECRET",
    sandbox=True,  # omit or set False for production
)

# 1. Authenticate (optional — called automatically on first request)
client.authenticate()

# 2. Register an IPN URL (once) to obtain a notification_id
ipn = client.register_ipn("https://your-app.com/ipn", "POST")
notification_id = ipn["ipn_id"]

# 3. Submit an order
order = OrderRequest(
    amount=1000,
    currency="UGX",
    description="Order #1234",
    callback_url="https://your-app.com/callback",
    notification_id=notification_id,
    branch="HQ",
    billing_address=BillingAddress(
        email_address="customer@example.com",
        phone_number="0775000000",
        country_code="UG",
        first_name="Jane",
        last_name="Doe",
    ),
)
submitted = client.submit_order(order)
order_tracking_id = submitted["order_tracking_id"]
redirect_url = submitted["redirect_url"]

# 4. Initiate mobile money (drives the hosted form; phone is prepopulated)
result = client.initiate_mobile_money_payment(redirect_url, headless=True)
print(result.success, result.tracking_id, result.response_id)

# 5. Check transaction status
status = client.get_transaction_status(order_tracking_id)
print(status["payment_status_description"])

# 6. Refund a completed transaction
client.refund(
    confirmation_code=status["confirmation_code"],
    amount=1000,
    username="Operator Name",
    remarks="Service not offered",
)

# 7. Cancel a pending order
client.cancel_order(order_tracking_id)
```

## Environments

| Environment | Base URL                                   |
| ----------- | ------------------------------------------ |
| Production  | `https://pay.pesapal.com/v3`               |
| Sandbox     | `https://cybqa.pesapal.com/pesapalv3`      |

Select with `PesapalClient(..., sandbox=True)` or pass a custom `base_url`.

## Error handling

All API failures raise a subclass of `PesapalError`:

```python
from pesapal import PesapalAPIError, PesapalAuthError

try:
    client.submit_order(order)
except PesapalAuthError as exc:
    ...  # bad credentials / token problem
except PesapalAPIError as exc:
    print(exc.status_code, exc.error, exc.response)
```

The mobile-money helper does **not** raise on failure; it returns a
`MobileMoneyResult` with `success=False` and an `error` message.

## License

MIT
