3

there is a limit of 256 characters on the custom field for a Paypal html button. Is there a way to increase that limit or are there other fields that I can user (like custom1, custom2, other), etc...

Thank you

user765368
  • 19,590
  • 27
  • 96
  • 167
  • 1
    No, why do you need more than 256 chars? – Steve Nov 25 '15 at 18:44
  • cause I send a lot of custom data – user765368 Nov 25 '15 at 18:44
  • Just to receive it back on your server via IPN? – Steve Nov 25 '15 at 18:46
  • To receive and update DB – user765368 Nov 25 '15 at 19:04
  • add the data to the DB before redirecting to paypal – Steve Nov 25 '15 at 19:42
  • What if the user cancels the transaction, how would I know which data to delete. Once the user is on Paypal's website, there's no way to know what's in my database. – user765368 Nov 25 '15 at 20:35
  • You save the data to the db, get the row id, and send that in the custom field. When the IPN comes in, you take the row id from the ipn custom field, and update the status column to completed. Only completed orders get processed. – Steve Nov 25 '15 at 20:41
  • But when the user cancels, IPN url is not executed, but **cancel_return**. So if I send data to IPN, I wouldn't know if the user cancelled the transaction. I wanna delete the temporary record when the user cancels the transaction. – user765368 Nov 25 '15 at 21:08
  • Are the transaction IPN variables also $_POSTED to cancel_return url? – user765368 Nov 25 '15 at 21:15
  • I cant remember, but there are 2 things you can do. 1> set the id as a url parameter for the cancel url: `cancel_return=>your/cancel/url?orderid=' . $id` then you can get it with `$_GET['orderid']` on cancel page. 2> run a cron job every hour/day/whatever to delete pending orders older than x minutes, eg `DELETE from ORDERS where status = pending and created_on < sometimestamp` – Steve Nov 25 '15 at 21:21
  • The cron clears orders that were abandoned without returning to the cancel url (eg close browser window) – Steve Nov 25 '15 at 21:27
  • As a bonus, by capturing the data before payment, you can follow up cancels if you like, eg instead of deleting them, send them a marketing email, discount etc – Steve Nov 25 '15 at 21:30
  • The problem is, my button that sends the user to Paypal is not generated dynamically. I have the button HTML in the code. So how will I know that the record id that I send as parameter to my cancel_return url is for a particular user for a particular transaction? – user765368 Nov 25 '15 at 21:48
  • I'll write an answer with the process explained – Steve Nov 25 '15 at 21:55
  • No problem, hopefully that helps explain the process. – Steve Nov 25 '15 at 23:01

2 Answers2

4

Instead of sending a whole load of data via the custom field, save the data in a database, and send a record id. On ipn / cancel, retrieve the ID and update/delete the record.

To do this, 1st you need to change the button code to post to a php file on your own site not paypal, so the regular button code:

<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_xclick">
<input type="hidden" name="business" value="seller@designerfotos.com">
<input type="hidden" name="item_name" value="hat">
<input type="hidden" name="item_number" value="123">
<input type="hidden" name="amount" value="15.00">
<input type="image" name="submit" border="0"
src="https://www.paypalobjects.com/en_US/i/btn/btn_buynow_LG.gif"
alt="PayPal - The safer, easier way to pay online">
</form>

Becomes:

<form action="buttonhandler.php" method="post">
    <input type="hidden" name="item_number" value="123">
    <input type="image" name="submit" border="0"
    src="https://www.paypalobjects.com/en_US/i/btn/btn_buynow_LG.gif"
    alt="PayPal - The safer, easier way to pay online">
</form>

Note that a few fields are missing - cmd, business, item_name and amount, as we will generate those in php.

You could have the amount defined in the button html, but it would be better to have it defined in your database, then you can automatically reject orders where the user paid the wrong amount (by fiddling with the data sent to paypal - something they can currently do with your normal html button system).

In the php file, you collect the product info, save the order to the db, and generate the paypal data that would normally be included in the button form fields

//buttonhandler.php

$item_number = $_POST['item_number'];
//get item name, price from DB
//Note made up ORM code here for brevity - 
//use whatever db acccess method you usually do:
$item = Items::getOne($item_number);

//save order in db, and retrieve order id. You can save whatever you need into the order, 
//this is a simple example that just takes item number, amount and timestamp
Orders::add($item->number, $item->amount, time());
$orderId = Orders::lastInsertId();

//create paypal data
$paypalData=array(
    'business'=>'seller@designerfotos.com',
    'cmd'=>'_xclick',
    'notify_url'=>'http://yoursite.com/1hd-ff-ipn.php', //call this something random, you dont want it getting hit by web bots
    'return'=>'http://yoursite.com/thanks-for-your-order.php',
    'cancel_return'=>'http://yoursite.com/cancel.php?orderid=' . $orderId,
    'amount'=>$item->amount,
    'currency_code'=>'GBP',
    'item_number'=>$item->number,
    'item_name'=>$item->name,
    'custom'=>$orderId
);
 //build a query string and redirect to paypal
$query_string = http_build_query($paypalData);
header("Location: https://www.paypal.com/cgi-bin/webscr?" . $query_string);
//done
die();

Now you can crosscheck price against orderid in your ipn script:

//1hd-ff-ipn.php
$order = Orders::getOne($_POST['custom']);
if ($_POST['mc_gross'] != $order->amount) {
    //price mismatch, handle accordingly
}
//more checks here as required, then
$order->paymentStatus = 'complete';
$order->save(); 

And delete orders in your cancel page

//cancel.php
Orders::delete($_GET['orderid');
?>
<h1>Sorry you cancelled</h1>

You can also run a crom every hour/day/whatever to handle abandoned orders

//cron.php
//delete pending older than 1 day, 
Orders::deleteWhere('status = ? and ordered_on <?','pending', time() - (24 * 60 * 60));
Steve
  • 20,703
  • 5
  • 41
  • 67
  • Thank you very much, I will follow your approach but I think it's better if I send the parameter to my cancel_return url with jQuery. It's gonna require too many changes if I do it exactly like you described. – user765368 Nov 25 '15 at 23:13
0

You can use these:

<input type="hidden" name="on0" value="Size">
<input type="hidden" name="on1" value="Position">

First option field name and label. The os0 variable contains the corresponding value for this option field. For example, if on0 is size, os0 could be large.

Second option field name and label. The os1 variable contains the corresponding value for this option field. For example, if on1 is color then os1 could be blue. You can specify a maximum of 7 option field names (6 with Subscribe buttons) by incrementing the option name index (on0 through on6).

Optional for Buy Now, Add to Cart, Subscribe, Automatic Billing, and Installment Plan buttons
Not used with Donate or Buy Gift Certificate buttons
Atif Tariq
  • 2,650
  • 27
  • 34