Search code examples
phpxmlquickbooks

Quickbooks Error "Response is not well-formed XML"


I'm trying to create a Sales Order in Quickbooks for Windows using Consolibyte's php library. However, everytime I do, the Quickbooks Web Connector fails with the error message "Response is not well-formed XML"

This is the XML request that I am passing in:

 <?xml version="1.0" encoding="utf-8"?><?qbxml version="13.0"?>
    <QBXML><QBXMLMsgsRq onError="stopOnError">
    <SalesOrderAddRq requestID="">
    <SalesOrderAdd>
                <CustomerRef>
                    <FullName>Matthew Ong</FullName>
                </CustomerRef>
                <TxnDate>08/07/2015</TxnDate>

                <BillAddress>
                    <Addr1>Matthew Ong</Addr1>
                    <Addr2>146 Woodland Ave</Addr2>
                    <City>Winnetka</City>
                    <State>IL</State>
                    <PostalCode>60093</PostalCode>
                    <Country>US</Country>
                </BillAddress>
                <ShipAddress>
                    <Addr1>Matthew Ong</Addr1>
                    <Addr2>146 Woodland Ave</Addr2>
                    <City>Winnetka</City>
                    <State>IL</State>
                    <PostalCode>60093</PostalCode>
                    <Country>US</Country>
                </ShipAddress>
                <ItemSalesTaxRef>
                    <FullName>Out of State</FullName>
                </ItemSalesTaxRef>

                             <SalesOrderLineAdd>
                    <ItemRef>
                        <FullName>FG.EP12SALOEP</FullName>
                    </ItemRef>
                    <Desc>12 oz - Aloe Vera &amp; Eucalyptus Shampoo</Desc>
                    <Quantity>5</Quantity>
                    <Amount>32.5</Amount>
                </SalesOrderLineAdd>

                             <SalesOrderLineAdd>
                    <ItemRef>
                        <FullName>FG.EP1OZ12PKBEARDOIL</FullName>
                    </ItemRef>
                    <Desc>1 oz - Beard Oil - Black Seed</Desc>
                    <Quantity>3</Quantity>
                    <Amount>27</Amount>
                </SalesOrderLineAdd>

                <SalesOrderLineAdd>
                    <ItemRef>
                        <FullName>Shipping</FullName>
                    </ItemRef>
                    <Quantity>1</Quantity>
                    <Amount>15.31</Amount>
                </SalesOrderLineAdd>
            </SalesOrderAdd>
</SalesOrderAddRq>
</QBXMLMsgsRq>
</QBXML>

Does anyone know what is going wrong?

EDIT: Here is my full web connector php file

    <?php
require_once("../../init.php");

error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', 1);

if (function_exists('date_default_timezone_set'))
{
    date_default_timezone_set('America/Chicago');
}

require_once '../../QuickBooks.php';

$user = '(blurred out)';
$pass = '(blurred out)';


// Map QuickBooks actions to handler functions
$map = array(
    QUICKBOOKS_ADD_CUSTOMER => array( '_quickbooks_customer_add_request', '_quickbooks_customer_add_response' ),
    QUICKBOOKS_ADD_SALESORDER => array( '_quickbooks_add_sales_order_request', '_quickbooks_add_sales_order_response' ),

    );


$errmap = array(
    3070 => '_quickbooks_error_stringtoolong',
    );

$hooks = array(

    );

$log_level = QUICKBOOKS_LOG_DEVELOP;    

$soapserver = QUICKBOOKS_SOAPSERVER_BUILTIN;        

$soap_options = array(  
    );

$handler_options = array(
    'deny_concurrent_logins' => false, 
    'deny_reallyfast_logins' => false, 
    );

$driver_options = array(    
    );

$callback_options = array(
    );


$dsn = '(blurred out)';


if (!QuickBooks_Utilities::initialized($dsn))
{

    QuickBooks_Utilities::initialize($dsn);

    QuickBooks_Utilities::createUser($dsn, $user, $pass);


}

