1
votes

Here is my scenario.

  1. There will be a company having business account on QuickBooks.

  2. Company will add Customers/Clients/Users to their account.

  3. Now the company will issue invoices to these Customers/Clients/Users.

  4. I have to show (list) the invoices generated by company and I will pass CustomerID (ClientID/UserID) as a parameter to get invoices for that Customer/User/Client only.

Note that the companies will provide us their credentials in order to fetch invoices of their Customers/Clients/Users. I just have to show the invoices, I don't have to do anything else with Quickbooks or Quickbooks API. Also note that I have fetch invoices from Quickbooks Online and the Desktop version (using Web connector).

Thanks in Advance,

1

1 Answers

4
votes

If you are building a SaaS service (e.g. you are charging your customers a monthly fee to connect their QuickBooks to your app) then you can do this using IPP/IDS. If you are not charging them a monthly fee, then you can do this with the Web Connector/qbXML.

Regardless of which connection type you go for, this doesn't make any sense:

  1. I have to show (list) the invoices generated by company and I will pass CustomerID (ClientID/UserID) as a parameter to get invoices for that Customer/User/Client only.

The OAuth tokens/connections are QuickBooks-company-file-specific, and there is no such field "CustomerID" (or "ClientID", or "UserID").

For a SaaS/IPP/IDS example, download this:

And look at these scripts:

  • docs/example_ipp_config.php
  • docs/example_ipp_oauth.php
  • docs/example_ipp_ids_5.php

You'll have to register here to get your own OAuth tokens:

The docs/example_ipp_ids_5.php script shows how to fetch all customers. You can change it to use QuickBooks_IPP_Service_Invoice to fetch all invoices instead.

Your code will end up looking something like this:

$Service = new QuickBooks_IPP_Service_Invoice();

$perpage = 3;
for ($page = 1; $page <= 3; $page++)
{
    print('PAGE ' . $page . "\n\n");

    $list = $InvoiceService->findAll($Context, $realm, null, $page, $perpage);

    foreach ($list as $Invoice)
    {
        print('Internal ID [' . $Invoice->getId() . ' => ' . $Invoice->getHeader()->getDocNumber() . ']' . "\n\n");
    }

    print("\n\n\n");
}

For a Web Connector example (QuickBooks desktop) download this:

And look at this example:

  • docs/example_web_connector_import.php

And the quick-start guide:

You'll end up with something similar to:

/**
 * 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']))
    {
        // 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 . '">
                    <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'] ));
    }

    // 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');

        foreach ($List->children() as $Invoice)
        {
            $arr = array(
                'TxnID' => $Invoice->getChildDataAt('InvoiceRet TxnID'),
                'TimeCreated' => $Invoice->getChildDataAt('InvoiceRet TimeCreated'),
                'TimeModified' => $Invoice->getChildDataAt('InvoiceRet TimeModified'),
                'RefNumber' => $Invoice->getChildDataAt('InvoiceRet RefNumber'),
                'Customer_ListID' => $Invoice->getChildDataAt('InvoiceRet CustomerRef ListID'),
                'Customer_FullName' => $Invoice->getChildDataAt('InvoiceRet CustomerRef FullName'),
                'ShipAddress_Addr1' => $Invoice->getChildDataAt('InvoiceRet ShipAddress Addr1'),
                'ShipAddress_Addr2' => $Invoice->getChildDataAt('InvoiceRet ShipAddress Addr2'),
                'ShipAddress_City' => $Invoice->getChildDataAt('InvoiceRet ShipAddress City'),
                'ShipAddress_State' => $Invoice->getChildDataAt('InvoiceRet ShipAddress State'),
                'ShipAddress_PostalCode' => $Invoice->getChildDataAt('InvoiceRet ShipAddress PostalCode'),
                'BalanceRemaining' => $Invoice->getChildDataAt('InvoiceRet BalanceRemaining'),
                );

            QuickBooks_Utilities::log(QB_QUICKBOOKS_DSN, 'Importing invoice #' . $arr['RefNumber'] . ': ' . print_r($arr, true));

            foreach ($arr as $key => $value)
            {
                $arr[$key] = mysql_real_escape_string($value);
            }

            // Store the invoices in MySQL
            mysql_query("
                REPLACE INTO
                    qb_example_invoice
                (
                    " . implode(", ", array_keys($arr)) . "
                ) VALUES (
                    '" . implode("', '", array_values($arr)) . "'
                )") or die(trigger_error(mysql_error()));

            // Remove any old line items
            mysql_query("DELETE FROM qb_example_invoice_lineitem WHERE TxnID = '" . mysql_real_escape_string($arr['TxnID']) . "' ") or die(trigger_error(mysql_error()));

            // Process the line items
            foreach ($Invoice->children() as $Child)
            {
                if ($Child->name() == 'InvoiceLineRet')
                {
                    $InvoiceLine = $Child;

                    $lineitem = array( 
                        'TxnID' => $arr['TxnID'], 
                        'TxnLineID' => $InvoiceLine->getChildDataAt('InvoiceLineRet TxnLineID'), 
                        'Item_ListID' => $InvoiceLine->getChildDataAt('InvoiceLineRet ItemRef ListID'), 
                        'Item_FullName' => $InvoiceLine->getChildDataAt('InvoiceLineRet ItemRef FullName'), 
                        'Descrip' => $InvoiceLine->getChildDataAt('InvoiceLineRet Desc'), 
                        'Quantity' => $InvoiceLine->getChildDataAt('InvoiceLineRet Quantity'),
                        'Rate' => $InvoiceLine->getChildDataAt('InvoiceLineRet Rate'), 
                        );

                    foreach ($lineitem as $key => $value)
                    {
                        $lineitem[$key] = mysql_real_escape_string($value);
                    }

                    // Store the lineitems in MySQL
                    mysql_query("
                        INSERT INTO
                            qb_example_invoice_lineitem
                        (
                            " . implode(", ", array_keys($lineitem)) . "
                        ) VALUES (
                            '" . implode("', '", array_values($lineitem)) . "'
                        ) ") or die(trigger_error(mysql_error()));
                }
            }
        }
    }

    return true;
}

For a QuickBooks Online via qbXML example (QuickBooks Online) download this:

And look at this example:

  • docs/example_online_edition.php

You'll end up with something similar to:

// Register in DESKTOP mode to get these. Docs: 
//  http://www.consolibyte.com/docs/index.php/QuickBooks_Online_via_qbXML#Connecting_with_the_.27Desktop.27_model_of_communication
$application_id = '134476472';
$application_login = 'qboe.test.test.com';
$connection_ticket = 'TGT-47-1sRm2nXMVfm$n8hb2MZfVQ';

// Create our new gateway instance 
$Gateway = new QuickBooks_Gateway_OnlineEdition(
    $application_id,
    $application_login,
    $connection_ticket);

$xml = '<QBXMLMsgsRq onError="stopOnError">
            <InvoiceQueryRq>

            </InvoiceQueryRq>
        </QBXMLMsgsRq>';

// Send the request
$resp = $Gateway->qbxml($xml);

print($resp);