Async client for bKash Tokenized Checkout (grant/refresh, create/execute, status, search, refund) and SNS IPN verification.
Project description
bkash-pgw-tokenized
Async Python client for bKash Tokenized Checkout: grant/refresh token, create/execute payment, payment status, search transaction, refund, plus helpers for SNS-signed IPN payloads.
Import package: bkash_pgw_tokenized
PyPI / pip name: bkash-pgw-tokenized
Install:
pip install -e "./packages/bkash_pgw_tokenized[dev]" # from repo root (+ pytest)
# default install includes httpx + cryptography (IPN / SNS signature verification)
pip install -e "./packages/bkash_pgw_tokenized"
Published wheels from PyPI: pip install bkash-pgw-tokenized includes cryptography so SNS IPN verification works without extras. The legacy extra bkash-pgw-tokenized[ipn] is a no-op (kept for old requirement lines).
Usage
from bkash_pgw_tokenized import Bkash, MemoryTokenStore, ensure_id_token
config = {
"app_key": "...",
"app_secret": "...",
"username": "...",
"password": "...",
"sandbox": True, # False for live
}
client = Bkash(config)
store = MemoryTokenStore()
id_token = await ensure_id_token(store, client)
create = await client.create_payment(
id_token,
mode="0011",
payer_reference="INV-001",
callback_url="https://your.site/payments/bkash/callback",
amount="100.00",
currency="BDT",
intent="sale",
merchant_invoice_number="INV-001",
)
# create["bkashURL"], create["paymentID"], ...
exec_res = await client.execute_payment(id_token, create["paymentID"])
status = await client.payment_status(id_token, create["paymentID"])
found = await client.search_transaction(id_token, trx_id="...")
refund = await client.refund(
id_token,
payment_id="...",
trx_id="...",
amount="100.00",
sku="sku-1",
reason="Customer request",
)
Optional keys: "sandbox" (defaults to True), "base_url" (overrides the default host for that mode).
On HTTP error responses, the client raises BkashHttpError with status_code and response_body.
Default API roots are BKASH_TOKENIZED_SANDBOX_BASE_URL and BKASH_TOKENIZED_LIVE_BASE_URL (exported from bkash_pgw_tokenized). For static typing of config, use BkashConfig (or BkashConfigRequired for only the four secret fields).
Authorization header: the raw id_token is sent as Authorization (no Bearer prefix), matching bKash’s tokenized API.
AsyncBkashClient is an alias for Bkash (backward-compatible name).
Status codes and outcomes (success, failure, cancel)
bKash surfaces outcomes in three places: the browser callback to your callbackURL, JSON from Execute / Payment status APIs, and IPN (SNS) payloads. Handle each as below.
1. Browser callback query parameters
After checkout, bKash redirects the customer to your callbackURL with query parameters (names are typically lowercase). You should read at least paymentID and status.
Treat status case-insensitively (normalize with .strip().lower()).
| User outcome | Typical status values |
What to do |
|---|---|---|
| Success | success |
Call await client.execute_payment(id_token, paymentID) (or confirm with payment_status if Execute is unclear). Treat paid only when the JSON outcome rules below say success. |
| Failure | failure, fail, failed |
Do not Execute. Payment did not complete; show an error and keep your order unpaid. |
| Cancel | cancel, cancelled, canceled |
Do not Execute. User backed out; show cancelled state. |
Any other status value should be treated as unknown / failure until you confirm with bKash documentation for your integration.
If paymentID or status is missing, you cannot complete the flow safely.
2. Execute and Payment status API JSON
After status=success on the callback, the source of truth for money movement is the Execute response (and optionally Payment status if Execute times out or returns an unusable body).
For Execute and Payment status, treat payment as completed only when all of the following hold (same rules many merchants use in production):
| Field | Success value |
|---|---|
statusCode |
"0000" |
statusMessage |
"Successful" |
transactionStatus |
"Completed" |
If statusCode is present and not "0000", or transactionStatus is present and not "Completed", treat as failure. Use errorCode / statusCode with describe_code from bkash_pgw_tokenized for human-readable messages:
from bkash_pgw_tokenized import describe_code, is_success_status_code
if is_success_status_code(response.get("statusCode")):
...
else:
reason = describe_code(response.get("statusCode") or response.get("errorCode"))
Non-success responses often include statusMessage, errorMessage, or message; fall back to those for display.
3. Create payment response
Create is successful at the API level when statusCode == "0000". You still need bkashURL and paymentID in the payload to send the user to bKash. Any other statusCode means create failed; use describe_code and the message fields above.
4. IPN (SNS inner Message JSON)
For server-side notifications, use ipn_inner_is_success(inner) (see IPN (SNS)). In short:
- If
errorCode/error_codeis set and non-empty → not success. - If
statusCode/status_codeis present → it must be"0000"; iftransactionStatus/transaction_statusis also present, it must be"Completed". - If
statusCodeis absent (some samples) →transactionStatusmust be"Completed".
Reference
- Full numeric codes: bKash error codes
- Success API code for many operations:
0000
IPN (SNS)
Payload parsing and validation (imported from bkash_pgw_tokenized):
from bkash_pgw_tokenized import (
amounts_match,
extract_inner_from_sns_envelope,
ipn_inner_is_success,
verify_topic_arn,
)
if not verify_topic_arn(envelope, expected_topic_arn):
...
inner = extract_inner_from_sns_envelope(envelope)
ok, reason = ipn_inner_is_success(inner)
SNS signature verification (depends on cryptography, installed by default):
from bkash_pgw_tokenized.sns_verify import SnsVerificationError, verify_sns_signature
try:
verify_sns_signature(envelope)
except SnsVerificationError:
...
Development
cd packages/bkash_pgw_tokenized
pip install -e ".[dev]"
pytest
Poetry (2.x reads PEP 621): cd packages/bkash_pgw_tokenized && poetry install --extras dev.
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 bkash_pgw_tokenized-0.1.0.tar.gz.
File metadata
- Download URL: bkash_pgw_tokenized-0.1.0.tar.gz
- Upload date:
- Size: 12.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: Hatch/1.16.5 cpython/3.12.2 HTTPX/0.28.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9e2728371b12fba0c2780665cb1bc6415817bff95c639830eafcc2935977517f
|
|
| MD5 |
a54d4a4804a5045768ce54827b7188fd
|
|
| BLAKE2b-256 |
09bbacc1b34ec6e70ec09dce5bd6ec9f71702f6d742be71b99c8c709aaa068c7
|
File details
Details for the file bkash_pgw_tokenized-0.1.0-py3-none-any.whl.
File metadata
- Download URL: bkash_pgw_tokenized-0.1.0-py3-none-any.whl
- Upload date:
- Size: 13.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: Hatch/1.16.5 cpython/3.12.2 HTTPX/0.28.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b0c7701ee72f945e674df7d953a1244e6406de67fbc7e4dace1e2d2302106da8
|
|
| MD5 |
8b4191e1afddc7f731376a8790d91064
|
|
| BLAKE2b-256 |
fb1c214ecd5a8999523e621ef6fa94c1b9573ab6185fcc792d485b6c8f185431
|