I am working on a website where users will have to pay to use some services. So I know that PayPal is the service I can use. User can pay with debit card, credit card, PayPal account etc. I know that PayPal button can be used for it. But in my website, I want to give user an option to add amount of their choice. User can pay $5 or $50,000 or anything they want. I don't know if I can use PayPal button or not for this.
In short user will enter amount in form. After submitting the form, it will redirect user to PayPal site where they can pay the amount. In return, I wanna make sure how much they have paid, and transaction was successful or not etc from PayPal so I can store details in database and if transaction was successful, user will get the amount balance in account.
So all I want to know is which service will be better for me from PayPal?
Like PayPal button or PayPal gateway or PayPal flow gateway?
I've done exactly this on my site. I'll post some code for it. Basically you create an input form that's not hidden, call it amount, so they user can enter the amount, then pass it to paypal. Paypal sites say it doesnt' work, but it does.
I used low end Paypal standard, not any of their fancier interfaces. I have the user add to cart then pay for the cart. But you can do the same for buy now buttons. It doesn't matter which paypal service you use. If it can be done with the basic paypal standard, you can do it with any of them...!
You can also get from paypal after the transaction, various aspects of what the user paid for. So there's a variable available for total amount, and individual amounts, and so on.
This is the key to setting up a donation amount for the user to input:
<input type="hidden" name="button_subtype" value="services">
and of course:
<b>Amount $: (Example: nnn.nn)</b>
<input type="text" name="amount">
I'm not as familar with the variables comign back from paypal. For what you want paypal standard should work from what I've read definitely. Here are the two ways to do it, and both work with paypal standard, so will work with any paypal:
This link Contains the two that follow below and also gives a brief overview.:
https://developer.paypal.com/webapps/developer/docs/classic/paypal-payments-standard/integration-guide/wp_standard_overview/
1)
https://developer.paypal.com/webapps/developer/docs/classic/paypal-payments-standard/integration-guide/paymentdatatransfer/
2)
https://developer.paypal.com/webapps/developer/docs/classic/ipn/integration-guide/IPNIntro/
Here's a body of code for the form.
<form target="_blank" action="https://www.paypal.com/cgi-bin/webscr" method="post">
value="https://www.yourwebsite.com/logo.jpg"> -->
<b>Amount $: (Example: nnn.nn)</b>
<input type="text" name="amount">
<input type="image" src="https://www.paypalobjects.com/en_US/i/btn /btn_cart_SM.gif" border="0" name="submit">
<input type="hidden" name="add" value="1">
<input type="hidden" name="cmd" value="_cart">
<input type="hidden" name="business" value="yours">
<input type="hidden" name="item_name" value="donation">
<input type="hidden" name="no_shipping" value="0">
<input type="hidden" name="shipping" value="0.00">
<input type="hidden" name="tax" value="0.00">
<!-- Replace value with the web page you want the customer to return to -->
<input type="hidden" name="shopping_url" value="http://www.yours">
<!-- services seems to be the trick -->
<input type="hidden" name="button_subtype" value="services">
<input type="hidden" name="country" value="US">
<input type="hidden" name="currency_code" value="USD">
<input type="hidden" name="lc" value="US">
<input type="hidden" name="bn" value="PP-ShopCartBF:btn_paynowCC_LG.gif:NonHosted">
</form>
I recommended use a paypal express checkout. Here one simple (PHP) example:
// Parameters for SetExpressCheckout, which will be sent to PayPal
$padata['L_BILLINGAGREEMENTDESCRIPTION0'] = 'Product description';
$padata['L_BILLINGAGREEMENTDESCRIPTION0'] = $padata['L_BILLINGAGREEMENTDESCRIPTION0'] .
' $'.$product->price.'/month';
$padata['L_PAYMENTREQUEST_0_DESC0'] = $padata['L_BILLINGAGREEMENTDESCRIPTION0'] .
' $'.$product->price.'/month';$padata['PAYMENTREQUEST_0_NOTIFYURL'] = 'http://site_url/paypal/ipn';
$padata['PAYMENTREQUEST_0_DESC'] = $product->name;
$padata['RETURNURL'] = 'http://site_url/paypal/returnurl';
$padata['CANCELURL'] = 'http://site_url/paypal/cancelurl';
$padata['PAYMENTREQUEST_0_CURRENCYCODE'] = 'USD';
$padata['PAYMENTREQUEST_0_PAYMENTACTION'] = 'SALE';
$padata['PAYMENTREQUEST_0_ITEMAMT'] = $product->price;$padata['PAYMENTREQUEST_0_AMT'] = $product->price;$padata['L_BILLINGTYPE0'] = 'RecurringPayments';$padata['L_PAYMENTREQUEST_0_NAME0'] = $product->name;$padata['L_PAYMENTREQUEST_0_NUMBER0']= '322';$padata['L_PAYMENTREQUEST_0_QTY0'] = '1';$padata['L_PAYMENTREQUEST_0_AMT0'] = $product->price;
$paypal_data = http_build_query($padata);
$httpParsedResponseAr = $this->PPHttpPost('SetExpressCheckout', $paypal_data);
//Respond according to message we receive from Paypal
if("SUCCESS" == strtoupper($httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($httpParsedResponseAr["ACK"])){
//Redirect user to PayPal store with Token received.
$paypalurl ='https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token='.$httpParsedResponseAr["TOKEN"].'';
header('Location: '.$paypalurl);
}else{
echo 'Error : '.urldecode($httpParsedResponseAr["L_LONGMESSAGE0"]).'';
}
Page returnurl:
$hosteddata['L_BILLINGAGREEMENTDESCRIPTION0'] = 'Recurring Description';$hosteddata['L_BILLINGAGREEMENTDESCRIPTION0'] = $hosteddata['L_BILLINGAGREEMENTDESCRIPTION0'] . ' $'.$pr->price.'/month';$hosteddata['L_PAYMENTREQUEST_0_NAME0'] = $pr->name;$hosteddata['PROFILEREFERENCE'] = $GetExpressCheckoutDetails['L_PAYMENTREQUEST_0_NUMBER0'];$hosteddata['PROFILESTARTDATE'] = date('Y-m-d') . 'T' . date('H:i:s').'Z';$hosteddata['SUBSCRIBERNAME'] = $GetExpressCheckoutDetails['FIRSTNAME'] . ' ' . $GetExpressCheckoutDetails['LASTNAME'];$hosteddata['TOKEN'] = urlencode($_POST['token']);$hosteddata['DESC'] = $hosteddata['L_BILLINGAGREEMENTDESCRIPTION0'];$hosteddata['AMT'] = $pr->price;$hosteddata['BILLINGPERIOD'] = 'Month';$hosteddata['BILLINGFREQUENCY'] = '1';$hosteddata['TOTALBILLINGCYCLES'] = '12';$hosteddata['REGULARTOTALBILLINGCYCLES'] = '1';$hosteddata['VERSION'] = '74.0';$hosteddata['MAXFAILEDPAYMENTS'] = '1';$hosteddata['L_PAYMENTREQUEST_0_QTY0'] = '1';$hosteddata['L_BILLINGTYPE0'] = 'RecurringPayments';$hosteddata['L_PAYMENTREQUEST_0_ITEMCATEGORY0'] = 'Digital';$hosteddata['L_PAYMENTREQUEST_0_AMT0'] = $pr->price;$hosteddata['INITAMT'] = $pr->price;$hosteddata['L_PAYMENTREQUEST_0_NUMBER0'] = $pr->id;$hosteddata['PAYMENTREQUEST_0_NOTIFYURL'] = 'http://site_url/paypal/ipn';
$paypal_data = http_build_query($hosteddata);
$hosted_saas_response = $this->PPHttpPost('CreateRecurringPaymentsProfile', $paypal_data);
I used a separate method to post parameters to paypal
private function PPHttpPost( $methodName_, $nvpStr_ ) {
$api_username = 'yourpaypal#email.com';
$api_password = 'QWEQWEWQEQWEQEQWE';$api_signature = 'WQEQWEQWEQWEWQEQWEQWEQWEQWEQWE.cT';$api_endpoint = "https://api-3t.paypal.com/nvp";$version = '124.0';
$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $api_endpoint); curl_setopt($ch, CURLOPT_VERBOSE, 1);curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
$nvpreq = "METHOD=$methodName_&VERSION=$version&PWD=$api_password&USER=$api_username&SIGNATURE=$api_signature&$nvpStr_";
curl_setopt($ch, CURLOPT_POSTFIELDS, $nvpreq);$httpResponse = curl_exec($ch);
if(!$httpResponse) {
exit("$methodName_ failed: ".curl_error($ch).'('.curl_errno($ch).')');}
// Extract the response details.
$httpResponseAr = explode("&", $httpResponse);
$httpParsedResponseAr = array();
foreach ($httpResponseAr as $i => $value) {
$tmpAr = explode("=", $value);
if(sizeof($tmpAr) > 1) {
$httpParsedResponseAr[$tmpAr[0]] = $tmpAr[1];
}
}
if((0 == sizeof($httpParsedResponseAr)) || !array_key_exists('ACK', $httpParsedResponseAr)) {
exit("Invalid HTTP Response for POST request($nvpreq) to $api_endpoint.");
}
return $httpParsedResponseAr;
}
Related
I am trying to add a Paypal Payments button onto our website. I have Auto Return and Payment Data Transfer turned on.
When I point to sandbox, everything works correctly and it returns to my website with the transaction id in the url.
When I point to production PayPal, no transaction id is returned. Payment does go through.
Here is the form code:
<form action="#VARIABLES.strHostAddress#" method="post" target="_top" id="testform">
<input type="hidden" name="cmd" value="_donations">
<input type="hidden" name="business" value="#VARIABLES.strBusinessEmail#">
<input type="hidden" name="item_name" value="#VARIABLES.strGiftDesignation# - #VARIABLES.strGiftDesignation2#">
<input type="hidden" name="amount" value="#VARIABLES.intPayAmt#">
<input type="hidden" name="first_name" value="#VARIABLES.strFirstName#">
<input type="hidden" name="last_name" value="#VARIABLES.strLastName#">
<input type="hidden" name="address1" value="#VARIABLES.strLine1#">
<input type="hidden" name="address2" value="#VARIABLES.strLine2#">
<input type="hidden" name="city" value="#VARIABLES.strCity#">
<input type="hidden" name="state" value="#VARIABLES.strState#">
<input type="hidden" name="zip" value="#VARIABLES.strPostalCode#">
<input type="hidden" name="email" value="#VARIABLES.strEmail#">
<input type="hidden" name="cancel_return" value="#VARIABLES.strCancelPage#">
<input type="hidden" name="return" value="#VARIABLES.strThankYouPage#">
<input type="hidden" name="rm" value="2">
</form>
where #VARIABLES.strHostAddress# is "https://www.paypal.com/cgi-bin/webscr" for live or "https://www.sandbox.paypal.com/cgi-bin/webscr" for sandbox.
Any suggestions or idea why this would happen?
I am including a step by step explanation that PayPal has on their developers website and the important part is that you get the "tx" value, and send it back with the PDT "Identity Token" which you can find on the PayPal account when you login to configure PDT.
The following steps illustrate the basic flow of a PDT transaction.
"A customer submits a payment.
PayPal sends the transaction ID of the payment through HTTP as a GET variable (tx). This information is sent to the Return URL you specified in your PayPal account profile.
Your return URL web page contains an HTML POST form that retrieves the transaction ID and sends the transaction ID and your unique PDT token to PayPal.
PayPal replies with a message indicating SUCCESS or FAIL. The SUCCESS message includes transaction details, one per line, in the = format. This key-value pair string is URL encoded."
Ok, I just found this GitHub link that gives various code versions of how to get the "tx" and use it and the Identity Key to get all the name value pairs and parse them. It has an example in each language. Just click on the file name.
// ASP .NET C#
using System;
using System.IO;
using System.Text;
using System.Net;
using System.Web;
using System.Collections.Generic;
public partial class csPDTSample : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// CUSTOMIZE THIS: This is the seller's Payment Data Transfer authorization token.
// Replace this with the PDT token in "Website Payment Preferences" under your account.
string authToken = "Dc7P6f0ZadXW-U1X8oxf8_vUK09EHBMD7_53IiTT-CfTpfzkN0nipFKUPYy";
string txToken = Request.QueryString["tx"];
string query = "cmd=_notify-synch&tx=" + txToken + "&at=" + authToken;
//Post back to either sandbox or live
string strSandbox = "https://www.sandbox.paypal.com/cgi-bin/webscr";
string strLive = "https://www.paypal.com/cgi-bin/webscr";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(strSandbox);
//Set values for the request back
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
req.ContentLength = query.Length;
//Send the request to PayPal and get the response
StreamWriter streamOut = new StreamWriter(req.GetRequestStream(), System.Text.Encoding.ASCII);
streamOut.Write(query);
streamOut.Close();
StreamReader streamIn = new StreamReader(req.GetResponse().GetResponseStream());
string strResponse = streamIn.ReadToEnd();
streamIn.Close();
Dictionary<string,string> results = new Dictionary<string,string>();
if(strResponse != "")
{
StringReader reader = new StringReader(strResponse);
string line=reader.ReadLine();
if(line == "SUCCESS")
{
while ((line = reader.ReadLine()) != null)
{
results.Add(line.Split('=')[0], line.Split('=')[1]);
}
Response.Write("<p><h3>Your order has been received.</h3></p>");
Response.Write("<b>Details</b><br>");
Response.Write("<li>Name: " + results["first_name"] + " " + results["last_name"] + "</li>");
Response.Write("<li>Item: " + results["item_name"] + "</li>");
Response.Write("<li>Amount: " + results["payment_gross"] + "</li>");
Response.Write("<hr>");
}
else if(line == "FAIL")
{
// Log for manual investigation
Response.Write("Unable to retrive transaction detail");
}
}
else
{
//unknown error
Response.Write("ERROR");
}
}
}
PDT-Code-Samples on GitHub
I have some problem with XSS scan on sitelock. They said that some of URL from html input form is vulnerable. They said each parameters which I sent through the form was vulnerable. In this case the vulnerability is from Paypal input form. I build my website with Paypal redirect so the user will input their own data into the form and the system will send it to paypal. This is the example of my form code:
<div class="col-md-5">
<input type="text" class="form-control" name="L_PAYMENTREQUEST_FIRSTNAME" id="L_PAYMENTREQUEST_FIRSTNAME" value="<?=$_SESSION['post_value']['shipping_first_name']?>" readonly="readonly">
</div>
<input type="hidden" name="billing_first_name" value="<?=$_POST['billing_first_name']?>">
<input type="hidden" name="billing_last_name" value="<?=$_POST['billing_last_name']?>">
<input type="hidden" name="billing_email" value="<?=$_POST['billing_email']?>">
<input type="hidden" name="billing_phone" value="<?=$_POST['billing_phone']?>">
<input type="hidden" name="billing_address" value="<?=$_POST['billing_address']?>">
<input type="hidden" name="billing_city" value="<?=$_POST['billing_city']?>">
<input type="hidden" name="billing_postcode" value="<?=$_POST['billing_postcode']?>">
<input type="hidden" name="billing_state" value="<?=$_POST['billing_state']?>">
That is some part of my form. What I want to know is whats wrong with that form and how to prevent Sitelock to scan XSS vulnerability ? Please anyone knows could help me.
I would also recommend using the HTTP header.
X-XSS-Protection: 1; mode=block
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection
you probably dont check/nullify the data you are getting in the input fields
and by typing <script>alert('hacked')</script> in billing_address field
on next page where you print the billing_address you will get a popup window calling hacked
On the page that process your form you should validate that input fields doesn't have any javascript code.
for example
<?php
// define variables and set to empty values
$name = $email = $gender = $comment = $website = "";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$name = test_input($_POST["name"]);
$email = test_input($_POST["email"]);
$website = test_input($_POST["website"]);
$comment = test_input($_POST["comment"]);
$gender = test_input($_POST["gender"]);
}
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
?>
you need to create a function like test_input and run for all your input fields
I am using such paypal form(the payment is ok) for subscription plan and don't get any IPN notifications, but when I use standart paypal forms generated by paypal everything with IPN notification is ok. Is there a way to get IPN with this form? Thanks
Here is my form. I can get the data only on notify_url or by IPM if I remove the notify_url from this form.
PS> The main question! Is there a way to use both ipn + notify_url? Example?
<form action="https://www.paypal.com/a-bin/webscr" method="post" target="_top">
<!-- Identify your business so that you can collect the payments. -->
<input type="hidden" name="business" value="info#****.***">
<!-- Specify a Buy Now button. -->
<input type="hidden" name="cmd" value="_xclick-subscriptions">
<!-- Specify details about the item that buyers will purchase. -->
<table>
<tbody><tr>
<td>
<input type="hidden" name="on1" value="Mobile/Cell Phone number:"><strong>Mobile/Cell Phone number:</strong>
</td>
<td>
<input type="text" maxlength="200" name="os1" required="">
</td>
</tr>
<tr>
<td>
<input id="item_name" type="hidden" name="item_name" value="kp4">
<input id="item_number" type="hidden" name="item_number" value="1">
<label>Subscription Plans</label>
</td>
<td>
<!-- <input type="hidden" name="a3" value="5.00"> -->
<input data-name="kp4" data-id="1" type="radio" name="a3" value="0.01" checked=""> 0,01 /month <br>
<input data-name="kp5" data-id="2" type="radio" name="a3" value="0.02"> 0,01 /month <br>
<input data-name="kp6" data-id="3" type="radio" name="a3" value="0.03">0,01 /month <br>
<input data-name="kp7" data-id="4" type="radio" name="a3" value="0.04> 0,01 /month <br>
<input data-name="kp8+" data-id="5" type="radio" name="a3" value="0.05"> 0,05 /month <br>
<input type="hidden" name="p3" value="1">
<input type="hidden" name="t3" value="M">
<input type="hidden" name="src" value="1">
<input type="hidden" name="sra" value="1">
<input type="hidden" name="custom" value="ORG">
</td>
</tr>
</tbody></table>
<!-- Specify Currency Code -->
<input type="hidden" name="currency_code" value="USD">
<input type="hidden" name="no_shipping" value="1">
<input type="hidden" name="rm" value="2">
<!-- Specify URLs -->
<input type="hidden" name="notify_url" value="***payment-success.php?site_name=ORG">
<input type="hidden" name="cancel_return" value="****payment-cancel.php">
<input type="hidden" name="return" value="***payment-success.php">
<input type="image" name="submit" border="0" src="https://www.paypalobjects.com/en_US/i/btn/btn_subscribeCC_LG.gif" alt="PayPal - The safer, easier way to pay online">
<img alt="" border="0" width="1" height="1" src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif">
</form>
PS> The main question! Is there a way to use both ipn + notify_url?
Example?
In short: No
But can your desired results be achieved? Yes
This has been something haunting Paypal for years and still does.
There is a very popular method (for those who know) to get around this using php and curl and is distributed by Codeseekah. (Not affiliated)
The concept
An single IPN URL is setup for PayPal to notify your application of
payments. The IPN handler code broadcasts PayPal’s payload to other
IPN URLs you may have selectively or in bulk.
multiple PayPal IPN URLs now possible
no need to change any IPN code unless it filters requests by IP
can centralize IP filtering into the broadcast IPN, which means easier to maintain when PayPal’s IP ranges change
can centralize logging
can have queuing and rebroadcast if satellites (all your other IPN URLs) are unreachable
The Code
This IPN broadcast code is in PHP, but the concept is non-language specific. Simply port the code and it will do equally well or even better.
<?php
/*
* This is a PayPal IPN (Instant Payment Notification) broadcaster
* Since PayPal does not provide any straightforward way to add
* multiple IPN listeners we'll have to create a central IPN
* listener that will broadcast (or filter and dispatch) Instant
* Payment Notifications to different destinations (IPN listeners)
*
* Destination IPN listeners must not panic and recognize IPNs sent
* by this central broadcast as valid ones in terms of source IP
* and any other fingerprints. Any IP filtering must add this host,
* other adjustments made as necessary.
*
* IPNs are logged into files for debugging and maintenance purposes
*
* this code comes with absolutely no warranty
* https://codeseekah.com
*/
ini_set( 'max_execution_time', 0 ); /* Do not abort with timeouts */
ini_set( 'display_errors', 'Off' ); /* Do not display any errors to anyone */
$urls = array(); /* The broadcast session queue */
/* List of IPN listener points */
$ipns = array(
'mystore' => 'http://mystore.com/ipn.php',
'myotherstore' => 'http://mybigstore.com/paypal_ipn.php',
'myotherandbetterstore' => 'http://slickstore.com/paypal/ipn.php'
);
/* Fingerprints */
if ( /* My Store IPN Fingerprint */
preg_match( '#^\d+\|[a-f0-9]{32}$#', $_POST['custom'] ) /* Custom hash */
and $_POST['num_cart_items'] == 2 /* alwayst 1 item in cart */
and strpos( $_POST['item_name1'], 'MySite.com Product' ) == 0 /* First item name */
) $urls []= $ipns['mystore']; /* Choose this IPN URL if all conditions have been met */
if ( /* My Other Store IPN Fingerprint */
sizeof( explode('_', $_POST['custom']) ) == 7 /* has 7 custom pieces */
) $urls []= $ipns['myotherstore']; /* Choose this IPN URL if all conditions have been met */
/* My Other And Better Store IPN Fingerprint */
$custom = explode('|', $_POST['custom']);
if (
isset($custom[2]) and $custom[2] == 'FROM_OB_STORE' /* custom prefixes */
) $urls []= $ipns['myotherandbetterstore']; /* Choose this IPN URL if all conditions have been met */
/* ... */
/* Broadcast */
if ( !sizeof($urls) ) $urls = $ipns; /* No URLs have been matched */
$urls = array_unique( $urls ); /* Unique, just in case */
/* Broadcast (excluding IPNs from the list according to filter is possible */
foreach ( $urls as $url ) broadcast( $url );
header( 'HTTP/1.1 200 OK', true, 200 );
exit(); /* Thank you, bye */
/* Perform a simple cURL-powered proxy request to broadcast */
function broadcast( $url ) {
/* Format POST data accordingly */
$data = array();
foreach ($_POST as $key => $value) $data []= urlencode($key).'='.urlencode($value);
$data = implode('&', $data);
/* Log the broadcast */
file_put_contents('_logs/'.time().'.'.reverse_lookup( $url ).'-'.rand(1,100), $data);
$ch = curl_init(); /* Initialize */
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, count($data));
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_exec($ch); /* Execute HTTP request */
curl_close($ch); /* Close */
}
function reverse_lookup( $url ) {
global $ipns;
foreach ( $ipns as $tag => $_url ) {
if ( $url == $_url ) return $tag;
}
return 'unknown';
}
?>
The full article is at https://codeseekah.com/2012/02/11/how-to-setup-multiple-ipn-receivers-in-paypal/
Note: the author is very active and replies to all questions.
I'm struggling with this problem for some days now but with no success, I'm relatively
new to paypal ipn but have used it succesfully in the past few monhts, now maybe I'm
doing some silly mistake or paypal sandbox ipn server is unresponsible.
The payment is processed properly, the money goes from the buyer account to the seller but still no details are entered in the database.
So this is the html form code:
<form action="https://www.sandbox.paypal.com/cgi-bin/webscr" method="POST">
<input type="hidden" name="cmd" value="_xclick">
<input type="hidden" name="business" value="sanboxselleremail">
<input type="hidden" name="item_name" value="Product">
<input type="hidden" name="item_number" value="1">
<input type="hidden" name="amount" value="15">
<input type="hidden" name="no_shipping" value="1">
<input type="hidden" name="no_note" value="1">
<input type="hidden" name="currency_code" value="USD">
<input type="hidden" name="lc" value="EN">
<input type="hidden" name="bn" value="PP-BuyNowBF">
<input type="hidden" name="return" value="http://mysite.com/testipn/">
<input type="hidden" name="cancel_return" value="http://mysite.com/testipn/">
<input type="hidden" name="rm" value="2">
<input type="hidden" name="notify_url" value="http://mysite.com/testipn/ipn.php" />
<input type="submit" value="submit" />
</form>
And this is the ipn code that I found at paypal:
include('db.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";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
$fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
// 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 (!$fp) {
// HTTP ERROR
} else {
fputs ($fp, $header . $req);
while (!feof($fp)) {
$res = fgets ($fp, 1024);
if (strcmp ($res, "VERIFIED") == 0) {
if($payment_status=='Completed'){
$paylog = $db->query("INSERT INTO....);
}
else if (strcmp ($res, "INVALID") == 0) {
// log for manual investigation
}
}
fclose ($fp);
}
I've double checked everything, I know that you must post back all the variables so I checked them too. The sql syntax has no problems because I've tested it and it enters
the values to the database table I want.
Can you please take a quick look and please point any errors you might find?
Thank you.
This problem is costing me lot of time and stress... :(
Your code is outdated and doesn't include the HTTP 'Host' header, which is (now) required.
So with this code, it would never get back 'VERIFIED', but instead get a HTTP/1.1 400 'Bad Request' back from PayPal.
To fix this, simply change:
$header .= "POST /cgi-bin/webscr HTTP/1.0\r\n";
To:
$header .= "POST /cgi-bin/webscr HTTP/1.1\r\n";
And add:
$header .= "Host: www.sandbox.paypal.com\r\n";
Should you just wish to use updated sample code, you can find this at https://www.paypal.com/ipn/
hi it seems to me its blocked as dont regcongnise you when it trys to complete the process ,ive read alot of people are experiencing problems with the sandbox theres a thing on paypal that tells you about it brb ill find
easily solved you need a buyer sandbox account and a seller one do you have both sorry for my spelling hope this helps
use this to test it
https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_testing_SBAccessing
I have the following post button that i use for paypal transactions:
<form action="https://www.sandbox.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_xclick">
<input type="hidden" name="business" value="my#email.com">
<input type="hidden" name="item_name" value="Item description">
<input type="hidden" name="item_number" value="1">
<input type="hidden" name="amount" value="00.30">
<input type="hidden" name="no_shipping" value="1">
<input type="hidden" name="no_note" value="1">
<input type="hidden" name="currency_code" value="USD">
<input type="hidden" name="lc" value="US">
<input type="hidden" name="bn" value="PP-BuyNowBF">
<input type="hidden" name="return" value="website.com/index.php" />
<input type="hidden" name="cancel_return" value="website.com/index.php" />
<input type="hidden" name="rm" value="2">
<input type="hidden" name="notify_url" value="website.com/ipn/ipn.php">
<input type="hidden" name="custom" value="user_id">
<input type="submit" value="upgrade" />
</form>
and the following code in ipn.php
<?php
include_once 'config.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";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
//$fp = fsockopen ('ssl://www.paypal.com', 443, $errno, $errstr, 30);
$fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
// 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 (!$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
mysql_query("UPDATE table SET column='1' WHERE column2='13'");
}
else if (strcmp ($res, "INVALID") == 0) {
// log for manual investigation
}
}
fclose ($fp);
}
?>
when i click the upgrade button and pay, it doesnt show me a go back to the website button... but there is a go back to my#email.com button, which has a 10 sec delay and takes me back to my website... although it popups a warning about encrypted data, which i dont know what it is.
Also the query i use in ipn.php does not execute.I dont even know if it goes to ipn.php.
Regarding go back to "my#email.com", this could happen if the email you specified doesn't map to an account in the PayPal sandbox. Perhaps you're using your real email in the button instead of a sandbox account email?
Another possibility is that your test account at "my#email.com" is not a business account. If you have a business account it should reflect your business name instead.
As for not receiving the IPNs, the sandbox doesn't always do a great job at delivering IPNs on time, if at all. I'd actually suggest that you try integrating using Express Checkout instead of Website Payments Standard. Express Checkout is a little bit of a confusing dance initially but it is easy to implement after you try to understand it. Here's what I think is the best doc explaining how Express Checkout works:
https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_ECSimpleIntegration
And when you're ready to dive into the implementation you should look here:
https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/howto_api_reference
The nice thing about using Express Checkout instead of relying on IPN is that you get to figure out the payment status the moment your user returns to your site, and you don't have to sit around waiting for the IPN to show up.
With Express Checkout you also get to override your business name with a custom "brand name" so you can use the same receiving PayPal account on different sites with different "brands".
Good luck!