$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_customer_add_request($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale)
{

     $order = "SELECT * FROM patron_orders WHERE order_id = $ID";
    $result = mysql_query($order);
    $data = mysql_fetch_row($result);


    $type = $data[23];
    $database_company = $data[22];
    $database_billing_name = $data[10];
    $database_billing_address = $data[11];
    $database_billing_zipcode = $data[12];
    $database_billing_state = $data[13];
    $database_billing_city = $data[14];
    $database_phone = $data[9];
    $database_email = $data[8];


    $contactname = $data[10];


    if($type == "salon") {
        $listingname = $database_company;
        $companyname = "<CompanyName>" . $database_company . "</CompanyName>";  
    } else {
        $listingname = strtoupper($database_billing_name);
    }


    $xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>
        <?qbxml version=\"2.0\"?>
        <QBXML>
            <QBXMLMsgsRq onError=\"stopOnError\">
                <CustomerAddRq requestID=\"$requestID\">
                    <CustomerAdd>
                        <Name>$listingname</Name>
                        $companyname
                        <FirstName>$contactname</FirstName>
                        <BillAddress>
                            <Addr1>$contactname</Addr1>
                            <Addr2>$database_billing_address</Addr2>
                            <City>$database_billing_city</City>
                            <State>$database_billing_state</State>
                            <PostalCode>$database_billing_zipcode</PostalCode>
                            <Country>United States</Country>
                        </BillAddress>
                        <Phone>$database_phone</Phone>
                        <Email>$database_email</Email>
                        <Contact>$contactname</Contact>
                    </CustomerAdd>
                </CustomerAddRq>
            </QBXMLMsgsRq>
        </QBXML>";

    return $xml;
}

function _quickbooks_customer_add_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents)
{   

}


