Skip to main content

Encryption

Implement end-to-end encryption for Paywize API requests using AES-256-CBC.

Last updated: 2026-02-21

Encryption and Decryption

Overview

All Paywize APIs use AES-256-CBC encryption to secure sensitive data transmission. This guide provides implementation details for encrypting request data and decrypting response data across all Paywize products.

Quick Reference

AttributeDetails
Encryption AlgorithmAES-256-CBC
Key SourceAPI Key (32 characters)
IV SourceSecret Key (16 characters)
EncodingBase64 after encryption
Data FormatJSON before encryption
Security LevelEnterprise-grade

Encryption Process

Step-by-Step Encryption

  1. Prepare Data: Convert JSON object to string format
  2. AES-256-CBC Encryption: Encrypt using your API Key as encryption key
  3. Initialization Vector: Use your Secret Key as the IV
  4. Base64 Encoding: Encode encrypted data for safe transmission

Implementation

JavaScript

import crypto from 'crypto';

// Encrypt merchant data
export function encryptMerchantData(data, key, iv) {
  if (typeof data === 'object') {
    data = JSON.stringify(data);
  }

  const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
  const encrypted = Buffer.concat([cipher.update(data, 'utf8'), cipher.final()]);
  return encrypted.toString('base64');
}

// Decrypt merchant data
export function decryptMerchantData(data, key, iv) {
  const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
  const decrypted = Buffer.concat([
    decipher.update(Buffer.from(data, 'base64')),
    decipher.final()
  ]);
  return decrypted.toString('utf8');
}

// Example usage
const apiKey = 'your_32_char_api_key_here_123456';
const secretKey = 'your_16_char_iv_12';

// Encrypt request data
const requestData = {
  senderId: "TXN123456",
  txnType: "INTENT",
  requestAmount: "100.50"
};

const encryptedPayload = encryptMerchantData(requestData, apiKey, secretKey);
console.log('Encrypted:', encryptedPayload);

// Decrypt response data
const decryptedResponse = decryptMerchantData(encryptedPayload, apiKey, secretKey);
console.log('Decrypted:', JSON.parse(decryptedResponse));

Python

import json
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad

def encrypt_merchant_data(data, key, iv):
    """
    Encrypt data using AES-256-CBC

    Args:
        data: Data to encrypt (string or dict)
        key: 32-byte encryption key
        iv: 16-byte initialization vector

    Returns:
        Base64 encoded encrypted string
    """
    if isinstance(data, dict):
        data = json.dumps(data)

    # Convert strings to bytes
    key_bytes = key.encode('utf-8')
    iv_bytes = iv.encode('utf-8')
    data_bytes = data.encode('utf-8')

    # Create cipher and encrypt
    cipher = AES.new(key_bytes, AES.MODE_CBC, iv_bytes)
    padded_data = pad(data_bytes, AES.block_size)
    encrypted = cipher.encrypt(padded_data)

    # Return base64 encoded result
    return base64.b64encode(encrypted).decode('utf-8')

def decrypt_merchant_data(encrypted_data, key, iv):
    """
    Decrypt data using AES-256-CBC

    Args:
        encrypted_data: Base64 encoded encrypted string
        key: 32-byte encryption key
        iv: 16-byte initialization vector

    Returns:
        Decrypted string
    """
    # Convert strings to bytes
    key_bytes = key.encode('utf-8')
    iv_bytes = iv.encode('utf-8')

    # Decode base64 and decrypt
    encrypted_bytes = base64.b64decode(encrypted_data)
    cipher = AES.new(key_bytes, AES.MODE_CBC, iv_bytes)
    decrypted_padded = cipher.decrypt(encrypted_bytes)
    decrypted = unpad(decrypted_padded, AES.block_size)

    return decrypted.decode('utf-8')

# Example usage
api_key = 'your_32_char_api_key_here_123456'
secret_key = 'your_16_char_iv_12'

# Encrypt request data
request_data = {
    "senderId": "TXN123456",
    "txnType": "INTENT",
    "requestAmount": "100.50"
}

encrypted_payload = encrypt_merchant_data(request_data, api_key, secret_key)
print(f"Encrypted: {encrypted_payload}")

# Decrypt response data
decrypted_response = decrypt_merchant_data(encrypted_payload, api_key, secret_key)
print(f"Decrypted: {json.loads(decrypted_response)}")

PHP

<?php

class PaywizeEncryption {

    /**
     * Encrypt data using AES-256-CBC
     */
    public static function encryptMerchantData($data, $key, $iv) {
        if (is_array($data) || is_object($data)) {
            $data = json_encode($data);
        }

        $encrypted = openssl_encrypt(
            $data,
            'AES-256-CBC',
            $key,
            OPENSSL_RAW_DATA,
            $iv
        );

        return base64_encode($encrypted);
    }

    /**
     * Decrypt data using AES-256-CBC
     */
    public static function decryptMerchantData($encryptedData, $key, $iv) {
        $data = base64_decode($encryptedData);

        $decrypted = openssl_decrypt(
            $data,
            'AES-256-CBC',
            $key,
            OPENSSL_RAW_DATA,
            $iv
        );

        return $decrypted;
    }
}

