我想将Consolibyte PHP QuickBooks库与PDO一起使用

时间:2018-09-24 19:13:48

标签: php pdo quickbooks

已更新!!

我正在尝试将您的PHP Web Connector库与我的网站集成。我对所有数据库操作都使用 PHP PDO 。我还没有找到这种设置的任何示例,我将您的msqli $ dsn db连接与标准PDO对象连接混合在一起,我敢肯定,很多人都可以使用。

当我将更新的PHP PDO连接文件包含在“具有自定义身份验证的示例QuickBooks Web连接器Web服务”功能文件中,并尝试查询PDO对象时,我得到”错误消息:客户端找到响应内容类型为'text / xml; charset = UTF-8',但预期为'text / xml'。”“

我的qb_config.php代码:         

/**
 * Example QuickBooks Web Connector web service with custom authentication
 * 
 * This example shows how to use a custom authentication function to 
 * 
 * @author Keith Palmer <keith@consolibyte.com>
 * 
 * @package QuickBooks
 * @subpackage Documentation
 */

ini_set('display_errors', '0');

// This sets the $site_id variable and is used throughout the site
include_once($_SERVER['DOCUMENT_ROOT'].'/config_site.php'); 

//This file creates the PDO Connection Objects $db, $dbMain and $dbQB
//When included PDO objects are created successfully and Web Connector does not error.
include_once($_SERVER['DOCUMENT_ROOT'].'/QB_Int/conn_qb.php');  

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

// I always program in E_STRICT error mode... 
error_reporting(E_ALL | E_STRICT);

//ini_set('display_errors', true);

define('QUICKBOOKS_LOG', 'qb-debug.log');

// Require the framework
//require_once '../QuickBooks.php';
require_once 'library/phpQB/QuickBooks.php';

// A username and password you'll use in: 
//  a) Your .QWC file
//  b) The Web Connector
//  c) The QuickBooks framework
$qbwc_user = 'Admin';
$qbwc_pass = 'xxxxxx';

/**
 * QuickBooks request to delete a customer record
 * @var string
 */

// Map QuickBooks actions to handler functions
$map = array(
    QUICKBOOKS_ADD_CUSTOMER => array( '_quickbooks_customer_add_request', '_quickbooks_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();

// * MAKE SURE YOU CHANGE THE DATABASE CONNECTION STRING BELOW TO A VALID MYSQL USERNAME/PASSWORD/HOSTNAME *
$dsn = 'mysqli://xxxxxx_user:xxxxxxxxxxx@localhost/xxxxxx_qb_integration';


// Handler options
$handler_options = array(
    'authenticate' => '_quickbooks_custom_auth', 
    //'authenticate' => '_QuickBooksClass::theStaticMethod',
    'deny_concurrent_logins' => false, 
    );

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, $qbwc_user, $qbwc_pass);

    // Create our test table
    mysql_query("CREATE TABLE `customers` (
          `id` int(10) unsigned NOT NULL,
          `name` varchar(64) NOT NULL,
          `company_name` varchar(64) NOT NULL,
          `fname` varchar(64) NOT NULL,
          `lname` varchar(64) NOT NULL,
          `addr1` varchar(64) NOT NULL,
          `addr2` varchar(64) NOT NULL,
          `city` varchar(64) NOT NULL,
          `state` varchar(64) NOT NULL,
          `postal_code` varchar(20) NOT NULL,
          `country` varchar(64) NOT NULL,
          `phone` varchar(24) NOT NULL,
          `email` varchar(64) NOT NULL,
          `quickbooks_listid` varchar(255) DEFAULT NULL,
          `quickbooks_editsequence` varchar(255) DEFAULT NULL,
          `quickbooks_errnum` varchar(255) DEFAULT NULL,
          `quickbooks_errmsg` varchar(255) DEFAULT NULL,
          PRIMARY KEY (id)
          ) ENGINE=MyISAM");

}

/**
 * Authenticate a Web Connector session
 */
function _quickbooks_custom_auth($username, $password, &$qb_company_file){

    if ($qbwc_user == 'Admin' && $qbwc_pass== 'xxxxxx'){    
        // Use this company file and auth successfully
        $qb_company_file = $qb_file_name;

        return true;
    }

    // Login failure
    return false;
}

更新后的conn_qb.php代码:

