-
Posts
827 -
Joined
-
Last visited
-
Days Won
9
Everything posted by fastsol
-
What kind of information are you storing that you need to encrypt only to decrypt to show it to the same person that gave it to you? Some more details from you would give us a better comprehension of your goal and how to advise you.
-
PayPal IPN getting payment status and other values
fastsol replied to seany123's topic in PHP Coding Help
In my opinion, you don't need both the api and the ipn, it's one or the other depending on your system. With the api all of the transaction is taken care of right then, you can update and do whatever you want in the db at that time. With the ipn, you need to wait for paypal to send the ipn and then update the db. Also with the ipn way, paypal doesn't redirect back immediately after the transaction, whereas the api redirects back as soon as paypal secures the payment on your behalf so you can finish the payment on your site. The new api is really the better way to go about taking payments on your website, I only used the ipn cause the other older versions of things they had were far to complicated to integrate easily, unlike the new api which is far easier now. -
PayPal IPN getting payment status and other values
fastsol replied to seany123's topic in PHP Coding Help
Here is the basic script that paypal provides for the ipn service. <?php //reading raw POST data from input stream. reading pot data from $_POST may cause serialization issues since POST data may contain arrays $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_exits = true; } foreach ($myPost as $key => $value) { if($get_magic_quotes_exits == true && get_magic_quotes_gpc() == 1) { $value = urlencode(stripslashes($value)); } else { $value = urlencode($value); } $req .= "&$key=$value"; } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'https://www.paypal.com/cgi-bin/webscr'); 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_HTTPHEADER, array('Host: www.paypal.com')); // In wamp like environment where the root authority certificate doesn't comes in the bundle, you need // to 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'); $res = curl_exec($ch); curl_close($ch); // assign posted variables to local variables //$item_name = htmlentities($_POST['item_name_1']); //$item_number = (int)$_POST['item_number_1']; 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 } else if (strcmp ($res, "INVALID") == 0) { // log for manual investigation } ?> You then go into your paypal account and turn on ipn service and provide the full url path to your ipn processing script. I can tell you from experience that making sure your script works properly can be tricky since your can't really see the errors it throws when ran cause it's called from paypals side. I started by making a simple db table to hold the full posted results from paypal so I could see what they send back and how it was named. foreach($_POST as $k => $v) { $value.= $k.' / '.$v.', '; } $set = $db->prepare("INSERT INTO `test` SET `posted_values` = ?"); $set->execute(array($value)); Then to do my own testing based on the posted info I made another script that puts all the info into a form with text fields so I could repeatedly post the info and test additional query stuff or processing stuff. <?php // This list needs to be coppied from the posted text in the table paypal posted to in the other script I showed you. $test = 'mc_gross / 65.00, protection_eligibility / Eligible, address_status / confirmed, item_number1 / 14, payer_id / KP3ZSMAGVU764, tax / 0.00, address_street / 3415 Delaware Dr., payment_date / 15:22:41 Mar 04 2014 PST, payment_status / Completed, charset / windows-1252, address_zip / 29040, mc_shipping / 0.00, mc_handling / 0.00, first_name / kevin, mc_fee / 2.19, address_country_code / US, address_name / kevin korstange, notify_version / 3.7, custom / 0::standard::c, payer_status / unverified, business / [email protected], address_country / United States, num_cart_items / 1, mc_handling1 / 0.00, address_city / Dalzell, verify_sign / AFcWxV21C7fd0v3bYYYRCpSSRl31AQ50RA-5fQQNKQEAtVOK-KdptSAk, payer_email / [email protected], mc_shipping1 / 0.00, tax1 / 0.00, txn_id / 8JV23519RC589220L, payment_type / instant, last_name / korstange, address_state / SC, item_name1 / CWP Certification Course - 3/15/2014, receiver_email / [email protected], payment_fee / 2.19, quantity1 / 1, receiver_id / UK6DJWQC3AXBE, txn_type / cart, mc_gross_1 / 65.00, mc_currency / USD, residence_country / US, transaction_subject / 0::standard::c, payment_gross / 65.00, ipn_track_id / 1d2ea5b3bcfad'; if(isset($_POST['submit'])) { print_r($_POST); } ?> <div style="width:350px; text-align: right"> <form action="" method="post"> <?php $item = explode(",", $test); echo '<input type="submit" name="submit" value="submit"><br>'; foreach($item as $i) { $ex = explode(" / ", $i); echo trim($ex[0]).' <input type="text" name="'.trim($ex[0]).'" value="'.$ex[1].'"><br>'."\n"; //$ex[] = explode(" / ", $i); } $op_array = array(); foreach($item as $i) { $ex = explode(" / ", $i); //echo $ex[0].' - '.$ex[1].'<br>'; } echo ''; ?> <input type="submit" name="submit" value="submit"> </form> </div> Be aware though, at least cause of how I stored the info and how I explode it, the "address_street /" in the $test usually contains a "," in the value part. I usually just delete the last half of the address since that's not really the data you need to deal with anyway, otherwise the explode will give you unexpected results and the input names won't match up right. Here is what one of my full ipn scripts looks like. <?php require_once($_SERVER['DOCUMENT_ROOT'].'/site_req/core.php'); require_once(ROOT.'site_inc/system_inc/includes.php'); //reading raw POST data from input stream. reading pot data from $_POST may cause serialization issues since POST data may contain arrays $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_exits = true; } foreach ($myPost as $key => $value) { if($get_magic_quotes_exits == true && get_magic_quotes_gpc() == 1) { $value = urlencode(stripslashes($value)); } else { $value = urlencode($value); } $req .= "&$key=$value"; } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'https://www.paypal.com/cgi-bin/webscr'); 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_HTTPHEADER, array('Host: www.paypal.com')); // In wamp like environment where the root authority certificate doesn't comes in the bundle, you need // to 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'); $res = curl_exec($ch); curl_close($ch); // assign posted variables to local variables //$item_name = sanitize($_POST['item_name_1']); //$item_number = (int)$_POST['item_number_1']; if(isset($_POST['item_name_1'])){ $item_name = sanitize($_POST['item_name_1']); } elseif(isset($_POST['item_name1'])){ $item_name = sanitize($_POST['item_name1']); } elseif(isset($_POST['item_name'])){ $item_name = sanitize($_POST['item_name']); } if(isset($_POST['item_number_1'])){ $item_number = (int)$_POST['item_number_1']; } elseif(isset($_POST['item_number1'])){ $item_number = (int)$_POST['item_number1']; } elseif(isset($_POST['item_number'])){ $item_number = (int)$_POST['item_number']; } else{$item_number = '';} $payment_status = $_POST['payment_status']; $payment_amount = (float)$_POST['mc_gross']; $payment_currency = $_POST['mc_currency']; $txn_id = sanitize($_POST['txn_id']); $receiver_email = $_POST['receiver_email']; $payer_email = $_POST['payer_email']; $product_id = (int)$_POST['custom']; 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 $bad = FALSE; if($payment_status != 'Completed'){ $bad = TRUE; $what='status';} if(checkDepositTxn($txn_id) === TRUE) { $bad = TRUE; $what='txn';} if($receiver_email != Settings::get('paypal_email')) { $bad = TRUE; $what='email';} //if($payment_amount != '20.00') { $bad = TRUE; $what='amount';} if($payment_currency != 'USD') { $bad = TRUE; $what='currency';} if(empty($item_number)){ $bad = TRUE; $what = 'other charge'; } $db = DB::getInstance(); if($bad === FALSE) { //Process payment stats $now = time(); $set = $db->prepare("INSERT INTO `".QUOTE_DEPOSITS."` SET `txn_id`= ?, `q_id`='$item_number', `part_num`= ?, `dep_date`='$now', `product_id`=$product_id, `deposit_amount`=$payment_amount"); $set->execute(array($txn_id, $item_name)); //$db->query("UPDATE `".QUOTE_RESPONSES."` SET `purchased`=1 WHERE `id`='$item_number'"); } elseif($bad === TRUE && $what != 'other charge') { $valu=''; foreach($_POST as $k => $v) { $valu.= $k.' / '.$v.', '; } $valu = sanitize($valu); $set2 = $db->prepare("INSERT INTO `".QUOTE_DEPOSITS."` SET `why` = ?, `params` = ?"); $set2->execute(array($what, $valu)); } } else if (strcmp ($res, "INVALID") == 0) { // log for manual investigation } ?> I have another that my cms uses that is much longer. And no you can't use 2 different ipn scripts, I have this one as a special use for a particular site, whereas my cms script is used in typical cases. Hope that helps get you started. NOTE: the code I posted to test the values sent by paypal was pieced together on this post since the whole script contains other stuff that was specific to my site and would only confuse anyone else using it so I removed those parts. So that code is untested as it sits on this post, maybe syntax errors if I missed something in the piecing together. -
PayPal IPN getting payment status and other values
fastsol replied to seany123's topic in PHP Coding Help
You're confusing the 2 concepts between the tutorial and what IPN is. -
PayPal IPN getting payment status and other values
fastsol replied to seany123's topic in PHP Coding Help
No the IPN doesn't redirect, paypal redirects and then paypal sends a separate POST to the IPN file you list inside your actual paypal account. The tutorial does not have anything to do with IPN. Like I said, I'm pretty sure that the new api doesn't handle anything with IPN, that's something totally different. -
PayPal IPN getting payment status and other values
fastsol replied to seany123's topic in PHP Coding Help
I have not used the new paypal api as of yet, but understand it a little. The IPN service i don't think is really part of the api. IPN is a separate thing that paypal does on it's own AFTER a transaction has happened on THEIR site. I use the IPN for my business so I know how it works not using the api anyway. I have considered switching to the new api stuff as it seems easier to understand and gives a certainly faster response of the transaction than the classic IPN does. The IPN can take sometimes a minute to finally process to your server, where as the new api it's pretty much handled by you instantly. Here is a good tutorial on the new api https://youtu.be/BD1dOWIABe0