6

I've made a form. Currently this form does the following operations:

  1. customer fills up the form (creates an order)
  2. clicks on "Submit" button
  3. all form entries are entered into a database.

I'd like to change it to do the following operations:

  1. customer fills up the form
  2. in the end of the form there is a text box showing much this order will cost him.
  3. clicks on "Submit" button (if accepts the price)
  4. redirected to paypal
  5. if the payment is successful -> all form entries are entered into a database. Else -> echo "transaction failed".

Here is what I've done so far:

"form.php" contents

<html><head><title>Title</title></head><body>
<form action="php-form-processor.php" method="post">
    <table border="0" cellspacing="5" width = "500">
        <tr>
            <td align="right" width="160">Choose an Item:</td>
            <td align="left">
            <select name="formItem" value="<?=$varItem;?>" class="input_full" >
                <option value="1">Cheese</option>
            </select>
            </td>
        </tr>
        <tr bgcolor="#D0E8F5">
            <td align="right" >Item count:</td>
            <td align="left">
                <input type="text" name="formItemCount" maxlength="50" value="<?=$varItemCount = 1;?>"  class="input_full" />
            </td>
        </tr>
    </table>
    <p align="center">
    <input type="submit" name="formSubmit" align = "center" value="Submit" />
    </p>
</form></body></html>

"php-form-processor.php" contents

<?php
if($_POST['formSubmit'] == "Submit")
{
    $varItem = $_POST['formItem'];
    $varItemCount = $_POST['formItemCount'];

    //database stuff
    $username = "...";
    $password = "...";
    $hostname = "..."; 
 // connect and add to the database varItem and varItemCount
    mysql_query($sql);
    mysql_close($dbhandle);
}
?>

The form is much bigger but i've simplified the stackoverflow's version of it. The price of an order must change according to "varItem" and "varItemCount" value. Basically I want to add "Pay with PayPal" option before writing an order into the database. P.S. I've already registered paypal Sandbox account and added "Buyer" and a "Seller".

what should I do next?

EDIT: ok, so here is a small guide how to solve the problem. Here are some advises:

  • first, download paypal IPN listener wrapper: https://github.com/Quixotix/PHP-PayPal-IPN
  • then register SandBox account plus 1 buyer and 1 seller acc
  • login as a seller and create a form (with non-hosted button!)
  • place the form into your page and parse the ID or any other necessary information via "custom" input (some helpful advises can be found here: http://www.devshed.com/c/a/PHP/Creating-a-Paypal-IPN-System-in-PHP-Part-Two/)
  • now place redirect to this page after Form submit
  • don't forget to enable IPN at paypal Seller account and enter IPNlistener link into a necessary address field
  • submit a paypal form and wait for response on listener
  • done

Whole proccess looks like this:

  1. customer fills up the form
  2. after submitting the form - all entries are written into the database + ID + 1 additional field called "payed" which represents: 1 - if customer payed for an order and 0 - if not
  3. use header("Location: URL") to redirect from Form_Processing to Paypal_Form
  4. use the "session" to write order ID into a session or use POST message
  5. submit the PaypalForm and use "custom" field as a carier for our order ID
  6. set up the listener to update the database as following: if transaction was successful -> update the database column "payed" to 1 (done). Use the ID from "custom" field to select needed order i.e.:

$sql = "UPDATE paypal_test SET payed = '1' WHERE id = '".$_POST['custom']."'";

Now we have a database with completed and non-completed forms. Additionaly you can write a logic which will remove "old" uncompleted orders. For this reason you can create additional column called "date" and then compare: if (current_date.days - old_date.days > 7) -> remove from DB. That's it!

Alex
  • 4,607
  • 9
  • 61
  • 99
  • What is your actual question? It seems to me you still need confirmation from Paypal on this transaction (your step 5). Are you using the IPN mechanism for this? – Patrick Savalle Aug 06 '12 at 12:48
  • Make sure you are checking the amount the person(s) paid - you can modify the input POST variables to PayPal with some client hacking so someone could pay $1 for a $100 item and unless you check it they could get away with it. PayPal will respond with the amount if I remember correctly. Also ensure this is the correct type of transaction (I think "Web Payment Accept" but there is loads of different ones like "eCheque" which do not represent a completed transaction - the IPN sends all notifications, including refunds) – williamvicary Aug 07 '12 at 14:06
  • oops not enough time to edit the comment so I'll create a new one soon – Alex Aug 07 '12 at 19:15
  • @williamvicary Thank you for suggestion regarding price check.. I'll create a database column which will contain the price that customer has to pay.. If the response I receive from the paypal has a different sum of money -> database won't be updated. If there are some other methods/ideas to improve the security I'll gladly hear them out! Also, regarding "transaction type" I don't fully understand how "eCheque" is any worse than "Web Payment Accept" and how can I ensure that customer won't use the "bad" method? Unless paypal has that option ofc. – Alex Aug 07 '12 at 19:26
  • Paypal doesn't have that option, an eCheque takes time to clear and afaik can be cancelled by the payee. I suggest you read the variable docs https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_admin_IPNReference#id08CTB0S055Z it was a few years ago and things might have changed. – williamvicary Aug 08 '12 at 09:57
  • very good explanation and thank you it has helped a lot. – Kirill Fuchs Sep 11 '12 at 13:21

3 Answers3

2

Well, you pretty much already described what you need to do:

  • 1st: make an onChange javascript, that sums up the value and posts it at the place you want;
  • 2nd: do a php check of the values after submit ( make sure to also check for injection issues );
  • 3rd: redirect to paypal and wait for the answer;
  • 4th: according to paypals answer echo out the result;

PS: I hope you are not waiting for someone to actually rewrite the whole script for you ;)

Peon
  • 7,902
  • 7
  • 59
  • 100
1

I would not accept what the PayPal post back is giving you, it's a sloppy way of checking the authentication of the user and expects the user to click the "go back to website" button. Instead use the IPN (https://www.paypal.com/ipn/) and make sure you post the response back to PayPal for verification.

Checkout this PHP example from PayPal: https://cms.paypal.com/uk/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_admin_IPNImplementation

williamvicary
  • 805
  • 5
  • 20
  • thank you! your IPN suggestion was helpful. Look at "edit" to see how i solved the problem in the end. (if you want to ofc) ;) – Alex Aug 06 '12 at 20:28
0

Tat late to the party....but in 2021 try this..

If you want to use a custom form in combination with paypals Smart Payment Buttons (https://developer.paypal.com/docs/checkout/) then you could try this approach. That works for me and you also don't need IPN (below approach is most current and much faster).

On your frontend use this (w/ this you can send your form data to your server):
https://developer.paypal.com/demo/checkout/#/pattern/server

On you backend use this (I put create & capture code in one file):
To create the order:
https://developer.paypal.com/docs/checkout/reference/server-integration/set-up-transaction/
To capture the order:
https://developer.paypal.com/docs/checkout/reference/server-integration/capture-transaction/
To set it up:
https://developer.paypal.com/docs/checkout/reference/server-integration/setup-sdk/

Now you can write form data to your db after paypal approved the order.

Gave similar answer here
How to submit data for the address and payment details after PayPal payment is made

Chris K.
  • 75
  • 6