Back end for iOS app with relational databases - ios

I am currently trying to build an ios application that will need to be able to retrieve and store data in a remote relational database. I have investigated using RestKit for the front end, which seems adequate. I have experience developing with both mysql and php, though I am not sure where to start in getting a web server to send information that is not html. (php enhanced html, that is)
I would appreciate any input on where I might get started. Thanks in advance!

I use PHP to query a mySQL database on my server and format the response as XML which I then parse in the app.
Here is a PHP example from my server....This also sends a size response to allow the App to track the download completion percentage and a file name response too. Also, if the database is empty, it will send a dummy record.
<?php
header("Content-type: text/text");
//get the values from the url query string
$user = $_GET['user'];
$pass = $_GET['password'];
$db = $_GET['database'];
$dbhost = 'localhost';
//create connection to mysql or tell user something has gone wrong
$connection = mysql_connect( $dbhost, $user, $pass ) or die('Could not connect to MySQL');
//select database or tell user something has gone wrong
mysql_select_db( $db ) or die('Could not select database');
// Construct and run query.
$sql = 'SELECT * FROM itemInfo WHERE itemStatus = "active" ORDER BY itemSortKey ASC';
//echo $sql;
$result = mysql_query($sql) or die('<result>fail</result>');
$xml_output = "<?xml version=\"1.0\"?>\n";
$xml_output .= "<bodyimage>\n";
while($record = mysql_fetch_assoc($result)) {
$xml_output .= "\t<storeitems>\n";
$xml_output .= "\t\t<itemSortKey>" . $record['itemSortKey'] . "</itemSortKey>\n";
$xml_output .= "\t\t<itemDesc>" . $record['itemDesc'] . "</itemDesc>\n";
$xml_output .= "\t\t<itemPrice>" . $record['itemPrice'] . "</itemPrice>\n";
$xml_output .= "\t\t<productID>" . $record['productID'] . "</productID>\n";
$xml_output .= "\t\t<field1>" . $record['field1'] . "</field1>\n";
$xml_output .= "\t\t<field2>" . $record['field2'] . "</field2>\n";
$xml_output .= "\t\t<field3>" . $record['field3'] . "</field3>\n";
$xml_output .= "\t\t<field4>" . $record['field4'] . "</field4>\n";
$xml_output .= "\t\t<dateCreated>" . $record['dateCreated'] . "</dateCreated>\n";
$xml_output .= "\t\t<dateModified>" . $record['dateModified'] . "</dateModified>\n";
// Escaping illegal characters
//$row['text'] = str_replace("&", "&", $row['text']);
//$row['text'] = str_replace("<", "<", $row['text']);
//$row['text'] = str_replace(">", ">", $row['text']);
//$row['text'] = str_replace("\"", """, $row['text']);
//$xml_output .= "\t\t<text>" . $row['text'] . "</text>\n";
$xml_output .= "\t</storeitems>\n";
//add this record to the output
//$output = '|facilityname|' .$record['facilityname'] . '|/facilityname||customername|' . $record['customername'] . '|/customername||imageurl|' . $record['imageurl'] . '|/imageurl|';
//print $output;
}
$xml_output .= "</bodyimage>";
header("HTTP/1.0 200 OK");
header('Content-type: text/xml');
header('Content-Disposition: attachment; filename="storeitems.xml"');
header("Content-Length: ".strlen ( $xml_output ));
// redundent.....$xml_output .= "</bmrcontrol>";
//echo strlen( $xml_output );
//the next statement relates if there are NO lines in the table - it sends a message
if ( strlen( $xml_output ) == 61 ) {
$xml_output = "<?xml version=\"1.0\"?>\n";
$xml_output .= "<bodyimage>\n";
$xml_output .= "\t<storeitems>\n";
$xml_output .= "\t\t<itemSortKey>aaaa</itemSortKey>\n";
$xml_output .= "\t\t<itemDesc>Store Items Missing</itemDesc>\n";
$xml_output .= "\t\t<itemPrice>0.0</itemPrice>\n";
$xml_output .= "\t\t<productID>blank</productID>\n";
$xml_output .= "\t\t<field1>.</field1>\n";
$xml_output .= "\t\t<field2>.</field2>\n";
$xml_output .= "\t\t<field3>.</field3>\n";
$xml_output .= "\t\t<field4>.</field4>\n";
$xml_output .= "\t\t<dateCreated>2012-02-13 09:03:49</dateCreated>\n";
$xml_output .= "\t\t<dateModified>2012-02-13 09:03:49</dateModified>\n";
// Escaping illegal characters
//$row['text'] = str_replace("&", "&", $row['text']);
//$row['text'] = str_replace("<", "<", $row['text']);
//$row['text'] = str_replace(">", ">", $row['text']);
//$row['text'] = str_replace("\"", """, $row['text']);
//$xml_output .= "\t\t<text>" . $row['text'] . "</text>\n";
$xml_output .= "\t</storeitems>\n";
$xml_output .= "</bodyimage>";
}
echo $xml_output;
if(mysql_num_rows($result)) {
//mysql_close($connection);
}
else
die('<result>fail</result>');
//mysql_close($connection);
?>

Related

QBSDK iterator support in consolibyte

