Hack 73 Implement Price Checking with IPN

 < Day Day Up > 

figs/moderate.gif figs/hack73.gif

Prevent fraudulent transactions by comparing the value of the goods purchased with the amount received .

PayPal has taken many steps to ensure that their system is secured against fraudulent transactions. However, just like any online eCommerce system, there are always ways for an unscrupulous person to attempt to cheat you. The PayPal Buy Now and Shopping Cart buttons , for example, are normally displayed as plain text in your web page's source code, which means that anyone can view your HTML code ormore importantlycopy and modify the code, and then submit a spoof payment (presumably with a lower price) to PayPal. And since PayPal doesn't maintain an active database of all the current prices of your products, it's up to you to engage in some proactive price checking.

See [Hack #36] for ways to hide your payment button code from customers and reduce the possibility of spoofed payments.


Obviously, the primary concern is the price, given how easily it can be changed from, say, $18.00 to $.18. While a merchant who is able to view each and every transaction will likely notice when a $100 item was purchased for $.01, but it can, of course, be easy to miss this kind of thing, especially for high-volume merchants . And if you have a fully automated fulfillment system, such as for digital goods [Hack #71] , you'll need to employ some sort of price checking.

The following solution employs the trusty IPN system to check whether a customer has paid the correct amount.

7.13.1 Simple Price Checking with Single Item Purchases

The PayPal IPN system posts the variables as they were originally submitted to PayPal, so a spoofed price will be reflected in our IPN postback from PayPal. Because PayPal does not store any of your product information on their servers, you have to query your product information to ensure it matches the price the customer paid.

To use a price-checking system on your site, you need to be able to run a dynamic server page technology (e.g., ASP, as is used in this example) and a simple database (e.g., Microsoft Access). The table in this example, tblProducts , has only two columns : item_number , containing a list of all of the unique product numbers , and item_price , in which the corresponding prices are stored. Naturally, your product database will be more sophisticated, but it will likely have analogous fields.

Here is some skeleton code, written in ASP, that does rudimentary price checking for items purchased with Buy Now buttons:

 'Declare and populate our price checking variables Dim item_number, item_amount item_number = Request.Form("item_number") item_amount = "Request.Form("mc_gross") 'Connect to database and create recordset connStore = "DRIVER={Microsoft Access Driver (*.mdb)};DBQ=                 "C:/InetPub/wwwroot/database/dbPayPal.mdb") set rsPriceCheck = Server.CreateObject("ADODB.Recordset") rsPriceCheck.ActiveConnection = connStore rsPriceCheck.Source = "SELECT item_price FROM tblProducts                  WHERE item_number = 'item_number'" rsPriceCheck.Open( ) 'Compare the values to see if amount paid is equal to or                  greater than required If rsPriceCheck("item_amount") >= item_amount Then  'Price paid is at least as much as required, process order  'Order processing code here Else  'Price paid is less than required, stop order processing  'Send alert to purchaser and merchant End If 

See the "Database Coding and Platform Choices" section of the Preface for the additional information needed to put this SQL statement to work with this and the other hacks in this book.


This code relies on the mc_gross variable, which is equal to the purchase price plus any shipping, handling, or tax charges applied to the order (note that mc_gross does not include the deduction of any applicable PayPal fees).

This code merely checks to see if the price paid is equal to or higher than the price in your database. You'll want to account for shipping and sales tax, because these values can also be spoofed by customers.


7.13.2 Price Checking for Shopping Cart Purchases

PayPal does not pass back individual item prices in Shopping Cart transactions. If a customer buys three items worth $1.00, $2.00, and $5.00, respectively (and agrees to pay $3.50 for shipping), you don't get any of those individual values in the IPN data. Rather, the mc_gross variable will have a value of the total amount paid (in this case, $11.50). Thankfully, PayPal does pass back the individual item_number fields, which means that you can still look up the individual prices in your database.

In the long run, however, it might be easier to keep a running total on file for each customer's Shopping Cart so that you can easily cross-check this value with the amount paid.


As described in [Hack #45] and [Hack #50] , the PayPal Shopping Cart system returns an item number for each item in the cart. The variables are in the form item_number n , where n is the cart number for that item, starting with 1 . PayPal also provides the num_cart_items variable to indicate the number of items in the cart. To verify the order, add the values of each item as listed in your database and compare the total to the gross amount paid:

 Dim item_number, mc_gross, I, num_cart_items, price_check mc_gross = Request.Form("mc_gross") num_cart_items = Request.Form("num_cart_items") price_check = 0 For i=1 to num_cart_items  'Populate variable with value  item_number = Request.Form("item_number" & i)  'Execute SQL query on database with item_number value  'Connect to database and create recordset   connStore = "DRIVER={Microsoft Access Driver (*.mdb)};                 DBQ="C:/InetPub/wwwroot/database/dbPayPal.mdb")   set rsPriceCheck = Server.CreateObject("ADODB.Recordset")   rsPriceCheck.ActiveConnection = connStore   rsPriceCheck.Source = "SELECT item_price FROM tblProducts                  WHERE item_number = 'item_number'"   rsPriceCheck.Open( )  'Add value from database to our running count  price_check = price_check + rsPriceCheck("item_price") Next If price_check = mc_gross OR price_check > mc_gross Then  'Price paid is at least as much as required, process order  'Order processing code here Else  'Price paid is less than required, stop order processing  'Send alert to purchaser and merchant End If 

This ASP code assumes a quantity of 1 for each cart item. If you offer multiple quantities of items, you will need to take the item_quantity value into account by multiplying the database price value by the price of the item.


7.13.3 Sending a Price Check Alert

Once you see a problem with an order, it's up to you to send an alert. Use any simple mail component available to you and your server technology. In ASP, you can use the Common Data Objects (CDO) mail component with the following code:

 Dim PriceErrorCDO Set PriceErrorCDO = Server.CreateObject("CDOSYS.NewMail") PriceErrorCDO.From = Request.Form("receiver_email") PriceErrorCDO.To = Request.Form("receiver_email") PriceErrorCDO.CC = Request.Form("payer_email") PriceErrorCDO.Subject = "IPN Price Checking Error" PriceErrorCDO.Body = "There has been a price-checking error          on the following transaction: " & Request.Form("txn_id") & "" PriceErrorCDO.Send( ) Set PriceErrorCDO = Nothing 

This email alert code sends an email to the recipient of the payment (you), but you might also want to send an automatic email to the customer to indicate that there will be a delay in processing the order.

If you want a truly automated system, you can simply refund any irregular payments using the PayPal API [Hack #91] .


 < Day Day Up > 


PayPal Hacks
PayPal Hacks
ISBN: 0596007515
EAN: 2147483647
Year: 2004
Pages: 169

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net