ClickBank IPN with PHP 7.2 and above

ClickBank’s Instant Notification Service is a webhook that lets you get transaction notifications in real time.

For example, you can use them to inform your membership software when members join/pay/cancel.

ClickBank provides the following sample code for PHP:

<?php
// NOTE: the mcrypt libraries need to be installed and listed as an
// available extension in your phpinfo() to be able to use this
// method of decryption.
 
$secretKey = "YOUR SECRET KEY"; // secret key from your ClickBank account
 
// get JSON from raw body...
$message = json_decode(file_get_contents('php://input'));
 
// Pull out the encrypted notification and the initialization vector for
// AES/CBC/PKCS5Padding decryption
$encrypted = $message->{'notification'};
$iv = $message->{'iv'};
error_log("IV: $iv");
 
// decrypt the body...
$decrypted = trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128,
 substr(sha1($secretKey), 0, 32),
 base64_decode($encrypted),
 MCRYPT_MODE_CBC,
 base64_decode($iv)), "\0..\32");
error_log("Decrypted: $decrypted");
 
////UTF8 Encoding, remove escape back slashes, and convert the decrypted string to a JSON object...
$sanitizedData = utf8_encode(stripslashes($decrypted));
$order = json_decode($decrypted);
 
// Ready to rock and roll - If the decoding of the JSON string wasn't
// successful, then you can assume the notification wasn't encrypted
// with your secret key.
 
?>

The problem is that the mcrypt libraries – required to decrypt the notification – were abandoned back in 2007, and because of this, use of the library has been deprecated in PHP 7.1 and removed from PHP 7.2 entirely.

In other words, the minute your web host upgrades to PHP 7.2 or higher, you’ll find your membership site is totally unable to decode and read ClickBank’s notifications.

The answer is to switch to using the more modern OpenSSL instead.

The problematic part of ClickBank’s sample code is the mcrypt_decrypt() operation here:

// decrypt the body...
$decrypted = trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128,
 substr(sha1($secretKey), 0, 32),
 base64_decode($encrypted),
 MCRYPT_MODE_CBC,
 base64_decode($iv)), "\0..\32");

The OpenSSL equivalent is:

// decrypt the body...
$decrypted = trim(openssl_decrypt(
 base64_decode($encrypted),
 'aes-256-cbc',
 substr(sha1($secretKey), 0, 32),
 OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING,
 base64_decode($iv)), "\0..\32");

Here’s the entire updated code sample:

<?php
// NOTE: the mcrypt libraries need to be installed and listed as an
// available extension in your phpinfo() to be able to use this
// method of decryption.
 
$secretKey = "YOUR SECRET KEY"; // secret key from your ClickBank account
 
// get JSON from raw body...
$message = json_decode(file_get_contents('php://input'));
 
// Pull out the encrypted notification and the initialization vector for
// AES/CBC/PKCS5Padding decryption
$encrypted = $message->{'notification'};
$iv = $message->{'iv'};
error_log("IV: $iv");
 
// decrypt the body...
$decrypted = trim(openssl_decrypt(
 base64_decode($encrypted),
 'aes-256-cbc',
 substr(sha1($secretKey), 0, 32),
 OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING,
 base64_decode($iv)), "\0..\32");
error_log("Decrypted: $decrypted");
 
////UTF8 Encoding, remove escape back slashes, and convert the decrypted string to a JSON object...
$sanitizedData = utf8_encode(stripslashes($decrypted));
$order = json_decode($decrypted);
 
// Ready to rock and roll - If the decoding of the JSON string wasn't
// successful, then you can assume the notification wasn't encrypted
// with your secret key.
 
?>

Hope this saves you some time and hassle.