I am trying to code a simple PayPal purchase page with options on my site. However, I am having trouble testing it. For some odd reason, when I use "http://paypal.com/cgi-bin/webscr" as the form URL, it seems to work, however I can't test the IPN without someone purchasing it. If I leave it as "http://sandbox.paypal.com/cgi-bin/webscr", it will pop up with this on the PayPal Sandbox site,
PayPal cannot process this transaction because of a problem with the seller's website. Please contact the seller directly to resolve this problem.
Below is my Form:
<form action="https://www.sandbox.paypal.com/cgi-bin/webscr" method="post" target="_top">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="hidden" name="hosted_button_id" value="YDPZBQ2LRBCSE">
<table>
<tr><td><input type="hidden" name="on0" value="Packages">Packages</td></tr><tr><td><select name="os0">
<option value="Bronze">Bronze $10.00 USD</option>
<option value="Silver">Silver $25.00 USD</option>
<option value="Gold">Gold $50.00 USD</option>
</select> </td></tr>
<tr><td><input type="hidden" name="on1" value="Wubbo Username">Wubbo Username</td></tr><tr><td><input type="text" name="os1" maxlength="200"></td></tr>
</table>
<input type="hidden" name="currency_code" value="USD">
<input type="image" src="http://wubbo.me/paypal/buynow.png" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
<img alt="" border="0" src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" width="1" height="1">
</form>
And here is my IPN Code:
<?php
mysql_connect("localhost", "root", "PASSWORD") or die(mysql_error());
mysql_select_db("DATABASE") or die(mysql_error());
// STEP 1: read POST data
// Reading POSTed data directly from $_POST causes serialization issues with array data in the POST.
// Instead, read raw POST data from the input stream.
$raw_post_data = file_get_contents('php://input');
$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 IPN message sent from PayPal and prepend 'cmd=_notify-validate'
$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";
}
// Step 2: POST IPN data back to PayPal to validate
$ch = curl_init('https://www.sandbox.paypal.com/cgi-bin/webscr');
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
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);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
// In wamp-like environments that do not come bundled with root authority certificates,
// please download 'cacert.pem' from "http://curl.haxx.se/docs/caextract.html" and set
// the directory path of the certificate as shown below:
// curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__) . '/cacert.pem');
if( !($res = curl_exec($ch)) ) {
// error_log("Got " . curl_error($ch) . " when processing IPN data");
curl_close($ch);
exit;
}
curl_close($ch);
// inspect IPN validation result and act accordingly
if (strcmp ($res, "VERIFIED") == 0) {
// The IPN is verified, process it:
// check whether 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 the notification
// assign posted variables to local variables
$package = $_POST['os0'];
$username = $_POST['os1'];
if ($package == 'Bronze') {
mysql_query("UPDATE `users` SET `vip_points` = (`vip_points` + 10) WHERE username = '" . $username . "'");
} else if ($package == 'Silver') {
mysql_query("UPDATE `users` SET `vip_points` = (`vip_points` + 30) WHERE username = '" . $username . "'");
} else if ($package == 'Gold') {
mysql_query("UPDATE `users` SET `vip_points` = (`vip_points` + 100) WHERE username = '" . $username . "'");
}
}
} else if (strcmp ($res, "INVALID") == 0) {
// IPN invalid, log for manual investigation
echo "The response from IPN was: <b>" .$res ."</b>";
}
?>
Any assistance would be greatly appreciated!
You should create a sandbox account and create a sandbox button to test.
To create a sandbox account, you should access developer.paypal.com, login with your live PayPal account,
then follow up the link below to create a sandbox account(from step 2):
https://ppmts.custhelp.com/app/answers/detail/a_id/744/kw/sandbox
After created sandbox account, you can access www.sandbox.paypal.com and login with the sandbox account,
then follow up the link below to create a button for sandbox environment:
https://ppmts.custhelp.com/app/answers/detail/a_id/740/kw/create%20button
You're getting that error message because you modified a hosted button. If you create the button on PayPal then change the button code after you have copied it you get that error. You need to either make all modifications on PayPal or use an open source button.
Here is an example of an open source button you will need to add your own email or merchant id from your PayPal Account for it to work:
<form target="paypal" action="https://www.paypal.com/cgi-bin/webscr" method="post" >
<input type="hidden" name="cmd" value="_cart">
<input type="hidden" name="business" value="youremail#email.com">
<input type="hidden" name="lc" value="US">
<input type="hidden" name="item_name" value="Sample Cart">
<input type="hidden" name="button_subtype" value="products">
<input type="hidden" name="no_note" value="0">
<input type="hidden" name="cn" value="Add special instructions to the seller:">
<input type="hidden" name="no_shipping" value="2">
<input type="hidden" name="currency_code" value="USD">
<input type="hidden" name="add" value="1">
<input type="hidden" name="bn" value="PP-ShopCartBF:btn_cart_LG.gif:NonHosted">
<table>
<tr><td><input type="hidden" name="on0" value="Registration">Registration</td></tr><tr><td><select name="os0">
<option value="Bronze">Bronze $10.00 USD</option>
<option value="Silver">Silver $25.00 USD</option>
<option value="Gold">Gold $50.00 USD</option>
</select> </td></tr>
<input type="hidden" name="currency_code" value="USD">
<input type="hidden" name="option_select0" value="Bronze">
<input type="hidden" name="option_amount0" value="10.00">
<input type="hidden" name="option_select1" value="Silver">
<input type="hidden" name="option_amount1" value="25.00">
<input type="hidden" name="option_select2" value="Gold">
<input type="hidden" name="option_amount2" value="50.00">
<input type="hidden" name="option_index" value="0">
</select> </td></tr>
<tr><td><input type="hidden" name="on1" value="Wubbo Username">Wubbo Username</td></tr><tr><td><input type="text" name="os1" maxlength="200"> </td></tr>
</table>
<input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_cart_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
<img alt="" border="0" src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" width="1" height="1">
</form>
Related
I am unable to get variables in my return address while paying with Paypal.
My form is like below:
<form action="<?php echo $ps_paypal_url; ?>" method="post">
<input type="hidden" name="business" value="<?php echo $ps_paypal_merchant; ?>">
<input type="hidden" name="notify_url" value="<?php echo 'http://'.$_SERVER['SERVER_NAME'].CONF_WEBROOT_URL. 'paypal-ipn.php'; ?>">
<input type="hidden" name="item_name" value="<?php echo 'For Order ' . $_POST['ORDER']; ?>">
<input type="hidden" name="user_name" value="<?php echo $_SESSION['logged_user']['user_id']; ?>">
<input type="hidden" name="quantity" value="1">
<input type="hidden" name="item_number" value="<?php echo $_POST['ORDER']; ?>">
<input TYPE="hidden" name="cmd" value="_xclick">
<input type="hidden" name="amount" value="<?php echo round($total_payable, 2); ?>">
<?php if($_POST['wallet'] > 0){ ?>
<input type="hidden" name="discount_amount" value="<?php echo round($_POST['wallet'],2); ?>" />
<?php } ?>
<input type="hidden" name="no_shipping" value="1">
<input type="hidden" name="custom" value="<?php echo $_SESSION['logged_user']['user_id']; ?>">
<?php
$success = 'http://' . $_SERVER['SERVER_NAME'] . CONF_WEBROOT_URL .'success/;
?>
<input type='hidden' name='rm' value='2'>
<input type="hidden" name="return" value="<?php echo $success ; ?>">
<input type="hidden" name="currency_code" value="<?php echo CONF_CURRENCY_CODE; ?>">
</form>
In my return address I am trying to read for example item_name or amount. But no success so far. I beleive paypal is disabled this function and variables are not allowed to be posted to return address. In my return file I am trying to read the variables like below:
<?php
$amount = $_GET['amount'];
$amountpost = $_POST['amount'];
echo $amount;
echo $amountpost ;
?>
The result is empty. There is not any problem with ipn file once it is verified I am able to get the result with ipn file but why it is needed for me is because I need to add pending orderd in users purchase history. So when user will be redirected to success.php I will add pending order to account and once it is completed I will check via ipn and will change the status to "paid".
Any help would be highly appreciated.
PS: I don't want to send parameters in URL as $_GET parameters. I just want to get parameters of form.
First, please enable IPN explicitly after logging in your Paypal account and set the IPN url (e.g. set as http://www.yoursite.com/payment1234A.php)
Second, please remove notify_url from your form (to avoid hacking)
Thirdly, please add return and cancel_return url as hidden fields. For example:
<input type="hidden" name="return" value="http://www.yoursite.com/success.php">
<input type="hidden" name="cancel_return" value="http://www.yoursite.com/cancelled.php">
So, if you want to collect USD1000 , then the form to be sent to paypal should be like the following form:
Note:
I have added a javascript autosubmit so that the user does not need to click a submit button);
I have used the "custom" field to send a unique data, it can be something like [customerserial-transactionserial] so that your IPN script can use it to do your db update.
The minimum requested fields to be submitted in the form are:
business, item_name, amount, currency_code. For further details please refer to Paypal's official documentation.
<form id=form1 action="https://www.paypal.com/cgi-bin/webscr" method="post">
<!-- Identify your business so that you can collect the payments. -->
<input type="hidden" name="business" value="yourpaypalemail#yoursite.com">
<!-- Specify a Buy Now button. -->
<input type="hidden" name="cmd" value="_xclick">
<!-- Specify details about the item that buyers will purchase. -->
<input type="hidden" name="item_name" value="Purchase">
<input type="hidden" name="amount" value="1000">
<input type="hidden" name="currency_code" value="USD">
<input type="hidden" name="custom" value="<?php echo $_SESSION["checkcode"]; ?>">
<input type="hidden" name="return" value="http://www.yoursite.com/success.php">
<input type="hidden" name="cancel_return" value="http://www.yoursite.com/cancelled.php">
</form>
<script>
document.getElementById('form1').submit();
</script>
Finally, use (and customize if necessary) the following standard paypal IPN php script in your IPN link (e.g.payment1234A.php). Please note that the amount you submitted will be returned as $_POST['mc_gross'] (not $_GET['amount'] nor $_POST['amount']) . But the custom field will be returned as $_POST['custom'].
The file below : payment1234A.php
<?php
// STEP 1: Read POST data
// reading posted data from directly from $_POST causes serialization
// issues with array data in POST
// reading raw POST data from input stream instead.
$raw_post_data = file_get_contents('php://input');
$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";
}
if (1==2) {
// STEP 2: Post IPN data back to paypal to validate
// only works if your IPN url is https, otherwise remark this block as 1==2
$ch = curl_init('https://ipnpb.paypal.com/cgi-bin/webscr');
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
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);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
// In wamp like environments that do not come bundled with root authority certificates,
// please download 'cacert.pem' from "http://curl.haxx.se/docs/caextract.html" and set the directory path
// of the certificate as shown below.
// curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__) . '/cacert.pem');
if( !($res = curl_exec($ch)) ) {
// error_log("Got " . curl_error($ch) . " when processing IPN data");
curl_close($ch);
exit;
}
curl_close($ch);
}
// STEP 3: Inspect IPN validation result and act accordingly
if (1==1) {
// check whether 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
// assign posted variables to local variables
$item_name = $_POST['item_name'];
$item_number = $_POST['item_number'];
$payment_status = $_POST['payment_status'];
$payment_amount = $_POST['mc_gross'];
$custom = $_POST['custom'];
$payment_currency = $_POST['mc_currency'];
$txn_id = $_POST['txn_id'];
$receiver_email = $_POST['receiver_email'];
$payer_email = $_POST['payer_email'];
// <---- HERE you can do your INSERT to the database
if ( trim($payment_status)=="Completed" ) {
/// do whatever you want for successful transaction
}
}
?>
Here, I'm want to using auto recurring payment in paypal for my subscription plan. I have found some solutions but not working in IPN recurring payment.
First time payment is working but not getting recurring payment auto deduction.
i'm using html code for payment in paypal gateway.
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<!-- Identify your business so that you can collect the payments. -->
<input type="hidden" name="business" value="alice#mystore.com">
<!-- Specify a Subscribe button. -->
<input type="hidden" name="cmd" value="_xclick-subscriptions">
<!-- Identify the subscription. -->
<input type="hidden" name="item_name" value="Alice's Weekly Digest">
<input type="hidden" name="item_number" value="DIG Weekly">
<!-- Set the terms of the regular subscription. -->
<input type="hidden" name="currency_code" value="USD">
<input type="hidden" name="a3" value="5.00">
<input type="hidden" name="p3" value="1">
<input type="hidden" name="t3" value="M">
<!-- Set recurring payments until canceled. -->
<input type="hidden" name="src" value="1">
<!-- Display the payment button. -->
<input type="image" name="submit"
src="https://www.paypalobjects.com/en_US/i/btn/btn_subscribe_LG.gif"
alt="Subscribe">
<img alt="" width="1" height="1"
src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" >
</form>
For auto recurring payment you have to use ipn also. Add below code in your HTML form before submit button.
<input type="hidden" name="custom" value="User_id">
<!-- specify urls -->
<!-- paypal_cancel_url -->
<input type="hidden" name="cancel_return" value="http://localhost/xxxxx/paypal/cancel">
<!-- paypal success return url -->
<input type="hidden" name="return" value="http://localhost/xxxxx/paypal/success">
<!-- paypal ipn return url for auto recurring payment -->
<input type="hidden" name="notify_url" value="http://localhost/xxxxx/paypal/ipn">
I'm only showing recurring payment guide as you said first time payment is working. Add below code in PayPal controller.
function ipn(){
if ($_SERVER['REQUEST_METHOD'] != "POST") die ("No Post Variables");
$req = 'cmd=_notify-validate';
// Read the post from PayPal
foreach ($_POST as $key => $value) {
$value = urlencode(stripslashes($value));
$req .= "&$key=$value";
}
/* i'm using sandbox for demo change it with live */
$paypalURL = 'https://www.sandbox.paypal.com/cgi-bin/webscr';
// Now Post all of that back to PayPal's server using curl, and validate everything with PayPal
// We will use CURL instead of PHP for this for a more universally operable script (fsockopen has issues on some environments)
//$url = "https://www.sandbox.paypal.com/cgi-bin/webscr"; //USE SANDBOX ACCOUNT TO TEST WITH
//$url = "https://www.paypal.com/cgi-bin/webscr"; //LIVE ACCOUNT
$curl_result=$curl_err='';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$paypalURL);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: application/x-www-form-urlencoded", "Content-Length: " . strlen($req)));
curl_setopt($ch, CURLOPT_HEADER , 0);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$curl_result = #curl_exec($ch);
$curl_err = curl_error($ch);
curl_close($ch);
$req = str_replace("&", "\n", $req); // Make it a nice list in case we want to email it to ourselves for reporting
// Check that the result verifies with PayPal
if (strpos($curl_result, "VERIFIED") !== false) {
$req .= "\n\nPaypal Verified OK";
} else {
$req .= "\n\nData NOT verified from Paypal!";
//mail("email#gmail.com", "IPN interaction not verified", "$req", "From: email#gmail.com" );
exit();
}
if (array_key_exists("txn_id", $_POST)) {
/* all response for future use conver it into json format */
$payment_rawData = json_encode($_POST);
$item_number = $_POST['item_number'];
$txn_id = $_POST['txn_id'];
$amount = $_POST['mc_gross'];
$currency_code = $_POST['mc_currency'];
$custom = $_POST['custom'];
$payment_status = $_POST['payment_status'];
//Insert tansaction data into the database
$payment_info = array('payment_userId'=>$custom,'payment_planId'=>$item_number,'payment_txnId'=>$txn_id,'payment_amount'=>$amount,'payment_currency'=>$currency_code,'payment_status'=> $payment_status,'payment_rawData'=>$payment_rawData,'createdDate'=>date('Y-m-d H:i:s'),'updatedDate'=>date('Y-m-d H:i:s'));
$this->paypal_model->insertTransaction($payment_info);
}
}
I have the following Paypal payment form:
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_xclick">
<input type="hidden" name="business" value="******">
<input type="hidden" name="item_name" value="******">
<input type="hidden" name="item_number" value="1">
<input type="hidden" name="amount" value="25">
<input type="hidden" name="no_shipping" value="0">
<input type="hidden" name="no_note" value="1">
<input type="hidden" name="currency_code" value="USD">
<input type="hidden" name="bn" value="PP-BuyNowBF">
<input id="afield" type="text" placeholder="Name"</input>
<input id="afield" type="text" placeholder="Email Address"</input>
<!-- Saved buttons display an appropriate button image. -->
<input type="image" name="submit"
src="https://www.paypalobjects.com/en_US/i/btn/btn_buynow_LG.gif"
alt="PayPal - The safer, easier way to pay online">
<img alt="" width="1" height="1"
src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" >
My question is, how can I get the two inputs (id: afield) so that I can save them for when the user returns to my website after paying, I can use them. I am using PHP.
Thanks
Here is how I have dealt with this in the past.
First step is to fix the input field:
<input id="afield" type="text" placeholder="Name" name="afield">
I have corrected your HTML syntax and called the field afield
You then need to set another hidden field called notify_url - this is the URL that PayPal will POST the transaction details back to after a payment has been made.
e.g.
<input type="hidden" name="notify_url" value="https://www.yourdomain.com/paypal.php">
Inside paypal.php you can then access $_POST['afield']
In case it helps, here is the sort of thing you need inside paypal.php - this verifies that the transaction details POSTed back from PayPal are genuine and that the payment was successful:
$raw_post_data = file_get_contents('php://input');
$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 IPN message sent from PayPal and prepend 'cmd=_notify-validate'
$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";
}
// Step 2: POST IPN data back to PayPal to validate
$ch = curl_init('https://ipnpb.paypal.com/cgi-bin/webscr');
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
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);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
if ( !($res = curl_exec($ch)) ) {
curl_close($ch);
exit;
}
curl_close($ch);
if (strcmp ($res, "VERIFIED") == 0 and $_POST['payment_status'] == 'Completed') {
// payment has been verified
}
You can add a field with the name custom
The only issue is this field can't be returned by Paypal in the answer, even in the PDT
Only can see this field in the IPN text
https://developer.paypal.com/docs/classic/ipn/integration-guide/IPNandPDTVariables/#transaction-and-notification-related-variables
https://developer.paypal.com/docs/classic/ipn/integration-guide/IPNPDTAnAlternativetoIPN/
Using 1and1 web hosting
The error message
Can't connect to PayPal to validate IPN message: error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
test form
<form action="http://dev.myurlishere.com/ipn.php" method="POST">
<input name="mc_gross" type="hidden" value="500.00" />
<input name="custom" type="hidden" value="some custom data" />
<input name="address_status" type="hidden" value="confirmed" />
<input name="item_number1" type="hidden" value="6" />
<input name="item_number2" type="hidden" value="4" />
<input name="payer_id" type="hidden" value="FW5W7ZUC3T4KL" />
<input name="tax" type="hidden" value="0.00" />
<input name="address_street" type="hidden" value="1234 Rock Road" />
<input name="payment_date" type="hidden" value="14:55 15 Jan 07 2005 PST" />
<input name="payment_status" type="hidden" value="Completed" />
<input name="address_zip" type="hidden" value="12345" />
<input name="mc_shipping" type="hidden" value="0.00" />
<input name="mc_handling" type="hidden" value="0.00" />
<input name="first_name" type="hidden" value="Jason" />
<input name="last_name" type="hidden" value="Anderson" />
<input name="mc_fee" type="hidden" value="0.02" />
<input name="address_name" type="hidden" value="Jason Anderson" />
<input name="notify_version" type="hidden" value="1.6" />
<input name="payer_status" type="hidden" value="verified" />
<input name="business" type="hidden" value="paypal#emailaddress.com" />
<input name="address_country" type="hidden" value="United States" />
<input name="num_cart_items" type="hidden" value="2" />
<input name="mc_handling1" type="hidden" value="0.00" />
<input name="mc_handling2" type="hidden" value="0.00" />
<input name="address_city" type="hidden" value="Los Angeles" />
<input name="verify_sign" type="hidden" value="AlUbUcinRR5pIo2KwP4xjo9OxxHMAi6.s6AES.4Z6C65yv1Ob2eNqrHm" />
<input name="mc_shipping1" type="hidden" value="0.00" />
<input name="mc_shipping2" type="hidden" value="0.00" />
<input name="tax1" type="hidden" value="0.00" />
<input name="tax2" type="hidden" value="0.00" />
<input name="txn_id" type="hidden" value="TESTER" />
<input name="payment_type" type="hidden" value="instant" />
<input name="last_name=Borduin" type="hidden" />
<input name="payer_email" type="hidden" value="test#domain.com" />
<input name="item_name1" type="hidden" value="Rubber+clog" />
<input name="address_state" type="hidden" value="CA" />
<input name="payment_fee" type="hidden" value="0.02" />
<input name="item_name2" type="hidden" value="Roman sandal" />
<input name="invoice" type="hidden" value="123456" />
<input name="quantity" type="hidden" value="1" />
<input name="quantity1" type="hidden" value="1" />
<input name="receiver_id" type="hidden" value="5HRS8SCK9NSJ2" />
<input name="quantity2" type="hidden" value="1" />
<input name="txn_type" type="hidden" value="web_accept" />
<input name="mc_gross_1" type="hidden" value="0.01" />
<input name="mc_currency" type="hidden" value="USD" />
<input name="mc_gross_2" type="hidden" value="0.01" />
<input name="payment_gross" type="hidden" value="0.02" />
<input name="subscr_id" type="hidden" value="PP-1234" />
<input name="test" type="submit" value="test" />
</form>
ipn.php
<?php
// CONFIG: Enable debug mode. This means we'll log requests into 'ipn.log' in the same directory.
// Especially useful if you encounter network errors or other intermittent problems with IPN (validation).
// Set this to 0 once you go live or don't require logging.
define("DEBUG", 1);
// Set to 0 once you're ready to go live
define("USE_SANDBOX", 1);
define("LOG_FILE", "./ipn.log");
// Read POST data
// reading posted data directly from $_POST causes serialization
// issues with array data in POST. Reading raw POST data from input stream instead.
$raw_post_data = file_get_contents('php://input');
$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";
}
// Post IPN data back to PayPal to validate the IPN data is genuine
// Without this step anyone can fake IPN data
if(USE_SANDBOX == true) {
$paypal_url = "https://www.sandbox.paypal.com/cgi-bin/webscr";
} else {
$paypal_url = "https://www.paypal.com/cgi-bin/webscr";
}
$ch = curl_init($paypal_url);
if ($ch == FALSE) {
return FALSE;
}
curl_setopt($ch, CURLOPT_SSLVERSION, 4);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
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);
if(DEBUG == true) {
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLINFO_HEADER_OUT, 1);
}
// CONFIG: Optional proxy configuration
//curl_setopt($ch, CURLOPT_PROXY, $proxy);
//curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1);
// Set TCP timeout to 30 seconds
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
// CONFIG: Please download 'cacert.pem' from "http://curl.haxx.se/docs/caextract.html" and set the directory path
// of the certificate as shown below. Ensure the file is readable by the webserver.
// This is mandatory for some environments.
//$cert = __DIR__ . "./cacert.pem";
//curl_setopt($ch, CURLOPT_CAINFO, $cert);
$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);
}
curl_close($ch);
exit;
} 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);
}
curl_close($ch);
}
// Inspect IPN validation result and act accordingly
// Split response headers and payload, a better way for strcmp
$tokens = explode("\r\n\r\n", trim($res));
$res = trim(end($tokens));
if (strcmp ($res, "VERIFIED") == 0) {
// check whether the payment_status is Completed
// check that txn_id has not been previously processed
// check that receiver_email is your PayPal email
// check that payment_amount/payment_currency are correct
// process payment and mark item as paid.
// assign posted variables to local variables
//$item_name = $_POST['item_name'];
//$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(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) {
// log for manual investigation
// Add business logic here which deals with invalid IPN messages
if(DEBUG == true) {
error_log(date('[Y-m-d H:i e] '). "Invalid IPN: $req" . PHP_EOL, 3, LOG_FILE);
}
}
?>
I believe that the reason you get this error is because you are using SSL v3, which has severe security issues and therefore is not supported by any serious website anymore. (more information here: http://disablessl3.com/)
in your above code, you specify
curl_setopt($ch, CURLOPT_SSLVERSION, 4);
however, in the error message, it says
sslv3 alert handshake failure
so obviousely ssl v3 was used by PHP. instead try
curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, "TLSv1")
as indicated here: SSL error can not change to TLS
hope that helps you
I've been trying to tackle this for some time now. I have an order page where the customer must enter information like name, address, etc. and some more unique fields. I have set up IPN with Paypal and the customer is redirected to the page I specified. But the data does not come along with it. I hope I'm asking my question properly so that I don't get "closed." Here is the HTML in the Paypal submit button that redirects to their page.
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="hidden" name="hosted_button_id" value="NT2YC6LP7SWBE">
<input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_paynowCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
<input type="hidden" name="child_name" id="child_name" value ="<? echo $child_name; ?>" maxlength="20"/>
<input type="hidden" name="age" id="age" value ="<? echo $age; ?>" maxlength="4"/>
<input type="hidden" name="hometown" id="hometown" value ="<? echo $hometown; ?>" maxlength="32"/>
<input type="hidden" name="boy_girl" id="boy_girl" value ="<? echo $boy_girl; ?>" maxlength="4"/>
<input type="hidden" name="first_name" id="first_name" value ="<? echo $first_name; ?>" maxlength="32"/>
<input type="hidden" name="last_name" id="last_name" value ="<? echo $last_name; ?>" maxlength="32"/>
<input type="hidden" name="email" id="email" value ="<? echo $email; ?>" maxlength="64"/>
<input type="hidden" name="address1" id="address1" value ="<? echo $address1; ?>" maxlength="64"/>
<input type="hidden" name="address2" id="address2" value ="<? echo $address2; ?>" maxlength="32"/>
<input type="hidden" name="city" id="city" value ="<? echo $city; ?>" maxlength="32"/>
<input type="hidden" name="state" id="state" value ="<? echo $state; ?>" maxlength="20"/>
<input type="hidden" name="zip" id="zip" value ="<? echo $zip; ?>" maxlength="10"/>
<input type="hidden" name="country" id="country" value ="<? echo $country; ?>" maxlength="32"/>
<input type="hidden" name="payment_type" id="payment_type" value ="paypal" maxlength="6"/>
<input type="hidden" name="paid" id="paid" value ="yes" maxlength="3"/>
<input type="hidden" name="mailed" id="mailed" value ="no" maxlength="3"/>
<img alt="" border="0" src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" width="1" height="1">
</form>
It has been pointed out to me that some of the variables are not "Paypal variables" and I can fix that later, but none of my data is making it back to my specified page after visiting Paypal, even the variables that Paypal supports like "city." Here is the PHP that I have on the page that they get redirected to.
$raw_post_data = file_get_contents('php://input');
$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]);
}
$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";
}
$ch = curl_init('https://www.paypal.com/cgi-bin/webscr');
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
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);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
if( !($res = curl_exec($ch)) ) {
// error_log("Got " . curl_error($ch) . " when processing IPN data");
curl_close($ch);
exit;
}
curl_close($ch);
if (strcmp ($res, "VERIFIED") == 0) {
$child_name = htmlentities($_POST['child_name']);
$age = $_POST['age'];
$hometown = $_POST['hometown'];
$boy_girl = $_POST['boy_girl'];
$email = $_POST['email'];
$first_name = htmlentities($_POST['first_name']);
$last_name = htmlentities($_POST['last_name']);
$address1 = htmlentities($_POST['address1']);
$address2 = htmlentities($_POST['address2']);
$city = htmlentities($_POST['city']);
$state = $_POST['state'];
$zip = htmlentities($_POST['zip']);
$country = htmlentities($_POST['country']);
$payment_type = $_POST['payment_type'];
$paid = $_POST['paid'];
$mailed = $_POST['mailed'];
} else if (strcmp ($res, "INVALID") == 0) {
}
$query = "INSERT INTO customer_list (
number, child_name, age, hometown, boy_girl, first_name, last_name, email,
address1, address2, city, state, zip, country, payment_type, paid, mailed)
VALUES ('',
'".mysql_real_escape_string($child_name)."',
'".mysql_real_escape_string($age)."',
'".mysql_real_escape_string($hometown)."',
'".mysql_real_escape_string($boy_girl)."',
'".mysql_real_escape_string($first_name)."',
'".mysql_real_escape_string($last_name)."',
'".mysql_real_escape_string($email)."',
'".mysql_real_escape_string($address1)."',
'".mysql_real_escape_string($address2)."',
'".mysql_real_escape_string($city)."',
'".mysql_real_escape_string($state)."',
'".mysql_real_escape_string($zip)."',
'".mysql_real_escape_string($country)."',
'".mysql_real_escape_string($payment_type)."',
'".mysql_real_escape_string($paid)."',
'".mysql_real_escape_string($mailed)."')";
if ($query_run = mysql_query($query)) {
$subject = "Thank You for Your Order";
$message = "Thank you for placing your order with My-Letter-From-Santa-Claus.com. \n\nYou can expect to receive your personalized letter soon. Please make note of your customer number. Your customer number is: ".mysql_insert_id().". \n\nPlease send all inquiries to : info#my-letter-from-santa-claus.com";
$from = "info#my-letter-from-santa-claus.com";
$headers = "From:" . $from;
mail($email, $subject, $message, $headers);
echo 'Thank you for your order.';
echo 'Letter For '.$child_name;
} else {
echo mysql_error();
}
I copied most of it directly from x.com except for changing to my own variables of course. Nothing is getting posted to the database but that's not the issue since I cannot even echo the data. A couple things are being entered into the database but it's not the data from my order page - it is the first name and last name that is entered as the credit card info on Paypal, and for payment_type it says "instan" (I maxed it at 6 characters) but as you can see from the hidden input field in the HTML, I wanted to post the value "paypal." How do I fix this?
are you using the Paypal Sandbox for testing? If not, I strongly recommend it: https://developer.paypal.com/, and the manual: https://cms.paypal.com/cms_content/US/en_US/files/developer/PP_Sandbox_UserGuide.pdf.
I don't see the field name="business" in you code. That is the field which Paypal uses to identify you seller account. But maybe it only has to do with the "cmd" parameter (I use _xclick).
Here is a set of fields which works at this time for me, maybe it helps you:
<form name="_xclick" action="https://www.paypal.com/de/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_xclick">
<input type="hidden" name="business" value="seller_email_here">
<input type="hidden" name="notify_url" value="ipn_url_here">
<input type="hidden" name="return" value="redirect_url">
<input type="hidden" name="cancel_return" value="redirect_if_cancelled_url">
<input type="hidden" name="amount" value="number_of_items">
<input type="hidden" name="currency_code" value="EUR">
<input type="hidden" name="item_name" value="product_name">
<input type="hidden" name="item_number" value="product_number">
Your problem is that you're using a hosted button. You can't include custom stuff in the general HTML for those. The only custom fields that can be included have to be done in the PayPal button creation wizard.
You also need to make sure you're not confusing IPN and PDT. If you simply want data to come back to your return URL that the user is sent to after completing payment that would be PDT. It's not recommended that you handle post-order-processing with this, though, because there is no guarantee the user will make it there.
IPN can be used for that because it will be triggered no matter what, but again, that's totally separate from your checkout and PDT.
I would highly recommend using Express Checkout instead of standard buttons since you seem to be familiar with PHP, too. I've got a PHP class library for PayPal that makes this very simple for you, and I can provide 30 min of free training if you need it, which is generally more than enough to get people up-and-running as long as you understand PHP and how to work with array data.
You can do it with Standard, too, but you'd have to move away from using a hosted button #AndreiHardau is showing. That would allow you to include additional fields like address1, address2, address_overide, etc, and those fields would then be returned in IPN, PDT, and in GetTransactionDetails.