Skip to main content

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_code is set and non-empty → not success.
  • If statusCode / status_code is present → it must be "0000"; if transactionStatus / transaction_status is also present, it must be "Completed".
  • If statusCode is absent (some samples) → transactionStatus must be "Completed".

Reference

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

bkash_pgw_tokenized-0.1.0.tar.gz (12.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

bkash_pgw_tokenized-0.1.0-py3-none-any.whl (13.6 kB view details)

Uploaded Python 3

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

Hashes for bkash_pgw_tokenized-0.1.0.tar.gz
Algorithm Hash digest
SHA256 9e2728371b12fba0c2780665cb1bc6415817bff95c639830eafcc2935977517f
MD5 a54d4a4804a5045768ce54827b7188fd
BLAKE2b-256 09bbacc1b34ec6e70ec09dce5bd6ec9f71702f6d742be71b99c8c709aaa068c7

See more details on using hashes here.

File details

Details for the file bkash_pgw_tokenized-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for bkash_pgw_tokenized-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b0c7701ee72f945e674df7d953a1244e6406de67fbc7e4dace1e2d2302106da8
MD5 8b4191e1afddc7f731376a8790d91064
BLAKE2b-256 fb1c214ecd5a8999523e621ef6fa94c1b9573ab6185fcc792d485b6c8f185431

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page