Jump to content

Paypal IPN issue


szepesif

Recommended Posts

We have a small Wordpress based site and we're using the WP E-commerce plugin to sell digital downloads. Everything is working, except the PayPal IPN function so when the customer pays he never receives the download e-mail until we change the transaction's status manually. Unfortunately it's not an option here because it's a digital download store so we have to fix the IPN somehow. My PHP knowledge is almost zero, so i'm here to ask some help from you guys.

Store URL: http://brainwaveentrainment.eu
WordPress version: 3.6.1
WP e-Commerce version: 3.8.12.1
Theme: Xyloto by Storefrontthemes

I did this: Enabled IPN in Paypal with the store URL (http://brainwaveentrainment.eu) Enabled IPN in the PayPal Standard module. Send shipping details: No, Allow owerride: No. Currently i'm testing with a Sandbox account but it's not working with a live account either. I set up paypal to accept payments automatically also.

I expected WP e-Commerce to do this: Modify the "Incomplete sale" status to "Accepted payment"

Instead it did this: It's not changing the orders' status.

It's pretty annoying. I tried everything, changed every setting, currency, IPN URL, etc but nothing helps. We want to start the store but we can't until it's not working. We purchased this theme and it's only working with this shopping cart so i can't just simply switch to a different e-commerce plugin.

One IPN log from paypal:

Notification URL
http://brainwaveentrainment.eu/?wpsc...aypal_standard
HTTP response code
What's this?
200
Delivery status
Sent
No. of retries
0
Transaction ID
7W214573HJ105310Y
IPN type
Transaction made

mc_gross=7.00&invoice=4151379432588&protection_eligibility=Eligible&address_status=confirmed&item_number1=531&tax=0.00&item_number2=568&payer_id=LYXHGVEQ4ASFN&address_street=1 Main St&payment_date=08:42:47 Sep 17, 2013 PDT&payment_status=Completed&charset=windows-1252&address_zip=95131&mc_shipping=0.00&mc_handling=0.00&first_name=Ferenc&mc_fee=0.50&address_country_code=US&address_name=Ferenc Szepesi's Test Store&notify_version=3.7&custom=&payer_status=verified&business=beatofficial@gmail.com&address_country=United States&num_cart_items=2&mc_handling1=0.00&mc_handling2=0.00&address_city=San Jose&verify_sign=AiPC9BjkCyDFQXbSkoZcgqH3hpacA.v.7UClmMzrTiiKgIJVSBufA1UT&payer_email=ferenc@szepesiweb.com&mc_shipping1=0.00&mc_shipping2=0.00&tax1=0.00&tax2=0.00&txn_id=7W214573HJ105310Y&payment_type=instant&payer_business_name=Ferenc Szepesi's Test Store&last_name=Szepesi&address_state=CA&item_name1=Gamma Energizer (Wind background), 45 minutes&receiver_email=beatofficial@gmail.com&item_name2=15 minutes relaxation Break (Wind chimes background)&payment_fee=0.50&quantity1=1&quantity2=1&receiver_id=5YKCMZKL6G46G&txn_type=cart&mc_gross_1=3.50&mc_currency=USD&mc_gross_2=3.50&residence_country=US&test_ipn=1&transaction_subject=&payment_gross=7.00&ipn_track_id=8542bf47e444e

So it seems everything is working fine on the PayPal's side.

I didn't gave up so i found this:

The Paypal IPN log shows this URL in my case: http://brainwaveentrainment.eu/?wpsc...aypal_standard

I tried to open this and i got this error message:

"Fatal error: Cannot use object of type WP_Error as array in C:\xampp\htdocs\brainwaveentrainment.eu\wp-content\plugins\wp-e-commerce\wpsc-merchants\paypal-standard.merchant.php on line 400"

On line 400 i found this:

if ( 'VERIFIED' == $response['body'] ) {

I googled for the error message and i found this fix: https://getsatisfaction.com/tweet_bl...error_as_array

So i changed that line to look like this:

if ( 'VERIFIED' == $response->body ) {

Result: The error message is gone when i open that page! But... the IPN is still not working. I don't have PHP skills so i'm sure this single modification is not enough.

Maybe somebody can help me with this here.

I uploaded the original "paypal-standard.merchant.php" file's content to pastebin so you can check what's wrong with it: http://pastebin.com/9Dcd75LM

Please help me if you can. I'm clueless and we really have to make this work somehow. I asked in the plugin's support forum too, but it's abandoned as a desert.

Link to comment
Share on other sites

when you browse directly to the file, you are not supplying any of the post data. the code should have actually done nothing (except to log the fact that it was requested without any post data.)

 

the code, because of what it is doing (handling the post-back from a payment transaction) should already have verbose error logging in it. every conditional test that fails should log the value that failed and the who, what, when, where, and why about the conditional test that failed.

 

you will need to do some debugging of the problem, by determining the execution path the code is taking and the values the code is using to find out where the code doesn't do what is expected. you can use the php error_log() statement to write information to your own log file for debugging purposes.

 

you know at least that the code is executing at line 400 in that file. start there by finding out what value is in $response->body for an actual paypal sandbox reply.

 

for quicker debugging, you can repeatedly submit your own data (those values you have from an actual transaction) by making a html form with those values hard coded into the fields, then submit the form to the url of your ipn script. you will need to (and should) bypass the part of the code in that file that sends the post data back to paypal for verification and is checking for the 'VERIFIED' status back from paypal (the code at line 400.) this will allow you to easily track down what the code is doing for those values. you will even be able to echo messages back out of the code and see them in the browser.

Link to comment
Share on other sites

here's a form, mentioned in my last paragraph above, that will submit those values to your ipn script for debugging what the code is doing -

<form method='post' action='url_of_your_ipn_script'>
<input type='submit'><br>
<input type='text' name='mc_gross' value='7.00'><br>
<input type='text' name='invoice' value='4151379432588'><br>
<input type='text' name='protection_eligibility' value='Eligible'><br>
<input type='text' name='address_status' value='confirmed'><br>
<input type='text' name='item_number1' value='531'><br>
<input type='text' name='tax' value='0.00'><br>
<input type='text' name='item_number2' value='568'><br>
<input type='text' name='payer_id' value='LYXHGVEQ4ASFN'><br>
<input type='text' name='address_street' value='1 Main St'><br>
<input type='text' name='payment_date' value='08:42:47 Sep 17, 2013 PDT'><br>
<input type='text' name='payment_status' value='Completed'><br>
<input type='text' name='charset' value='windows-1252'><br>
<input type='text' name='address_zip' value='95131'><br>
<input type='text' name='mc_shipping' value='0.00'><br>
<input type='text' name='mc_handling' value='0.00'><br>
<input type='text' name='first_name' value='Ferenc'><br>
<input type='text' name='mc_fee' value='0.50'><br>
<input type='text' name='address_country_code' value='US'><br>
<input type='text' name='address_name' value="Ferenc Szepesi's Test Store"><br>
<input type='text' name='notify_version' value='3.7'><br>
<input type='text' name='custom' value=''><br>
<input type='text' name='payer_status' value='verified'><br>
<input type='text' name='business' value='beatofficial@gmail.com'><br>
<input type='text' name='address_country' value='United States'><br>
<input type='text' name='num_cart_items' value='2'><br>
<input type='text' name='mc_handling1' value='0.00'><br>
<input type='text' name='mc_handling2' value='0.00'><br>
<input type='text' name='address_city' value='San Jose'><br>
<input type='text' name='verify_sign' value='AiPC9BjkCyDFQXbSkoZcgqH3hpacA.v.7UClmMzrTiiKgIJVSBufA1UT'><br>
<input type='text' name='payer_email' value='ferenc@szepesiweb.com'><br>
<input type='text' name='mc_shipping1' value='0.00'><br>
<input type='text' name='mc_shipping2' value='0.00'><br>
<input type='text' name='tax1' value='0.00'><br>
<input type='text' name='tax2' value='0.00'><br>
<input type='text' name='txn_id' value='7W214573HJ105310Y'><br>
<input type='text' name='payment_type' value='instant'><br>
<input type='text' name='payer_business_name' value="Ferenc Szepesi's Test Store"><br>
<input type='text' name='last_name' value='Szepesi'><br>
<input type='text' name='address_state' value='CA'><br>
<input type='text' name='item_name1' value='Gamma Energizer (Wind background), 45 minutes'><br>
<input type='text' name='receiver_email' value='beatofficial@gmail.com'><br>
<input type='text' name='item_name2' value='15 minutes relaxation Break (Wind chimes background)'><br>
<input type='text' name='payment_fee' value='0.50'><br>
<input type='text' name='quantity1' value='1'><br>
<input type='text' name='quantity2' value='1'><br>
<input type='text' name='receiver_id' value='5YKCMZKL6G46G'><br>
<input type='text' name='txn_type' value='cart'><br>
<input type='text' name='mc_gross_1' value='3.50'><br>
<input type='text' name='mc_currency' value='USD'><br>
<input type='text' name='mc_gross_2' value='3.50'><br>
<input type='text' name='residence_country' value='US'><br>
<input type='text' name='test_ipn' value='1'><br>
<input type='text' name='transaction_subject' value=''><br>
<input type='text' name='payment_gross' value='7.00'><br>
<input type='text' name='ipn_track_id' value='8542bf47e444e'><br>
<form>
Link to comment
Share on other sites

Thank you for trying to help me, i really appreciate it.

 

I moved the whole site to my private server so i can work on it without any restrictions. I have root access and i can see the error logs. I've created the form what you mentioned and i tried to send the post data to the e-commerce IPN URL.

 

This line appears in the error log every time when i submit the form:

[Fri Sep 20 17:05:39 2013] [error] [client myip] PHP Fatal error:  Cannot use object of type WP_Error as array in /var/www/clients/client1/web10/web/wp-content/plugins/wp-e-commerce/wpsc-merchants/paypal-standard.merchant.php on line 400

So i was right and something is wrong with that file on line 400. I know if i open the file withput the post data it's not suppoed to work but it's not supposed to write an error message either, except the "IPN request failure" message. But that's not the case with the original file.

 

I know it was a silly idea but i tried to modify the code in the "paypal-standard.merchant.php" file.

 

So i changed this:

        $response = wp_remote_post( $paypal_url, $options );
        if ( 'VERIFIED' == $response->body ) {
            $this->paypal_ipn_values = $received_values;
            $this->session_id = $received_values->invoice;
        } else {
            exit( "IPN Request Failure" );
        }

To this:

        $response = wp_remote_post( $paypal_url, $options );
        if ( 'VERIFIED' == $response->body ) {
            $this->paypal_ipn_values = $received_values;
            $this->session_id = $received_values->invoice;
        } else {
            $this->paypal_ipn_values = $received_values;
            $this->session_id = $received_values->invoice;
        }

And this error message appeared in the error log:

[Fri Sep 20 17:08:09 2013] [error] [client myip] WordPress database error You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 for query SELECT * FROM `wp_wpsc_cart_contents` WHERE `purchaseid` =  made by require('wp-blog-header.php'), require_once('wp-load.php'), require_once('wp-config.php'), require_once('wp-settings.php'), do_action('init'), call_user_func_array, wpsc_gateway_notification, wpsc_merchant_paypal_standard->__construct, wpsc_merchant->__construct, wpsc_merchant->collate_cart, referer: http://mytestsite.com/form.php

I have no idea what i sould do or try next.

Link to comment
Share on other sites

are you sure the code had $response->body in it on line 400? the fatal error, suggests that the actual code running was still $response['body'].

 

just changing the else{ ... } logic wouldn't have made the fatal error on line 400 go away.

 

Good guess.

 

I tried with the original (unmodified) file first.

 

Now i changed the $response['body'] to $response->body and there's no new error message in the log after the submit but i get an "IPN Request Failure" message in the browser so the "else" part is running instead of the $response.

Link to comment
Share on other sites

here's the documentation for the wp_remote_post function - http://codex.wordpress.org/Function_Reference/wp_remote_post

 

when it works, the result is an array and the original code $result['body'] is correct.

 

when it fails, it returns an error object, that the code should be testing for before blindly attempting to use the result.

 

so, this at least pins down the problem to what the wp_remote_post is doing and what error it returns. here's the error checking/reporting logic from that documentation -

if ( is_wp_error( $response ) ) {
   $error_message = $response->get_error_message();
   echo "Something went wrong: $error_message";
} else {
   // you would use the $response['body'] here..
}
Link to comment
Share on other sites

 

here's the documentation for the wp_remote_post function - http://codex.wordpress.org/Function_Reference/wp_remote_post

 

when it works, the result is an array and the original code $result['body'] is correct.

 

when it fails, it returns an error object, that the code should be testing for before blindly attempting to use the result.

 

so, this at least pins down the problem to what the wp_remote_post is doing and what error it returns. here's the error checking/reporting logic from that documentation -

if ( is_wp_error( $response ) ) {
   $error_message = $response->get_error_message();
   echo "Something went wrong: $error_message";
} else {
   // you would use the $response['body'] here..
}

 

I don't understand much but i'm happy you know what you're doing :-)

 

So i have to replace this:

        $response = wp_remote_post( $paypal_url, $options );
        if ( 'VERIFIED' == $response['body'] ) {
            $this->paypal_ipn_values = $received_values;
            $this->session_id = $received_values['invoice'];
        } else {
            exit( "IPN Request Failure" );
        }

To this?

if ( is_wp_error( $response ) ) {
$error_message = $response->get_error_message();
echo "Something went wrong: $error_message";
} else {
// you would use the $response['body'] here..
}

How should i add the $response['body'] part?

Link to comment
Share on other sites

this is that block of code with some needed error handling in it -

        $response = wp_remote_post( $paypal_url, $options );
        if ( is_wp_error( $response ) ) {
            $error_message = $response->get_error_message();
            $msg = "wp_remote_post for IPN verify step failed, error: $error_message";
            trigger_error($msg, E_USER_ERROR); // this halts execution due to E_USER_ERROR
        } else {
            // you would use the $response['body'] here..
            if ( 'VERIFIED' == $response['body'] ) {
                $this->paypal_ipn_values = $received_values;
                $this->session_id = $received_values['invoice'];
            } else {
                $msg = "IPN verify step failed with status: {$response['body']}";
                trigger_error($msg, E_USER_ERROR); // this halts execution due to E_USER_ERROR                
            }
        }

i used trigger_error() here because it makes use of php's error_reporting/display_errors/log_errors settings. if error_reporting is set to show fatal user errors (it should be set to E_ALL always), then if display_errors is ON and you are browsing to this file or posting your test form to it, you will see any error messages in the browser. when actually using paypal, you need to have log_errors set to ON and any error messages will be written to the server's error log file.

 

the original exit( "IPN Request Failure" ) code was only helpful if you are viewing the result in a browser, which paypal isn't. whomever wrote this code was only about half finished when he published it on the Internet.

Link to comment
Share on other sites

this is that block of code with some needed error handling in it -

        $response = wp_remote_post( $paypal_url, $options );
        if ( is_wp_error( $response ) ) {
            $error_message = $response->get_error_message();
            $msg = "wp_remote_post for IPN verify step failed, error: $error_message";
            trigger_error($msg, E_USER_ERROR); // this halts execution due to E_USER_ERROR
        } else {
            // you would use the $response['body'] here..
            if ( 'VERIFIED' == $response['body'] ) {
                $this->paypal_ipn_values = $received_values;
                $this->session_id = $received_values['invoice'];
            } else {
                $msg = "IPN verify step failed with status: {$response['body']}";
                trigger_error($msg, E_USER_ERROR); // this halts execution due to E_USER_ERROR                
            }
        }

i used trigger_error() here because it makes use of php's error_reporting/display_errors/log_errors settings. if error_reporting is set to show fatal user errors (it should be set to E_ALL always), then if display_errors is ON and you are browsing to this file or posting your test form to it, you will see any error messages in the browser. when actually using paypal, you need to have log_errors set to ON and any error messages will be written to the server's error log file.

 

the original exit( "IPN Request Failure" ) code was only helpful if you are viewing the result in a browser, which paypal isn't. whomever wrote this code was only about half finished when he published it on the Internet.

 

Thank you!

 

This is the error message in the log after the modification:

[Fri Sep 20 18:42:19 2013] [error] [client myip] PHP Fatal error:  wp_remote_post for IPN verify step failed, error: SSL certificate problem: unable to get local issuer certificate in /var/www/clients/client1/web10/web/wp-content/plugins/wp-e-commerce/wpsc-merchants/paypal-standard.merchant.php on line 403, referer: http://mytestsite.com/form.php
Link to comment
Share on other sites

that specific error is because your test server couldn't post using SSL to the paypal server (most likely because the openssl extension is not enabled/installed.)

 

what result do you get using this current code on the live server? make sure that php's error_reporting is E_ALL and log_errors are ON to get the trigger_error() statements to write to the server's error log.

Link to comment
Share on other sites

that specific error is because your test server couldn't post using SSL to the paypal server (most likely because the openssl extension is not enabled/installed.)

 

what result do you get using this current code on the live server? make sure that php's error_reporting is E_ALL and log_errors are ON to get the trigger_error() statements to write to the server's error log.

 

I moved back to the live (original) server.

 

This is the error message what appears after submit:

Fatal error: wp_remote_post for IPN verify step failed, error: There are no HTTP transports available which can complete the requested request. in C:\xampp\htdocs\brainwaveentrainment.eu\wp-content\plugins\wp-e-commerce\wpsc-merchants\paypal-standard.merchant.php on line 403
Link to comment
Share on other sites

nothing specific, but best guess, the url that $paypal_url = get_option( 'paypal_multiple_url' ); is returning is something that isn't possible/valid.

 

check what the setting is set to (i have no idea where/how it is set.)

 

The 'paypal_multiple_url' refers to the current "account type" (and it's URL). I can set this up in the PayPal Standard's settings. Right now it's in sandbox mode but the error message is the same even if i change that to live. I know this because i checked the source code there and i found this:

<td>Account Type:</td>
        <td>
            <select name='paypal_multiple_url'>
<option value='https://www.paypal.com/cgi-bin/webscr' >Live Account</option><option value='https://www.sandbox.paypal.com/cgi-bin/webscr' selected='selected'>Sandbox Account</option>
            </select>
            <p class='description'>
                If you have a PayPal developers Sandbox account please use Sandbox mode, if you just have a standard PayPal account then you will want to use Live mode.
            </p>
        </td>

I googled the "no HTTP transports available" error message and found this thread: http://wordpress.org/support/topic/wp-http-error-there-are-no-http-transports-available-which-can-complete-the-req

 

Maybe there's no curl on the live server? I know it's using xamp and it's not a real web hosting server. That's their own machine and they are using it to host their own sites.

 

On the other hand my test server is Debian based and i have ISPConfig installed. I have full root access. Maybe that's a better place to test these things. And i have openssl + curl installed there so i don't understand why i got that error message there.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.