try {

    global $db;

    $db = new PDO("mysql:host=localhost;dbname=xxxxxx_site_1", "xxxxxxxx_user", "xxxxxxxxxxxxxx");

    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

}catch(PDOException $e) {

    error_log($errorLogPrefix.$e->getMessage()."\n",3,"PDOErrors.log");

    //throw $e;

}   

try {

    global $dbMain;

    $dbMain = new PDO("mysql:host=localhost;dbname=xxxxxx_main", "xxxxxx_user", "xxxxxxxxxxxxxxxxx");

    $dbMain->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $dbMain->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);


} catch (PDOException $e) {

    //die("DB ERROR: ". $e->getMessage());

}

try {

    global $dbQB;

    $dbQB = new PDO("mysql:host=localhost;dbname=xxxxx_qb_integration", "xxxx_user", "xxxxxxxx");

    $dbQB->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $dbQB->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);


} catch (PDOException $e) {

    //die("DB ERROR: ". $e->getMessage());

}

$qb_file_name='';

$sql="SELECT qb_desktop_filename FROM qb_settings WHERE site_id=".$site_id;

$results = $dbMain->query($sql);    

while($row = $results->fetch(PDO::FETCH_ASSOC)) {

   $qb_file_name=$row['qb_desktop_filename'];

}   

如您所见,我已经注释掉die语句并抛出$ e;行,因为它们可能会导致“客户端发现响应内容类型为'text / html; charset = UTF-8',但预期为'text / xml'” 错误。我已经确认PDO对象已成功创建,并且可以使用它们查询数据库。

我的functions.php代码:

以下是我尝试用“错误消息查询PDO对象和Web连接器错误的地方:客户端找到了'text / xml; charset = UTF-8'的响应内容类型,但预期为'text / xml'。'“

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

    global $dbQB;

    // Grab the data from our MySQL database via PDO        
    $arr=array();

    $result = $dbQB->prepare("SELECT * FROM customers WHERE action=:action AND id = :id");

    $result->execute(array(':action' => 1, ':id' => $ID));  

    while($row = $result->fetch(PDO::FETCH_ASSOC)) {

        $arr=$row;

    }

    $user_type_num=$arr['user_type'];

    switch ($user_type_num) {
        case '2':
            $user_type='Owner';
            break;
        case '3':
            $user_type='Guest';
            break;
        case '5':
            $user_type='Admin';
            break;          
        case '6':
            $user_type='Admin';
            break;
        case '7':
            $user_type='Admin';
            break;
        case '4':
            $user_type='Staff';
            break;  

    }

    $xml = '<?xml version="1.0" encoding="utf-8"?>
        <?qbxml version="12.0"?>
        <QBXML>
            <QBXMLMsgsRq onError="stopOnError">
                <CustomerAddRq requestID="'.$requestID.'">              
                    <CustomerAdd>
                        <Name>'.$arr['name'].'</Name>
                        <CompanyName>'.$arr['company_name'].'</CompanyName>
                        <FirstName>'.$arr['fname'].'</FirstName>
                        <LastName>'.$arr['lname'].'</LastName>
                        <BillAddress>
                            <Addr1>'.$arr['addr1'].'</Addr1>
                            <Addr2>'.$arr['addr2'].'</Addr2>
                            <City>'.$arr['city'].'</City>
                            <State>'.$arr['state'].'</State>
                            <PostalCode>'.$arr['postal_code'].'</PostalCode>
                            <Country>'.$arr['country'].'</Country>
                        </BillAddress>
                        <Phone>'.$arr['phone'].'</Phone>
                        <Email>'.$arr['email'].'</Email>
                        <CustomerTypeRef> 
                            <FullName>'.$user_type.'</FullName> 
                        </CustomerTypeRef>
                    </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){   

    global $dbQB, $db, $dbMain;

    $quickbooks_listid=mysql_real_escape_string($idents['ListID']);

    $quickbooks_editsequence=mysql_real_escape_string($idents['EditSequence']); 

    // Get site_id, user_id from our quickbooks MySQL customer table via PDO    
    $arr_1=array();

    $result_1 = $dbQB->prepare("SELECT * FROM customers WHERE action=:action AND id = :id");

    $result_1->execute(array(':action' => 1, ':id' => $ID));

    while($row = $result_1->fetch(PDO::FETCH_ASSOC)) {

        $arr_1=$row;

    }

    $user_id=$arr_1['user_id']; 

    $site_id=$arr_1['site_id'];

    // Update Quickbooks customer table via PDO
    $result_customer=$dbQB->prepare("UPDATE customers SET quickbooks_listid=?, quickbooks_editsequence =? WHERE id=?"); 

    $result_customer->execute(array($quickbooks_listid, $quickbooks_editsequence, (int)$ID));   

    // Update main users table via PDO
    $sql_3="UPDATE users 

            SET quickbooks_listid = '" . $quickbooks_listid . "', quickbooks_editsequence = '" . $quickbooks_editsequence . "'

            WHERE id = ".$user_id;

    $result_user=$db->prepare("UPDATE users SET quickbooks_listid=?, quickbooks_editsequence =? WHERE site_id=? AND user_id=?");

    $result_user->execute(array($quickbooks_listid, $quickbooks_editsequence, $site_id, $user_id));         

}

