Python SDK for the Pesapal API v3 (authentication, orders, transaction status, refunds, cancellations) with an optional Selenium mobile-money helper.
Project description
pesapal-python
A lightweight Python SDK for the Pesapal API v3, 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
pip install pesapal-python
To use the Selenium mobile-money helper (requires Google Chrome + chromedriver):
pip install "pesapal-python[mobilemoney]"
Configuration via .env
Copy .env.example to .env and fill in your credentials:
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:
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
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:
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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pesapal_python-1.0.0.tar.gz.
File metadata
- Download URL: pesapal_python-1.0.0.tar.gz
- Upload date:
- Size: 14.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5cbd3d3b9cf38ad97701ebc6791f5f09933919e23ab81bdd9d962ced3ba8a683
|
|
| MD5 |
cfa4c816212acb6a07890ea9ceb8e750
|
|
| BLAKE2b-256 |
624b00a8b6efa7eb8fb78f6e93cd5d0a774b3441104e90fd35f6e211e3a43435
|
Provenance
The following attestation bundles were made for pesapal_python-1.0.0.tar.gz:
Publisher:
publish.yml on robin-001/pesapal-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pesapal_python-1.0.0.tar.gz -
Subject digest:
5cbd3d3b9cf38ad97701ebc6791f5f09933919e23ab81bdd9d962ced3ba8a683 - Sigstore transparency entry: 1915200000
- Sigstore integration time:
-
Permalink:
robin-001/pesapal-py@eff5591a3dcb70910303c4b9247663f56b37c835 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/robin-001
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@eff5591a3dcb70910303c4b9247663f56b37c835 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pesapal_python-1.0.0-py3-none-any.whl.
File metadata
- Download URL: pesapal_python-1.0.0-py3-none-any.whl
- Upload date:
- Size: 12.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d8a9e9840286dcdaad204020ea6dde93a1ed8121eefdf2876b232b02cf23013f
|
|
| MD5 |
7c67462040c1e5060aa42357aa9e813d
|
|
| BLAKE2b-256 |
a334b238c23f0cbd23ef4e7e39e5f8b665b12622e1c960c14847c742602a9910
|
Provenance
The following attestation bundles were made for pesapal_python-1.0.0-py3-none-any.whl:
Publisher:
publish.yml on robin-001/pesapal-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pesapal_python-1.0.0-py3-none-any.whl -
Subject digest:
d8a9e9840286dcdaad204020ea6dde93a1ed8121eefdf2876b232b02cf23013f - Sigstore transparency entry: 1915200129
- Sigstore integration time:
-
Permalink:
robin-001/pesapal-py@eff5591a3dcb70910303c4b9247663f56b37c835 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/robin-001
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@eff5591a3dcb70910303c4b9247663f56b37c835 -
Trigger Event:
push
-
Statement type: