alejandro Posted November 22, 2013 Share Posted November 22, 2013 Hello, Maybe not a PW directly related question, but just in case anyone has done it before: I'm triying to process the transaction data received from foxycart api, in a page/endpoint in PW. In this page there is a script such as: //Set Globals and Get Settings $apikey = "my api key"; //----------------------------------------------------- // TRANSACTION DATAFEED //----------------------------------------------------- if (isset($_POST["FoxyData"])) { //DECRYPT (required) //----------------------------------------------------- $FoxyData_decrypted = foxycart_decrypt($_POST["FoxyData"]); $xml = simplexml_load_string($FoxyData_decrypted, NULL, LIBXML_NOCDATA); //For Each Transaction foreach($xml->transactions->transaction as $transaction) { //This variable will tell us whether this is a multi-ship store or not $is_multiship = 0; //Get FoxyCart Transaction Information //Simply setting lots of helpful data to PHP variables so you can access it easily //If you need to access more variables, you can see some sample XML here: http://wiki.foxycart.com/v/1.1/transaction_xml_datafeed $transaction_id = (string)$transaction->id; $transaction_date = (string)$transaction->transaction_date; $customer_ip = (string)$transaction->customer_ip; $customer_id = (string)$transaction->customer_id; $customer_first_name = (string)$transaction->customer_first_name; $customer_last_name = (string)$transaction->customer_last_name; $customer_company = (string)$transaction->customer_company; $customer_email = (string)$transaction->customer_email; $customer_password = (string)$transaction->customer_password; $customer_address1 = (string)$transaction->customer_address1; $customer_address2 = (string)$transaction->customer_address2; $customer_city = (string)$transaction->customer_city; $customer_state = (string)$transaction->customer_state; $customer_postal_code = (string)$transaction->customer_postal_code; $customer_country = (string)$transaction->customer_country; $customer_phone = (string)$transaction->customer_phone; //Putting the Custom Fields in an array if they are there if (!empty($shipto_address->custom_fields)) { foreach($shipto_address->custom_fields->custom_field as $custom_field) { $shipto[$shipto_name]['custom_fields'][(string)$custom_field->custom_field_name] = (string)$custom_field->custom_field_value; } } } //For Each Transaction Detail foreach($transaction->transaction_details->transaction_detail as $transaction_detail) { $product_name = (string)$transaction_detail->product_name; $product_code = (string)$transaction_detail->product_code; $product_quantity = (int)$transaction_detail->product_quantity; $product_price = (double)$transaction_detail->product_price; $product_shipto = (double)$transaction_detail->shipto; $category_code = (string)$transaction_detail->category_code; $product_delivery_type = (string)$transaction_detail->product_delivery_type; $sub_token_url = (string)$transaction_detail->sub_token_url; $subscription_frequency = (string)$transaction_detail->subscription_frequency; $subscription_startdate = (string)$transaction_detail->subscription_startdate; $subscription_nextdate = (string)$transaction_detail->subscription_nextdate; $subscription_enddate = (string)$transaction_detail->subscription_enddate; //These are the options for the product $transaction_detail_options = array(); foreach($transaction_detail->transaction_detail_options->transaction_detail_option as $transaction_detail_option) { $product_option_name = $transaction_detail_option->product_option_name; $product_option_value = (string)$transaction_detail_option->product_option_value; $price_mod = (double)$transaction_detail_option->price_mod; $weight_mod = (double)$transaction_detail_option->weight_mod; } //If you have custom code to run for each product, put it here: } //If you have custom code to run for each order, put it here: $p = new Page(); $p->parent = $pages->get("1350"); $p->template = $templates->get("receipt"); $p->title = "Transaction id: ". $transaction_id; $p->save(); } //All Done! die("foxy"); //----------------------------------------------------- // NO POST CONTENT SENT //----------------------------------------------------- } else { die('No Content Received From Datafeed'); } //Decrypt Data From Source function foxycart_decrypt($src) { global $apikey; return rc4crypt::decrypt($apikey,urldecode($src)); } // ====================================================================================== // RC4 ENCRYPTION CLASS // Do not modify. // ===================================================================================== . . . ..script continues with the encryption, part of the code's been cut, just for clarity... The script captures a FoxyCart $_Post variable, decrypts it, and parses the XML data with SimpleXML and apparently works fine, as tested by Foxycart support, and returns ok ('foxy') to Foxycart servers. But the pages in PW are not created. Well, if the PW code is placed outside the foreach, not intended, it works but has no access to the PHP variables, eg $transaction_id number. Another weird thing, for me, is that every page that holds this script appears as "301 moved permanently" when requested the http headers, and maybe could be this the culprit ¿?. Well, as said before, just in case anyone here has done it before... Thanks in advance, Alejandro. Link to comment Share on other sites More sharing options...
Macrura Posted November 22, 2013 Share Posted November 22, 2013 @alejandro wow - i need something like this TODAY - i was taking apart and recoding the Modx inventory http://modx.com/extras/package/foxycartinventory - could you post the whole script? Link to comment Share on other sites More sharing options...
alejandro Posted November 22, 2013 Author Share Posted November 22, 2013 Of course, but do not give any credit to me, is just copied from the FoxyCart docs https://wiki.foxycart.com/v/1.1/transaction_xml_datafeed /Script by David Hollander, www.foxy-shop.com //version 1.0, 7/9/2012 //Set Globals and Get Settings $apikey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; //----------------------------------------------------- // TRANSACTION DATAFEED //----------------------------------------------------- if (isset($_POST["FoxyData"])) { //DECRYPT (required) //----------------------------------------------------- $FoxyData_decrypted = foxycart_decrypt($_POST["FoxyData"]); $xml = simplexml_load_string($FoxyData_decrypted, NULL, LIBXML_NOCDATA); //For Each Transaction foreach($xml->transactions->transaction as $transaction) { //This variable will tell us whether this is a multi-ship store or not $is_multiship = 0; //Get FoxyCart Transaction Information //Simply setting lots of helpful data to PHP variables so you can access it easily //If you need to access more variables, you can see some sample XML here: http://wiki.foxycart.com/v/1.1/transaction_xml_datafeed $transaction_id = (string)$transaction->id; $transaction_date = (string)$transaction->transaction_date; $customer_ip = (string)$transaction->customer_ip; $customer_id = (string)$transaction->customer_id; $customer_first_name = (string)$transaction->customer_first_name; $customer_last_name = (string)$transaction->customer_last_name; $customer_company = (string)$transaction->customer_company; $customer_email = (string)$transaction->customer_email; $customer_password = (string)$transaction->customer_password; $customer_address1 = (string)$transaction->customer_address1; $customer_address2 = (string)$transaction->customer_address2; $customer_city = (string)$transaction->customer_city; $customer_state = (string)$transaction->customer_state; $customer_postal_code = (string)$transaction->customer_postal_code; $customer_country = (string)$transaction->customer_country; $customer_phone = (string)$transaction->customer_phone; //This is for a multi-ship store. The shipping addresses will go in a $shipto array with the address name as the key $shipto = array(); foreach($transaction->shipto_addresses->shipto_address as $shipto_address) { $is_multiship = 1; $shipto_name = (string)$shipto_address->address_name; $shipto[$shipto_name] = array( 'first_name' => (string)$shipto_address->shipto_first_name, 'last_name' => (string)$shipto_address->shipto_last_name, 'company' => (string)$shipto_address->shipto_company, 'address1' => (string)$shipto_address->shipto_address1, 'address2' => (string)$shipto_address->shipto_address2, 'city' => (string)$shipto_address->shipto_city, 'state' => (string)$shipto_address->shipto_state, 'postal_code' => (string)$shipto_address->shipto_postal_code, 'country' => (string)$shipto_address->shipto_country, 'shipping_service_description' => (string)$shipto_address->shipto_shipping_service_description, 'subtotal' => (string)$shipto_address->shipto_subtotal, 'tax_total' => (string)$shipto_address->shipto_tax_total, 'shipping_total' => (string)$shipto_address->shipto_shipping_total, 'total' => (string)$shipto_address->shipto_, 'custom_fields' => array() ); //Putting the Custom Fields in an array if they are there if (!empty($shipto_address->custom_fields)) { foreach($shipto_address->custom_fields->custom_field as $custom_field) { $shipto[$shipto_name]['custom_fields'][(string)$custom_field->custom_field_name] = (string)$custom_field->custom_field_value; } } } //This is setup for a single ship store if (!$is_multiship) { $shipping_first_name = (string)$transaction->shipping_first_name ? (string)$transaction->shipping_first_name : $customer_first_name; $shipping_last_name = (string)$transaction->shipping_last_name ? (string)$transaction->shipping_last_name : $customer_last_name; $shipping_company = (string)$transaction->shipping_company ? (string)$transaction->shipping_company : $customer_company; $shipping_address1 = (string)$transaction->shipping_address1 ? (string)$transaction->shipping_address1 : $customer_address1; $shipping_address2 = (string)$transaction->shipping_address1 ? (string)$transaction->shipping_address2 : $customer_address2; $shipping_city = (string)$transaction->shipping_city ? (string)$transaction->shipping_city : $customer_city; $shipping_state = (string)$transaction->shipping_state ? (string)$transaction->shipping_state : $customer_state; $shipping_postal_code = (string)$transaction->shipping_postal_code ? (string)$transaction->shipping_postal_code : $customer_postal_code; $shipping_country = (string)$transaction->shipping_country ? (string)$transaction->shipping_country : $customer_country; $shipping_phone = (string)$transaction->shipping_phone ? (string)$transaction->shipping_phone : $customer_phone; $shipto_shipping_service_description = (string)$transaction->shipto_shipping_service_description; } //Putting the Custom Fields in an array if they are there. These are on the top level and could be there for both single ship and multiship stores $custom_fields = array(); if (!empty($transaction->custom_fields)) { foreach($transaction->custom_fields->custom_field as $custom_field) { $custom_fields[(string)$custom_field->custom_field_name] = (string)$custom_field->custom_field_value; } } //For Each Transaction Detail foreach($transaction->transaction_details->transaction_detail as $transaction_detail) { $product_name = (string)$transaction_detail->product_name; $product_code = (string)$transaction_detail->product_code; $product_quantity = (int)$transaction_detail->product_quantity; $product_price = (double)$transaction_detail->product_price; $product_shipto = (double)$transaction_detail->shipto; $category_code = (string)$transaction_detail->category_code; $product_delivery_type = (string)$transaction_detail->product_delivery_type; $sub_token_url = (string)$transaction_detail->sub_token_url; $subscription_frequency = (string)$transaction_detail->subscription_frequency; $subscription_startdate = (string)$transaction_detail->subscription_startdate; $subscription_nextdate = (string)$transaction_detail->subscription_nextdate; $subscription_enddate = (string)$transaction_detail->subscription_enddate; //These are the options for the product $transaction_detail_options = array(); foreach($transaction_detail->transaction_detail_options->transaction_detail_option as $transaction_detail_option) { $product_option_name = $transaction_detail_option->product_option_name; $product_option_value = (string)$transaction_detail_option->product_option_value; $price_mod = (double)$transaction_detail_option->price_mod; $weight_mod = (double)$transaction_detail_option->weight_mod; } //If you have custom code to run for each product, put it here: } //If you have custom code to run for each order, put it here: //////// PW code is supposed to be here } //All Done! die("foxy"); //----------------------------------------------------- // NO POST CONTENT SENT //----------------------------------------------------- } else { die('No Content Received From Datafeed'); } //Decrypt Data From Source function foxycart_decrypt($src) { global $apikey; return rc4crypt::decrypt($apikey,urldecode($src)); } // ====================================================================================== // RC4 ENCRYPTION CLASS // Do not modify. // ====================================================================================== /** * RC4Crypt 3.2 * * RC4Crypt is a petite library that allows you to use RC4 * encryption easily in PHP. It's OO and can produce outputs * in binary and hex. * * © Copyright 2006 Mukul Sabharwal [http://mjsabby.com] * All Rights Reserved * * @link http://rc4crypt.devhome.org * @author Mukul Sabharwal <mjsabby@gmail.com> * @version $Id: class.rc4crypt.php,v 3.2 2006/03/10 05:47:24 mukul Exp $ * @copyright Copyright © 2006 Mukul Sabharwal * @license http://www.gnu.org/copyleft/gpl.html * @package RC4Crypt */ class rc4crypt { /** * The symmetric encryption function * * @param string $pwd Key to encrypt with (can be binary of hex) * @param string $data Content to be encrypted * @param bool $ispwdHex Key passed is in hexadecimal or not * @access public * @return string */ function encrypt ($pwd, $data, $ispwdHex = 0) { if ($ispwdHex) $pwd = @pack('H*', $pwd); // valid input, please! $key[] = ''; $box[] = ''; $cipher = ''; $pwd_length = strlen($pwd); $data_length = strlen($data); for ($i = 0; $i < 256; $i++) { $key[$i] = ord($pwd[$i % $pwd_length]); $box[$i] = $i; } for ($j = $i = 0; $i < 256; $i++) { $j = ($j + $box[$i] + $key[$i]) % 256; $tmp = $box[$i]; $box[$i] = $box[$j]; $box[$j] = $tmp; } for ($a = $j = $i = 0; $i < $data_length; $i++) { $a = ($a + 1) % 256; $j = ($j + $box[$a]) % 256; $tmp = $box[$a]; $box[$a] = $box[$j]; $box[$j] = $tmp; $k = $box[(($box[$a] + $box[$j]) % 256)]; $cipher .= chr(ord($data[$i]) ^ $k); } return $cipher; } /** * Decryption, recall encryption * * @param string $pwd Key to decrypt with (can be binary of hex) * @param string $data Content to be decrypted * @param bool $ispwdHex Key passed is in hexadecimal or not * @access public * @return string */ function decrypt ($pwd, $data, $ispwdHex = 0) { return rc4crypt::encrypt($pwd, $data, $ispwdHex); } } Just let me know if it works for you. I can´t get it working. Link to comment Share on other sites More sharing options...
Macrura Posted November 22, 2013 Share Posted November 22, 2013 This works: https://gist.github.com/outflux3/7608974 let me know if it works for you! 1 Link to comment Share on other sites More sharing options...
alejandro Posted November 25, 2013 Author Share Posted November 25, 2013 Doesn´t work for me Meanwhile i found a different solution, it needs a bit of javascript: 1) In my endpoint set up a script that'd request the transaction info using curl. It needs the transacton id to do so: <?php $foxy_domain = "domain.foxycart.com"; $foxyData = array(); $foxyData["api_token"] = "apikey"; $foxyData["api_action"] = "transaction_get"; $foxyData["transaction_id"] = $_GET["fcorderid"]; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://" . $foxy_domain . "/api"); curl_setopt($ch, CURLOPT_POSTFIELDS, $foxyData); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); curl_setopt($ch, CURLOPT_TIMEOUT, 15); // If you get SSL errors, you can uncomment the following, or ask your host to add the appropriate CA bundle // curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); $response = trim(curl_exec($ch)); // The following if block will print any CURL errors you might have // if ($response == false) { // print "CURL Error: \n" . curl_error($ch); // } else { // print "Response to customer save of " . $foxyData['customer_email'] . "\n"; // print $response; // } curl_close($ch); $foxyResponse = simplexml_load_string($response, NULL, LIBXML_NOCDATA); $client = $foxyResponse->transaction->customer_first_name; $transaction_id = $foxyResponse->transaction->id; $email = $foxyResponse->transaction->customer_email; $product = $foxyResponse->transaction->transaction_details->transaction_detail->product_name; $price = $foxyResponse->transaction->transaction_details->transaction_detail->product_price; foreach ($foxyResponse->transaction->transaction_details->transaction_detail->transaction_detail_options->transaction_detail_option as $option) { $product_option_name = $transaction_detail_option->product_option_name; $product_option_value = (string)$transaction_detail_option->product_option_value; $price_mod = (double)$transaction_detail_option->price_mod; } print "<pre>"; print_r($foxyResponse); print "</pre>"; $fwd = $pages->get("title=$transaction_id"); if($fwd->id) { $session->redirect($fwd->url); } else { $p = new Page(); $p->parent = $pages->get("1350"); $p->template = $templates->get("upload_area"); $p->title = $transaction_id; $p->email = $foxyResponse->transaction->customer_email; $p->fcdate = $foxyResponse->transaction->transaction_date; $p->fcfirst = $foxyResponse->transaction->customer_first_name; $p->fclast = $foxyResponse->transaction->customer_last_name; $p->fcprice = $foxyResponse->transaction->order_total; $p->fcproduct = $foxyResponse->transaction->transaction_details->transaction_detail->product_name; $p->save(); echo $p->render(); } 2) In the Foxycart receipt template I use a bit of javascript to get the transaction id and send it with a hidden form and a hidden target iframe to avoid redirection. Link to comment Share on other sites More sharing options...
Macrura Posted November 25, 2013 Share Posted November 25, 2013 that's cool - didn't know you could request fc transactions via curl.. not sure why the code i posted didn't work for you though - i tested by re-feeding transactions from FC and was eventually able to have it reply with success and also it was successfully updating the processwire page (in my case decrementing the inventory)// did you include all of the scripts; // get these from http://modx.com/extras/package/foxycartinventory $rc4cryptPath = "/path/to/class.rc4crypt.php"; $xmlParserPath = "/path/to/class.xmlparser_php5.php"; i also have datafeed log working but commented out, since it's only needed for testing... anyway thanks for posting your solution, that could be useful at some point in the future... Link to comment Share on other sites More sharing options...
alejandro Posted November 25, 2013 Author Share Posted November 25, 2013 Finally! It works! Well it was about slashes... when including the scripts $rc4cryptPaht = "/inc/clas...." doesn´t work $rc4cryptPaht = "inc/clas...." it works. Same for the parser. Addtionally in the Foxycart settings, the datafeed URL needs a slash at the end, otherwise returns an error: http://site.com/feed/ Now, it returns 'foxy' and creates the page in PW. ehem, as a designer, these "subtleties" don´t seem always that important. Your script is working great, thank you. Maybe you could post this Foxycart integration to their docs: https://wiki.foxycart.com/integration/start Link to comment Share on other sites More sharing options...
Macrura Posted November 26, 2013 Share Posted November 26, 2013 hi alejandro - cool - glad that's working... and you reminded me that i probably don't need to put the server path, that's why i had the leading slashes, i can include those liek you did since they are in the templates directory... Link to comment Share on other sites More sharing options...
EssickAir Posted April 7, 2020 Share Posted April 7, 2020 I know this is an old thread, but I could use some help trying to get the same result if anyone on here has any suggestions. Link to comment Share on other sites More sharing options...
dab Posted April 8, 2020 Share Posted April 8, 2020 Are you getting any errors? Link to comment Share on other sites More sharing options...
Recommended Posts