PHP QuickBooks Desktop Customer Query - php

I have been using [quickbooks-php][1] library by the Consolibyte. I wanted to log in the Customer Query Result in a file named CustomerQuery.txt but the messages I am getting as follows-
Version:
Not provided by service
Message:
No data exchange required
Description:
No data to exchange for this application. Job ending.
and here is the PHP code-
<?php
error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', true);
require_once('config.php');
require_once($QuickBooksFile);
if (function_exists('date_default_timezone_set'))
{
date_default_timezone_set('America/New_York');
}
$map = array(
QUICKBOOKS_QUERY_CUSTOMER => array( '_quickbooks_customer_query_request', '_quickbooks_customer_query_response' ),
);
$errmap = array();
$hooks = array();
$log_level = QUICKBOOKS_LOG_DEVELOP;
$soap = QUICKBOOKS_SOAPSERVER_BUILTIN;
$soap_options = array();
$handler_options = array(
'authenticate' => '_quickbooks_custom_auth',
'deny_concurrent_logins' => false,
);
if (!QuickBooks_Utilities::initialized($DSN))
{
QuickBooks_Utilities::initialize($DSN);
QuickBooks_Utilities::createUser($DSN, $user, $pass);
$primary_key_of_your_customer = 5;
$Queue = new QuickBooks_WebConnector_Queue($DSN);
$Queue->enqueue(QUICKBOOKS_QUERY_CUSTOMER, $primary_key_of_your_customer);
}
$Server = new QuickBooks_WebConnector_Server($DSN, $map, $errmap, $hooks, $log_level, $soap, QUICKBOOKS_WSDL, $soap_options, $handler_options);
$response = $Server->handle(true, true);
function _quickbooks_custom_auth($Username, $Password, &$QuickBooksCompanyFile){
return true;
}
function _quickbooks_customer_query_request($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale)
{
$xml = '<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="13.0"?>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
<CustomerQueryRq requestID="1">
<FullName>Kaley Baker</FullName>
<OwnerID>0</OwnerID>
</CustomerQueryRq>
</QBXMLMsgsRq>
</QBXML>';
return $xml;
}
function _quickbooks_customer_query_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents)
{
file_put_contents('CustomerQuery.txt', $xml);
}
The config.php file contents are as follows-
$UserName='Admin';
$Password='Test123';
$DSN='mysqli://root#localhost/qb';
$QuickBooksCompanyFile = 'E:\QB.QBW';
$QuickBooksFile='C:\xampp\htdocs\accounting\qb\QuickBooks.php';
$Email='demo.code#gmail.com';
$DBHost='localhost';
$DBUser='root';
$DBPass='';
$DBName='qb';
*/

A quick Google or StackOverflow search yields the following link (together with a sea of other posts saying the same thing):
http://www.consolibyte.com/docs/index.php/QuickBooks_Web_Connector_-_No_data_exchange_required
Which says:
What does "No data exchange required" mean?
That message means exactly what it says:
There's no data to exchange. There's nothing to do. The Web Connector
(and most frameworks/dev kits built around it) use a 'queue' concept.
Once the queue is empty, there's nothing else to do, and you'll get
that message. If you add something to the queue, then it will process
those items until there's nothing left to do, and then you'll get the
"No Data Exchange..." message again.
So, for instance, say you want to build a process whereby every time a
customer is created within your store, the customer gets created in
QuickBooks. You'd then want to set up a process where when that
customer is created within your store, you queue up a request to add
the customer to QuickBooks.
Looking at your code, there is only one call to any sort of queue method:
$Queue->enqueue(QUICKBOOKS_QUERY_CUSTOMER, $primary_key_of_your_customer);
And if you go back to the docs/examples where you found this code:
https://github.com/consolibyte/quickbooks-php/blob/master/docs/web_connector/example_web_connector.php#L288
From this library:
https://github.com/consolibyte/quickbooks-php
You'll see the big comment that says:
// IMPORTANT NOTE: This particular example of queueing something up will
// only ever happen *once* when these scripts are first run/used. After
// this initial test, you MUST do your queueing in another script. DO NOT
// DO YOUR OWN QUEUEING IN THIS FILE! See
// docs/example_web_connector_queueing.php for more details and examples
// of queueing things up.
Sooooo...
Have you queued anything up that needs to be processed? Doesn't look like it.
If you have, where's the code for that? What do the database records (stored in the quickbooks_queue SQL table) look like?
Go queue something up, and you won't get this message anymore.
Need to know how to queue up something? Refer to the example that the code links you to:
Example:
https://github.com/consolibyte/quickbooks-php/blob/master/docs/web_connector/example_web_connector_queueing.php

Related

PHP QuickBooks Web Connector consolibyte - no data exchange required

Goal: We are attempting to get all transactions once an hour out of QuickBooks Desktop for Windows using QuickBooks Web Connector.
Status: QuickBooks Web Connector runs successfully with the configured qwc file.
Issue: QuickBooks Web Connector returns a green message 'No Data Exchange Required'. I am expecting transactions to be stored in log.txt. Below is my code. I suspect this is a queing issue?. I would like all queing to be in this file that runs every hour in QBWC to get all transactions. Any assistance you can provide would be greatly appreciated.
//web_connector.php - called every 60 min from QBWC
$map = array(
'*' => array( '_quickbooks_get_transactions', '_quickbooks_get_transactions_response' ),
);
$log_level = QUICKBOOKS_LOG_DEVELOP;
$soapserver = QUICKBOOKS_SOAPSERVER_BUILTIN;
$handler_options = array(
'deny_concurrent_logins' => false,
'deny_reallyfast_logins' => false,
);
$dsn = 'mysqli://'.$dbUser.':'.$dbPass.'#localhost/'.$dbName;
if (!QuickBooks_Utilities::initialized($dsn))
{
// Initialize creates the neccessary database schema for queueing up requests and logging
QuickBooks_Utilities::initialize($dsn);
// This creates a username and password which is used by the Web Connector to authenticate
QuickBooks_Utilities::createUser($dsn, $user, $pass);
}
//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);
function _quickbooks_get_transactions($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale)
{
//I want to get all transactions from this QuickBooks file and then insert into a database table on my cloud server.
$xml = '<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="2.0"?>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
<TransactionQuery requestID="' . $requestID . '">
</TransactionQuery>
</QBXMLMsgsRq>
</QBXML>';
return $xml;
}
function _quickbooks_get_transactions_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents)
{
//I want to get all transactions from this QuickBooks file and then insert into a database table on my cloud server.
//store returned data in text file for testing
$fp = fopen('log.txt', 'a+');
fwrite($fp, $xml);
fclose($fp);
return;
}
That message means exactly what it says:
There's no data to exchange. There's nothing to do.
The Web Connector and this framework work using a 'queue' concept. Once the queue is empty, there's nothing else to do, and you'll get that message. If you add something to the queue, then it will process those items until there's nothing left to do, and then you'll get the “No Data Exchange…” message again.
You haven't added anything to the queue.
You could do this with a cron job, or by registering a function that runs whenever the Web Connector connects, and immediately stuffs something in the queue. e.g.:
// An array of callback hooks
$hooks = array(
QuickBooks_WebConnector_Handlers::HOOK_LOGINSUCCESS => '_quickbooks_hook_loginsuccess', // call this whenever a successful login occurs
);
/**
* 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();
$Queue->enqueue(QUICKBOOKS_IMPORT_TRANSACTION);
}
You can see an extended example of this here:
https://github.com/consolibyte/quickbooks-php/blob/master/docs/web_connector/example_web_connector_import.php#L214
Some other things you may want to take away from the example:
With larger data sets, you won't be able to query all of the transactions in just a single request. You can use iterators as shown in the GitHub example to page the records 25 or 100 at a time for better performance/reliability.
Use the highest qbXML version your QuickBooks supports (you're using <?qbxml version="2.0"?>)

QuickBooks Desktop Web Connector Autorun a Request Queue

I'm using quickbooks desktop. I want to dump the CustomerQueryRq response every 5 minutes. I started on top of ConsoliBYTE docs/web_connector/example_app_web_connector
What I want to do:
I'm looking for a way where I don't have to visit the handler.php file every 5 minutes to trigger the queue. I believe there's a better way.
Here's what I did:
Created and registered a .qwc file in web connector
Modified the config, qbwc, handler and functions files
Created cron job that calls the handler.php file every 5 minutes.
It gives me a json file like this: json file which is exactly what I want.
qbwc.php:
require_once dirname(__FILE__) . '/config.php';
require_once dirname(__FILE__) . '/functions.php';
// Map QuickBooks actions to handler functions
$map = array(
QUICKBOOKS_QUERY_CUSTOMER => array( '_quickbooks_customer_query_request', '_quickbooks_customer_query_response' ),
);
$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);
functions.php:
function _quickbooks_customer_query_request($ListID = null, $FullName = null)
{
$xml = '
<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="2.0"?>
<QBXML>
<QBXMLMsgsRq onError="continueOnError">
<CustomerQueryRq />
</QBXMLMsgsRq>
</QBXML>
';
return $xml;
}
function _quickbooks_customer_query_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents)
{
$xmlData = simplexml_load_string($xml);
$json = json_encode($xmlData->QBXMLMsgsRs->CustomerQueryRs, true);
file_put_contents('customerDump.json', $json);
}
handler.php:
require_once dirname(__FILE__) . '/config.php';
// Queue up the customer dump
$Queue = new QuickBooks_WebConnector_Queue($con);
$Queue->enqueue(QUICKBOOKS_QUERY_CUSTOMER, 2);
die('Great, queued up customer dump!');
The easiest way to do this is to make it so that every time the Web Connector connects, it queues up the request you want to run.
To do that:
Register a hook function which runs whenever the Web Connector connects
$hooks = array(
QuickBooks_WebConnector_Handlers::HOOK_LOGINSUCCESS => 'your_function_name_here', // call this whenever a successful login occurs
);
https://github.com/consolibyte/quickbooks-php/blob/master/docs/web_connector/example_web_connector_import.php#L125
Make that function throw something into the queue
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();
// Queue stuff up
$Queue->enqueue(QUICKBOOKS_QUERY_CUSTOMER, 2);
}
https://github.com/consolibyte/quickbooks-php/blob/master/docs/web_connector/example_web_connector_import.php#L219
So, every time the Web Connector connects your thing gets stuffed into the queue and processed. No cron job required.

Using Consolibyte's PHP Devkit to Add a Customer to Quickbooks POS Desktop v.12 w/ Web Connector

I'm out of my depth and am hoping a few coders will help with a noble cause.
I haven't done much programming outside of college classes and need some help with some basics. I've started a nonprofit technology service provider for other nonprofits. The integration described below is part of my first project which I've completely donated. If I were charging any fees, I'd pay for this help as it's certainly not my wheel house. I have many other items to attend to in this project and am hoping that somebody will help speed things along.
The integration that I'm working on is simple. The nonprofit sells donated goods and offers a ten percent discount to folks that sign up for their discount program. Currently, users are signing up via a google form and at a later date, the information is manually added to the Quickbooks v. 12 POS system. As the organization is using wordpress, php seemed like a goodfit. I'm totally open to other methods, the following is simply where my research landed.
I'm using the following
Intuit Quickbooks POS v.12
http://dlm2.download.intuit.com/akdlm/SBD/QuickBooks/2015/Latest/QuickBooksPOSV12Trial30.exe
Web Connector v. 2.1.0.30
developer.intuit.com/docs/0200_quickbooks_desktop/0100_essentials/quickbooks_web_connector
Keith Palmer's / Consolibyte's PHP Dev Kit
consolibyte.com/downloads/quickbooks-php-devkit/
I've been successful in using (it's a dev lamp stack): lamp.pond.im/qb/docs/web_connector/example_web_connector_point_of_sale.php
to add a static customer record
I'm struggling with some basic next steps. If I'm understanding the documentation correctly:
http://www.consolibyte.com/docs/index.php/PHP_DevKit_for_QuickBOoks_-_Point_of_Sale_Quick-Start
My next step is to queue a user provided by a form. My goal is to implement this for the organization using a wordpress plugin. That said, at this point I just need to get things functional. I believe the code below is what I need to queue up the new user, but I'm struggling with implementation. I think I need to create a form, but don't understand how to use the code below (docs/example_web_connector_queueing.php) with docs/example_web_connector_point_of_sale.php.
docs/example_web_connector_queueing.php
<?php
/**
* Example integration with an application
*
* The idea behind the action queue is basically just that you want to add an
* action/ID pair to the queue whenever something happens in your application
* that you need to tell QuickBooks about.
*
* #author Keith Palmer <keith#consolibyte.com>
*
* #package QuickBooks
* #subpackage Documentation
*/
// Error reporting for easier debugging
ini_set('display_errors', true);
error_reporting(E_ALL | E_STRICT);
// Require the queueuing class
require_once '../QuickBooks.php';
if (isset($_POST['customer']))
{
// Oooh, here's a new customer, let's do some stuff with them
// Connect to your own MySQL server....
$link = mysql_connect('localhost', 'your_mysql_username',
'your_mysql_password');
if (!$link)
{
die('Could not connect to MySQL: ' . mysql_error());
}
// ... and use the correct database
$selected = mysql_select_db('your_database_name', $link);
if (!$selected)
{
die ('Could not select database: ' . mysql_error());
}
// Insert into our local MySQL database
mysql_query("INSERT INTO my_customer_table ( name, phone, email ) VALUES ( '" . $_POST['customer']['name'] . "', '" . $_POST['customer']['phone'] . "', '" . $_POST['customer']['email'] . "' ) ");
$id_value = mysql_insert_id();
// QuickBooks queueing class
$Queue = new QuickBooks_WebConnector_Queue('mysql://root:password#localhost/my_database');
// Queue it up!
$Queue->enqueue(QUICKBOOKS_ADD_CUSTOMER, $id_value);
}
Here's the example_web_connector_point_of_sale.php code
<?php
/**
* Example QuickBooks SOAP Server / Web Service for QuickBooks Point of Sale
*
* This is an example Web Service which adds test dummy customers to QuickBooks
* Point of Sale via the Web Connector.
*
* You should probably also look through docs/example_web_connector.php for
* some additional documentation about what things do.
*
* #author Keith Palmer <keith#consolibyte.com>
*
* #package QuickBooks
* #subpackage Documentation
*/
// 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');
}
// Error reporting for easier debugging
error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', true);
// Require the framework
require_once '../QuickBooks.php';
// A username and password you'll use in:
// a) Your .QWC file
// b) The Web Connector
// c) The QuickBooks framework
$user = 'quickbooks';
$pass = 'password';
// Map QuickBooks actions to handler functions
$map = array(
QUICKBOOKS_ADD_CUSTOMER => array( '_quickbooks_pos_customer_add_request', '_quickbooks_pos_customer_add_response' ),
// ... more action handlers here ...
);
// This is entirely optional, use it to trigger actions when an error is returned by QuickBooks
$errmap = array(
);
// An array of callback hooks
$hooks = array(
);
// Logging level
//$log_level = QUICKBOOKS_LOG_NORMAL;
//$log_level = QUICKBOOKS_LOG_VERBOSE;
//$log_level = QUICKBOOKS_LOG_DEBUG;
$log_level = QUICKBOOKS_LOG_DEVELOP; // Use this level until you're sure everything works!!!
// 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(
'deny_concurrent_logins' => false,
); // See the comments in the QuickBooks/Server/Handlers.php file
$driver_options = array( // See the comments in the QuickBooks/Driver/<YOUR DRIVER HERE>.php file ( i.e. 'Mysql.php', etc. )
);
$callback_options = array(
);
// * MAKE SURE YOU CHANGE THE DATABASE CONNECTION STRING BELOW TO A VALID MYSQL USERNAME/PASSWORD/HOSTNAME *
$dsn = 'mysql://root:root#localhost/quickbooks_pos_server';
if (!QuickBooks_Utilities::initialized($dsn))
{
// Initialize creates the neccessary database schema for queueing up requests and logging
QuickBooks_Utilities::initialize($dsn);
// This creates a username and password which is used by the Web Connector to authenticate
QuickBooks_Utilities::createUser($dsn, $user, $pass);
// We're going to queue up a request to add a customer, just as a test...
$primary_key_of_your_customer = 5;
$Queue = new QuickBooks_WebConnector_Queue($dsn);
$Queue->enqueue(QUICKBOOKS_ADD_CUSTOMER, $primary_key_of_your_customer);
}
// Create a new server and tell it to handle the requests
// __construct($dsn_or_conn, $map, $errmap = array(), $hooks = array(), $log_level = QUICKBOOKS_LOG_NORMAL, $soap = QUICKBOOKS_SOAPSERVER_PHP, $wsdl = QUICKBOOKS_WSDL, $soap_options = array(), $handler_options = array(), $driver_options = array(), $callback_options = array()
$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);
/**
* Generate a qbXML request for QuickBooks Point of Sale
*/
function _quickbooks_pos_customer_add_request($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale)
{
// We're just testing, so we'll just use a static test request:
$xml = '
<?xml version="1.0" encoding="utf-8"?>
<?qbposxml version="3.0"?>
<QBPOSXML>
<QBPOSXMLMsgsRq onError="stopOnError">
<CustomerAddRq>
<CustomerAdd>
<CompanyName>ConsoliBYTE, LLC</CompanyName>
<EMail>support#ConsoliBYTE.com</EMail>
<FirstName>Keith</FirstName>
<LastName>Palmer Jr.</LastName>
<Phone>860-341-1464</Phone>
<Salutation>Mr.</Salutation>
<BillAddress>
<City>Willington</City>
<Country>USA</Country>
<PostalCode>06279</PostalCode>
<State>CT</State>
<Street>56 Cowles Road</Street>
</BillAddress>
<ShipAddress>
<City>Willington</City>
<Country>USA</Country>
<PostalCode>06279</PostalCode>
<State>CT</State>
<Street>56 Cowles Road</Street>
</ShipAddress>
</CustomerAdd>
</CustomerAddRq>
</QBPOSXMLMsgsRq>
</QBPOSXML>';
return $xml;
}
/**
* Receive a response from QuickBooks
*/
function _quickbooks_pos_customer_add_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents)
{
// Great, customer $ID has been added to QuickBooks with a QuickBooks
// ListID value of: $idents['ListID']
//
// We probably want to store that ListID in our database, so we can use it
// later. (You'll need to refer to the customer by either ListID or Name
// in other requests, say, to update the customer or to add an invoice for
// the customer.
/*
mysql_query("UPDATE your_customer_table SET quickbooks_listid = '" . mysql_escape_string($idents['ListID']) . "' WHERE your_customer_ID_field = " . (int) $ID);
*/
}
First, create a WordPress form and store whatever is input in the database. Lots of tutorials online about how to do that. Here's one:
https://wordpress.stackexchange.com/questions/77258/custom-form-that-store-input-in-database
You should get back some sort of Id value for the record you inserted. Use that to queue up the record immediately after saving it to the database:
require_once 'path/to/QuickBooks.php';
// QuickBooks queueing class
$Queue = new QuickBooks_WebConnector_Queue('mysql://root:password#localhost/my_database');
// Queue it up!
$Queue->enqueue(QUICKBOOKS_ADD_CUSTOMER, $id_value);
Separately, in a totally separate script, modify your function to add a customer to QuickBooks POS:
function _quickbooks_pos_customer_add_request($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale)
{
// Pull the data out of the database that we stored from the WordPress form submission
$arr = mysql_fetch_array(mysql_query("SELECT * FROM your_table WHERE id = " . (int) $ID));
// Build $xml using the data in $arr
$xml = '
As other users have pointed out, this code is old so take some time to clean it up and make sure it's secure. Among the things you'll want to look at:
Use PDO or mysqli or another database later instead of the mysql_* functions (they are deprecated)
Prepared statements or parameterized statements are good idea for database queries

Full Customer Data is not adding up in quickbooks desktop

I am using keith's codeignitor example to add customer data in quickbook desktop from my online pos.
I fetched the data from database and created XML which is perfect and showing all 5109 records. However after running the web service I can only import 165 entries .
Please keep following in mind -
1)There is no XML breakage . The XML is fine
2)Webservice time is set to 500 min so no interruption.
Attached is my code for controller and database file -
Controller -
http://quicktotals.com/quickbooks.txt
SQL -
http://quicktotals.com/phppos_people.sql
<?php
class QuickBooks extends CI_Controller
{
public function __construct()
{
parent::__construct();
// QuickBooks config
$this->load->config('quickbooks');
// Load your other models here...
//$this->load->model('yourmodel1');
//$this->load->model('yourmodel2');
//$this->load->model('yourmodel3');
}
/**
* Generate and return a .QWC Web Connector configuration file
*/
public function config()
{
$name = 'CodeIgniter QuickBooks Demo'; // A name for your server (make it whatever you want)
$descrip = 'CodeIgniter QuickBooks Demo'; // A description of your server
$appurl = 'https://' . $_SERVER['HTTP_HOST'] . dirname($_SERVER['REQUEST_URI']) . '/qbwc'; // This *must* be httpS:// (path to your QuickBooks SOAP server)
$appsupport = $appurl; // This *must* be httpS:// and the domain name must match the domain name above
//$dsn = 'mysql://quicktot_admin:hunter2001#localhost/quicktot_pointofsale';
//QuickBooks_Utilities::createUser($dsn,'vijay','test#1234');
$username = $this->config->item('quickbooks_user'); // This is the username you stored in the 'quickbooks_user' table by using QuickBooks_Utilities::createUser()
$fileid = QuickBooks_WebConnector_QWC::fileID(); // Just make this up, but make sure it keeps that format
$ownerid = QuickBooks_WebConnector_QWC::ownerID(); // Just make this up, but make sure it keeps that format
$qbtype = QUICKBOOKS_TYPE_QBFS; // You can leave this as-is unless you're using QuickBooks POS
$readonly = false; // No, we want to write data to QuickBooks
$run_every_n_seconds = 600; // Run every 600 seconds (10 minutes)
// Generate the XML file
$QWC = new QuickBooks_WebConnector_QWC($name, $descrip, $appurl, $appsupport, $username, $fileid, $ownerid, $qbtype, $readonly, $run_every_n_seconds);
$xml = $QWC->generate();
// Send as a file download
header('Content-type: text/xml');
//header('Content-Disposition: attachment; filename="my-quickbooks-wc-file.qwc"');
print($xml);
exit;
}
/**
* SOAP endpoint for the Web Connector to connect to
*/
public function qbwc()
{
$user = $this->config->item('quickbooks_user');
$pass = $this->config->item('quickbooks_pass');
// Memory limit
ini_set('memory_limit', $this->config->item('quickbooks_memorylimit'));
// 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($this->config->item('quickbooks_tz'));
}
// Map QuickBooks actions to handler functions
$map = array(
QUICKBOOKS_ADD_CUSTOMER => array( array( $this, '_addCustomerRequest' ), array( $this, '_addCustomerResponse' )
),
);
// Catch all errors that QuickBooks throws with this function
$errmap = array(
'*' => array( $this, '_catchallErrors' ),
);
// Call this method whenever the Web Connector connects
$hooks = array(
QuickBooks_WebConnector_Handlers::HOOK_LOGINSUCCESS => array( array( $this, '_loginSuccess' ) ), // Run this function whenever a successful login occurs
);
// An array of callback options
$callback_options = array();
// Logging level
$log_level = $this->config->item('quickbooks_loglevel');
// 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(
'deny_concurrent_logins' => false,
'deny_reallyfast_logins' => false,
); // See the comments in the QuickBooks/Server/Handlers.php file
$driver_options = array( // See the comments in the QuickBooks/Driver/<YOUR DRIVER HERE>.php file ( i.e. 'Mysql.php', etc. )
'max_log_history' => 32000, // Limit the number of quickbooks_log entries to 1024
'max_queue_history' => 1024, // Limit the number of *successfully processed* quickbooks_queue entries to 64
);
// Build the database connection string
$dsn = 'mysql://' . $this->db->username . ':' . $this->db->password . '#' . $this->db->hostname . '/' . $this->db->database;
// Check to make sure our database is set up
if (!QuickBooks_Utilities::initialized($dsn))
{
//echo "aaa"; die;
// Initialize creates the neccessary database schema for queueing up requests and logging
QuickBooks_Utilities::initialize($dsn);
// This creates a username and password which is used by the Web Connector to authenticate
QuickBooks_Utilities::createUser($dsn, $user, $pass);
}
QuickBooks_Utilities::createUser($dsn, $user, $pass);
//echo "bbb"; die;
// Set up our queue singleton
QuickBooks_WebConnector_Queue_Singleton::initialize($dsn);
// Create a new server and tell it to handle the requests
//__construct($dsn_or_conn, $map, $errmap = array(), $hooks = array(), $log_level = QUICKBOOKS_LOG_NORMAL, $soap = QUICKBOOKS_SOAPSERVER_PHP, $wsdl = QUICKBOOKS_WSDL, $soap_options = array(), $handler_options = array(), $driver_options = array(), $callback_options = array()
$Server = new QuickBooks_WebConnector_Server($dsn, $map, $errmap, $hooks, $log_level, $soapserver, QUICKBOOKS_WSDL, $soap_options,$handler_options, $driver_options, $callback_options);
$Queue = new QuickBooks_WebConnector_Queue($dsn);
$Queue->enqueue(QUICKBOOKS_ADD_CUSTOMER);
$response = $Server->handle(true, true);
}
/**
* Issue a request to QuickBooks to add a customer
*/
public function _addCustomerRequest($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale)
{
// Do something to store the form data here
$this->load->model('Myquickbooks');
$data = $this->Myquickbooks->getCustomerData();
$xml ='';
$xml .= '<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="11.0"?>';
$xml .= '<QBXML>';
$xml .= '<QBXMLMsgsRq onError="stopOnError">';
foreach ($data as $dta)
{
$xml .='<CustomerAddRq requestID="' . $requestID . '">
<CustomerAdd>
<Name>'.$dta['first_name'].'_'.$dta['person_id'].'</Name>
<CompanyName>'.$dta['company_name'].'</CompanyName>
<FirstName>'.$dta['first_name'].'</FirstName>
<LastName>'.$dta['last_name'].'</LastName>
<BillAddress>
<Addr1>'.$dta['address_1'].'</Addr1>
<Addr2>'.$dta['address_2'].'</Addr2>
<City>'.$dta['city'].'</City>
<State>'.$dta['state'].'</State>
<PostalCode>'.$dta['zip'].'</PostalCode>
<Country>'.$dta['country'].'</Country>
</BillAddress>
<Phone>'.$dta['phone_number'].'</Phone>
<AltPhone>'.$dta['phone_number'].'</AltPhone>
<Fax>'.$dta['phone_number'].'</Fax>
<Email>'.$dta['email'].'</Email>
<Contact>'.$dta['phone_number'].'</Contact>
</CustomerAdd>
</CustomerAddRq>';
}
$xml .='</QBXMLMsgsRq>';
$xml .='</QBXML>';
$xml = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $xml);
return $xml;
}
/**
* Handle a response from QuickBooks indicating a new customer has been added
*/
public function _addCustomerResponse($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents)
{
return true;
}
/**
* Catch and handle errors from QuickBooks
*/
public function _catchallErrors($requestID, $user, $action, $ID, $extra, &$err, $xml, $errnum, $errmsg)
{
if ($action == QUICKBOOKS_ADD_CUSTOMER and $errnum == 3100)
{
return true; // Ignore this error, all is OK - customer already exists
}
// Some other error occurred, stop processing
return false;
}
/**
* Whenever the Web Connector connects, do something (e.g. queue some stuff up if you want to)
*/
public function _loginSuccess($requestID, $user, $hook, &$err, $hook_data, $callback_config)
{
return true;
}
}
?>
Your code has numerous problems, and for anyone to help you, you're going to have to fix the problems first. Details:
You're using a 13-year-old version of qbXML. Why? You should use the highest version your QuickBooks supports:
<?qbxml version="2.0"?>
You're bundling multiple customers up into a single qbXML request. This is bad -- it destroys any ability you have to actually track and report on errors. Do not do this. Each customer add request should be it's own individual request, with it's own specific entry in the queue. Refer to the documentation.
foreach ($data as $dta)
You are specifically bypassing all error checking and error reporting. Why? This makes it impossible to know if something went wrong or not.
return true;
Fix your code, and then re-post the actual code instead of a .txt file.

