UPI QR Python Version 3.0.0
Python package to generate UPI payment QR codes with specified amounts, automatic transaction splitting (splitTransactionQR), runtime schema validation, and precision paise arithmetic.
What's New in v3.0.0
- ✂️ Transaction Splitting (
splitTransactionQR): Automatically breaks transactions above ₹2,000 into ₹1,999 intervals (e.g., ₹5,000 becomes ₹1,999 + ₹1,999 + ₹1,002). - 🛡️ Pydantic Validation: Robust runtime schema validation equivalent to Zod, checking UPI IDs, transaction boundaries, and parameters.
- 🏷️ Optional Transaction Metadata: Support for payee name (
name), transaction note (note), and currency (currency, defaults toINR). - ⚡ Precision Math: Uses paise-level integer arithmetic (
round(amount * 100)) to prevent floating-point rounding errors. - 📦 Dual Import & Flexible Signatures: Full support for keyword arguments, dictionary payloads, Pydantic models, and positional parameters.
Installation
pip install omkarbhosale-upi-qr
1. splitTransactionQR(params)
Splits large transactions exceeding a threshold (default ₹2,000) into ₹1,999 intervals and generates a QR code for each chunk concurrently.
Why Split at ₹1,999?
Under NPCI guidelines, transactions $\le$ ₹2,000 often bypass merchant interchange fees on PPI wallets and qualify for streamlined processing. Splitting larger payments into ₹1,999 chunks ensures each transaction remains under the ₹2,000 threshold.
Parameters (SplitQRParams)
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
UPI_ID |
str |
Yes | — | Valid UPI ID (e.g., merchant@okhdfcbank, user@upi). |
AMOUNT |
float |
Yes | — | Total transaction amount (positive number up to ₹10,00,000). |
splitInterval |
float |
No | 1999 |
Maximum amount per split chunk. |
threshold |
float |
No | 2000 |
Amount above which splitting is triggered. If AMOUNT <= threshold, only 1 QR is generated. |
name |
str |
No | None |
Payee name (pn). |
note |
str |
No | None |
Transaction note (tn). Each chunk automatically appends (Part X/Y). |
currency |
str |
No | "INR" |
Currency code. |
Return Value (List[SplitQRItem])
A list of SplitQRItem objects (which support both attribute access and dictionary indexing):
| Property | Type | Description |
|---|---|---|
id |
str |
Unique UUID (v4) for this specific split QR. |
amount |
int | float |
The split portion amount. |
image |
str |
Base64-encoded Data URL of the generated QR code (data:image/png;base64,...). |
Code Examples
Basic Split (₹5,000)
from omkarbhosale_upi_qr import splitTransactionQR
splits = splitTransactionQR({
"UPI_ID": "store@upi",
"AMOUNT": 5000,
"name": "Omkar Store",
"note": "Order #12345"
})
for item in splits:
print(f"ID: {item.id} | Amount: Rs. {item.amount}")
print(f"QR Data URL: {item.image[:40]}...\n")
Output:
[
{
"id": "4a236fad-ebc5-471f-86ab-86a4f9e621e7",
"amount": 1999,
"image": "data:image/png;base64,iVBORw0KGgo..."
},
{
"id": "c19ba6ae-664a-47d7-9948-bf3558fefb6d",
"amount": 1999,
"image": "data:image/png;base64,iVBORw0KGgo..."
},
{
"id": "3c44b4ad-44e7-414f-86c4-60ae9f228ec6",
"amount": 1002,
"image": "data:image/png;base64,iVBORw0KGgo..."
}
]
Custom Split Interval & Threshold
splits = splitTransactionQR(
UPI_ID="store@upi",
AMOUNT=1000,
threshold=500, # Split anything above ₹500
splitInterval=400, # Chunk in ₹400 intervals
name="Omkar Store",
note="Order #12345"
)
# Returns 3 QRs: ₹400 + ₹400 + ₹200
Amounts Within Threshold ($\le$ ₹2,000)
splits = splitTransactionQR(UPI_ID="store@upi", AMOUNT=1500)
# Returns 1 QR: [SplitQRItem(id="...", amount=1500, image="data:image/png;base64,...")]
2. generateQR(params)
Generates a single UPI QR code as a base64 Data URL.
Parameters (QRParams)
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
UPI_ID |
str |
Yes | — | Valid UPI ID handle. |
AMOUNT |
float |
Yes | — | Amount to receive (positive number $\le$ ₹1,00,000). |
name |
str |
No | None |
Payee Name (pn). |
note |
str |
No | None |
Transaction note (tn). |
currency |
str |
No | "INR" |
Currency code. |
Example
from omkarbhosale_upi_qr import generateQR
qr_data_url = generateQR(
UPI_ID="omkar@upi",
AMOUNT=750,
name="Omkar Bhosale",
note="Coffee bill"
)
print(qr_data_url) # data:image/png;base64,iVBORw0KGgo...
3. Schema Pre-validation
Exported schemas provide runtime validation with .safeParse(...) and .parse(...) methods directly mirroring Zod:
from omkarbhosale_upi_qr import upiIdSchema
# Validate a UPI ID directly
result = upiIdSchema.safeParse("invalid-upi")
if not result.success:
print(result.error.issues[0].message)
# "Invalid UPI ID format. Expected format: username@bank"
Exported Schemas & Models
upiIdSchema/UPIIdSchemaqrParamsSchema/QRParamssplitQRParamsSchema/SplitQRParamssplitQRItemSchema/SplitQRItem
Validation Rules
- UPI ID: Matches regex
^[\w.-]+@[\w.-]+$, 3 to 50 characters, trimmed of whitespace. - Single QR Amount: Positive finite number $\le$ ₹1,00,000.
- Split QR Amount: Positive finite number $\le$ ₹10,00,000.
- Error Handling: Raises
UPIValidationError(inherits fromValueError) with format:Validation error: field: message.
4. Import Compatibility
omkarbhosale_upi_qr supports named imports, pythonic snake_case aliases, and callable default style:
# Named imports
from omkarbhosale_upi_qr import generateQR, splitTransactionQR
# Callable default object (JS-style parity)
from omkarbhosale_upi_qr import upiqr
single = upiqr(UPI_ID="user@upi", AMOUNT=500)
splits = upiqr.splitTransactionQR(UPI_ID="user@upi", AMOUNT=5000)
License
MIT License.
Release files for omkarbhosale-upi-qr 3.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| omkarbhosale_upi_qr-3.0.0.tar.gz | 13.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| omkarbhosale_upi_qr-3.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 22.9 kB
Release files / omkarbhosale_upi_qr-3.0.0.tar.gz
| Download URL | omkarbhosale_upi_qr-3.0.0.tar.gz |
|---|---|
| Size | 13.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
295011a770d3159a92b7327ec2729c18ce9b5cead791f591e4b6970eab5b566a
|
|
BLAKE2b-256 checksum How to use checksums |
693d376dee70931a9f95a656f075db5c44e4ae4b153d5f1492b0277db06b5105
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.0
|
Release files / omkarbhosale_upi_qr-3.0.0-py3-none-any.whl
| Download URL | omkarbhosale_upi_qr-3.0.0-py3-none-any.whl |
|---|---|
| Size | 9.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
74e463b0b5bb5f96f022a4d09bd2751fcd4ce6d2fd0d3ad9c692be9bfbaac8b0
|
|
BLAKE2b-256 checksum How to use checksums |
09005e1731c8b61beaef7a02c130ec7730663815ff2c3b4b5451699ab363917f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.0
|