Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature(app): Add precheckout webhook endpoint #103

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
242 changes: 242 additions & 0 deletions Tests/prepaymentwebhook_test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
{
"_links": {
},
"_embedded": {
"fx:items": [
{
"_links": {
},
"_embedded": {
"fx:item_options": [
{
"_links": {
},
"name": "size",
"value": "medium",
"price_mod": 0,
"weight_mod": 0,
"date_created": null,
"date_modified": null
},
{
"_links": {
},
"name": "color",
"value": "red",
"price_mod": 0,
"weight_mod": 0,
"date_created": null,
"date_modified": null
}
],
"fx:item_category": {
"_links": {
},
"admin_email_template_uri": "",
"customer_email_template_uri": "",
"code": "DEFAULT",
"name": "Default for all products",
"item_delivery_type": "flat_rate",
"max_downloads_per_customer": 3,
"max_downloads_time_period": 24,
"default_weight": 0,
"default_weight_unit": "LBS",
"default_length_unit": "IN",
"shipping_flat_rate_type": "per_item",
"shipping_flat_rate": 5,
"handling_fee_type": "none",
"handling_fee": 0,
"handling_fee_minimum": 0,
"handling_fee_percentage": 0,
"customs_value": 0,
"discount_type": "",
"discount_name": "",
"discount_details": "",
"send_customer_email": false,
"send_admin_email": false,
"admin_email": "",
"date_created": null,
"date_modified": null
}
},
"item_category_uri": "https://api.foxycart.com/item_categories/100",
"name": "Example Product",
"price": 15.99,
"quantity": 1,
"quantity_min": 0,
"quantity_max": 0,
"weight": 0,
"code": "1234",
"parent_code": "",
"discount_name": "",
"discount_type": "",
"discount_details": "",
"subscription_frequency": "",
"subscription_start_date": null,
"subscription_next_transaction_date": null,
"subscription_end_date": null,
"is_future_line_item": false,
"shipto": "Me",
"url": "",
"image": "",
"length": 0,
"width": 0,
"height": 0,
"expires": 0,
"date_created": null,
"date_modified": "2017-07-20T04:13:08-0700"
},
{
"_links": {
},
"_embedded": {
"fx:item_category": {
"_links": {
},
"admin_email_template_uri": "",
"customer_email_template_uri": "",
"code": "live",
"name": "Live Rates",
"item_delivery_type": "shipped",
"max_downloads_per_customer": 3,
"max_downloads_time_period": 24,
"default_weight": 5,
"default_weight_unit": "LBS",
"default_length_unit": "IN",
"shipping_flat_rate_type": "per_order",
"shipping_flat_rate": 1,
"handling_fee_type": "none",
"handling_fee": 0,
"handling_fee_minimum": 0,
"handling_fee_percentage": 0,
"customs_value": 0,
"discount_type": "",
"discount_name": "",
"discount_details": "",
"send_customer_email": false,
"send_admin_email": false,
"admin_email": "",
"date_created": null,
"date_modified": null
}
},
"item_category_uri": "https://api.foxycart.com/item_categories/101",
"name": "Another Product",
"price": 20,
"quantity": 1,
"quantity_min": 0,
"quantity_max": 0,
"weight": 5,
"code": "foo321",
"parent_code": "",
"discount_name": "",
"discount_type": "",
"discount_details": "",
"subscription_frequency": "",
"subscription_start_date": null,
"subscription_next_transaction_date": null,
"subscription_end_date": null,
"is_future_line_item": false,
"shipto": "Me",
"url": "",
"image": "",
"length": 0,
"width": 0,
"height": 0,
"expires": 0,
"date_created": null,
"date_modified": "2017-07-20T04:14:03-0700"
}
],
"fx:discounts": [
{
"code": "coupon",
"amount": -3.6,
"name": "Default Discount",
"display": "-$3.60",
"is_taxable": false,
"is_future_discount": false
}
],
"fx:custom_fields": [
{
"name": "custom_note",
"value": "Happy Birthday!",
"is_hidden": 0
}],
"fx:shipment": {
"address_name": "",
"first_name": "John",
"last_name": "Smith",
"company": "",
"address1": "Main Street",
"address2": "",
"city": "Saint Paul",
"region": "MN",
"postal_code": "55116",
"country": "US",
"origin_region": "TX",
"origin_postal_code": "77018",
"origin_country": "US",
"shipping_service_id": 0,
"shipping_service_description": "",
"is_residential": false,
"item_count": 2,
"total_weight": 5,
"total_customs_value": 0,
"total_handling_fee": 0,
"total_flat_rate_shipping": 5,
"total_item_price": 35.99,
"total_tax": 3.24,
"total_shipping": 0,
"total_price": 39.23
},
"fx:customer": {
"id": "1512345",
"first_name": "John",
"last_name": "Smith",
"email": "[email protected]",
"tax_id": "",
"is_anonymous": "0",
"_embedded": {
"fx:payments": [
{
"cc_type": "plastic",
"cc_number_masked": "xxxx xxxx xxxx 4242",
"cc_exp_month": "10",
"cc_exp_year": "2020",
"purchase_order": null
}
],
"fx:default_billing_address": {
"country": "US",
"region": "MN",
"city": "Saint Paul",
"postal_code": "55116",
"address1": "Main Street",
"address2": "",
"company": "",
"full_name": "John Smith",
"first_name": "John",
"last_name": "Smith",
"phone": ""
}
}
}
},
"customer_uri": "",
"template_set_uri": "",
"language": "",
"locale_code": "en_US",
"customer_ip": "192.168.0.1",
"ip_country": "United States",
"session_name": "fcsid",
"session_id": "hvcv28l8md0qc8qt5rrjh4qo85",
"total_item_price": 35.99,
"total_tax": 3.24,
"total_shipping": 14.23,
"total_future_shipping": 0,
"total_order": 49.86,
"date_created": null,
"date_modified": "2017-07-20T04:12:25-0700"
}
74 changes: 74 additions & 0 deletions prepaymentwebhookfunctions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php
//Exit if not called in proper context
if (!defined('ABSPATH')) exit();

