Last active
August 29, 2015 13:56
-
-
Save BenRacicot/9174899 to your computer and use it in GitHub Desktop.
PayPal IPN Script that creates a post in 'Orders_
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Add this code to functions.php to create a custom table to store order data. | |
// ALTERNATE | |
// Use a CPT to create a post each time an order is made. | |
// require_once('order-post-type.php'); | |
// ALTERNATE | |
// code to create custom table on theme activation | |
function create_orders_table_on_activate() { | |
// versioning for future db upgrades | |
$orders_db_version = "1.0"; | |
global $orders_db_version; | |
add_option( "orders_db_version", $orders_db_version ); | |
global $wpdb; | |
$table_name = $wpdb->prefix . "customer_orders"; | |
//http://codex.wordpress.org/Creating_Tables_with_Plugins | |
$sql = "CREATE TABLE $table_name ( | |
id mediumint(9) NOT NULL AUTO_INCREMENT, | |
time datetime DEFAULT '0000-00-00 00:00:00' NOT NULL, | |
first tinytext NOT NULL, | |
last tinytext NOT NULL, | |
email tinytext NOT NULL, | |
address tinytext NOT NULL, | |
zip VARCHAR(55) DEFAULT '' NOT NULL, | |
town tinytext NOT NULL, | |
product tinytext NOT NULL, | |
price tinytext NOT NULL, | |
userip tinytext NOT NULL, | |
UNIQUE KEY id (id) | |
);"; | |
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' ); | |
dbDelta( $sql ); // very picky! No unnessasary spaces, commas, dashes, underscroes etc in SQL | |
// Load in an example | |
$firstname = "Ben"; | |
$lastname = "Racicot"; | |
$dummy_email = "[email protected]"; | |
$dummy_address = "311 Their St."; | |
$dummy_zip = 02324; | |
$dummy_town = 'Boston'; | |
$item_purchased = "Coach Bag"; | |
$dummy_price = 500.00; | |
$dummyip = "192.168.1.1"; | |
$table_name = $wpdb->prefix . "customer_orders"; | |
$rows_affected = $wpdb->insert( $table_name, | |
array( | |
'time' => current_time('mysql'), | |
'first' => $firstname, | |
'last' => $lastname, | |
'email' => $dummy_email, | |
'address' => $dummy_address, | |
'zip' => $dummy_zip, | |
'town' => $dummy_town, | |
'product' => $domain_purchased, | |
'price' => $dummy_price, | |
'userip' => $dummyip, | |
) | |
); | |
} | |
add_action("after_switch_theme", "create_orders_table_on_activate"); | |
// End code to execute on theme activation | |
// Standard html table solution | |
function scientifik_wp_orders() { | |
add_menu_page('Orders', 'Orders', 'administrator', 'scientifik_orders', 'include_orders_page', 'dashicons-networking'); | |
} | |
function include_orders_page(){ | |
// Create sortable tables within this file to display and sort your tables data | |
require_once('orders.php'); | |
} | |
add_action('admin_menu', 'scientifik_wp_orders'); | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Relevant Links | |
// https://developer.paypal.com/docs/classic/paypal-payments-standard/integration-guide/Appx_websitestandard_htmlvariables/ | |
// 2014 IPN scripts https://github.com/paypal/ipn-code-samples | |
// https://developer.paypal.com/webapps/developer/applications/ipn_simulator | |
// CONFIG: Enable debug mode. This means we'll log requests into 'ipn.log' in the same directory. | |
// Especially useful if you encounter network errors or other intermittent problems with IPN (validation). | |
// Set this to 0 once you go live or don't require logging. | |
define("DEBUG", 1); | |
// Set to 0 once you're ready to go live | |
define("USE_SANDBOX", 1); | |
define("LOG_FILE", "./ipn.log"); | |
// Read POST data | |
// reading posted data directly from $_POST causes serialization | |
// issues with array data in POST. Reading raw POST data from input stream instead. | |
$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_exists = true; | |
} | |
foreach ($myPost as $key => $value) { | |
if($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) { | |
$value = urlencode(stripslashes($value)); | |
} else { | |
$value = urlencode($value); | |
} | |
$req .= "&$key=$value"; | |
} | |
// Post IPN data back to PayPal to validate the IPN data is genuine | |
// Without this step anyone can fake IPN data | |
if(USE_SANDBOX == true) { | |
$paypal_url = "https://www.sandbox.paypal.com/cgi-bin/webscr"; | |
} else { | |
$paypal_url = "https://www.paypal.com/cgi-bin/webscr"; | |
} | |
$ch = curl_init($paypal_url); | |
if ($ch == FALSE) { | |
return FALSE; | |
} | |
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); | |
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_FORBID_REUSE, 1); | |
if(DEBUG == true) { | |
curl_setopt($ch, CURLOPT_HEADER, 1); | |
curl_setopt($ch, CURLINFO_HEADER_OUT, 1); | |
} | |
// CONFIG: Optional proxy configuration | |
//curl_setopt($ch, CURLOPT_PROXY, $proxy); | |
//curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1); | |
// Set TCP timeout to 30 seconds | |
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30); | |
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close')); | |
// CONFIG: Please download 'cacert.pem' from "http://curl.haxx.se/docs/caextract.html" and set the directory path | |
// of the certificate as shown below. Ensure the file is readable by the webserver. | |
// This is mandatory for some environments. | |
//$cert = __DIR__ . "./cacert.pem"; | |
//curl_setopt($ch, CURLOPT_CAINFO, $cert); | |
$res = curl_exec($ch); | |
if (curl_errno($ch) != 0) // cURL error | |
{ | |
if(DEBUG == true) { | |
error_log(date('[Y-m-d H:i e] '). "Can't connect to PayPal to validate IPN message: " . curl_error($ch) . PHP_EOL, 3, LOG_FILE); | |
} | |
curl_close($ch); | |
exit; | |
} else { | |
// Log the entire HTTP response if debug is switched on. | |
if(DEBUG == true) { | |
error_log(date('[Y-m-d H:i e] '). "HTTP request of validation request:". curl_getinfo($ch, CURLINFO_HEADER_OUT) ." for IPN payload: $req" . PHP_EOL, 3, LOG_FILE); | |
error_log(date('[Y-m-d H:i e] '). "HTTP response of validation request: $res" . PHP_EOL, 3, LOG_FILE); | |
// Split response headers and payload | |
list($headers, $res) = explode("\r\n\r\n", $res, 2); | |
} | |
curl_close($ch); | |
} | |
// mail('[email protected]', 'php mail func', 'ipntwo.php has run.'); | |
// Inspect IPN validation result and act accordingly | |
if (strcmp ($res, "VERIFIED") == 0) { | |
// check whether the payment_status is Completed | |
// check that txn_id has not been previously processed | |
// check that receiver_email is your PayPal email | |
// check that payment_amount/payment_currency are correct | |
// process payment and mark item as paid. | |
// 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']; | |
// Test verification | |
// mail('[email protected]', 'You\'ve made a PayPal sale!', 'verified'); | |
// You should validate against these values. | |
$firstname = $_POST['first_name']; | |
$lastname = $_POST['last_name']; | |
$payeremail = $_POST['payer_email']; | |
$street = $_POST['address_street']; | |
$zip = $_POST['address_zip']; | |
$city = $_POST['address_city']; | |
$state = $_POST['address_state']; | |
$item = $_POST['item_name']; | |
$price = $_POST['payment_gross']; | |
$post_id = $_POST['item_number']; | |
$status = $_POST['payment_status']; | |
$receiver_email = $_POST['receiver_email']; | |
// Make sure we have access to WP functions namely WPDB | |
include_once($_SERVER['DOCUMENT_ROOT'].'/wp-load.php'); | |
global $wpdb; global $redux_options; | |
// Verify completed status | |
if ($status == 'Completed') { | |
// Just a test I used | |
//mail('[email protected]', 'IPN invalid message', 'The IPN returned Completed'); | |
// OPTIONAL Remove BIN btn by updating its value to nothing. | |
update_post_meta($post_id, '_cmb_bin_amount', '', $price); | |
// Send a notifcation email to admin via WPMAIL | |
$email = $redux_options['payment_email']; | |
$subject = $redux_options['payment_subject']; | |
$headers = "From: $payeremail\r\n"; | |
$message = | |
"Payment status verified as \'Completed\' from:\r\n". | |
"First: $firstname\r\n". | |
"Last: $lastname\r\n". | |
"Buyer Email: $payeremail\r\n". | |
"Address: $street\r\n". | |
"City: $city\r\n". | |
"State: $state\r\n". | |
"Zip: $zip\r\n". | |
"Domain: $item\r\n". | |
"Price: $price\r\n". | |
"Payment sent to $receiver_email\r\n". | |
"if $receiver_email is not your payment gateway\'s email address please investigate this transaction.\r\n". | |
"Always double check payment confirmation with your payment gateway before fulfilling any order.\r\n". | |
'BTW - congrats! You just sold an item.'; | |
wp_mail( $email, $subject, $message, $headers, $attachments ); | |
// Send a notifcation email to admin via PHP | |
mail('[email protected]', 'php mail func', $message); | |
// Create an Order's post | |
// Fill in its meta data from the buyer | |
// Update a custom table's data. | |
// $table_name = $wpdb->prefix . "customer_orders"; | |
// $wpdb->insert($table_name, | |
// array('firstname' => $firstname, | |
// 'lastname' => $lastname, | |
// 'email' => $payeremail, | |
// 'address' => $street, | |
// 'zip' => $zip, | |
// 'town' => $city, | |
// 'state' => $state, | |
// 'item' => $item, | |
// 'time' => current_time('mysql'), | |
// 'userip' => $_SERVER['REMOTE_ADDR'], | |
// 'price' => $price | |
// ), | |
// array('%s', // firstName | |
// '%s', // lastName | |
// '%s', // payerEmail | |
// '%s', // Street | |
// '%s', // zip | |
// '%s', // city | |
// '%s', // state | |
// '%s', // Item | |
// '%s', // Time | |
// '%s', // user ip | |
// '%s' // price | |
// ) | |
// ); | |
} | |
if(DEBUG == true) { | |
error_log(date('[Y-m-d H:i e] '). "Verified IPN: $req ". PHP_EOL, 3, LOG_FILE); | |
} | |
} else if (strcmp ($res, "INVALID") == 0) { | |
// log for manual investigation | |
// Add business logic here which deals with invalid IPN messages | |
// Seems to trigger even if "COMPLETED" | |
mail('[email protected]', 'IPN invalid message', 'The IPN returned invalid'); | |
if(DEBUG == true) { | |
error_log(date('[Y-m-d H:i e] '). "Invalid IPN: $req" . PHP_EOL, 3, LOG_FILE); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// This file makes sortable columns via HTML | |
// A better way would be to utilize native WordPress Tables. | |
// Use this -> http://wordpress.org/plugins/custom-list-table-example/ | |
// Let me know how you integrated your DB table's data into it! [email protected] | |
function orders_page() { ?> | |
<div class="wrap"> | |
<div id="icon-users" class="icon32"></div> | |
<h2>Orders</h2> | |
<p>Below is a list of all orders.</p> | |
<table class="widefat"> | |
<thead> | |
<th><input type="checkbox"></input></th> | |
<th>#</th> | |
<th>First</th> | |
<th>Last</th> | |
<th>Email</th> | |
<th>Address</th> | |
<th>Product</th> | |
<th>Date</th> | |
<th>User ip</th> | |
<th>Price</th> | |
</thead> | |
<tbody> | |
<?php | |
global $wpdb; | |
$table_name = $wpdb->prefix . "customer_orders"; | |
?> | |
<?php $orders = $wpdb->get_results("SELECT * FROM $table_name"); ?> | |
<?php if($orders) : ?> | |
<?php foreach($orders as $order) : ?> | |
<?php //$products = unserialize($order->domainpurchased); ?> | |
<tr> | |
<td><a href="" name="delete">delete</a></td> | |
<td><?php echo $order->id; ?></td> | |
<td><?php echo $order->first; ?></td> | |
<td><?php echo $order->last; ?></td> | |
<td><?php echo "<a href='mailto:$order->email' target='_blank'>$order->email</a>"; ?></td> | |
<td><?php echo $order->address; ?>, | |
<?php echo $order->zip; ?>, | |
<?php echo $order->town; ?> | |
</td> | |
<td><?php echo "<a href='http://".$order->product."' target='_blank'>$order->product</a>"; ?></td> | |
<td><?php echo $order->time; ?></td> | |
<td><?php echo $order->userip; ?></td> | |
<td><?php echo $order->price; ?></td> | |
<!-- <td> --> | |
<!-- <ul> --> | |
<?php | |
// for($i = 0; $i <= count($products); $i++) : | |
// echo '<li>'.$products[$i].'</li>'; | |
// endfor; | |
?> | |
<!-- </ul> --> | |
<!-- </td> --> | |
</tr> | |
<?php endforeach; ?> | |
<?php else : ?> | |
<tr colspan="8"> | |
<td>No orders yet.</td> | |
</tr> | |
<?php endif; ?> | |
</tbody> | |
</table> | |
</div> | |
<?php } | |
// Execute the function | |
orders_page(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment