连接QuickBooks Web连接器时出错

时间:2015-04-11 21:01:42

标签: php soap quickbooks

我正在使用Keith Palmer的QuickBooks PHP DevKit将PHP POS连接到QuickBooks。我已经安装了几个不同的安装,从来没有这样的问题。不幸的是,有人在一段时间之前编写了代码。请帮我找一下这个问题。

成功将应用程序添加到QB Webconnector后,在尝试连接时,我立即收到“身份验证失败”错误。整个信息如下。下面是qwc文件,也是我连接的php文件的一部分。

  

错误版本:服务不提供

     

消息:身份验证失败

     

描述:QBWC1012:由于以下错误导致身份验证失败   信息。客户发现响应内容类型为“text / html”,但是   预期'text / xml'。请求失败,并显示错误消息:    -
不推荐使用:mysql_connect():不推荐使用mysql扩展,将来会删除它:使用mysqli或PDO   相反    /home/domaincom/public_html/shop/qbconnector/QuickBooks/Driver/Sql/Mysql.php 的   在线 267

不推荐:mysql_connect():   不推荐使用mysql扩展,将来会删除它:   使用mysqli或PDO代替    /home/domaincom/public_html/shop/qbconnector/QuickBooks/Driver/Sql/Mysql.php 的   在线 267

警告:无法修改标题   信息 - 已经发送的标题(输出开始于   /home/domaincom/public_html/shop/qbconnector/QuickBooks/Driver/Sql/Mysql.php:267)   在    /home/domaincom/public_html/shop/qbconnector/QuickBooks/WebConnector/Server.php 的   在线 276
                                NVU                                - 。有关详细信息,请参阅QWCLog。记得打开登录。

这是qwc文件:

<?xml version="1.0"?>
<QBWCXML>
    <AppName>QuickBooks Integrator</AppName>
    <AppID></AppID>
    <AppURL>https://www.domain.com/shop/qbconnector/qbwc.php </AppURL>
    <AppDescription></AppDescription>
    <AppSupport>https://www.domain.com/shop/qbconnector/Skip_Receipt.php</AppSupport>
    <UserName>quickbooks</UserName>
    <OwnerID>{90F44FB7-33D9-4815-AC85-AC86A7E7D1EB}</OwnerID>
    <FileID>{5AF3B9B6-86F1-4fcc-B1FF-967DE1813D20}</FileID>
    <QBType>QBFS</QBType>
    <Scheduler>
        <RunEveryNMinutes>10</RunEveryNMinutes>
    </Scheduler>
    <IsReadOnly>false</IsReadOnly>
</QBWCXML>

这是我在上面指出的qbwc.php文件。如果您需要更多信息,请与我们联系:

<?php

// This makes debugging a bit easier...
error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', 1);

// 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! * See http://us3.php.net/manual/en/timezones.php
    date_default_timezone_set('America/Vancouver');
}

// Require the framework
require_once dirname(__FILE__) . '/QuickBooks.php';

// Web Connector username/password
$user = 'quickbooks';
$pass = 'password';

// Set connection to PCRT database
//$dsn = 'mysql://root:sysadmin@localhost/pcrt';
$dsn = 'mysql://dbuser:password@localhost/dbname';




// Map QuickBooks actions to handler functions
$map = array(
    QUICKBOOKS_ADD_INVOICE => array('_quickbooks_invoice_add_request', '_quickbooks_invoice_add_response'),
    QUICKBOOKS_ADD_CUSTOMER => array('_quickbooks_customer_add_request', '_quickbooks_customer_add_response'),
    QUICKBOOKS_ADD_INVENTORYITEM => array('_quickbooks_inventoryitem_add_request', '_quickbooks_inventoryitem_add_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 for a successful login
);

// Logging level

$log_level = QUICKBOOKS_LOG_DEVELOP;

// What SOAP server you're using 
$soapserver = QUICKBOOKS_SOAPSERVER_BUILTIN;  // A pure-PHP SOAP server (no extensions required)
// Some other options
$soap_options = array();
$handler_options = array(
    //'authenticate' => ' *** YOU DO NOT NEED TO PROVIDE THIS CONFIGURATION VARIABLE TO USE THE DEFAULT AUTHENTICATION METHOD FOR THE DRIVER YOU'RE USING (I.E.: MYSQL) *** '
    //'authenticate' => 'your_function_name_here', 
    //'authenticate' => array( 'YourClassName', 'YourStaticMethod' ),
    'deny_concurrent_logins' => false,
    'deny_reallyfast_logins' => false,
);  // See the comments in the QuickBooks/Server/Handlers.php file
$driver_options = array();
$callback_options = array();

// If we haven't done our one-time initialization yet, do it now!
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);
}

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
 * 
 * Every time the Web Connector logs in, we're going to queue up a request to 
 * import all of the customers from QuickBooks. 
 */