// Example usage
$apiKey = 'your_32_char_api_key_here_123456';
$secretKey = 'your_16_char_iv_12';

// Encrypt request data
$requestData = [
    'senderId' => 'TXN123456',
    'txnType' => 'INTENT',
    'requestAmount' => '100.50'
];

$encryptedPayload = PaywizeEncryption::encryptMerchantData($requestData, $apiKey, $secretKey);
echo "Encrypted: " . $encryptedPayload . "\n";

// Decrypt response data
$decryptedResponse = PaywizeEncryption::decryptMerchantData($encryptedPayload, $apiKey, $secretKey);
echo "Decrypted: " . $decryptedResponse . "\n";

?>

Java

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.nio.charset.StandardCharsets;

public class PaywizeEncryption {

    private static final String ALGORITHM = "AES/CBC/PKCS5Padding";
    private static final String KEY_ALGORITHM = "AES";

    /**
     * Encrypt data using AES-256-CBC
     */
    public static String encryptMerchantData(String data, String key, String iv)
            throws Exception {

        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), KEY_ALGORITHM);
        IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));

        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);

        byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encrypted);
    }

    /**
     * Decrypt data using AES-256-CBC
     */
    public static String decryptMerchantData(String encryptedData, String key, String iv)
            throws Exception {

        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), KEY_ALGORITHM);
        IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));

        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);

        byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encryptedData));
        return new String(decrypted, StandardCharsets.UTF_8);
    }

    // Example usage
    public static void main(String[] args) throws Exception {
        String apiKey = "your_32_char_api_key_here_123456";
        String secretKey = "your_16_char_iv_12";

        // Encrypt request data
        String requestData = "{\"senderId\":\"TXN123456\",\"txnType\":\"INTENT\",\"requestAmount\":\"100.50\"}";
        String encryptedPayload = encryptMerchantData(requestData, apiKey, secretKey);
        System.out.println("Encrypted: " + encryptedPayload);

        // Decrypt response data
        String decryptedResponse = decryptMerchantData(encryptedPayload, apiKey, secretKey);
        System.out.println("Decrypted: " + decryptedResponse);
    }
}

Key Requirements

API Key (Encryption Key)

  • Length: 32 characters (256 bits)
  • Usage: Used as the AES encryption key
  • Security: Keep this confidential and never expose in client-side code

Secret Key (Initialization Vector)

  • Length: 16 characters (128 bits)
  • Usage: Used as the Initialization Vector (IV) for CBC mode
  • Security: Keep this confidential and never expose in client-side code

Request/Response Flow

1. Encrypting Request Data

// Original request data
const requestData = {
  senderId: "TXN123456",
  txnType: "INTENT",
  requestAmount: "100.50"
};

// Encrypt the data
const encryptedPayload = encryptMerchantData(requestData, apiKey, secretKey);

// Send encrypted payload
const apiRequest = {
  payload: encryptedPayload
};

2. Decrypting Response Data

// API response contains encrypted data
const apiResponse = {
  respCode: 2000,
  respMessage: "Success",
  data: "encrypted_base64_string_here"
};

// Decrypt the response data
const decryptedData = decryptMerchantData(apiResponse.data, apiKey, secretKey);
const responseData = JSON.parse(decryptedData);

Error Handling

Common Encryption Errors

Error CodeMessageSolution
4014Decryption failed. Please check the encryptionVerify API Key and Secret Key are correct
4001Invalid request formatEnsure data is properly encrypted and Base64 encoded

Debugging Tips

  1. Verify Key Lengths: Ensure API Key is 32 characters and Secret Key is 16 characters
  2. Check Character Encoding: Use UTF-8 encoding for all string operations
  3. Validate Base64: Ensure encrypted data is properly Base64 encoded
  4. Test with Known Values: Use the provided test cases to verify your implementation

Security Best Practices

Critical Security Guidelines

  1. Never Log Sensitive Data: Don't log API keys, secret keys, or decrypted data
  2. Use Environment Variables: Store credentials securely outside your codebase
  3. Validate Input: Always validate data before encryption
  4. Handle Exceptions: Implement proper error handling for encryption/decryption operations
  5. Secure Key Storage: Use secure credential management systems in production
  6. Regular Key Rotation: Rotate your API credentials regularly

Additional Security Measures

  • HTTPS Only: Always use HTTPS for API requests
  • IP Whitelisting: Restrict API access to approved IP addresses
  • Rate Limiting: Implement proper rate limiting to prevent abuse
  • Audit Logging: Log API usage patterns without exposing sensitive data

Testing Your Implementation

Use these test vectors to verify your encryption implementation:

// Test case
const apiKey = 'test_api_key_32_characters_long';
const secretKey = 'test_secret_16ch';
const testData = '{"test": "data"}';

// Expected encrypted result (will vary due to padding)
const encrypted = encryptMerchantData(testData, apiKey, secretKey);
const decrypted = decryptMerchantData(encrypted, apiKey, secretKey);

// Should match original data
console.assert(decrypted === testData, 'Encryption/Decryption test failed');

Next Steps