Converting an application using Keith Palmer's QBWC framework to QuickBooks Online

We're using Keith Palmer/Consolibyte Solutions' excellent PHP QuickBooks Framework in our web application to communicate with QuickBooks Desktop edition via the QuickBooks Web Connector. We're using a QuickBooks_Server and a QuickBooks_Queue in our code as follows:
$this->myQBQueue = new QuickBooks_Queue($this->myDSN);
$mappedFunctions = array(
QUICKBOOKS_ADD_CUSTOMER,
QUICKBOOKS_ADD_SALESORDER,
QUICKBOOKS_ADD_SALESRECEIPT,
QUICKBOOKS_QUERY_CUSTOMER,
);
$map = array();
foreach($mappedFunctions as $function) {
$map[$function] = array(
array($this,"quickbooks{$function}Request"),
array($this,"quickbooks{$function}Response"),
);
}
$errmap = array('*' => array($this,'quickbooksErrorHandler'));
$hooks = array(
QUICKBOOKS_HANDLERS_HOOK_LOGINFAILURE => array(
array($this,'quickbooksLoginFailureHook')
),
QUICKBOOKS_HANDLERS_HOOK_LOGINSUCCESS => array(
array($this,'quickbooksLoginSuccessHook')
)
);
$soap_options = array();
$handler_options = array();
$driver_options = array();
$callback_options = array();
$this->myQBServer = new QuickBooks_Server($this->myDSN, $map, $errmap, $hooks, QUICKBOOKS_LOG_NORMAL, QUICKBOOKS_SOAPCLIENT_BUILTIN, QUICKBOOKS_WSDL, $soap_options, $handler_options, $driver_options, $callback_options);
We now have a customer who has requested that we add support for QuickBooks online. Can we still use a QuickBooks_Server and a QuickBooks_Queue using Keith Palmer's framework for QuickBooks online, or do we have to write new code for the QuickBooks online portion?
You could re-use the Queue stuff, but the framework doesn't natively support it - you could definitely hack it in easily though.
You will also definitely be able to re-use most (but not all) of your qbXML.
QuickBooks Online does support a qbXML interface (though it's not terribly good - Intuit has publicly stated that they will likely deprecate it within the next year or so, and they are no longer adding features to it). You should know that in the near future, it's very likely that you'll want to start thinking about moving towards Intuit Anywhere/IDS - especially if you're a SaaS app with a lot of QuickBooks Online customers.
You can find the qbXML docs for QuickBooks Online here:
http://developer.intuit.com/qbsdk-current/common/newosr/index.html
(make sure you tick the "OE" checkbox and uncheck the "US" checkbox)
A few things that bite a lot of people with QuickBooks Online:
When adding Payments, you MUST apply them to an invoice. There is no IsAutoApply in QBO
There's no support for UPDATING invoices in the qbXML API for QBO
There's no support for inventory items in the qbXML API for QBO
If you look at the docs/example_online_edition.php (or docs/example_raw_online_edition.php) file included with the QuickBooks PHP DevKit library code you have, you'll see how it works. Basically instead of a queue, you're just sending straight qbXML requests to Intuit's server via HTTPS instead of wrapping it in SOAP and waiting for the Web Connector to pick it up.
With that said, if you really wanted to continue using the Queue, you could - Queue stuff up just as you normally do, and just set up a script something like this that runs on a cron job:
(WARNING - totally untested code, you'll have to test and debug)
<?php
// Do some setup stuff here as shown in the example...
$res = mysql_query("SELECT * FROM quickbooks_queue WHERE qb_username = 'the username' AND qb_status = 'q'");
while ($arr = mysql_fetch_array($res))
{
$request_function = $map[$arr['qb_action']][0];
$response_function = $map[$arr['qb_action']][1];
$requestID = null; // not relevant for QBO
$user = 'the username';
$ID = $arr['ident'];
$extra = null;
if($arr['extra']) $extra = unserialize($arr['extra']);
$err = null;
$last_action_time = null;
$last_actionident_time = null;
$version = '6.0'; // QBO only supports 6.0
$locale = 'US'; // QBO only supports US
$qbxml = $request_function($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale);
$xml = $API->qbxml($qbxml);
$idents = _extractIdentifiers($xml); // You can find this function in QuickBooks/Handlers.php and pull it into your app as a function instead of a method
$response_function($requestID, $user, $action, $ID, $extra, $err, $last_action_time, $last_actionident_time, $xml, $idents);
}

Categories