Congrats, You are Subscribed to Receive Updates.

PayPal IPN Listener WordPress Without Using Plugin


PayPal IPN Listener WordPress Without Using Plugin. PayPal ipn will be sent you to validate each transactions. You can validate the transaction details with help of it. For IPN things,it will be sent you indirectly.  Your website users can’t see it.  So, this is private and hidden notification to you from PayPal.

Let’s begin with receiving Hidden URL and IPN functionality. It might be easy to receive it via wp-ajax.php file you can pass additional parameter to receive it. like this.


you can write the functionality like this. Let’s hook the function.

add_action( 'wp_ajax_kv_paypal_ipn', 'kv_paypal_ipn_callback' );
function kv_paypal_ipn_callback() {
	// here we can verify and validate the transactions.

The above one is a simple one to handle the ajax function on your own. We need debugging options to see if, any problem encounters in the middle.  so define a constant for debugging,

define("DEBUG", 1);

And we need a constant to change the sandbox to live. So lets create one more constant for it.


define("USE_SANDBOX", 1);

Here is the sandbox and live switching thing,

if(USE_SANDBOX == true) {
	$paypal_url = "https://www.sandbox.paypal.com/cgi-bin/webscr";
} else {
	$paypal_url = "https://www.paypal.com/cgi-bin/webscr";

PayPal IPN Listener

We need log file to check the  debugging things. so create  log file.

define("LOG_FILE", "./ipn.log");

Now, we can retrieve all the $_POST parameter and its entire things.

$raw_post_data = file_get_contents('php://input');

This might be array of parameters. let’s explode and add cmd validator with it.

$raw_post_array = explode('&', $raw_post_data);
$myPost = array();
foreach ($raw_post_array as $keyval) {
	$keyval = explode ('=', $keyval);
	if (count($keyval) == 2)
		$myPost[$keyval[0]] = urldecode($keyval[1]);
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
if(function_exists('get_magic_quotes_gpc')) {
	$get_magic_quotes_exists = true;
foreach ($myPost as $key => $value) {
	if($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) {
		$value = urlencode(stripslashes($value));
	} else {
		$value = urlencode($value);
	$req .= "&$key=$value";

Let’s begin the cURL to get connection and validate it.

$ch = curl_init($paypal_url);
if ($ch == FALSE) {
	return FALSE;

curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);

Suppose,if it has any error or problem we need to report it to log file.

if(DEBUG == true) {
	curl_setopt($ch, CURLOPT_HEADER, 1);
	curl_setopt($ch, CURLINFO_HEADER_OUT, 1);

cURL connection timeout and close function.

curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));

Getting result and either success of failure to create log.

$res = curl_exec($ch);
if (curl_errno($ch) != 0){ // cURL error	
	if(DEBUG == true) {	
		error_log(date('[Y-m-d H:i e] '). "Can't connect to PayPal to validate IPN message: " . curl_error($ch) . PHP_EOL, 3, LOG_FILE);
} else {
	// Log the entire HTTP response if debug is switched on.
	if(DEBUG == true) {
		error_log(date('[Y-m-d H:i e] '). "HTTP request of validation request:". curl_getinfo($ch, CURLINFO_HEADER_OUT) ." for IPN payload: $req" . PHP_EOL, 3, LOG_FILE);
		error_log(date('[Y-m-d H:i e] '). "HTTP response of validation request: $res" . PHP_EOL, 3, LOG_FILE);

$tokens = explode("\r\n\r\n", trim($res));
$res = trim(end($tokens));

Here, after you can validate the things with help of $res. With the help of following code,you can log the results either success or failure, than we will do further database things.

if (strcmp ($res, "VERIFIED") == 0) {
	if(DEBUG == true) {
		error_log(date('[Y-m-d H:i e] '). "Verified IPN: $req ". PHP_EOL, 3, LOG_FILE);
} else if (strcmp ($res, "INVALID") == 0) {
	if(DEBUG == true) {
		error_log(date('[Y-m-d H:i e] '). "Invalid IPN: $req" . PHP_EOL, 3, LOG_FILE);

That’s it. You can make this as plugin or you can simply put this function on your theme functions.php and make it working for you.

PayPal IPN Listener WordPress Without Using Plugin

If you need to store the values in Database, you can save it with below code.

 	global $wpdb; 
 	$ipnTable = $wpdb->prefix.'IPN_table';
 	$pack_id = $post_arr['item_number1']; 
 	$wp_user_id = 2; 
 	$wpdb->insert($ipnTable, array('pack_id' => $pack_id,'wp_user_id' => $wp_user_id));

This is a sample code to save it.


About Varadharaj V

The founder of Kvcodes, Varadharaj V is an ERP Analyst and a Web developer specializing in WordPress(WP), WP Theme development, WP Plugin development, Frontaccounting(FA), Sales, Purchases, Inventory, Ledgers, Payroll & HRM, CRM, FA Core Customization, OpenCart Theme Development, PHP, HTML, CSS, jQuery, Bootstrap development and content SEO.


  1. commenter

    How do I insert the IPN message into the wordpress database?

Comment Below

Your email address will not be published. Required fields are marked *


Current ye@r *



Subscribe E-mail Updates

Congrats, You are Subscribed to Receive Updates.


Category Posts