已更新!!现在,当我尝试查询_quickbooks_customer_add_request或_quickbooks_customer_add_response函数中的PDO对象时,我收到“错误消息:客户端发现响应内容类型为'text / xml; charset = UTF-8',但预期为'text / xml Web连接器中的'。'“

QBWCLog.txt日志文件摘录:

20180929.16:43:27 UTC   : QBWebConnector.SOAPWebService.do_sendRequestXML() : cfn="C:\Users\Public\Documents\Intuit\QuickBooks\Company Files\Test Company.qbw"
20180929.16:43:27 UTC   : QBWebConnector.SOAPWebService.do_sendRequestXML() : qbNationality="US"
20180929.16:43:27 UTC   : QBWebConnector.SOAPWebService.do_sendRequestXML() : qbXMLMajorVers="13"
20180929.16:43:27 UTC   : QBWebConnector.SOAPWebService.do_sendRequestXML() : qbXMLMinorVers="0"
20180929.16:43:29 UTC   : QBWebConnector.SOAPWebService.do_sendRequestXML() : QBWC1041: SendRequestXML failed.
Error message: Client found response content type of 'text/xml;charset=UTF-8', but expected 'text/xml'.
The request failed with an empty response.
More info:
StackTrace =    at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)
   at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
   at QBWebConnector.localhost.WCWebServiceDoc.sendRequestXML(String ticket, String strHCPResponse, String strCompanyFileName, String qbXMLCountry, Int32 qbXMLMajorVers, Int32 qbXMLMinorVers)
   at QBWebConnector.localhost.WCWebService.sendRequestXML(String ticket, String strHCPResponse, String strCompanyFileName, String qbXMLCountry, Int32 qbXMLMajorVers, Int32 qbXMLMinorVers)
   at QBWebConnector.SOAPWebService.sendRequestXML(String wcTicket, String HCPResponseXML, String cfn, String qbNationality, Int32 qbXMLMajorVers, Int32 qbXMLMinorVers)
   at QBWebConnector.WebService.do_sendRequestXML(Int32 x, String wcTicket, String HCPResponseXML, String cfn, String qbNationality, Int32 qbXMLMajorVers, Int32 qbXMLMinorVers, Boolean& timeout)
Source = System.Web.Services

任何帮助将不胜感激。

跳过

2 个答案:

答案 0 :(得分:0)

这可能来自org.w3c.dom.Node javax.xml.transform.Source , Result, TransformerFactory ,它将为throw $e;而非HTML服务。

修复XML连接,它应该可以正常工作而不会引发异常。

...在浏览器中调用URL可能有助于理解该问题。

答案 1 :(得分:0)

更新:创建PDO对象时,发现各种PHP错误。这看起来似乎很明显,但是在此调试框架中,使用PHP Log文件确实非常重要。我在Quickbooks配置文件 qb_config.php 中使用以下命令设置了PHP日志文件:

ini_set('log_errors', TRUE); // Turn Error logging on

ini_set('error_log', 'php_errors.log'); // Logging file location

ini_set('log_errors_max_len', 1024); // Optional Log file size

设置日志记录后,将显示所有可能导致 Web连接器错误的PHP错误。我还使用error_log('Some Text',0)写到日志中,以帮助调试代码。

谢谢大家