function check_inventory($cart_details, $local_test, $wpdb) {
$response = array(
'ok' => true,
'details' => ''
);

$log_file = './log.txt';
$date = new DateTime();
$date_string = $date->format('Y-m-d H:i:s');

$log_line = $date_string . ': ' . $cart_details['customer_ip'] . ' - '. $cart_details['_embedded']['fx:customer']['email'] . ' -- ';

$no_stock_products = array();
$limited_stock_products = array();

foreach($cart_details['_embedded']['fx:items'] as $item) {
$product_id = -1;
$code = $item['code'];

$inv_code = "%" . $wpdb->esc_like($code) . "%";
$sql = $wpdb->prepare( "SELECT * FROM $wpdb->postmeta WHERE meta_key = %s AND meta_value LIKE %s", '_inventory_levels', $inv_code );
$meta_list = $wpdb->get_results( $sql );

foreach ($meta_list as $meta) {
$product_id = $meta->post_id;
$val = unserialize($meta->meta_value);
if (!is_array($val)) $val = array();
foreach ($val as $ivcode => $iv) {
if ($ivcode == $code) {
$inventory = $iv['count'];
if ($inventory === 0) {
array_push($no_stock_products, $item['name']);
}
else if ($item['quantity'] > $inventory) {
array_push($limited_stock_products, $item['name']);
}
break;
}
}
}
}

$response_text = "";

if (count($no_stock_products) > 0) {
$response_text = "Sorry, we are currently out of stock of the following " . ((count($no_stock_products) > 1) ? "items" : "item") . ": " . join(", ", $no_stock_products) . ". Please remove " . ((count($no_stock_products) > 1) ? "them" : "it") . " from your cart and try again.";
}

if (count($limited_stock_products) > 0) {
if ($response_text) {
$response_text .= "/n";
}
$response_text .= "Sorry, we currently have only limited stock of the following " . ((count($limited_stock_products) > 1) ? "items" : "item") . ": " . join(", ", $limited_stock_products) . ". Please reduce the quantity of " . ((count($limited_stock_products) > 1) ? "them" : "it") . " in your cart and try again.";
}

if ($response_text) {
$response['ok'] = false;
$response['details'] = $response_text;
}

$log_line .= (string) $response['ok'] . "\n";
$fp = fopen($log_file, 'a');
fwrite($fp, $log_line);

if ($local_test === false) {
header('Content-Type: application/json');
}
return $response;
}
?>
6 changes: 6 additions & 0 deletions settings-page.php
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,12 @@ function foxyshop_settings_page() {
<input type="text" id="foxyshop_datafeed_url" name="foxyshop_datafeed_url" value="<?php echo esc_url(get_bloginfo('url') . '/foxycart-datafeed-' . $foxyshop_settings['datafeed_url_key']); ?>/" readonly="readonly" onclick="this.select();" />
<a href="#" class="foxyshophelp">FoxyCart can be configured to send order information to a url on your website. If you want to use FoxyShop's datafeed and take advantage of inventory, user management and more, copy this url and enable the datafeed in your FoxyCart admin panel.</a>

<div style="clear: both;"></div>

<label for="foxyshop_prepayment_webhook_url"><?php _e('Prepayment Webhook URL', 'foxyshop'); ?>:</label>
<input type="text" id="foxyshop_prepayment_webhook_url" name="foxyshop_prepayment_webhook_url" value="<?php echo esc_url(get_bloginfo('url') . '/foxycart-prepayment-webhook-' . $foxyshop_settings['datafeed_url_key']); ?>/" readonly="readonly" onclick="this.select();" />
<a href="#" class="foxyshophelp">FoxyCart can be configured to send order information to a url on your website for a final check before completing the order. If you want to use FoxyShop's prepayment webhook and do a final check of inventory or for a custom prepayment check, copy this url and enable the prepayment webhook in your FoxyCart admin panel.</a>

<div style="clear: both;margin-bottom: 5px;"></div>

<label for="foxyshop_sso_url"><?php _e('SSO Endpoint', 'foxyshop'); ?>:</label>
Expand Down
13 changes: 12 additions & 1 deletion templateredirect.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ function foxyshop_theme_redirect() {
$request_arr = explode("/",$wp->request);
$request_start = $request_arr[0];
$request_end = end($request_arr);
$foxyshop_indicators = array(FOXYSHOP_PRODUCTS_SLUG, FOXYSHOP_PRODUCT_CATEGORY_SLUG, 'product-search', 'foxycart-datafeed-'.$foxyshop_settings['datafeed_url_key'], 'foxycart-sso-'.$foxyshop_settings['datafeed_url_key'], 'upload-'.$foxyshop_settings['datafeed_url_key']);
$foxyshop_indicators = array(FOXYSHOP_PRODUCTS_SLUG, FOXYSHOP_PRODUCT_CATEGORY_SLUG, 'product-search', 'foxycart-datafeed-'.$foxyshop_settings['datafeed_url_key'], 'foxycart-prepayment-webhook-'.$foxyshop_settings['datafeed_url_key'], 'foxycart-sso-'.$foxyshop_settings['datafeed_url_key'], 'upload-'.$foxyshop_settings['datafeed_url_key']);
if (array_intersect($request_arr, $foxyshop_indicators)) {
if (in_array(FOXYSHOP_PRODUCTS_SLUG, $request_arr) && $request_end != FOXYSHOP_PRODUCTS_SLUG) {
$currentProduct = $request_end;
Expand Down Expand Up @@ -57,6 +57,8 @@ function foxyshop_theme_redirect() {
$currentPageName = 'product-search';
} elseif ($request_start == 'foxycart-datafeed-'.$foxyshop_settings['datafeed_url_key']) {
$currentPageName = 'foxycart-datafeed-'.$foxyshop_settings['datafeed_url_key'];
} elseif ($request_start == 'foxycart-prepayment-webhook-'.$foxyshop_settings['datafeed_url_key']) {
$currentPageName = 'foxycart-prepayment-webhook-'.$foxyshop_settings['datafeed_url_key'];
} elseif ($request_start == 'foxycart-sso-'.$foxyshop_settings['datafeed_url_key']) {
$currentPageName = 'foxycart-sso-'.$foxyshop_settings['datafeed_url_key'];
} elseif ($request_start == 'upload-'.$foxyshop_settings['datafeed_url_key']) {
Expand Down Expand Up @@ -141,6 +143,15 @@ function foxyshop_theme_redirect() {
include foxyshop_get_template_file('foxyshop-datafeed-endpoint.php');
die;

//FoxyCart Prepayment Webhook Endpoint
} elseif ($currentPageName == 'foxycart-prepayment-webhook-'.$foxyshop_settings['datafeed_url_key'] || $currentName == 'foxycart-prepayment-webhook-'.$foxyshop_settings['datafeed_url_key']) {
add_filter('body_class', 'foxyshop_body_class', 10, 2 );
status_header(200);
if (!defined("IS_FOXYSHOP")) define("IS_FOXYSHOP", 1);
$wp_query->is_404 = false;
include foxyshop_get_template_file('foxyshop-prepayment-webhook-endpoint.php');
die;

//FoxyCart SSO Endpoint
} elseif ($currentPageName == 'foxycart-sso-'.$foxyshop_settings['datafeed_url_key'] || $currentName == 'foxycart-sso-'.$foxyshop_settings['datafeed_url_key']) {
status_header(200);
Expand Down
Loading