Bayarcash Payment Gateway Python SDK
The Bayarcash SDK provides an expressive interface for interacting with Bayarcash's Payment Gateway API. It supports both API v2 (default) and v3, with additional query features available in v3. This is a feature-parity Python port of the official Bayarcash PHP SDK.
Table of Contents
- Requirements
- Installation
- Getting Started
- Quick Start: Accept a Payment
- Payment Channels
- Creating a Payment Intent
- Handling Callbacks
- Payment & Transaction Status
- Transactions
- FPX Direct Debit
- Manual Bank Transfer
- Portals & FPX Banks
- Error Handling
- Response Objects
- Security Recommendations
- Support
Requirements
- Python 3.8+
requests
Installation
Install from PyPI:
pip install bayarcash
You will need two credentials from your Bayarcash console:
- API token — used to authenticate SDK requests.
- API secret key — used to generate request checksums and verify callbacks.
Getting Started
from bayarcash import Bayarcash
bayarcash = Bayarcash("YOUR_API_TOKEN", secret_key="YOUR_API_SECRET_KEY")
bayarcash.use_sandbox() # remove this line in production
The constructor accepts optional keyword arguments:
bayarcash = Bayarcash(
"YOUR_API_TOKEN",
secret_key="YOUR_API_SECRET_KEY",
sandbox=True, # default False
api_version="v3", # "v2" (default) or "v3"
timeout=60, # request timeout in seconds (default 30)
)
Configuration
The same settings are available as chainable setters:
(bayarcash
.use_sandbox() # switch to the sandbox environment
.set_api_version("v3") # "v2" (default) or "v3"
.set_timeout(60)) # request timeout in seconds (default 30)
bayarcash.get_api_version() # read back the current version
Call
use_sandbox()/set_api_version()before making requests. Omituse_sandbox()in production to hit the live gateway.
When you construct the client with a secret_key, checksum and callback methods
can be called with None as the secret argument and will use the stored key.
Quick Start: Accept a Payment
A complete FPX payment flow, from creating the payment to redirecting the payer:
from bayarcash import Bayarcash
bayarcash = Bayarcash("YOUR_API_TOKEN", secret_key="YOUR_API_SECRET_KEY")
bayarcash.use_sandbox()
# 1. Build the payment request
data = {
"portal_key": "your_portal_key",
"payment_channel": Bayarcash.FPX,
"order_number": "INV-1001",
"amount": "10.00",
"payer_name": "Ahmad bin Abdullah",
"payer_email": "ahmad@example.com",
"payer_telephone_number": "0123456789",
"return_url": "https://your-site.com/payment/return",
"callback_url": "https://your-site.com/payment/callback",
}
# 2. Sign it (recommended). Pass None to use the client's stored secret_key.
data["checksum"] = bayarcash.create_payment_intent_checksum_value(None, data)
# 3. Create the payment intent and redirect the payer to Bayarcash
payment_intent = bayarcash.create_payment_intent(data)
# e.g. in a web framework: redirect(payment_intent.url)
print(payment_intent.url)
After payment, Bayarcash calls your callback_url (server-to-server) and
redirects the payer to your return_url. Verify both — see
Handling Callbacks.
Payment Channels
Pass one of these constants (or a list of them) as payment_channel:
Bayarcash.FPX # FPX Online Banking
Bayarcash.MANUAL_TRANSFER # Manual Bank Transfer
Bayarcash.FPX_DIRECT_DEBIT # FPX Direct Debit
Bayarcash.FPX_LINE_OF_CREDIT # FPX Line of Credit
Bayarcash.DUITNOW_DOBW # DuitNow Online Banking
Bayarcash.DUITNOW_QR # DuitNow QR
Bayarcash.SPAYLATER # ShopeePayLater
Bayarcash.BOOST_PAYFLEX # Boost PayFlex
Bayarcash.QRISOB # QRIS Online Banking
Bayarcash.QRISWALLET # QRIS Wallet
Bayarcash.NETS # NETS
Bayarcash.CREDIT_CARD # Credit Card
Bayarcash.ALIPAY # Alipay
Bayarcash.WECHATPAY # WeChat Pay
Bayarcash.PROMPTPAY # PromptPay
Bayarcash.TOUCH_N_GO # Touch 'n Go eWallet
Bayarcash.BOOST_WALLET # Boost Wallet
Bayarcash.GRABPAY # GrabPay
Bayarcash.GRABPL # Grab PayLater
Bayarcash.SHOPEE_PAY # ShopeePay
A PaymentChannel IntEnum is also available: from bayarcash import PaymentChannel.
Creating a Payment Intent
payment_intent = bayarcash.create_payment_intent(data)
Request fields:
| Field | Required | Description |
|---|---|---|
portal_key |
✅ | Your portal key. |
order_number |
✅ | Your reference. Max 30 chars. |
amount |
✅ | String with up to 2 decimals, e.g. "10.00". Range 1.00–30000.00 (min differs for some channels). |
payer_name |
✅ | Max 150 chars. |
payer_email |
✅ | Valid email, max 250 chars. |
payment_channel |
➖ | A Bayarcash.* channel id, or a list of ids. If omitted, the payer chooses on the Bayarcash page. |
payer_telephone_number |
➖ | Required for e-wallet / DuitNow channels. Max 20 chars. |
return_url |
➖ | Where the payer's browser is redirected after payment. |
callback_url |
➖ | Server-to-server notification URL. |
metadata |
➖ | Any extra data you want echoed back. |
checksum |
➖ | Recommended. See below. |
Checksum
The checksum protects the request from tampering. Generate it after building
the request and append it as checksum:
data["checksum"] = bayarcash.create_payment_intent_checksum_value(secret_key, data)
The checksum is computed from payment_channel, order_number, amount,
payer_name, and payer_email.
Handling Callbacks
Bayarcash sends two kinds of notification. Always verify them with your API secret key before trusting the data.
| Notification | How it arrives | Read it from |
|---|---|---|
callback_url (transaction) |
Server-to-server POST (form-encoded) | request form body |
return_url (payer redirect) |
Browser redirect — POST on v2, GET query on v3 | request form/query |
callback_data = dict(request.form) # framework-specific; a plain dict
# Transaction callback (sent to your callback_url)
if bayarcash.verify_transaction_callback_data(callback_data, secret_key):
... # Data is authentic — safe to process.
# Payer redirect (sent to your return_url)
if bayarcash.verify_return_url_callback_data(callback_data, secret_key):
...
# Pre-transaction callback (sent before the transaction record)
if bayarcash.verify_pre_transaction_callback_data(callback_data, secret_key):
...
Each verifier returns True only when the checksum matches. See
FPX Direct Debit for mandate-specific callback verifiers.
The verifiers can also be imported as standalone functions from
bayarcash if you prefer not to instantiate a client.
Payment & Transaction Status
Transaction status is an integer code. Use the Fpx helper instead of
hardcoding numbers:
from bayarcash import Fpx
Fpx.STATUS_NEW # 0
Fpx.STATUS_PENDING # 1
Fpx.STATUS_FAILED # 2
Fpx.STATUS_SUCCESS # 3
Fpx.STATUS_CANCELLED # 4
if int(callback_data["status"]) == Fpx.STATUS_SUCCESS:
... # Payment successful
print(Fpx.get_status_text(int(callback_data["status"]))) # e.g. "Successful"
Dobw (DuitNow) exposes the same status helpers: from bayarcash import Dobw.
Transactions
# Get a single transaction (v2 and v3)
transaction = bayarcash.get_transaction("transaction_id")
The following query helpers require API v3 and raise BayarcashError on v2:
bayarcash.set_api_version("v3")
result = bayarcash.get_all_transactions({
"order_number": "INV-1001",
"status": "3",
"payment_channel": Bayarcash.FPX,
"exchange_reference_number": "REF123",
"payer_email": "ahmad@example.com",
})
# result["data"] => list[TransactionResource], result["meta"] => pagination meta
by_order = bayarcash.get_transaction_by_order_number("INV-1001")
by_email = bayarcash.get_transactions_by_payer_email("ahmad@example.com")
by_status = bayarcash.get_transactions_by_status("3")
by_channel = bayarcash.get_transactions_by_payment_channel(Bayarcash.FPX)
by_ref = bayarcash.get_transaction_by_reference_number("REF123") # single or None
# Get a payment intent by id (v3 only)
intent = bayarcash.get_payment_intent("payment_intent_id")
# Cancel a payment intent (v3 only)
bayarcash.cancel_payment_intent("payment_intent_id")
FPX Direct Debit
FPX Direct Debit lets you set up a recurring mandate and later maintain or
terminate it. Constants live on the FpxDirectDebit class:
from bayarcash import FpxDirectDebit
# Payer ID type
FpxDirectDebit.NRIC # 1 (New IC)
FpxDirectDebit.OLD_IC # 2
FpxDirectDebit.PASSPORT # 3
FpxDirectDebit.BUSINESS_REGISTRATION # 4
FpxDirectDebit.OTHERS # 5
# Frequency mode
FpxDirectDebit.MODE_DAILY # "DL"
FpxDirectDebit.MODE_WEEKLY # "WK"
FpxDirectDebit.MODE_MONTHLY # "MT"
FpxDirectDebit.MODE_YEARLY # "YR"
1. Enrolment
data = {
"portal_key": "your_portal_key",
"order_number": "DD-1001",
"amount": "10.00", # range 5.00–30000.00
"payer_name": "Ahmad bin Abdullah",
"payer_id_type": FpxDirectDebit.NRIC,
"payer_id": "900101011234",
"payer_email": "ahmad@example.com", # max 27 chars
"payer_telephone_number": "0123456789",
"application_reason": "Monthly subscription",
"frequency_mode": FpxDirectDebit.MODE_MONTHLY,
"effective_date": "2026-08-01", # optional, YYYY-MM-DD
"expiry_date": "2027-08-01", # optional, YYYY-MM-DD
"return_url": "https://your-site.com/mandate/return",
}
data["checksum"] = bayarcash.create_fpx_direct_debit_enrolment_checksum_value(secret_key, data)
mandate = bayarcash.create_fpx_direct_debit_enrollment(data)
# redirect the payer to mandate.url
2. Maintenance
Update an existing mandate (identified by its mandate id):
data = {
"amount": "15.00",
"payer_email": "ahmad@example.com",
"payer_telephone_number": "0123456789",
"application_reason": "Update amount",
"frequency_mode": FpxDirectDebit.MODE_MONTHLY,
}
data["checksum"] = bayarcash.create_fpx_direct_debit_maintenance_checksum_value(secret_key, data)
mandate = bayarcash.create_fpx_direct_debit_maintenance(mandate_id, data)
# redirect the payer to mandate.url
3. Termination
mandate = bayarcash.create_fpx_direct_debit_termination(mandate_id, {
"application_reason": "Customer cancelled",
})
# redirect the payer to mandate.url
Retrieving mandates & verifying mandate callbacks
mandate = bayarcash.get_fpx_direct_debit(mandate_id)
transaction = bayarcash.get_fpx_direct_debit_transaction(transaction_id)
# Mandate callback verifiers
bayarcash.verify_direct_debit_bank_approval_callback_data(callback_data, secret_key)
bayarcash.verify_direct_debit_authorization_callback_data(callback_data, secret_key)
bayarcash.verify_direct_debit_transaction_callback_data(callback_data, secret_key)
Manual Bank Transfer
Submit a manual (offline) bank transfer with proof of payment:
response = bayarcash.create_manual_bank_transfer({
"portal_key": "your_portal_key",
"payment_gateway": Bayarcash.MANUAL_TRANSFER, # must be 2
"order_no": "MT-1001",
"buyer_name": "Ahmad bin Abdullah",
"buyer_email": "ahmad@example.com",
"buyer_tel_no": "0123456789", # optional
"order_amount": "10.00",
"merchant_bank_name": "Maybank",
"merchant_bank_account": "1234567890",
"merchant_bank_account_holder": "Your Company Sdn Bhd",
"bank_transfer_type": "Internet Banking", # or "Cash Deposit Machine (CDM)"
"bank_transfer_notes": "Payment for order MT-1001",
"bank_transfer_date": "2026-07-22", # optional, defaults to today
"proof_of_payment": "/path/to/receipt.jpg", # jpeg/png/gif/pdf, max 10 MB
})
Update the status of an existing transfer:
from bayarcash import Fpx
bayarcash.update_manual_bank_transfer_status(
"ref_no_here",
str(Fpx.STATUS_SUCCESS),
"10.00",
)
Portals & FPX Banks
# All portals for your account
portals = bayarcash.get_portals()
# Payment channels available for a portal
channels = bayarcash.get_channels("your_portal_key")
# FPX banks (for building a bank selector)
banks = bayarcash.fpx_banks_list()
Error Handling
Failed API calls raise typed exceptions. Catch them to handle errors gracefully:
from bayarcash import (
ValidationError,
FailedActionError,
NotFoundError,
RateLimitError,
APIError,
BayarcashError,
)
try:
payment_intent = bayarcash.create_payment_intent(data)
except ValidationError as e:
errors = e.errors # 422 — invalid request data
except NotFoundError:
... # 404 — resource not found
except RateLimitError as e:
reset_at = e.rate_limit_resets_at # 429 — unix timestamp or None
except FailedActionError as e:
message = str(e) # 400 — request failed
except APIError as e:
status = e.status_code # any other non-2xx (e.g. 500)
Every exception subclasses BayarcashError, so except BayarcashError catches
them all.
| Exception | HTTP | Meaning |
|---|---|---|
ValidationError |
422 | Invalid data. Read .errors for details. |
FailedActionError |
400 | Request failed. str(e) has the reason. |
NotFoundError |
404 | Resource not found. |
RateLimitError |
429 | Rate limited. .rate_limit_resets_at holds the reset time. |
APIError |
other | Any other non-2xx status. .status_code holds the code. |
Response Objects
API methods return typed resource objects with snake_case attributes. Any
missing field reads back as None.
PaymentIntentResource (from create_payment_intent / get_payment_intent)
payment_intent.url # checkout URL to redirect the payer to
payment_intent.id
payment_intent.status
payment_intent.amount
payment_intent.order_number
payment_intent.payer_name
payment_intent.payer_email
TransactionResource (from get_transaction / transaction queries)
transaction.id
transaction.status # int status code — see Fpx constants
transaction.status_description
transaction.amount
transaction.order_number
transaction.exchange_reference_number
transaction.payer_name
transaction.payer_email
Convert a resource (including nested resources) to a dict:
transaction.to_dict()
Security Recommendations
- Always send a
checksumwith payment and mandate requests. - Verify every callback with the provided verification methods before acting on it.
- Store and check transaction ids to prevent duplicate processing.
- Use HTTPS for your
return_urlandcallback_url. - Keep your API token and secret key out of source control.
API Documentation
For full API details, see the Official Bayarcash API Documentation.
Support
For support questions, contact Bayarcash support or open an issue in this repository.
Changelog
See CHANGELOG.md for the version history.
License
Open-sourced software licensed under the MIT license.
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 bayarcash-1.0.0.tar.gz.
File metadata
- Download URL: bayarcash-1.0.0.tar.gz
- Upload date:
- Size: 25.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5317fbb2406618f0606997f6801dd53372bddb16f4faecb688842dab16f59b88
|
|
| MD5 |
41a5559a47451c043fbeaee71b0ac9a5
|
|
| BLAKE2b-256 |
0ad533f8019db8f24ed06cd3461ecd57baa7fc30193e919a71ede27fdd45f3f7
|
Provenance
The following attestation bundles were made for bayarcash-1.0.0.tar.gz:
Publisher:
publish.yml on bayarcash/python-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bayarcash-1.0.0.tar.gz -
Subject digest:
5317fbb2406618f0606997f6801dd53372bddb16f4faecb688842dab16f59b88 - Sigstore transparency entry: 2215548046
- Sigstore integration time:
-
Permalink:
bayarcash/python-sdk@fbfe95c8138ea9ba80a900cd5f6ad2706964665f -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/bayarcash
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@fbfe95c8138ea9ba80a900cd5f6ad2706964665f -
Trigger Event:
push
-
Statement type:
File details
Details for the file bayarcash-1.0.0-py3-none-any.whl.
File metadata
- Download URL: bayarcash-1.0.0-py3-none-any.whl
- Upload date:
- Size: 22.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
219cc2d466c8558d97f70dc8c11ea8443f3c8a209063108329af529e99b9f6d8
|
|
| MD5 |
8adf7f0c8702f3bce6cc590e0546d4e7
|
|
| BLAKE2b-256 |
0e892517d67d18252457531e1aedf4f012527df326aabb75f9d6515ebf367e5e
|
Provenance
The following attestation bundles were made for bayarcash-1.0.0-py3-none-any.whl:
Publisher:
publish.yml on bayarcash/python-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bayarcash-1.0.0-py3-none-any.whl -
Subject digest:
219cc2d466c8558d97f70dc8c11ea8443f3c8a209063108329af529e99b9f6d8 - Sigstore transparency entry: 2215548057
- Sigstore integration time:
-
Permalink:
bayarcash/python-sdk@fbfe95c8138ea9ba80a900cd5f6ad2706964665f -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/bayarcash
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@fbfe95c8138ea9ba80a900cd5f6ad2706964665f -
Trigger Event:
push
-
Statement type: