Encrypted Payment Request
The encrypted variant wraps the entire Payment Request body in AES-256-CBC. The endpoint is the same as the plaintext form — Omniware decides which form you sent based on the presence of encrypted_data + iv.
Use it when there are intermediaries between your server and Omniware (CDNs, reverse proxies, observability layers) that you don't want to see the request body in plaintext.
Endpoint
POST https://pgbiz.omniware.in/v2/paymentrequest
Content-Type: application/x-www-form-urlencoded
Request parameters
api_keystring (40)requiredStays in plaintext so Omniware knows which encryption_key to use.
encrypted_datastring (5000)requiredBase64 of AES-256-CBC ciphertext of the JSON-serialised parameters.
ivstring (30)requiredBase64 of the random 16-byte initialisation vector used for this request.
The plaintext JSON is identical in shape to the regular Payment Request, including the inner hash field:
{
"api_key": "YOUR_API_KEY",
"address_line_1": "Address Line 1",
"address_line_2": "Address Line 2",
"amount": "35.56",
"city": "Bangalore",
"country": "IND",
"currency": "INR",
"description": "Payment Short Description",
"email": "amit@example.com",
"mode": "LIVE",
"name": "Amit",
"order_id": "XYZ419",
"phone": "9900990099",
"return_url": "https://yoursite.com/return.php",
"return_url_failure": "https://yoursite.com/failure.php",
"return_url_cancel": "https://yoursite.com/cancel.php",
"state": "Karnataka",
"udf1": "Users Defined Value",
"udf2": "", "udf3": "", "udf4": "", "udf5": "",
"zip_code": "560001",
"hash": "23CD8F59DB509F55951CE74C9228..."
}
Encrypt + post
- PHP
- Node.js
- Python
function encryptData(string $plain, string $key): array {
$iv = openssl_random_pseudo_bytes(16);
$ct = openssl_encrypt($plain, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
return [base64_encode($ct), base64_encode($iv)];
}
$params["hash"] = generateHashKey($params, $salt);
[$encrypted_data, $iv] = encryptData(json_encode($params), $encryption_key);
// POST to https://pgbiz.omniware.in/v2/paymentrequest with:
// api_key=$params["api_key"]
// encrypted_data=$encrypted_data
// iv=$iv
import crypto from "node:crypto";
function encrypt(plain, key) {
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv("aes-256-cbc", Buffer.from(key), iv);
const ct = Buffer.concat([cipher.update(plain, "utf8"), cipher.final()]);
return { encrypted_data: ct.toString("base64"), iv: iv.toString("base64") };
}
params.hash = generateHash(params, salt);
const { encrypted_data, iv } = encrypt(JSON.stringify(params), encryption_key);
await fetch("https://pgbiz.omniware.in/v2/paymentrequest", {
method: "POST",
body: new URLSearchParams({ api_key: params.api_key, encrypted_data, iv }),
});
import base64, json, os
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
def encrypt(plain: str, key: str):
iv = os.urandom(16)
cipher = AES.new(key.encode(), AES.MODE_CBC, iv)
ct = cipher.encrypt(pad(plain.encode(), AES.block_size))
return base64.b64encode(ct).decode(), base64.b64encode(iv).decode()
params["hash"] = generate_hash(params, SALT)
encrypted_data, iv = encrypt(json.dumps(params), ENCRYPTION_KEY)
requests.post(
"https://pgbiz.omniware.in/v2/paymentrequest",
data={"api_key": params["api_key"], "encrypted_data": encrypted_data, "iv": iv},
)
Sample auto-submit form
<form action="https://pgbiz.omniware.in/v2/paymentrequest" method="post">
<input type="hidden" name="api_key" value="<?= $apiKey ?>">
<input type="hidden" name="encrypted_data" value="<?= $encrypted ?>">
<input type="hidden" name="iv" value="<?= $iv ?>">
</form>
<script>document.forms[0].submit();</script>
Decrypting the response
Omniware encrypts the response in the same way and posts it to your return_url. Decrypt with your decryption_key and the iv Omniware returns.
function decryptData(string $encrypted_data, string $decryption_key, string $iv): string {
return openssl_decrypt(
base64_decode($encrypted_data),
'AES-256-CBC',
$decryption_key,
OPENSSL_RAW_DATA,
base64_decode($iv)
);
}
$plain = decryptData($_POST["encrypted_data"], $decryption_key, $_POST["iv"]);
$response = json_decode($plain, true);
// Verify $response["hash"] before trusting the payload.
The decrypted JSON has the same shape as the plaintext response.
Example decrypted response from the PDF:
{
"transaction_id": "FBEEBN12311231231",
"payment_mode": "NetBanking",
"payment_channel": "Federal Bank",
"payment_datetime": "2018-09-19 16:19:46",
"response_code": 1043,
"response_message": "Transaction cancelled",
"error_desc": "Transaction cancelled",
"order_id": "607",
"amount": "100.81",
"currency": "INR",
"description": "Payment Short Description",
"name": "Amit",
"email": "amit@example.com",
"phone": "9900990099",
"address_line_1": "Address Line 1",
"address_line_2": "Address Line 2",
"city": "Bangalore",
"state": "Karnataka",
"country": "IND",
"zip_code": "560001",
"udf1": null,
"udf2": null,
"udf3": null,
"udf4": null,
"udf5": null,
"hash": "64948C7CA2F8861285A246738FF48347FCAEB81D7EBB0F2D00B6BE661EAC1DADCFD59A0FA878CE8789F0DB9E045FC0943661A9DE4B5984F5D6E32DDEE1BBD4B6"
}
The iv is not secret but must be random per request. Reusing an IV with the same key in CBC mode leaks information about the plaintext.