function _quickbooks_add_sales_order_request($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale)
{



     $order = "SELECT * FROM patron_orders WHERE order_id = $ID";
    $result = mysql_query($order);
    $data = mysql_fetch_row($result);


    $type = $data[23];
    $database_company = $data[22];
    $database_billing_name = $data[10];
    $database_billing_address = $data[11];
    $database_billing_zipcode = $data[12];
    $database_billing_state = $data[13];
    $database_billing_city = $data[14];
    $database_phone = $data[9];
    $database_email = $data[8];
    $database_date = $data[3];
    $fullname = $database_billing_name;
    $dateformat = date("Y-m-d", $database_date);  
    $contactname = $data[10];

    $database_shipping_name = $data[1];
    $database_shipping_address = $data[4];
    $database_shipping_zipcode = $data[5];
    $database_shipping_state = $data[6];
    $database_shipping_city = $data[7];

    $database_shipping_cost = $data[19];
    $database_shipping_cost = number_format((float)($database_shipping_cost), 2, '.', '');



    if($type == "salon") {
        $listingname = $database_company;
        $companyname = "<CompanyName>" . $database_company . "</CompanyName>";  
    } else {
        $listingname = strtoupper($database_billing_name);
    }

    $orderlinesstr = "";



    $database_products = $data[2];

                        $cost = 0;
                        $database_products = rtrim($database_products, ',');
                        $database_products = trim($database_products, ',');
                    //echo($items);


                    $array = explode(',', $database_products);
                    foreach($array as $value) {
                        //echo $value . "<br>";
                            $numberarr = explode(":", $value);
                            $productnumber = $numberarr[0];
                    //  echo $productnumber . "<br>";
                            $quantity = substr($value, strpos($value, ":") + 1);
                        //echo $quantity . "<br>";
                            $itemcount += $quantity;

                            if($type == "salon") {
                            $price = mysql_result(mysql_query("SELECT `salon_price` FROM `patron_products` WHERE `product_id` = $productnumber"),0);
                            } else {
                                $price = mysql_result(mysql_query("SELECT `price` FROM `patron_products` WHERE `product_id` = $productnumber"),0);
                            }

                            $cost += $price * $quantity;
                            $totalitemprice = $price * $quantity;
                            $totalitemprice = number_format((float)($totalitemprice), 2, '.', '');
                            $name = mysql_result(mysql_query("SELECT `name` FROM `patron_products` WHERE `product_id` = $productnumber"),0);
                            $size = mysql_result(mysql_query("SELECT `size` FROM `patron_products` WHERE `product_id` = $productnumber"),0);
                            $itemreference = mysql_result(mysql_query("SELECT `item_reference` FROM `patron_products` WHERE `product_id` = $productnumber"),0);
                            $itemreference = htmlspecialchars($itemreference);



                            $qb_desc = mysql_result(mysql_query("SELECT `qb_desc` FROM `patron_products` WHERE `product_id` = $productnumber"),0);
                        $qb_desc = htmlspecialchars($qb_desc);

                            $orderlinesstr = $orderlinesstr . "
                <SalesOrderLineAdd>
                    <ItemRef>
                        <FullName>$itemreference</FullName>
                    </ItemRef>
                    <Desc>$qb_desc</Desc>
                    <Quantity>$quantity</Quantity>
                    <Amount>$totalitemprice</Amount>
                </SalesOrderLineAdd>
                            ";
                    }


    $xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>
    <?qbxml version=\"13.0\"?>
    <QBXML>
    <QBXMLMsgsRq onError=\"stopOnError\">
    <SalesOrderAddRq requestID=\"\">
    <SalesOrderAdd>
                <CustomerRef>
                    <FullName>$fullname</FullName>
                </CustomerRef>
                <TxnDate>$dateformat</TxnDate>
                <BillAddress>
                    <Addr1>$contactname</Addr1>
                    <Addr2>$database_billing_address</Addr2>
                    <City>$database_billing_city</City>
                    <State>$database_billing_state</State>
                    <PostalCode>$database_billing_zipcode</PostalCode>
                    <Country>US</Country>
                </BillAddress>
                <ShipAddress>
                    <Addr1>$database_shipping_name</Addr1>
                    <Addr2>$database_shipping_address</Addr2>
                    <City>$database_shipping_city</City>
                    <State>$database_shipping_state</State>
                    <PostalCode>$database_shipping_zipcode</PostalCode>
                    <Country>US</Country>
                </ShipAddress>
                <ItemSalesTaxRef>
                    <FullName>Out of State</FullName>
                </ItemSalesTaxRef>
                $orderlinesstr
                <SalesOrderLineAdd>
                    <ItemRef>
                        <FullName>Shipping</FullName>
                    </ItemRef>
                    <Desc>Shipping</Desc>
                    <Quantity>1</Quantity>
                    <Amount>$database_shipping_cost</Amount>
                </SalesOrderLineAdd>
            </SalesOrderAdd>
</SalesOrderAddRq>
</QBXMLMsgsRq>
</QBXML>";


    return $xml;
}



function _quickbooks_add_sales_order_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents)
{   

}


function _quickbooks_error_stringtoolong($requestID, $user, $action, $ID, $extra, &$err, $xml, $errnum, $errmsg)
{
    mail('[email protected]', 
        'QuickBooks error occured!', 
        'QuickBooks thinks that ' . $action . ': ' . $ID . ' has a value which will not fit in a QuickBooks field...');
}

Solution

  • This error:

    Response is not well-formed XML

    Has nothing at all to do with the XML you posted. The code you posted is irrelevant.

    If you look at the logs, the XML that isn't well formed is the actual SOAP response that the Web Connector/your SOAP service wraps the qbXML request in. Your actual SOAP response is not well formed.

    Check your PHP error log. Check your Apache error log. 99.999% of the time this is because you have made a PHP or SQL error when coding. Fix the error.