I have to fetch a large amount of data and so I want to use the iterator feature of QBSDK. I wanted to know if consolibyte library has any inherent support for it.
Several of the examples included with the lib use iterators:
https://github.com/consolibyte/quickbooks-php/blob/master/docs/web_connector/example_web_connector_import.php#L321
function _quickbooks_invoice_import_request($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale)
{
// Iterator support (break the result set into small chunks)
$attr_iteratorID = '';
$attr_iterator = ' iterator="Start" ';
if (empty($extra['iteratorID']))
{
// This is the first request in a new batch
$last = _quickbooks_get_last_run($user, $action);
_quickbooks_set_last_run($user, $action); // Update the last run time to NOW()
// Set the current run to $last
_quickbooks_set_current_run($user, $action, $last);
}
else
{
// This is a continuation of a batch
$attr_iteratorID = ' iteratorID="' . $extra['iteratorID'] . '" ';
$attr_iterator = ' iterator="Continue" ';
$last = _quickbooks_get_current_run($user, $action);
}
// Build the request
$xml = '<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="' . $version . '"?>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
<InvoiceQueryRq ' . $attr_iterator . ' ' . $attr_iteratorID . ' requestID="' . $requestID . '">
...

Intuit QuickBooks web connector IteratorID not valid error

I have been trying to integrate a PHP based solution with QuickBooks Enterprise edition. I use QuickBooks PHP Dev Kit (http://consolibyte.com/quickbooks-open-source/) to connect the application to sync multiple modules bidirectionally.
The first module (QuickBooks to VtigerCRM) with multiple records are getting synced perfectly. When I try with my next module, only few records are getting synced and throws a error IteratorID is not valid. Then, I tried sending the params with new IteratorID in XML with no success.
20180821.05:13:03 UTC : QBWebConnector.SOAPWebService.do_receiveResponseXML() : hresult=""
20180821.05:13:03 UTC : QBWebConnector.SOAPWebService.do_receiveResponseXML() : message=""
20180821.05:13:03 UTC : QBWebConnector.SOAPWebService.do_receiveResponseXML() : Received from receiveResponseXML() following parameters:
20180821.05:13:03 UTC : QBWebConnector.SOAPWebService.do_receiveResponseXML() : more="-1">
20180821.05:13:03 UTC : QBWebConnector.SOAPWebService.do_getLastError() : * Calling getLastError() with following parameter:
20180821.05:13:03 UTC : QBWebConnector.SOAPWebService.do_getLastError() : wcTicket="403c7856-d600-c664-5187-3d9e2036c0cc"
20180821.05:13:04 UTC : QBWebConnector.SOAPWebService.do_getLastError() : Received from getLastError() following parameter:
20180821.05:13:04 UTC : QBWebConnector.SOAPWebService.do_getLastError() : errorMsg="3391: The iteratorID "{80c35df0-ae92-43a3-af49-946da1c306fb}" is not valid."
20180821.05:13:04 UTC : QBWebConnector.SOAPWebService.do_getLastError() : Received error from application: 3391: The iteratorID "{80c35df0-ae92-43a3-af49-946da1c306fb}" is not valid.
20180821.05:13:04 UTC : QBWebConnector.CompanyFileLock.Send_CompanyQueryRqXML() : XML dump follows: -
<?xml version="1.0"?><?qbxml version="13.0"?><QBXML><QBXMLMsgsRq onError="stopOnError"><CompanyQueryRq requestID="1"><OwnerID>{90A44FB7-33D9-4815-AC85-AC86A7E7D1EB}</OwnerID></CompanyQueryRq></QBXMLMsgsRq></QBXML>
I have added the code of the Helper.php
<?php
// Support URL
if (!empty($_GET['support']))
{
header('Location: http://www.consolibyte.com/');
exit;
}
// We need to make sure the correct timezone is set, or some PHP installations will complain
if (function_exists('date_default_timezone_set'))
{
// * MAKE SURE YOU SET THIS TO THE CORRECT TIMEZONE! *
// List of valid timezones is here: http://us3.php.net/manual/en/timezones.php
date_default_timezone_set('America/New_York');
}
// Require the framework
require_once 'QuickBooks.php';
require_once('config.inc.php');
global $dbconfig;
$user = 'quickbooks';
$pass = 'password';
define('QB_QUICKBOOKS_CONFIG_LAST', 'last');
define('QB_QUICKBOOKS_CONFIG_CURR', 'curr');
define('QB_QUICKBOOKS_MAX_RETURNED', 1);
define('QB_PRIORITY_PURCHASEORDER', 1);
define('QB_PRIORITY_ITEM', 6);
define('QB_PRIORITY_CUSTOMER', 5);
define('QB_PRIORITY_SALESORDER', 2);
/**
* Request priorities, invoices last...
*/
define('QB_PRIORITY_INVOICE', 3);
define('QB_PRIORITY_ESTIMATE',4);
define('QB_QUICKBOOKS_MAILTO', 'keith#consolibyte.com');
// Map QuickBooks actions to handler functions
$map = array(
QUICKBOOKS_IMPORT_CUSTOMER => array( '_quickbooks_customer_import_request', '_quickbooks_customer_import_response' ),
QUICKBOOKS_IMPORT_ITEM => array( '_quickbooks_item_import_request', '_quickbooks_item_import_response' ),
QUICKBOOKS_IMPORT_ESTIMATE =>array( '_quickbooks_quote_import_request', '_quickbooks_quote_import_response' ),
QUICKBOOKS_IMPORT_SALESORDER => array( '_quickbooks_salesorder_import_request', '_quickbooks_salesorder_import_response' ),
QUICKBOOKS_IMPORT_INVOICE => array( '_quickbooks_invoice_import_request', '_quickbooks_invoice_import_response' ),
QUICKBOOKS_IMPORT_PURCHASEORDER => array( '_quickbooks_purchaseorder_import_request', '_quickbooks_purchaseorder_import_response' ),
);
// Error handlers
$errmap = array(
500 => '_quickbooks_error_e500_notfound', // Catch errors caused by searching for things not present in QuickBooks
1 => '_quickbooks_error_e500_notfound',
'*' => '_quickbooks_error_catchall', // Catch any other errors that might occur
);
// An array of callback hooks
$hooks = array(
QuickBooks_WebConnector_Handlers::HOOK_LOGINSUCCESS => '_quickbooks_hook_loginsuccess', // call this whenever a successful login occurs
);
// Logging level
//$log_level = QUICKBOOKS_LOG_NORMAL;
//$log_level = QUICKBOOKS_LOG_VERBOSE;
//$log_level = QUICKBOOKS_LOG_DEBUG; // Use this level until you're sure everything works!!!
$log_level = QUICKBOOKS_LOG_DEVELOP;
// What SOAP server you're using
//$soapserver = QUICKBOOKS_SOAPSERVER_PHP; // The PHP SOAP extension, see: www.php.net/soap
$soapserver = QUICKBOOKS_SOAPSERVER_BUILTIN; // A pure-PHP SOAP server (no PHP ext/soap extension required, also makes debugging easier)
$soap_options = array( // See http://www.php.net/soap
);
$handler_options = array( // See the comments in the QuickBooks/Server/Handlers.php file
'deny_concurrent_logins' => false,
'deny_reallyfast_logins' => false,
);
$driver_options = array( // See the comments in the QuickBooks/Driver/<YOUR DRIVER HERE>.php file ( i.e. 'Mysql.php', etc. )
);
$callback_options = array(
);
$dsn = $dbconfig['db_type']."://".$dbconfig['db_username'].":".$dbconfig['db_password']."#".$dbconfig['db_server']."/".$dbconfig['db_name'];
//$dsn = 'mysql://root:smackcoders#localhost/vtiger2';
//$dsn = 'mysql://testuser:testpassword#localhost/testdatabase';
define('QB_QUICKBOOKS_DSN', $dsn);
// If we haven't done our one-time initialization yet, do it now!
if (!QuickBooks_Utilities::initialized($dsn))
{
// Create the example tables
$file = dirname(__FILE__) . '/example.sql';
if (file_exists($file))
{
$contents = file_get_contents($file);
foreach (explode(';', $contents) as $sql)
{
if (!trim($sql))
{
continue;
}
mysql_query($sql) or die(trigger_error(mysql_error()));
}
}
else
{
die('Could not locate "./example.sql" to create the demo SQL schema!');
}
// Create the database tables
QuickBooks_Utilities::initialize($dsn);
// Add the default authentication username/password
QuickBooks_Utilities::createUser($dsn, $user, $pass);
}
// Initialize the queue
QuickBooks_WebConnector_Queue_Singleton::initialize($dsn);
// Create a new server and tell it to handle the requests
$Server = new QuickBooks_WebConnector_Server($dsn, $map, $errmap, $hooks, $log_level, $soapserver, QUICKBOOKS_WSDL, $soap_options, $handler_options, $driver_options, $callback_options);
$response = $Server->handle(true, true);
/**
* Login success hook - perform an action when a user logs in via the Web Connector
*
*
*/
function _quickbooks_hook_loginsuccess($requestID, $user, $hook, &$err, $hook_data, $callback_config)
{
// For new users, we need to set up a few things
// Fetch the queue instance
$Queue = QuickBooks_WebConnector_Queue_Singleton::getInstance();
$date = date('Y-m-d H:i:s');
// Set up the invoice imports
if (!_quickbooks_get_last_run($user, QUICKBOOKS_IMPORT_INVOICE))
{
// And write the initial sync time
_quickbooks_set_last_run($user, QUICKBOOKS_IMPORT_INVOICE, $date);
}
// Do the same for customers
if (!_quickbooks_get_last_run($user, QUICKBOOKS_IMPORT_CUSTOMER))
{
_quickbooks_set_last_run($user, QUICKBOOKS_IMPORT_CUSTOMER, $date);
}
// ... and for sales orders
if (!_quickbooks_get_last_run($user, QUICKBOOKS_IMPORT_SALESORDER))
{
_quickbooks_set_last_run($user, QUICKBOOKS_IMPORT_SALESORDER, $date);
}
// ... and for items
if (!_quickbooks_get_last_run($user, QUICKBOOKS_IMPORT_ITEM))
{
_quickbooks_set_last_run($user, QUICKBOOKS_IMPORT_ITEM, $date);
}
// Make sure the requests get queued up
$Queue->enqueue(QUICKBOOKS_IMPORT_CUSTOMER, 1, QB_PRIORITY_CUSTOMER, null, $user);
$Queue->enqueue(QUICKBOOKS_IMPORT_ITEM, 1, QB_PRIORITY_ITEM, null, $user);
$Queue->enqueue(QUICKBOOKS_IMPORT_ESTIMATE, 1, QB_PRIORITY_ESTIMATE, null, $user);
$Queue->enqueue(QUICKBOOKS_IMPORT_SALESORDER, 1, QB_PRIORITY_SALESORDER, null, $user);
$Queue->enqueue(QUICKBOOKS_IMPORT_INVOICE, 1, QB_PRIORITY_INVOICE, null, $user);
$Queue->enqueue(QUICKBOOKS_IMPORT_PURCHASEORDER, 1, QB_PRIORITY_PURCHASEORDER, null, $user);
}
/**
* Get the last date/time the QuickBooks sync ran
*
* #param string $user The web connector username
* #return string A date/time in this format: "yyyy-mm-dd hh:ii:ss"
*/
function _quickbooks_get_last_run($user, $action)
{
$type = null;
$opts = null;
return QuickBooks_Utilities::configRead(QB_QUICKBOOKS_DSN, $user, md5(__FILE__), QB_QUICKBOOKS_CONFIG_LAST . '-' . $action, $type, $opts);
}
function _quickbooks_set_last_run($user, $action, $force = null)
{
$value = date('Y-m-d') . 'T' . date('H:i:s');
if ($force)
{
$value = date('Y-m-d', strtotime($force)) . 'T' . date('H:i:s', strtotime($force));
}
return QuickBooks_Utilities::configWrite(QB_QUICKBOOKS_DSN, $user, md5(__FILE__), QB_QUICKBOOKS_CONFIG_LAST . '-' . $action, $value);
}
/**
*
*
*/
function _quickbooks_get_current_run($user, $action)
{
$type = null;
$opts = null;
return QuickBooks_Utilities::configRead(QB_QUICKBOOKS_DSN, $user, md5(__FILE__), QB_QUICKBOOKS_CONFIG_CURR . '-' . $action, $type, $opts);
}
/**
*
*
*/
function _quickbooks_set_current_run($user, $action, $force = null)
{
$value = date('Y-m-d') . 'T' . date('H:i:s');
if ($force)
{
$value = date('Y-m-d', strtotime($force)) . 'T' . date('H:i:s', strtotime($force));
}
return QuickBooks_Utilities::configWrite(QB_QUICKBOOKS_DSN, $user, md5(__FILE__), QB_QUICKBOOKS_CONFIG_CURR . '-' . $action, $value);
}
/**
* Build a request to import invoices already in QuickBooks into our application
*/
function _quickbooks_invoice_import_request($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale)
{
// Iterator support (break the result set into small chunks)
$attr_iteratorID = '';
$attr_iterator = ' iterator="Start" ';
if (empty($extra['iteratorID']))
{
$last = _quickbooks_get_last_run($user, $action);
_quickbooks_set_last_run($user, $action); // Update the last run time to NOW()
// Set the current run to $last
_quickbooks_set_current_run($user, $action, $last);
}
else
{
$extra['iteratorID'] = $saved_iterator_id; // From Table
// This is a continuation of a batch
$attr_iteratorID = ' iteratorID="' . $extra['iteratorID'] . '" ';
$attr_iterator = ' iterator="Continue" ';
$last = _quickbooks_get_current_run($user, $action);
}
// Build the request
$xml = '<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="' . $version . '"?>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
<InvoiceQueryRq ' . $attr_iterator . ' ' . $attr_iteratorID . ' requestID="' . $requestID . '">
<MaxReturned>' . QB_QUICKBOOKS_MAX_RETURNED . '</MaxReturned>
<ModifiedDateRangeFilter>
<FromModifiedDate>' . $last . '</FromModifiedDate>
</ModifiedDateRangeFilter>
<IncludeLineItems>true</IncludeLineItems>
<OwnerID>0</OwnerID>
</InvoiceQueryRq>
</QBXMLMsgsRq>
</QBXML>';
return $xml;
}
/**
* Handle a response from QuickBooks
*/
function _quickbooks_invoice_import_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents)
{
if (!empty($idents['iteratorRemainingCount']))
{
// Queue up another request
$Queue = QuickBooks_WebConnector_Queue_Singleton::getInstance();
$Queue->enqueue(QUICKBOOKS_IMPORT_INVOICE, null, QB_PRIORITY_INVOICE, array( 'iteratorID' => $idents['iteratorID'] ), $user);
}else{
return true;
}
// This piece of the response from QuickBooks is now stored in $xml. You
// can process the qbXML response in $xml in any way you like. Save it to
// a file, stuff it in a database, parse it and stuff the records in a
// database, etc. etc. etc.
//
// The following example shows how to use the built-in XML parser to parse
// the response and stuff it into a database.
// Import all of the records
$errnum = 0;
$errmsg = '';
$Parser = new QuickBooks_XML_Parser($xml);
if ($Doc = $Parser->parse($errnum, $errmsg))
{
$Root = $Doc->getRoot();
$List = $Root->getChildAt('QBXML/QBXMLMsgsRs/InvoiceQueryRs');
$smackHelper = new Quickbooks_vtigerHelper();
$smackHelper->addInvoice($List->children());
}
return true;
}
/**
* Build a request to import customers already in QuickBooks into our application
*/
function _quickbooks_customer_import_request($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale)
{
// Iterator support (break the result set into small chunks)
$attr_iteratorID = '';
$attr_iterator = ' iterator="Start" ';
if (empty($extra['iteratorID']))
{
// This is the first request in a new batch
$last = _quickbooks_get_last_run($user, $action);
_quickbooks_set_last_run($user, $action); // Update the last run time to NOW()
// Set the current run to $last
_quickbooks_set_current_run($user, $action, $last);
}
else
{
$extra['iteratorID'] = $saved_iterator_id; // From Table
// This is a continuation of a batch
$attr_iteratorID = ' iteratorID="' . $extra['iteratorID'] . '" ';
$attr_iterator = ' iterator="Continue" ';
$last = _quickbooks_get_current_run($user, $action);
}
// Build the request
$xml = '<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="' . $version . '"?>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
<CustomerQueryRq ' . $attr_iterator . ' ' . $attr_iteratorID . ' requestID="' . $requestID . '">
<MaxReturned>' . QB_QUICKBOOKS_MAX_RETURNED . '</MaxReturned>
<FromModifiedDate>' . $last . '</FromModifiedDate>
<OwnerID>0</OwnerID>
</CustomerQueryRq>
</QBXMLMsgsRq>
</QBXML>';
return $xml;
}
/**
* Handle a response from QuickBooks
*/
function _quickbooks_customer_import_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents)
{
if (!empty($idents['iteratorRemainingCount']))
{
// Queue up another request
$Queue = QuickBooks_WebConnector_Queue_Singleton::getInstance();
$Queue->enqueue(QUICKBOOKS_IMPORT_CUSTOMER, null, QB_PRIORITY_CUSTOMER, array( 'iteratorID' => $idents['iteratorID'] ), $user);
}else{
return true;
}
// Import all of the records
$errnum = 0;
$errmsg = '';
$Parser = new QuickBooks_XML_Parser($xml);
if ($Doc = $Parser->parse($errnum, $errmsg))
{
$Root = $Doc->getRoot();
$List = $Root->getChildAt('QBXML/QBXMLMsgsRs/CustomerQueryRs');
$smackHelper = new Quickbooks_vtigerHelper();
$smackHelper->addContacts($List->children());
}
return true;
}
function _quickbooks_quote_import_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents)
{
if (!empty($idents['iteratorRemainingCount']))
{
// Queue up another request
$Queue = QuickBooks_WebConnector_Queue_Singleton::getInstance();
$Queue->enqueue(QUICKBOOKS_IMPORT_ESTIMATE, null, QB_PRIORITY_ESTIMATE, array( 'iteratorID' => $idents['iteratorID'] ), $user);
}else{
return true;
}
// Import all of the records
$errnum = 0;
$errmsg = '';
$Parser = new QuickBooks_XML_Parser($xml);
if ($Doc = $Parser->parse($errnum, $errmsg))
{
$Root = $Doc->getRoot();
$List = $Root->getChildAt('QBXML/QBXMLMsgsRs/EstimateQueryRs');
$smackHelper = new Quickbooks_vtigerHelper();
$smackHelper->addQuotes($List->children());
}
return true;
}
function _quickbooks_quote_import_request($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale)
{
if (empty($extra['iteratorID']))
{
$last = _quickbooks_get_last_run($user, $action);
_quickbooks_set_last_run($user, $action); // Update the last run time to NOW()
$attr_iterator = ' iterator="Start" ';
// Set the current run to $last
_quickbooks_set_current_run($user, $action, $last);
}
else
{
$extra['iteratorID'] = $saved_iterator_id; // From Table
// This is a continuation of a batch
$attr_iteratorID = ' iteratorID="' . $extra['iteratorID'] . '" ';
$attr_iterator = ' iterator="Continue" ';
$last = _quickbooks_get_current_run($user, $action);
//$last = '2015-08-18T01:03:41';
//$last = _quickbooks_get_current_run($user, $action);
}
// Build the request
$xml = '<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="' . $version . '"?>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
<EstimateQueryRq ' . $attr_iterator . ' ' . $attr_iteratorID . ' requestID="' . $requestID . '">
<MaxReturned>' . QB_QUICKBOOKS_MAX_RETURNED . '</MaxReturned>
<ModifiedDateRangeFilter>
<FromModifiedDate>' . $last . '</FromModifiedDate>
</ModifiedDateRangeFilter>
<IncludeLineItems>true</IncludeLineItems>
<OwnerID>0</OwnerID>
</EstimateQueryRq>
</QBXMLMsgsRq>
</QBXML>';
return $xml;
}
function _quickbooks_salesorder_import_request($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale)
{
// Iterator support (break the result set into small chunks)
$attr_iteratorID = '';
$attr_iterator = ' iterator="Start" ';
if (empty($extra['iteratorID']))
{
// This is the first request in a new batch
$last = _quickbooks_get_last_run($user, $action);
_quickbooks_set_last_run($user, $action); // Update the last run time to NOW()
// Set the current run to $last
_quickbooks_set_current_run($user, $action, $last);
}
else
{
$extra['iteratorID'] = $saved_iterator_id; // From Table
// This is a continuation of a batch
$attr_iteratorID = ' iteratorID="' . $extra['iteratorID'] . '" ';
$attr_iterator = ' iterator="Continue" ';
$last = _quickbooks_get_current_run($user, $action);
}
// Build the request
$xml = '<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="' . $version . '"?>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
<SalesOrderQueryRq ' . $attr_iterator . ' ' . $attr_iteratorID . ' requestID="' . $requestID . '">
<MaxReturned>' . QB_QUICKBOOKS_MAX_RETURNED . '</MaxReturned>
<ModifiedDateRangeFilter>
<FromModifiedDate>' . $last . '</FromModifiedDate>
</ModifiedDateRangeFilter>
<IncludeLineItems>true</IncludeLineItems>
<OwnerID>0</OwnerID>
</SalesOrderQueryRq>
</QBXMLMsgsRq>
</QBXML>';
return $xml;
}
/**
* Handle a response from QuickBooks
*/
function _quickbooks_salesorder_import_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents)
{
if (!empty($idents['iteratorRemainingCount']))
{
// Queue up another request
$Queue = QuickBooks_WebConnector_Queue_Singleton::getInstance();
$Queue->enqueue(QUICKBOOKS_IMPORT_SALESORDER, null, QB_PRIORITY_SALESORDER, array( 'iteratorID' => $idents['iteratorID'] ), $user);
}else{
return true;
}
// Import all of the records
$errnum = 0;
$errmsg = '';
$Parser = new QuickBooks_XML_Parser($xml);
if ($Doc = $Parser->parse($errnum, $errmsg))
{
$Root = $Doc->getRoot();
$List = $Root->getChildAt('QBXML/QBXMLMsgsRs/SalesOrderQueryRs');
$smackHelper = new Quickbooks_vtigerHelper();
$smackHelper->addSalesOrder($List->children());
}
return true;
}
/**
* Build a request to import customers already in QuickBooks into our application
*/
function _quickbooks_item_import_request($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale)
{
// Iterator support (break the result set into small chunks)
$attr_iteratorID = '';
$attr_iterator = ' iterator="Start" ';
if (empty($extra['iteratorID']))
{
// This is the first request in a new batch
$last = _quickbooks_get_last_run($user, $action);
_quickbooks_set_last_run($user, $action); // Update the last run time to NOW()
// Set the current run to $last
_quickbooks_set_current_run($user, $action, $last);
}
else
{
$extra['iteratorID'] = $saved_iterator_id; // From Table
// This is a continuation of a batch
$attr_iteratorID = ' iteratorID="' . $extra['iteratorID'] . '" ';
$attr_iterator = ' iterator="Continue" ';
$last = _quickbooks_get_current_run($user, $action);
}
// Build the request
$xml = '<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="' . $version . '"?>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
<ItemQueryRq ' . $attr_iterator . ' ' . $attr_iteratorID . ' requestID="' . $requestID . '">
<MaxReturned>' . QB_QUICKBOOKS_MAX_RETURNED . '</MaxReturned>
<FromModifiedDate>' . $last . '</FromModifiedDate>
<OwnerID>0</OwnerID>
</ItemQueryRq>
</QBXMLMsgsRq>
</QBXML>';
return $xml;
}
/**
* Handle a response from QuickBooks
*/
function _quickbooks_item_import_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents)
{
if (!empty($idents['iteratorRemainingCount']))
{
// Queue up another request
$Queue = QuickBooks_WebConnector_Queue_Singleton::getInstance();
$Queue->enqueue(QUICKBOOKS_IMPORT_ITEM, null, QB_PRIORITY_ITEM, array( 'iteratorID' => $idents['iteratorID'] ), $user);
}else{
return true;
}
// Import all of the records
$errnum = 0;
$errmsg = '';
$Parser = new QuickBooks_XML_Parser($xml);
if ($Doc = $Parser->parse($errnum, $errmsg))
{
$Root = $Doc->getRoot();
$List = $Root->getChildAt('QBXML/QBXMLMsgsRs/ItemQueryRs');
$smackHelper = new Quickbooks_vtigerHelper();
$smackHelper->addProducts($List->children(),'Products');
}
return true;
}
/**
* Build a request to import invoices already in QuickBooks into our application
*/
function _quickbooks_purchaseorder_import_request($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale)
{
// Iterator support (break the result set into small chunks)
$attr_iteratorID = '';
$attr_iterator = ' iterator="Start" ';
if (empty($extra['iteratorID']))
{
// This is the first request in a new batch
$last = _quickbooks_get_last_run($user, $action);
_quickbooks_set_last_run($user, $action); // Update the last run time to NOW()
// Set the current run to $last
_quickbooks_set_current_run($user, $action, $last);
}
else
{
$extra['iteratorID'] = $saved_iterator_id; // From Table
// This is a continuation of a batch
$attr_iteratorID = ' iteratorID="' . $extra['iteratorID'] . '" ';
$attr_iterator = ' iterator="Continue" ';
$last = _quickbooks_get_current_run($user, $action);
}
// Build the request
$xml = '<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="' . $version . '"?>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
<PurchaseOrderQueryRq ' . $attr_iterator . ' ' . $attr_iteratorID . ' requestID="' . $requestID . '">
<MaxReturned>' . QB_QUICKBOOKS_MAX_RETURNED . '</MaxReturned>
<!--<ModifiedDateRangeFilter>
<FromModifiedDate>' . $last . '</FromModifiedDate>
</ModifiedDateRangeFilter>-->
<IncludeLineItems>true</IncludeLineItems>
<OwnerID>0</OwnerID>
</PurchaseOrderQueryRq>
</QBXMLMsgsRq>
</QBXML>';
return $xml;
}
/**
* Handle a response from QuickBooks
*/
function _quickbooks_purchaseorder_import_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents)
{
if (!empty($idents['iteratorRemainingCount']))
{
// Queue up another request
$Queue = QuickBooks_WebConnector_Queue_Singleton::getInstance();
$Queue->enqueue(QUICKBOOKS_IMPORT_PURCHASEORDER, null, QB_PRIORITY_PURCHASEORDER, array( 'iteratorID' => $idents['iteratorID'] ), $user);
}else{
return true;
}
// This piece of the response from QuickBooks is now stored in $xml. You
// can process the qbXML response in $xml in any way you like. Save it to
// a file, stuff it in a database, parse it and stuff the records in a
// database, etc. etc. etc.
//
// The following example shows how to use the built-in XML parser to parse
// the response and stuff it into a database.
// Import all of the records
$errnum = 0;
$errmsg = '';
$Parser = new QuickBooks_XML_Parser($xml);
if ($Doc = $Parser->parse($errnum, $errmsg))
{
$Root = $Doc->getRoot();
$List = $Root->getChildAt('QBXML/QBXMLMsgsRs/PurchaseOrderQueryRs');
// TODO
}
return true;
}
/**
* Handle a 500 not found error from QuickBooks
*
* Instead of returning empty result sets for queries that don't find any
* records, QuickBooks returns an error message. This handles those error
* messages, and acts on them by adding the missing item to QuickBooks.
*/
function _quickbooks_error_e500_notfound($requestID, $user, $action, $ID, $extra, &$err, $xml, $errnum, $errmsg)
{
$Queue = QuickBooks_WebConnector_Queue_Singleton::getInstance();
if ($action == QUICKBOOKS_IMPORT_INVOICE)
{
return true;
}
else if ($action == QUICKBOOKS_IMPORT_CUSTOMER)
{
return true;
}
else if ($action == QUICKBOOKS_IMPORT_SALESORDER)
{
return true;
}
else if ($action == QUICKBOOKS_IMPORT_ITEM)
{
return true;
}
else if ($action == QUICKBOOKS_IMPORT_PURCHASEORDER)
{
return true;
}
return false;
}
function _quickbooks_error_catchall($requestID, $user, $action, $ID, $extra, &$err, $xml, $errnum, $errmsg)
{
$message = '';
$message .= 'Request ID: ' . $requestID . "\r\n";
$message .= 'User: ' . $user . "\r\n";
$message .= 'Action: ' . $action . "\r\n";
$message .= 'ID: ' . $ID . "\r\n";
$message .= 'Extra: ' . print_r($extra, true) . "\r\n";
//$message .= 'Error: ' . $err . "\r\n";
$message .= 'Error number: ' . $errnum . "\r\n";
$message .= 'Error message: ' . $errmsg . "\r\n";
mail(QB_QUICKBOOKS_MAILTO,
'QuickBooks error occured!',
$message);
}
So I see at least a few potential issues, and have some questions. First, some background --
Iterators in QuickBooks work just like a database cursor. Part of that means that you can't have two iterators open at once - you have to finish with one iterator before you start and/or continue another iterator. So if you do this, you'll get the error you're seeing:
Start iterator #1
Fetch some data from iterator #1
Start iterator #2
Try to fetch some data from iterator #1 again
That will fail because starting the second iterator has closed/killed the first iterator. This is probably what's happening to you.
What is this?
$extra['iteratorID'] = $saved_iterator_id; // From Table
That looks like an undefined variable to me. Did you check your PHP error logs?
Why are you saving this to a table, and what table are you saving it to? Where in the code are you pulling it back out of the table? I don't see any code that gets it from the table.