function _quickbooks_hook_loginsuccess($requestID, $user, $hook, &$err, $hook_data, $callback_config) {
    // Fetch the queue instance
    $Queue = QuickBooks_WebConnector_Queue_Singleton::getInstance();
//$Queue->enqueue(QUICKBOOKS_ADD_INVOICE, 1000);


    $sql = "SELECT
        r.receipt_id
        FROM receipts r, sold_items s 
        WHERE r.storeid = '1' 
        AND r.receipt_id > 4809
        AND r.receipt_id NOT IN (SELECT DISTINCT q.receipt_id FROM qbinvoices q WHERE q.receipt_id = r.receipt_id)
        AND r.receipt_id = s.receipt
        ORDER BY r.date_sold DESC ";

    $result = mysql_query($sql);

    $i = 0;

    while ($row = mysql_fetch_assoc($result)) {

        $Queue->enqueue(QUICKBOOKS_ADD_INVOICE, (int) $row["receipt_id"], (int) $i);
        ++$i;
        $Queue->enqueue(QUICKBOOKS_ADD_INVENTORYITEM, (int) $row["receipt_id"], (int) $i);
        ++$i;
        $Queue->enqueue(QUICKBOOKS_ADD_CUSTOMER, (int) $row["receipt_id"], (int) $i);
        ++$i;
        //break;
    }

    // Queue request
}

/**
 * Build a request to import customers from web store to quickbooks
 */
function _quickbooks_customer_add_request($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale) {
    // Grab the data from our MySQL database


    $sql = "SELECT address1,
        address2,
        city,
        zip,
        email,
        person_name,
        phone_number,
        state,
        company

        FROM receipts    
        WHERE receipt_id = " . (int) $ID;


    $customer = mysql_fetch_assoc(mysql_query($sql));

    $pieces = explode(" ", $customer["person_name"]);

    $custname = '';
    if (count($pieces) > 1) {
        $custname = '<FirstName>' . $pieces[0] . '</FirstName>
           <LastName>' . $pieces[1] . '</LastName>';
    } else {
        $custname = '<FirstName>' . $pieces[0] . '</FirstName>';
    }








    $xml = '<?xml version="1.0" encoding="utf-8"?>
        <?qbxml version="2.0"?>
        <QBXML>
            <QBXMLMsgsRq onError="continueOnError">
                <CustomerAddRq requestID="' . $requestID . '">
                    <CustomerAdd>
                        <Name>' . htmlspecialchars($customer["person_name"]) . '</Name>
                        <CompanyName>' . htmlspecialchars($customer["company"]) . '</CompanyName>
                        ' . $custname . '
                        <BillAddress>
                            <Addr1>' . htmlspecialchars($customer["address1"]) . '</Addr1>
                            <Addr2>' . htmlspecialchars($customer["address2"]) . '</Addr2>
                            <City>' . htmlspecialchars($customer["city"]) . '</City>
                            <State>' . htmlspecialchars($customer["state"]) . '</State>
                            <PostalCode>' . htmlspecialchars($customer["zip"]) . '</PostalCode>
                            <Country>Canada</Country>
                        </BillAddress>
                        <Phone>' . htmlspecialchars($customer["phone_number"]) . '</Phone>
                        <Email>' . htmlspecialchars($customer["email"]) . '</Email>
                        <Contact>' . htmlspecialchars($customer["person_name"]) . '</Contact>
                    </CustomerAdd>
                </CustomerAddRq>
            </QBXMLMsgsRq>
        </QBXML>';


    return $xml;
}

/**
 * Build a request to import items from web store to quickbooks
 */
