Solved

PHP - PayPal listerner script help?

Posted on 2014-03-09
14
657 Views
Last Modified: 2016-03-24
Hi,
When an order is placed via my website I use the code below to send order details to PayPal , I then have a PayPal listener script waiting for payment confirmation from PayPal to complete the order process.

I would like to add a PayPal express option to bypass the normal website order & customer information and just go directly to PayPal from the cart page.
Therefore I will need to modify the below script to exclude the fields that would normally get entered on the website, such as first_name, last_name, address1, address2, city, state, country, zip.

My question is will PayPal return "first_name, last_name, address1, address2, city, state, country, zip" automatically to my paypal_listener.phps script?
If so, I can then add these details to the orders and customers table stored on my website?


if ($_SESSION['payment_option'] == "credit_paypal"){

$orderid = $_SESSION["orderid"];
$user_id = $_SESSION["user_id"];
$customers_email = $_SESSION["email"];

$tax = number_format(($_SESSION['order_total'] /11), 2, ".", ",");
$amount = number_format((($_SESSION['order_total'] /11)*10), 2, ".", ",");


$first_name = $_SESSION['payment_first_name'];
$last_name = $_SESSION['payment_last_name'];
$address1 = $_SESSION['payment_address1'];
$address2 = $_SESSION['payment_address2'];
$city = $_SESSION['payment_city'];
$state = $_SESSION['payment_state'];
$country = $_SESSION['payment_country'];
$zip = $_SESSION['payment_postal_code'];

$cmd="_xclick";
$paypal_cpp_header_image = $row_settings['paypal_cpp_header_image'];          
$paypal_business = $_SESSION['paypal_email'];
      
$paypal_item_name = $row_settings['paypal_item_name'];             
$paypal_notify_url = $row_settings['paypal_notify_url'];            
$paypal_return = $row_settings['paypal_return'];   
$paypal_cancel_return = $row_settings['paypal_cancel_return']; ;

$extra = "?cmd=$cmd";
$extra .= "&business=$paypal_business";
$extra .= "&item_name=$paypal_item_name";
$extra .= "&email=$customers_email";
$extra .= "&amount=$amount";
$extra .= "&tax=$tax";
$extra .= "&invoice=$orderid";
$extra .= "&first_name=$first_name";
$extra .= "&last_name=$last_name";
$extra .= "&address1=$address1";
$extra .= "&address2=$address1";
$extra .= "&zip=$zip";
$extra .= "&city=$city";
$extra .= "&state=$state";
$extra .= "&country=$country";
$extra .= "&cpp_header_image=$paypal_cpp_header_image";
$extra .= "&notify_url=$paypal_notify_url";
$extra .= "&cancel_return=$paypal_cancel_return";
$extra .= "&return=$paypal_return";
$extra .= "&rm=2";
$extra .= "&no_shipping=1";
$extra .= "&currency_code=AUD";
$extra .= "&no_note=1";
$extra .= "&lc=AU";
$extra .= "&bn=PP-BuyNowBF";
$extra .= "&custom=$cartId";

header("Location: https://www.paypal.com/au/cgi-bin/webscr$extra");
//header("Location: https://www.sandbox.paypal.com/au/cgi-bin/webscr$extra");
exit;

}
				

paypal_listener.php

<?php // read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';

foreach ($_POST as $key => $value) {
$value = urlencode(stripslashes($value));
$req .= "&$key=$value";
}

// post back to PayPal system to validate
     
$header = "POST /cgi-bin/webscr HTTP/1.0\r\n";
 
     // If testing on Sandbox use: 
     // $header .= "Host: www.sandbox.paypal.com:443\r\n";
$header .= "Host: www.paypal.com:443\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";

     // If testing on Sandbox use:
     //$fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
$fp = fsockopen ('ssl://www.paypal.com', 443, $errno, $errstr, 30);

// assign posted variables to local variables
$item_name = $_POST['item_name'];
$order_id = $_POST['invoice'];
$cartId = $_POST['custom'];
$item_number = $_POST['item_number'];
$payment_status = $_POST['payment_status'];
$payment_amount = $_POST['mc_gross'];
$payment_currency = $_POST['mc_currency'];
$txn_id = $_POST['txn_id'];
$receiver_email = $_POST['receiver_email'];
$payer_email = $_POST['payer_email'];