Hooking up OpenCart with an iOS App via web services

I need to develop an iOS app that fetches data from an OpenCart installation online. This includes ordering online, adding things to wish list, creating a user account. Logging in to an already existing user account and everything else that open cart offers. Basically, it is an iOS version of the OpenCart website that connects to the OpenCart's MySQL database.
I googled a little bit but couldn't find a proper API that I can use to hookup my app with OpenCart. What other options do I have? Does OpenCart offer any web service? (Like WordPress offers XML-RPC). Or is there a good API that I can use?
Unfortunately, OpenCart does not offer any API straight away. (that's for an answer).
There is an opensource OpenCart API project on GitHub that you can download (google it, I do not remember it's name) but this offers only the very limited and basic methods for just reading of data (if I remember correctly there were methods for getting the list of categories, list of products and product details and few more).
This could be your starting point: fork, add methods, share. Or create your own API from a scratch if you wish (again, sharing will be highly welcomed :-) - I believe you could even find users willing to pay for it - I would have created one if I had time - but sadly I have not...).
<?php
include_once 'functions.php';
class ControllerJsonJson extends Controller {
public function index() {
// Menu
$this->load->model('catalog/category');
$this->load->model('catalog/product');
$this->load->model('tool/image');
$data['categories'] = array();
$categories = $this->model_catalog_category->getCategories(0);
foreach ($categories as $category) {
if ($category['top']) {
// Level 2
$children_data = array();
$children = $this->model_catalog_category->getCategories($category['category_id']);
foreach ($children as $child) {
if ($child['image']) {
$childpopup = $this->model_tool_image->resize($child['image'], $this->config->get('config_image_popup_width'), $this->config->get('config_image_popup_height'));
$childthumb = $this->model_tool_image->resize($child['image'], 74,74);
} else {
$childthumb='';
$childpopup = '';
}
$filter_data = array(
'filter_category_id' => $child['category_id'],
'filter_sub_category' => true
);
$children_data[] = array(
'popup'=>$childpopup,
'thumb'=>$childthumb,
'id' => $child['category_id'],
'name' => $child['name'] . ($this->config->get('config_product_count') ? ' (' . $this->model_catalog_product->getTotalProducts($filter_data) . ')' : ''),
'href' => $this->url->link('product/category', 'path=' . $category['category_id'] . '_' . $child['category_id'])
);
}
if ($category['image']) {
$categorypopup = $this->model_tool_image->resize($category['image'], $this->config->get('config_image_popup_width'), $this->config->get('config_image_popup_height'));
$categorythumb = $this->model_tool_image->resize($category['image'], 74,74);
} else {
$categorypopup = '';
$categorythumb='';
}
// Level 1
$data['categories'][] = array(
'popup' => $categorypopup,
'thumb' => $categorythumb,
'id' => $category['category_id'],
'name' => $category['name'],
'children' => $children_data,
'column' => $category['column'] ? $category['column'] : 1,
'href' => $this->url->link('product/category', 'path=' . $category['category_id'])
);
}
}
$obj=new functions();
echo $obj->json_pretty_encode($data);
}
}
<?php
class functions {
//put your code here
public function json_pretty_encode($obj){
header("Content-type: application/json");
$json = json_encode($obj);
if (!$json) return $json;
$f = '';
$len = strlen($json);
$depth = 0;
$newline = false;
for ($i = 0; $i < $len; ++$i)
{
if ($newline)
{
$f .= "\n";
$f .= str_repeat(' ', $depth);
$newline = false;
}
$c = $json[$i];
if ($c == '{' || $c == '[')
{
$f .= $c;
$depth++;
$newline = true;
}
else if ($c == '}' || $c == ']')
{
$depth--;
$f .= "\n";
$f .= str_repeat(' ', $depth);
$f .= $c;
}
else if ($c == '"')
{
$s = $i;
do {
$c = $json[++$i];
if ($c == '\\')
{
$i += 2;
$c = $json[$i];
}
} while ($c != '"');
$f .= substr($json, $s, $i-$s+1);
}
else if ($c == ':')
{
$f .= ': ';
}
else if ($c == ',')
{
$f .= ',';
$newline = true;
}
else
{
$f .= $c;
}
}
return $f;
}
}

.swf file upload script files will not upload

Im trying to get this very basic script to upload .swf files to my server with no luck.
I get an invalid file error when i try to upload.
.jpg,gifs,pngs all upload fine.
I tried changing a few things putting swf where jpg is etc. but no joy.
Is it not possible to upload swf files in this way?
and help appreciated, many thanks.
`
Filename:
<?php
$allowedExts = array("gif", "jpeg", "jpg","swf","png");
$extension = end(explode(".", $_FILES["file"]["name"]));
if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/jpg")
|| ($_FILES["file"]["type"] == "application/x-shockwave-flash/swf")
|| ($_FILES["file"]["type"] == "image/png"))
&& ($_FILES["file"]["size"] < 8388608)
&& in_array($extension, $allowedExts))
{
if ($_FILES["file"]["error"] > 0)
{
echo "Return Code: " . $_FILES["file"]["error"] . "<br>";
}
else
{
echo "Upload: " . $_FILES["file"]["name"] . "<br>";
echo "Type: " . $_FILES["file"]["type"] . "<br>";
echo "Size: " . ($_FILES["file"]["size"] / 1024) . " kB<br>";
echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br>";
if (file_exists("upload/" . $_FILES["file"]["name"]))
{
echo $_FILES["file"]["name"] . " already exists. ";
}
else
{
move_uploaded_file($_FILES["file"]["tmp_name"],
"upload/" . $_FILES["file"]["name"]);
echo "Stored in: " . "upload/" . $_FILES["file"]["name"];
}
}
}
else
{
echo "Invalid file";
}
?> `
function addAdFields($post,$files){
//print_r( $files);
$allowedExts = array("gif", "jpeg", "jpg", "png" ,"tiff","tif","swf");
$fileType=$files["bannerType"]["type"];
$tmpName=$files["bannerType"]["tmp_name"];
$fileName=$files["bannerType"]["name"];
$imageName = mysql_real_escape_string($files["bannerType"]["name"]);
$imageData = mysql_real_escape_string(file_get_contents($files["bannerType"]["tmp_name"]));
$imageType = mysql_real_escape_string($files["bannerType"]["type"]);
list($width, $height, $type, $attr) = getimagesize($tmpName);
$dimArr= array($width, $height);
$temp = explode(".", $fileName);
$files["bannerType"]["name"];
$extension = end($temp);
$fileTmpName= mysql_real_escape_string($tmpName);
$curDate = "";
$ipadd = $_SERVER['REMOTE_ADDR'];
$camDetail=explode('_',$post['campaignType']);
$this -> tableName = "_ads";
$this -> fieldValues['campaignID'] = $camDetail[0];
$this -> fieldValues['campaignName'] =$camDetail[1];
$this -> fieldValues['adTitle'] = $post['adTitle'];
$this -> fieldValues['bannerID'] = $post['bannerType'];
if($_SESSION['bannerTyp']=='Placement')
{
$this -> fieldValues['uploadFileName'] = $post['placementText'];
}
else{
$this -> fieldValues['uploadFileName'] = $imageName;
$this -> fieldValues['uploadedFile'] = $imageData;
}
$this -> fieldValues['dimantation'] = json_encode($dimArr);
$this -> fieldValues['addDateTime'] = $curDate;
$this -> fieldValues['addIpAddress'] = $ipadd;
$this->insert();
//echo $this->query;
header('Location: main.html?action=add-ads&menuid=155');
}

How to get the total number of tweets, retweets and replies on a particular tag or account, in Twitter using its API?

I have a requirement to get the total no.of tweets, retweets and replies on a particular tag or user account. How to get these numbers efficiently? The numbers should be exact and not like 100+.
I also need to get the total no.of direct messages.
Using this site as a starting point I've been trying the same thing:
Pull Twitter feed into your site
<?php
require_once 'db-functions.inc.php' ; //custom database functions
function saveTweets($screen_name) {
global $link;
$screen_name = dbEscape(strtolower(trim($screen_name)));
if (!$screen_name) { echo "<p><strong>Error: No screen name declared.</strong></p>\n"; return false; }
$row = dbGetRow("SELECT `id` FROM `retweet` WHERE `screen_name`='$screen_name' ORDER BY `id` DESC LIMIT 1");
$last_id = $row['id'];
$url = "http://api.twitter.com/1/statuses/user_timeline.xml?screen_name=$screen_name&count=1500&include_rts=true" ;
if ($last_id) { $url .= "&since_id=$last_id" ; }
$ch = curl_init($url);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, TRUE);
$xml = curl_exec ($ch);
curl_close ($ch);
$affected = 0;
$twelement = new SimpleXMLElement($xml);
foreach ($twelement->status as $status) {
$text = dbEscape(trim($status->text));
$time = strtotime($status->created_at);
$id = $status->id;
$retweet_count = $status->retweet_count;
dbQuery("INSERT INTO `twit` (`id`,`screen_name`,`time`,`text`,`hidden`,`retweet_count`) VALUES ('$id','$screen_name','$time','$text','n','$retweet_count')");
$affected = $affected + dbAffectedRows();
}
return "<p>".number_format($affected)." new tweets from $screen_name saved.</p>\n" ;
}
echo saveTweets('stackoverflow');
echo saveTweets('Apple');
echo saveTweets('Android');
echo saveTweets('Google');
?>
<h3>Stackoverflow</h3>
<?php
require_once 'databaseconnection.php' ; //database connection function
$result = dbQuery("SELECT * FROM `retweet` WHERE `hidden` != 'y' ORDER BY `retweet_count` DESC");
while ($row = mysql_fetch_array($result)) {
echo $row[0];
echo "<br>";
echo date("l, M j, Y, G:i a",$row[3]);
echo " : ";
echo stripslashes($row[2]);
echo "<br>";
echo stripslashes($row[4]);
echo "<br>Retweet: ";
echo stripslashes($row[6]);
echo "<br>";
echo "<br>";
}
?>
At the present time this doesn't have an "UPDATE" clause in it to take into account the retweet_count increasing, and you can remove:
return "<p>".number_format($affected)." new tweets from $screen_name saved.</p>\n" ;
If you don't need to see what has been updated.
Hope that helps

Resources