function _quickbooks_invoice_add_request($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale) {
    // Grab the data from our MySQL database
    //$arr = mysql_fetch_assoc(mysql_query("SELECT * FROM my_customer_table WHERE id = " . (int) $ID));

    $sql = "SELECT address1,
        address2,
        city,
        zip,
        date_sold,
        email,
        check_number,
        grandtax,
        grandtotal,
        paywith,
        pay_type,
        person_name,
        phone_number,
        receipt_id,
        state

        FROM receipts    
        WHERE receipt_id = " . (int) $ID;



    $arr = mysql_fetch_assoc(mysql_query($sql));


    $sql = "SELECT   
        stock_title,
        labor_desc,
        sold_type,
        sold_price,
        CASE
            WHEN taxex = 0 THEN 'E'
            ELSE  'E'
        END AS taxex
        FROM sold_items i LEFT JOIN stock s on s.stock_id=i.stockid WHERE i.receipt=" . (int) $arr["receipt_id"];

    $items = mysql_query($sql);

    $itemxml = '';

    while ($item = mysql_fetch_assoc($items)) {

        $varname = '';

        if ($item["sold_type"] == "labor") { //For labor type 
            if (is_null($item["labor_desc"])) {
                $varname = "Labor";
            } else {
                $varname = $item["labor_desc"];
            }
        } else {
            if (is_null($item["stock_title"])) {
                $varname = "Non-Inventory Item";
            } else {
                $varname = $item["stock_title"];
            }
        }



        $itemxml = $itemxml . '<InvoiceLineAdd>
                                <ItemRef>
                                        <FullName>' . htmlspecialchars($varname) . '</FullName>
                                </ItemRef>
                                <Quantity>1.00000</Quantity>
                                <Rate>' . $item["sold_price"] . '</Rate>
                                <SalesTaxCodeRef>
                                    <FullName>' . $item["taxex"] . '</FullName>
                                </SalesTaxCodeRef>
                        </InvoiceLineAdd>';
    }




    //print_r($arr);
    //die();

    $tdate = date('Y-m-d', strtotime($arr["date_sold"])); //. 'T' . date('H:i:s', strtotime($arr["date_sold"])) . 'Z';

    $xml = '<?xml version="1.0" encoding="utf-8"?>
            <?qbxml version="5.0"?>
            <QBXML> 
                <QBXMLMsgsRq onError="continueOnError">
                    <InvoiceAddRq requestID="' . $requestID . '">
                        <InvoiceAdd>
                            <CustomerRef>

                                <FullName>' . htmlspecialchars($arr["person_name"]) . '</FullName>
                            </CustomerRef>
                            <TxnDate>' . $tdate . '</TxnDate>
                            <BillAddress>
                                <Addr1>' . htmlspecialchars($arr["address1"]) . '</Addr1>
                                <Addr2>' . htmlspecialchars($arr["address2"]) . '</Addr2>
                                <Addr3 />
                                <City>' . htmlspecialchars($arr["city"]) . '</City>
                                <State>' . htmlspecialchars($arr["state"]) . '</State>
                                <PostalCode>' . htmlspecialchars($arr["zip"]) . '</PostalCode>
                                <Country>Canada</Country>
                            </BillAddress>
                            <ShipAddress>
                                <Addr1>' . htmlspecialchars($arr["address1"]) . '</Addr1>
                                <Addr2>' . htmlspecialchars($arr["address2"]) . '</Addr2>
                                <Addr3 />
                                <City>' . htmlspecialchars($arr["city"]) . '</City>
                                <State>' . htmlspecialchars($arr["state"]) . '</State>
                                <PostalCode>' . htmlspecialchars($arr["zip"]) . '</PostalCode>
                                <Country>Canada</Country>
                            </ShipAddress>

                            <Memo>Imported from PCRT</Memo>

                            ' . $itemxml . '
                        </InvoiceAdd>
                    </InvoiceAddRq>
                </QBXMLMsgsRq>
            </QBXML>';




    return $xml;
}

/**
 * Build a request to import Invoice from web store to quickbooks
 */