if (!$fp) {
// HTTP ERROR
} else {
fputs ($fp, $header . $req);
while (!feof($fp)) {
$res = fgets ($fp, 1024);
if (strcmp ($res, "VERIFIED") == 0) {
// check the payment_status is Completed
// check that txn_id has not been previously processed
// check that receiver_email is your Primary PayPal email
// check that payment_amount/payment_currency are correct
// process payment

...
..
.

Open in new window

0
Comment
Question by:sabecs
  • 6
  • 5
  • 3
14 Comments
 
LVL 58

Expert Comment

by:Gary
ID: 39916428
It will return everything back to you, full list of vars is here
https://developer.paypal.com/docs/classic/ipn/integration-guide/IPNandPDTVariables/
0
 

Author Comment

by:sabecs
ID: 39916722
Thanks Gary for your response,
It appears I am only receiving the following fields?
Is there a setting I need to change in order to receive the address details?


cmd                        
mc_gross                    
invoice                    
protection_eligibility      
payer_id                    
tax                        
payment_date                
payment_status              
charset                    
first_name                  
mc_fee                      
notify_version              
custom                      
payer_status                
business                    
quantity                    
verify_sign                
payer_email                
txn_id                      
payment_type                
last_name                  
receiver_email              
payment_fee                
receiver_id                
txn_type                    
item_name                  
mc_currency                
item_number                
residence_country          
handling_amount            
transaction_subject        
payment_gross              
shipping                    
ipn_track_id
0
 
LVL 58

Assisted Solution

by:Gary
Gary earned 250 total points
ID: 39917904
Look under Buyer Information Variables
0
 

Author Comment

by:sabecs
ID: 39918390
Thanks Gary, I can see the variables that I need but they don't appear to be returned to the PayPal listener script?

address_country
address_city
address_country_code
address_name
address_state
address_street
0
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 39921531
I think we might need to see a little more information than we have here.  Could you describe or illustrate the process a bit more?  For example, it might be helpful to see the var_dump() output of the $_SESSION array and the $extra variable.
0
 

Author Comment

by:sabecs
ID: 39925529
Thanks for your help, when I login to PayPal account and view my IPN history I see the following?

Instant Payment Notification (IPN) details

mc_gross=2.99&invoice=75&protection_eligibility=Ineligible&payer_id=HSKJDKJDLKJDLKJ&tax=0.27&payment_date=20:34:15 Mar 12, 2014 PDT&payment_status=Completed&charset=windows-1252&first_name=Johnw&mc_fee=0.37&notify_version=3.7&custom=4f811gfdgdfgc7834c3dba35be1a84e&payer_status=unverified&business=john@test.com&quantity=1&verify_sign=AdsadsadsadtreMGWAXaihwXxwk0EmEdG7&payer_email=andrew@test.com&txn_id=8BX1HHJSDJSX510384L&payment_type=instant&last_name=Testing&receiver_email=john@test.com.au&payment_fee=&receiver_id=345DGKQ2KED6&txn_type=web_accept&item_name=TEST COMPANY&mc_currency=AUD&item_number=&residence_country=AU&receipt_id=3456-6741-2412-1021&handling_amount=0.00&transaction_subject=876gdfgt7834c3dba35be1a84e&payment_gross=&shipping=0.00&ipn_track_id=83598877816

Open in new window

0
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 39925974
Reformatted for readability.

mc_gross = 2.99
&invoice = 75
&protection_eligibility = Ineligible
&payer_id = HSKJDKJDLKJDLKJ
&tax = 0.27
&payment_date = 20:34:15 Mar 12, 2014 PDT
&payment_status = Completed
&charset = windows-1252
&first_name = Johnw
&mc_fee = 0.37
&notify_version = 3.7
&custom = 4f811gfdgdfgc7834c3dba35be1a84e
&payer_status = unverified
&business = john@test.com
&quantity = 1
&verify_sign = AdsadsadsadtreMGWAXaihwXxwk0EmEdG7
&payer_email = andrew@test.com
&txn_id = 8BX1HHJSDJSX510384L
&payment_type = instant
&last_name = Testing
&receiver_email = john@test.com.au
&payment_fee = 
&receiver_id = 345DGKQ2KED6
&txn_type = web_accept
&item_name = TEST COMPANY
&mc_currency = AUD
&item_number = 
&residence_country = AU
&receipt_id = 3456-6741-2412-1021
&handling_amount = 0.00
&transaction_subject = 876gdfgt7834c3dba35be1a84e
&payment_gross = 
&shipping = 0.00
&ipn_track_id = 83598877816

Open in new window

0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 108

Accepted Solution

by:
Ray Paseur earned 250 total points
ID: 39926014
Looks like the PayPal documentation has gotten a lot better since the last time I worked with it!  Since this is a data-dependent question we need to explore the way the software (both your software and PayPal's software) handles the data.

Have a look at this page:
https://developer.paypal.com/docs/classic/ipn/gs_IPN/

On that page it shows that the information presented to the IPN arrives in the form of a POST-method request.  PHP will take the raw post variables and create $_POST before starting your script.  Look at Step 3 under Receiving Your First Notification and you will see the sample code using a foreach() iterator to access all of the elements of $_POST.  The code creates a variable named $req that is used in Step 5 as the body of an email message.

Questions:

(1) Have you followed this process exactly to get the $req email sent to you, and is that the exact information posted here?

(2) Can I please see the var_dump() output of the $_SESSION array and the $extra variable, as shown in the first code snippet at line 55, immediately before the header() to redirect the browser.
0
 

Author Comment

by:sabecs
ID: 39929933
Thanks again for your help.
I have followed the process exactly to get the $req email sent to me and the var dumps are shown below:

Not sure if the "&bn=PP-BuyNowBF" is the reason for address not being returned in IPN?

Note: the above script has been working fine for my shopping carts when customers place an order through the normal process (login or entering order details on website). However one of my customers would like to use PayPal express checkout, and basically all I will be passing to PayPal is an order id and some totals, I then want to update this order id on the website via the paypal listener script, I receive most of the details I need to do this except for the address?

I hope that makes sense.  


array(65) { ["cart_cost"]=> int(0) ["cart_tax"]=> string(4) "0.27" ["cart_total"]=> string(4) "2.99" ["cart_ex_tax"]=> float(2.72) ["cost_items"]=> string(4) "2.99" ["business_name"]=> string(27) "Test Company" ["gst_included"]=> string(1) "Y" ["cart_items"]=> int(1) ["layout"]=> string(7) "desktop" ["securimage_code_value"]=> string(4) "wmev" ["from_page"]=> string(48) "http://www.test.com/index.php?page_id=200" ["delivery_option_chosen"]=> string(12) "aus_post_reg" ["date_required"]=> string(5) "reset" ["surcharge"]=> string(4) "0.00" ["store_id"]=> string(1) "2" ["store_name"]=> NULL ["access_key"]=> NULL ["store_address_01"]=> NULL ["store_address_02"]=> NULL ["store_address_03"]=> NULL ["store_address_04"]=> NULL ["cheque_details_01"]=> NULL ["cheque_details_02"]=> NULL ["cheque_details_03"]=> NULL ["cheque_details_04"]=> NULL ["deposit_details_01"]=> NULL ["deposit_details_02"]=> NULL ["deposit_details_03"]=> NULL ["deposit_details_04"]=> NULL ["sms_acc_name"]=> NULL ["sms_acc_password"]=> NULL ["mobiles"]=> NULL ["days_of_week_open"]=> bool(false) ["days_of_week_deliver"]=> bool(false) ["avail_payment_options"]=> bool(false) ["dates_closed"]=> NULL ["paypal_email"]=> NULL ["store_email"]=> NULL ["eway_id"]=> NULL ["shipping_cost"]=> string(4) "1.20" ["postage_cost_msg"]=> string(49) " Regular Parcel Post via Australia Post - $ 1.20" ["postage_area"]=> string(2) "NA" ["pickup"]=> string(1) "N" ["postage_quote"]=> string(1) "N" ["PHPSESSID"]=> string(32) "5ad0c8656546656e03f71b9c460cda4f" ["cartId"]=> string(32) "5ad0c8276dba956e03f71b9c460cda4f" ["__utma"]=> string(54) "224746116.497422988.12232323.1394817778.1" ["__utmb"]=> string(25) "224746116.3.10.1394817778" ["__utmc"]=> string(9) "224746116" ["__utmz"]=> string(92) "224746116.1394817778.1.1.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not provided)" ["to_post_code"]=> string(4) "2111" ["regular_post"]=> float(1.2) ["express_post"]=> string(2) "NA" ["payment_option"]=> string(14) "paypal_express" ["payment_first_name"]=> string(6) "PayPal" ["payment_last_name"]=> string(7) "Express" ["password"]=> string(6) "kes456" ["username"]=> NULL ["user_access_key"]=> string(12) "tibgamrm8747" ["user_id"]=> int(5067) ["orderid"]=> int(76) ["overseas_order"]=> int(0) ["order_total"]=> string(4) "4.19" ["order_tax"]=> string(4) "0.38" ["order_ex_tax"]=> string(4) "3.81" } 

string(564) "?cmd=_xclick&business=admin@test.com&item_name=TEST COMPANY&email=&amount=3.81&tax=0.38&invoice=76&first_name=PayPal&last_name=Express&address1=&address2=&zip=&city=&state=&country=&cpp_header_image=http://www.test.com/images/our_logo_on_payapal.jpg¬ify_url=http://www.test.com/paypal_listener.php&cancel_return=http://www.test.com/index.php?page=cancel_order&return=http://www.test.com/index.php?page=process_order_complete&rm=2&no_shipping=1¤cy_code=AUD&no_note=1&lc=AU&bn=PP-BuyNowBF&custom=5ad0c8276dba956e03f71b9c460cda4f" 

Open in new window

0
 
LVL 58

Expert Comment

by:Gary
ID: 39929967
Have a read through this
https://developer.paypal.com/docs/classic/express-checkout/integration-guide/ECGettingStarted/

And see if you are doing anything different/or not doing
0
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 39930287
This might be trouble...
string(564) "?cmd=_xclick&business=admin@test.com&item_name=TEST COMPANY&email=&amount=3.81... etc.

Open in new window

The data is supposed to be urlencoded.  That would put a + or a %20 in place of the blank.  Also, it appears that you may have some undefined variables in play.  Not sure about that.  If you have not already done so, add error_reporting(E_ALL) to your PHP scripts so you can avoid undefined variables.  If you don't explicitly ask for the error messages, PHP will suppress them and you can find yourself in the dark about something that should be easy to fix.

I'll look at the rest of it in a moment.
0
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 39930299
Data reformatted for readability.

array(65) { 
["cart_cost"]=> int(0) 
["cart_tax"]=> string(4) "0.27" 
["cart_total"]=> string(4) "2.99" 
["cart_ex_tax"]=> float(2.72) 
["cost_items"]=> string(4) "2.99" 
["business_name"]=> string(27) "Test Company" 
["gst_included"]=> string(1) "Y" 
["cart_items"]=> int(1) 
["layout"]=> string(7) "desktop" 
["securimage_code_value"]=> string(4) "wmev" 
["from_page"]=> string(48) "http://www.test.com/index.php?page_id=200" 
["delivery_option_chosen"]=> string(12) "aus_post_reg" 
["date_required"]=> string(5) "reset" 
["surcharge"]=> string(4) "0.00" 
["store_id"]=> string(1) "2" 
["store_name"]=> NULL 
["access_key"]=> NULL 
["store_address_01"]=> NULL 
["store_address_02"]=> NULL 
["store_address_03"]=> NULL 
["store_address_04"]=> NULL 
["cheque_details_01"]=> NULL 
["cheque_details_02"]=> NULL 
["cheque_details_03"]=> NULL 
["cheque_details_04"]=> NULL 
["deposit_details_01"]=> NULL 
["deposit_details_02"]=> NULL 
["deposit_details_03"]=> NULL 
["deposit_details_04"]=> NULL 
["sms_acc_name"]=> NULL 
["sms_acc_password"]=> NULL 
["mobiles"]=> NULL 
["days_of_week_open"]=> bool(false) 
["days_of_week_deliver"]=> bool(false) 
["avail_payment_options"]=> bool(false) 
["dates_closed"]=> NULL 
["paypal_email"]=> NULL 
["store_email"]=> NULL 
["eway_id"]=> NULL 
["shipping_cost"]=> string(4) "1.20" 
["postage_cost_msg"]=> string(49) " Regular Parcel Post via Australia Post - $ 1.20" 
["postage_area"]=> string(2) "NA" 
["pickup"]=> string(1) "N" 
["postage_quote"]=> string(1) "N" 
["PHPSESSID"]=> string(32) "5ad0c8656546656e03f71b9c460cda4f" 
["cartId"]=> string(32) "5ad0c8276dba956e03f71b9c460cda4f" 
["__utma"]=> string(54) "224746116.497422988.12232323.1394817778.1" 
["__utmb"]=> string(25) "224746116.3.10.1394817778" 
["__utmc"]=> string(9) "224746116" 
["__utmz"]=> string(92) "224746116.1394817778.1.1.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not provided)" 
["to_post_code"]=> string(4) "2111" 
["regular_post"]=> float(1.2) 
["express_post"]=> string(2) "NA" 
["payment_option"]=> string(14) "paypal_express" 
["payment_first_name"]=> string(6) "PayPal" 
["payment_last_name"]=> string(7) "Express" 
["password"]=> string(6) "kes456" 
["username"]=> NULL 
["user_access_key"]=> string(12) "tibgamrm8747" 
["user_id"]=> int(5067) 
["orderid"]=> int(76) 
["overseas_order"]=> int(0) 
["order_total"]=> string(4) "4.19" 
["order_tax"]=> string(4) "0.38" 
["order_ex_tax"]=> string(4) "3.81" 
} 




string(564) 
"
?cmd=_xclick
&business=admin@test.com
&item_name=TEST COMPANY
&email=
&amount=3.81
&tax=0.38
&invoice=76
&first_name=PayPal
&last_name=Express
&address1=
&address2=
&zip=
&city=
&state=
&country=
&cpp_header_image=http://www.test.com/images/our_logo_on_payapal.jpg¬ify_url=http://www.test.com/paypal_listener.php
&cancel_return=http://www.test.com/index.php?page=cancel_order
&return=http://www.test.com/index.php?page=process_order_complete
&rm=2
&no_shipping=1¤cy_code=AUD
&no_note=1
&lc=AU
&bn=PP-BuyNowBF
&custom=5ad0c8276dba956e03f71b9c460cda4f
"

Open in new window

My guess is that if you're going to use Express Checkout you will need to have your own address data in your own data base, and you will need to be able to look this up, perhaps by using the client email address as a key.  I say "guess" because I have never tested it, but it seems intuitively correct.
0
 

Author Comment

by:sabecs
ID: 39930638
Thanks for your help, very much appreciated.
I ended up finding the problem which was due to no_shipping set to 1, which worked fine for regular checkout but not for express, should be set to 2 which I have, IPN returned to listener script now contains all the information needed.

From PayPal:
no_shipping  - Optional  Do not prompt buyers for a shipping address. Allowable values are:
 
•0 – prompt for an address, but do not require one
•1 – do not prompt for an address
•2 – prompt for an address, and require one

The default is 0.
 

Found solution here:
http://stackoverflow.com/questions/13573193/paypal-ipn-get-buyer-address
0
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 39930723
I wondered about that at first, but I wasn't sure enough to guess at it.  Glad you've got a good solution! ~Ray
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
How do I edit this Drupal page? 9 29
PHP Sum Column in Table 3 27
Filter wordpress query 3 8
showing numeric numbers 2 0
Read about how to choose the best possible content marketing agency to suit your needs. Content marketing has become an integral part of running a successful tech business, so it is wise to be informed.
Since pre-biblical times, humans have sought ways to keep secrets, and share the secrets selectively.  This article explores the ways PHP can be used to hide and encrypt information.
Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will w…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now