Skip to content

Commit

Permalink
Order Parsing and History Rework (#254)
Browse files Browse the repository at this point in the history
Replaced relationships between OrderDetail and OptionItems with new OrderOption object.

Overhaul of the various parsing functions, simplifying and clarifying. Moved to Order.

Order History page displays Product info from Datafeed, links to Product page if it exists/matches.

Order->Response is now saved encrypted.

Added two new BuildTasks:

FoxyStripe: ParseOrders - loops through all orders in the database that have a value for Response, and re-parses the Order data.

FoxyStripe: EncryptReponses - loops through all Orders and encrypts any Response fields that are unencrypted XML. For legacy migrations.
  • Loading branch information
jsirish authored Mar 2, 2018
1 parent aa83e24 commit f8f77e9
Show file tree
Hide file tree
Showing 7 changed files with 305 additions and 208 deletions.
184 changes: 15 additions & 169 deletions code/controllers/FoxyStripe_Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,16 @@ public function getURLSegment() {
);

public function index() {

// handle POST from FoxyCart API transaction
if ((isset($_POST["FoxyData"]) OR isset($_POST['FoxySubscriptionData']))) {

$FoxyData_encrypted = (isset($_POST["FoxyData"])) ?
urldecode($_POST["FoxyData"]) :
urldecode($_POST["FoxySubscriptionData"]);
$FoxyData_decrypted = rc4crypt::decrypt(FoxyCart::getStoreKey(),$FoxyData_encrypted);

// parse the response and save the order
self::handleDataFeed($FoxyData_encrypted, $FoxyData_decrypted);

// extend to allow for additional integrations with Datafeed
Expand All @@ -35,188 +39,30 @@ public function index() {
}

public function handleDataFeed($encrypted, $decrypted){
//handle encrypted & decrypted data

$orders = new SimpleXMLElement($decrypted);

// loop over each transaction to find FoxyCart Order ID
foreach ($orders->transactions->transaction as $order) {

if (isset($order->id)) {
($transaction = Order::get()->filter('Order_ID', $order->id)->First()) ?
$transaction :
$transaction = Order::create();
}

// save base order info
$transaction->Order_ID = (int) $order->id;
$transaction->Response = $decrypted;

// record transaction as order
$transaction->write();

// parse order
$this->parseOrder($order->id);

}
}

public function parseOrder($Order_ID) {

$transaction = Order::get()->filter(array('Order_ID' => $Order_ID))->First();

if ($transaction) {
// grab response, parse as XML
$orders = new SimpleXMLElement($transaction->Response);

$this->parseOrderInfo($orders, $transaction);
$this->parseOrderCustomer($orders, $transaction);
// record transaction so user info can be accessed from parseOrderDetails()
$transaction->write();
$this->parseOrderDetails($orders, $transaction);

// record transaction as order
$transaction->write();
}
}

public function parseOrderInfo($orders, $transaction) {

foreach ($orders->transactions->transaction as $order) {

// Record transaction data from FoxyCart Datafeed:
$transaction->Store_ID = (int)$order->store_id;
$transaction->TransactionDate = (string)$order->transaction_date;
$transaction->ProductTotal = (float)$order->product_total;
$transaction->TaxTotal = (float)$order->tax_total;
$transaction->ShippingTotal = (float)$order->shipping_total;
$transaction->OrderTotal = (float)$order->order_total;
$transaction->ReceiptURL = (string)$order->receipt_url;
$transaction->OrderStatus = (string)$order->status;
}
}

public function parseOrderCustomer($orders, $transaction) {

foreach ($orders->transactions->transaction as $order) {

// if not a guest transaction in FoxyCart
if (isset($order->customer_email) && $order->is_anonymous == 0) {

// if Customer is existing member, associate with current order
if(Member::get()->filter('Email', $order->customer_email)->First()) {

$customer = Member::get()->filter('Email', $order->customer_email)->First();

/* todo: make sure local password is updated if changed on FoxyCart
$customer->Password = (string)$order->customer_password;
$customer->write();
foreach ($orders->transactions->transaction as $transaction) {

$customer->Password = (string)$order->customer_password;
$customer->Salt = (string)$order->customer_password_salt;
$customer->write();
*/
// if FoxyCart order id, then parse order
if (isset($transaction->id)) {

} else {
($order = Order::get()->filter('Order_ID', (int) $transaction->id)->First()) ?
$order = Order::get()->filter('Order_ID', (int) $transaction->id)->First() :
$order = Order::create();

// set PasswordEncryption to 'none' so imported, encrypted password is not encrypted again
Config::inst()->update('Security', 'password_encryption_algorithm', 'none');

// create new Member, set password info from FoxyCart
$customer = Member::create();
$customer->Customer_ID = (int)$order->customer_id;
$customer->FirstName = (string)$order->customer_first_name;
$customer->Surname = (string)$order->customer_last_name;
$customer->Email = (string)$order->customer_email;
$customer->Password = (string)$order->customer_password;
$customer->PasswordEncryption = 'none';

// record member record
$customer->write();

$customer->Password = (string)$order->customer_password;
$customer->Salt = (string)$order->customer_password_salt;

$customer->write();

}

// set Order MemberID
$transaction->MemberID = $customer->ID;
// save base order info
$order->Order_ID = (int) $transaction->id;
$order->Response = urlencode($encrypted);
$order->write();

}
}
}

public function parseOrderDetails($orders, $transaction) {

// remove previous OrderDetails so we don't end up with duplicates
foreach ($transaction->Details() as $detail) {
$detail->delete();
}

foreach ($orders->transactions->transaction as $order) {

// Associate ProductPages, Options, Quanity with Order
foreach ($order->transaction_details->transaction_detail as $product) {

$OrderDetail = OrderDetail::create();

// set Quantity
$OrderDetail->Quantity = (int)$product->product_quantity;

// set calculated price (after option modifiers)
$OrderDetail->Price = (float)$product->product_price;

// Find product via product_id custom variable
foreach ($product->transaction_detail_options->transaction_detail_option as $productID) {
if ($productID->product_option_name == 'product_id') {

$OrderProduct = ProductPage::get()
->filter('ID', (int)$productID->product_option_value)
->First();

// if product could be found, then set Option Items
if ($OrderProduct) {

// set ProductID
$OrderDetail->ProductID = $OrderProduct->ID;

// loop through all Product Options
foreach ($product->transaction_detail_options->transaction_detail_option as $option) {

$OptionItem = OptionItem::get()->filter(array(
'ProductID' => (string)$OrderProduct->ID,
'Title' => (string)$option->product_option_value
))->First();

if ($OptionItem) {
$OrderDetail->Options()->add($OptionItem);

// modify product price
if ($priceMod = $option->price_mod) {
$OrderDetail->Price += $priceMod;
}
}
}
}
}

// associate with this order
$OrderDetail->OrderID = $transaction->ID;

// extend OrderDetail parsing, allowing for recording custom fields from FoxyCart
$this->extend('handleOrderItem', $decrypted, $product, $OrderDetail);

// write
$OrderDetail->write();

}
}
}
}



// Single Sign on integration with FoxyCart
public function sso() {

Expand Down
Loading

0 comments on commit f8f77e9

Please sign in to comment.