function _quickbooks_inventoryitem_add_request($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale) {
    // Grab the data from our MySQL database


    $sql = "SELECT   
        stock_title,
        labor_desc,
        sold_type,
        sold_price,
        CASE
            WHEN taxex = 0 THEN 'E'
            ELSE  'E'
        END AS taxex 
    FROM sold_items i LEFT JOIN stock s on s.stock_id=i.stockid  WHERE i.receipt=" . (int) $ID;

    $items = mysql_query($sql);

    $itemxml = '<?xml version="1.0" encoding="utf-8"?>
        <?qbxml version="7.0"?>
        <QBXML>
        <QBXMLMsgsRq onError="continueOnError">';

    $varname = '';

    while ($item = mysql_fetch_assoc($items)) {

        if ($item["sold_type"] == "labor") { //For labor type create Service item
            if (is_null($item["labor_desc"])) {
                $varname = "Labor";
            } else {
                $varname = $item["labor_desc"];
            }
    $varnametrim = substr($varname,0,31);

            $itemxml = $itemxml . ' <ItemServiceAddRq requestID="' . $requestID . '" >

                        <ItemServiceAdd>
                <Name>' . htmlspecialchars($varnametrim) . '</Name>
                                <SalesOrPurchase>
                                    <Desc>' . htmlspecialchars($varname) . ' </Desc>
                                    <Price>' . htmlspecialchars($item["sold_price"]) . '</Price>
                                    <AccountRef>
                                        <FullName>Sales - Unsorted</FullName>
                                    </AccountRef>
                                </SalesOrPurchase>
            </ItemServiceAdd>
            </ItemServiceAddRq>';
//        </QBXMLMsgsRq> 
//        </QBXML>';
        } else {
            //if ($item["sold_type"] == "labor") 
            //For labor type create Service item
            if (is_null($item["stock_title"])) {
                $varname = "Non-Inventory Item";
            } else {
                $varname = $item["stock_title"];
            }

     $varnametrim = substr($varname,0,31);

            // This is for Inventory Item - Change IncomeAccountRef, COGSAccountRef and AssetAccountRef
//            $itemxml = $itemxml . ' <ItemInventoryAddRq requestID="' . $requestID . '" >
//          <ItemInventoryAdd>
//              <Name>' . $varnametrim . '</Name>
//              <SalesDesc>' . $varname . ' - Auto-added by PCRT QuickBooks Integrator</SalesDesc>
//              <SalesPrice>' . $item["sold_price"] . '</SalesPrice>
//              <IncomeAccountRef>
//                  <FullName>Sales</FullName>
//              </IncomeAccountRef>
//              <COGSAccountRef>
//                  <FullName>Cost of Goods Sold</FullName> 
//              </COGSAccountRef>
//              <AssetAccountRef>
//                  <FullName>Inventory Assets</FullName>
//              </AssetAccountRef>
//          </ItemInventoryAdd>
//      </ItemInventoryAddRq>';

            ////This is for Non_inventory Item
            $itemxml = $itemxml . '<ItemNonInventoryAddRq requestID="' . $requestID . '" >
            <ItemNonInventoryAdd>
                <Name>' . htmlspecialchars($varnametrim) . '</Name>
                <SalesOrPurchase>
                    <Desc>' . htmlspecialchars($varname) . ' - Auto-added by PCRT QuickBooks Integrator</Desc>
                    <Price>' . htmlspecialchars($item["sold_price"]) . '</Price>
                    <AccountRef>
                        <FullName>Sales - Unsorted</FullName>
                    </AccountRef>
                </SalesOrPurchase>
            </ItemNonInventoryAdd>
        </ItemNonInventoryAddRq>';
        }
    }




    $itemxml = $itemxml . '</QBXMLMsgsRq>
    </QBXML>';




    return $itemxml;
}

/**
 * Receive a response from QuickBooks 
 */
function _quickbooks_invoice_add_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents) {
    mysql_query("
        INSERT INTO 
            qbinvoices (receipt_id,qb_listid,qb_editsequence)
        VALUES( " . (int) $ID . "," . (int) $idents['ListID'] . "," . (int) $idents['EditSequence'] . ")");


    // return;
}

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



    // return;
}

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



    // return;
}

/**
 * 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) {
    // if ($action == QUICKBOOKS_ADD_INVOICE) {
    //     return true;
    // }
    if ($err == 3200) {
        return true;
    }

    return false;
}

/**
 * Catch any errors that occur
 * 
 * @param string $requestID         
 * @param string $action
 * @param mixed $ID
 * @param mixed $extra
 * @param string $err
 * @param string $xml
 * @param mixed $errnum
 * @param string $errmsg
 * @return void
 */
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";

    // Do something to handle the error
    // mail( ... );

    if ($errnum == 3100) {
        return true;
    }

    return false;
}

1 个答案:

答案 0 :(得分:0)

任何时候你看到这个:

  

描述:QBWC1012:由于以下原因导致身份验证失败   错误信息。客户发现了响应内容类型   'text / html',但预计'text / xml'。

您知道这是某种PHP或SQL错误。

在您的情况下,这是PHP错误:

  

不推荐使用:mysql_connect():不推荐使用mysql扩展   将来会被删除:在

中使用mysqli或PDO

这告诉您不推荐使用PHP中的mysql扩展名,而是需要使用mysqli

所以,在你的代码中:

$dsn = 'mysql://dbuser:password@localhost/dbname';

只需将mysql更改为mysqli,您就可以了:

$dsn = 'mysqli://dbuser:password@localhost/dbname';