Created
February 2, 2026 07:35
-
-
Save Pushkraj19/ba6c9bc8a77ae780db015bd56148654c to your computer and use it in GitHub Desktop.
PayU Hash Generator Utility PHP Class
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| namespace App\Services\Gateways\PayU; | |
| /** | |
| * PayU Hash Generator Utility Class | |
| * | |
| * Handles all hash generation and validation scenarios for PayU payment gateway. | |
| * | |
| * @see https://docs.payu.in/docs/generate-hash-merchant-hosted | |
| * @see https://docs.payu.in/docs/api-authentication-and-security | |
| */ | |
| class PayUHashGenerator | |
| { | |
| // Hash sequence constants | |
| public const PAYMENT_HASH_SEQUENCE = 'key|txnid|amount|productinfo|firstname|email|udf1|udf2|udf3|udf4|udf5|udf6|udf7|udf8|udf9|udf10'; | |
| public const UDF_COUNT = 5; | |
| // API command constants | |
| public const CMD_VERIFY_PAYMENT = 'verify_payment'; | |
| public const CMD_CANCEL_REFUND = 'cancel_refund_transaction'; | |
| public const CMD_CHECK_OFFER_STATUS = 'check_offer_status'; | |
| public const CMD_GET_TRANSACTION_DETAILS = 'get_transaction_details'; | |
| public const CMD_GET_EMI_AMOUNT = 'get_emi_amount_according_to_interest'; | |
| public const CMD_CAPTURE_TRANSACTION = 'capture_transaction'; | |
| public const CMD_CHECK_ACTION_STATUS = 'check_action_status'; | |
| public const CMD_GET_TDR = 'get_TDR'; | |
| public const CMD_PAYMENT_DETAILS_SDK = 'payment_related_details_for_mobile_sdk'; | |
| /** | |
| * Generate hash for payment transaction request. | |
| * | |
| * Formula: sha512(key|txnid|amount|productinfo|firstname|email|udf1|...|udf10||||||salt) | |
| * | |
| * @param array $params Transaction parameters | |
| * @param string $salt Merchant salt | |
| * @return string Generated hash (lowercase) | |
| */ | |
| public static function generatePaymentHash(array $params, string $salt): string | |
| { | |
| $hashString = self::buildPaymentHashString($params, $salt); | |
| return self::computeHash($hashString); | |
| } | |
| /** | |
| * Validate response hash from PayU callback (reverse hash). | |
| * | |
| * Formula: sha512([additionalCharges|]salt|status||||||udf10|...|udf1|email|firstname|productinfo|amount|txnid|key) | |
| * | |
| * @param array $responseParams Response parameters from PayU | |
| * @param string $salt Merchant salt | |
| * @return bool True if hash is valid, false otherwise | |
| */ | |
| public static function validateResponseHash(array $responseParams, string $salt): bool | |
| { | |
| if (empty($responseParams['hash'])) { | |
| return false; | |
| } | |
| $hashString = self::buildResponseHashString($responseParams, $salt); | |
| $computedHash = self::computeHash($hashString); | |
| // Use constant-time comparison to prevent timing attacks | |
| return hash_equals($computedHash, strtolower($responseParams['hash'])); | |
| } | |
| /** | |
| * Generate hash for PayU API operations. | |
| * | |
| * Formula: sha512(key|command|var1|salt) | |
| * | |
| * @param string $command API command name | |
| * @param string $var1 Variable parameter (differs by command) | |
| * @param string $key Merchant key | |
| * @param string $salt Merchant salt | |
| * @return string Generated hash (lowercase) | |
| */ | |
| public static function generateApiHash(string $command, string $var1, string $key, string $salt): string | |
| { | |
| $hashString = "{$key}|{$command}|{$var1}|{$salt}"; | |
| return self::computeHash($hashString); | |
| } | |
| /** | |
| * Build hash string for payment request. | |
| * | |
| * @param array $params Transaction parameters | |
| * @param string $salt Merchant salt | |
| * @return string Hash string ready for hashing | |
| */ | |
| private static function buildPaymentHashString(array $params, string $salt): string | |
| { | |
| $hashString = self::getSafeValue($params, 'key').'|'; | |
| $hashString .= self::getSafeValue($params, 'txnid').'|'; | |
| $hashString .= self::getSafeValue($params, 'amount').'|'; | |
| $hashString .= self::getSafeValue($params, 'productinfo').'|'; | |
| $hashString .= self::getSafeValue($params, 'firstname').'|'; | |
| $hashString .= self::getSafeValue($params, 'email').'|'; | |
| // UDF fields 1-10 | |
| for ($i = 1; $i <= self::UDF_COUNT; $i++) { | |
| $hashString .= self::getSafeValue($params, "udf{$i}").'|'; | |
| } | |
| // 6 empty pipes for reserved fields (required by PayU) | |
| $hashString .= '|||||'; | |
| $hashString .= $salt; | |
| return $hashString; | |
| } | |
| /** | |
| * Build reverse hash string for response validation. | |
| * | |
| * @param array $params Response parameters | |
| * @param string $salt Merchant salt | |
| * @return string Hash string ready for hashing | |
| */ | |
| private static function buildResponseHashString(array $params, string $salt): string | |
| { | |
| $hashString = ''; | |
| // Check for additional charges (may be named differently) | |
| $additionalCharges = self::getSafeValue($params, 'additionalCharges') | |
| ?: self::getSafeValue($params, 'additional_charges'); | |
| if (! empty($additionalCharges)) { | |
| $hashString .= $additionalCharges.'|'; | |
| } | |
| $hashString .= $salt.'|'; | |
| $hashString .= self::getSafeValue($params, 'status').'|'; | |
| // 6 empty pipes for reserved fields (required by PayU) | |
| $hashString .= '|||||'; | |
| // UDF fields in reverse order: udf10 to udf1 | |
| for ($i = self::UDF_COUNT; $i >= 1; $i--) { | |
| $hashString .= self::getSafeValue($params, "udf{$i}").'|'; | |
| } | |
| $hashString .= self::getSafeValue($params, 'email').'|'; | |
| $hashString .= self::getSafeValue($params, 'firstname').'|'; | |
| $hashString .= self::getSafeValue($params, 'productinfo').'|'; | |
| $hashString .= self::getSafeValue($params, 'amount').'|'; | |
| $hashString .= self::getSafeValue($params, 'txnid').'|'; | |
| $hashString .= self::getSafeValue($params, 'key'); | |
| return $hashString; | |
| } | |
| /** | |
| * Compute SHA-512 hash from a string. | |
| * | |
| * @param string $hashString String to hash | |
| * @return string Lowercase SHA-512 hash | |
| */ | |
| private static function computeHash(string $hashString): string | |
| { | |
| return strtolower(hash('sha512', $hashString)); | |
| } | |
| /** | |
| * Get safe value (empty string if null/missing). | |
| * | |
| * @param array $params Parameters array | |
| * @param string $key Parameter key | |
| * @return string Parameter value or empty string | |
| */ | |
| private static function getSafeValue(array $params, string $key): string | |
| { | |
| return isset($params[$key]) ? (string) $params[$key] : ''; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment