douliao7354 2016-11-01 23:31 采纳率: 0%
浏览 51
已采纳

CustomerAddRq QuickBooks XML包括ClientsController CakePHP3中的文件

I'm working on integrating QuickBooks Desktop with a CakePHP 3.3 app using consolibyte's php dev kit (http://www.consolibyte.com/docs/index.php/PHP_DevKit_for_QuickBooks_-_Quick-Start / https://github.com/consolibyte/quickbooks-php). I was able to work through the quick start guide and add a customer from within my QuickbooksController.php (removed that test add and now receive 'No Data Exchange Required' when updating through web connector -which is good). but now i'm trying to move that queuing of adding a customer to where it should be, in ClientsController.php. I'm encountering a couple different errors depending on what i require_once

First Scenario: To start, I just tried to copy QuickbooksController.php so I require_once'd everything the same as in there. This is why there are so many commented out lines. This resulted in trying to load the file /.php. require_once(/var/www/html/pivot/vendor/quickbooks-php-master/QuickBooks/Driver/.php): failed to open stream: No such file or directory [ROOT/vendor/quickbooks-php-master/QuickBooks/Loader.php, line 56]

Second Scenario I then figured I should only really need the Queue class, so that was the only class I require_once'd. This resulted in the error Class 'QuickBooks_Loader' not found

Third Scenario Next I included QuickBooks_Loader as well as Queue. This resulted in the error Notice (8): Use of undefined constant QUICKBOOKS_BASEDIR - assumed 'QUICKBOOKS_BASEDIR' [ROOT/vendor/quickbooks-php-master/QuickBooks/Loader.php, line 56] require_once(QUICKBOOKS_BASEDIR/QuickBooks/Driver/Factory.php) [function.require-once]: failed to open stream: No such file or directory [ROOT/vendor/quickbooks-php-master/QuickBooks/Loader.php, line 56] Fatal error: require_once() [function.require]: Failed opening required 'QUICKBOOKS_BASEDIR/QuickBooks/Driver/Factory.php' (include_path='.:/usr/share/php') in /var/www/html/pivot/vendor/quickbooks-php-master/QuickBooks/Loader.php on line 56

I can post my QuickbooksController.php if it would be useful, but for now omitting for space since I'm getting no errors when updating with Web Connector. Here is my [updated] Clients Controller

ClientsController.php

<?php
namespace App\Controller;
require_once(ROOT . DS . 'vendor' . DS . 'quickbooks-php-master' . DS . 'QuickBooks.php');

use App\Controller\AppController;
use Cake\I18n\Time;
use Cake\Utility\Text;
use Cake\Mailer\MailerAwareTrait;
use Cake\Log\Log;
use Cake\Core\Configure;
use QuickBooks;


/**
 * Clients Controller
 *
 * @property \App\Model\Table\ClientsTable $Clients
 */
class ClientsController extends AppController
{
    use MailerAwareTrait;
    //...skipping to add function
  /**
 * Add method
 *
 * @return void Redirects on successful add, renders view otherwise.
 */
    public function add()
    {
        $this->viewBuilder()->layout('dialog'); // we're gonna be opening in dialog
        $dsn = Configure::read('qbDsn');
        $client = $this->Clients->newEntity();
        if ($this->request->is('post')) {
            $newClientData = $this->request->data(); // transfer post data to $newClientData so we can manipulate further
            //data manipulation omitted
            $client = $this->Clients->patchEntity($client, $newClientData);
            if ($this->Clients->save($client)) {
                // incorrect - need to use global namespace not App\Controller
                //$queue = new QuickBooks_WebConnector_Queue($dsn);

                // Updated - confirmed correct
                $queue = new \QuickBooks_WebConnector_Queue($dsn)
                $queue->enqueue(QUICKBOOKS_ADD_CUSTOMER, $client->id);
                $this->Flash->success(__('The client has been saved.'));
                return $this->redirect(['action' => 'view', $client->id]); 
            } else {
                Log::write('debug', $client->errors());
                $this->Flash->error(__('The client could not be saved. Please, try again.'));
                //return $this->redirect(($this->referer()));
            }
        }
    }


Complete QuickBooksController.php

<?php
namespace App\Controller;
require_once(ROOT . DS . 'vendor' . DS . 'quickbooks-php-master' . DS . 'QuickBooks.php');
require_once(ROOT . DS . 'vendor' . DS . 'quickbooks-php-master' . DS . 'QuickBooks' . DS . 'Utilities.php');
require_once(ROOT . DS . 'vendor' . DS . 'quickbooks-php-master' . DS . 'QuickBooks' . DS . 'WebConnector' . DS . 'Server.php');
//require_once(ROOT . DS . 'vendor' . DS . 'quickbooks-php-master' . DS . 'QuickBooks' . DS . 'WebConnector' . DS . 'Queue.php');
require_once(ROOT . DS . 'vendor' . DS . 'quickbooks-php-master' . DS . 'QuickBooks' . DS . 'WebConnector' . DS . 'Handlers.php');
//require_once(ROOT . DS . 'vendor' . DS . 'quickbooks-php-master' . DS . 'QuickBooks' . DS . 'WebConnector' . DS . 'Functions.php');

use QuickBooks;

use App\Controller\AppController;
use Cake\Log\Log;
use QuickBooks_WebConnector_Server;
use QuickBooks_Utilities;
//use QuickBooks_WebConnector_Queue;
use QuickBooks_WebConnector_Handlers;
//use QuickBooks_WebConnector_Functions;

//use QuickBooks_WebConnector_QWC;

/**
* Quickbooks Controller
*
* @property \App\Model\Table\QuickbooksTable $Quickbooks
*/
class QuickbooksController extends AppController
{

    public function initialize()
    {
        parent::initialize();
        $this->Auth->allow();
        $dsn = 'mysqli://qb@192.168.16.243/pivot';
        $qbwc_user = 'quickbooks';
        $qbwc_pass = 'password';
        if(!QuickBooks_Utilities::initialized($dsn)) {
            QuickBooks_Utilities::initialize($dsn);
            QuickBooks_Utilities::createUser($dsn, $qbwc_user, $qbwc_pass);

        }
    }

    public function endpoint() 
    {
        $this->viewBuilder()->layout('qb');
        $this->response->type(['xml' => 'text/xml']);
        $this->response->type('xml');
        $map = array(
            //QuickBooks_WebConnector_Functions::QUICKBOOKS_ADD_CUSTOMER => array( '_quickbooks_customer_add_request', '_quickbooks_customer_add_response' ),
        QUICKBOOKS_ADD_CUSTOMER => array(array($this, '_quickbooks_customer_add_request'), array($this, '_quickbooks_customer_add_response' )),
        //QUICKBOOKS_ADD_SALESRECEIPT => array( '_quickbooks_salesreceipt_add_request', '_quickbooks_salesreceipt_add_response'     ), 
            //'*' => 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(
            3070 => '_quickbooks_error_stringtoolong',              // Whenever a string is too long to fit in a field, call this function: _quickbooks_error_stringtolong()
                // 'CustomerAdd' => '_quickbooks_error_customeradd',    // Whenever an error occurs while trying to perform an 'AddCustomer' action, call this function: _quickbooks_error_customeradd()
                // '*' => '_quickbooks_error_catchall',                 // Using a key value of '*' will catch any errors which were not caught by another error handler
                // ... more error handlers here ...
                );

        // An array of callback hooks
        $hooks = array(
            // There are many hooks defined which allow you to run your own functions/methods when certain events happen within the framework
             QuickBooks_WebConnector_Handlers::HOOK_LOGINSUCCESS => '_quickbooks_hook_loginsuccess',    // Run this function whenever a successful login occurs
            );

        // 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(
            //'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(        // See the comments in the QuickBooks/Driver/<YOUR DRIVER HERE>.php file ( i.e. 'Mysql.php', etc. )
            //'max_log_history' => 1024,    // Limit the number of quickbooks_log entries to 1024
            //'max_queue_history' => 64,    // Limit the number of *successfully processed* quickbooks_queue entries to 64
            );
        $callback_options = array();

        $dsn = 'mysqli://qb@192.168.16.243/pivot';
        //$queue = new QuickBooks_WebConnector_Queue($dsn);
        //$testKey = 25215;
        //$queue->enqueue(QUICKBOOKS_ADD_CUSTOMER, $testKey);

        $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)
    {
        $this->loadModel('Clients');
        $client = $this->Clients->get($ID);

        // Create and return a qbXML request
        $qbxml = '<?xml version="1.0" encoding="utf-8"?>
        <?qbxml version="2.0"?>
        <QBXML>
            <QBXMLMsgsRq onError="stopOnError">
                <CustomerAddRq requestID="' . $requestID . '">
                    <CustomerAdd>
                        <Name>' . $client->company_name . '</Name>
                        <CompanyName>' . $client->company_name . '</CompanyName>
                        <BillAddress>
                            <Addr1>' . $client->address . '</Addr1>
                            <City>' . $client->city . '</City>
                            <State>' . $client->state . '</State>
                            <PostalCode>' . $client->zip . '</PostalCode>
                            <Country>' . $client->country . '</Country>
                        </BillAddress>';

        if (isset($client->mailing_address) && isset($client->mailing_city) && 
        isset($client->mailing_state) && isset($client->mailing_zip) &&
        isset($client->mailing_country)){
            $qbxml .= '<ShipAddress>
                    <Addr1>' . $client->mailing_address . '</Addr1>
                    <City>' . $client->mailing_city . '</City>
                    <State>' . $client->mailing_state . '</State>
                    <PostalCode>' . $client->mailing_zip . '</PostalCode>
                    <Country>' . $client->mailing_country . '</Country>
            </ShipAddress>';
        }
        if (isset($client->primary_phone)){
            $qbxml .= '<Phone>' . $client->primary_phone . '</Phone>';
        }
        if (isset($client->secondary_phone)){
            $qbxml .= '<AltPhone>' . $client->secondary_phone . '</AltPhone>';
        }
        if (isset($client->fax)){
            $qbxml .= '<Fax>' . $client->fax . '</Fax>';
        }        
        if (isset($client->email)){
            $qbxml .= '<Email>' . $client->email . '</Email>';
        }  
        $qbxml .= '</CustomerAdd></CustomerAddRq></QBXMLMsgsRq></QBXML>';

        return $qbxml;
    }

    function _quickbooks_customer_add_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents)
    {   
        $this->loadModel('Clients');
        $client = $this->Clients->get($ID);
        $data = [
            'qb_list_id' => $idents['ListID']
        ];
        $client = $this->Clients->patchEntity($client, $data);
        if (!$this->Clients->save($client)){
            Log::write('debug', 'failed updating client qb_list_id in qb response');
            Log::write('debug', $client->errors());
        }
    }

    public function isAuthorized($user)
    {
        return true;
    }

}
?>


Namespace error after only require_once'ing QuickBooks.php as per Keith's suggestion (but not using global namespace)

2016-11-02 09:50:16 Error: [Error] Class 'App\Controller\QuickBooks_WebConnector_Queue' not found
Request URL: /clients/add.json
Referer URL: http://pivotstaging.efs.net/landings/admin
Client IP: 192.168.16.172
Stack Trace:
#0 [internal function]: App\Controller\ClientsController->add()
#1 /var/www/html/pivot/vendor/cakephp/cakephp/src/Controller/Controller.php(435): call_user_func_array(Array, Array)
#2 /var/www/html/pivot/vendor/cakephp/cakephp/src/Http/ActionDispatcher.php(122): Cake\Controller\Controller->invokeAction()
#3 /var/www/html/pivot/vendor/cakephp/cakephp/src/Http/ActionDispatcher.php(96): Cake\Http\ActionDispatcher->_invoke(Object(App\Controller\ClientsController))
#4 /var/www/html/pivot/vendor/cakephp/cakephp/src/Routing/Dispatcher.php(60): Cake\Http\ActionDispatcher->dispatch(Object(Cake\Network\Request), Object(Cake\Network\Response))
#5 /var/www/html/pivot/webroot/index.php(36): Cake\Routing\Dispatcher->dispatch(Object(Cake\Network\Request), Object(Cake\Network\Response))
#6 {main}

Most recent error

2016-11-03 07:47:39 Warning: Warning (2): require_once(/var/www/html/pivot/vendor/quickbooks-php-master/QuickBooks/Driver/.php): failed to open stream: No such file or directory in [/var/www/html/pivot/vendor/quickbooks-php-master/QuickBooks/Loader.php, line 56]
Request URL: /clients/add.json
Referer URL: http://pivotstaging.efs.net/landings/admin
Client IP: 192.168.16.172
Trace:
Cake\Error\BaseErrorHandler::handleError() - CORE/src/Error/BaseErrorHandler.php, line 146
require_once - ROOT/vendor/quickbooks-php-master/QuickBooks/Loader.php, line 56
QuickBooks_Loader::load() - ROOT/vendor/quickbooks-php-master/QuickBooks/Loader.php, line 56
QuickBooks_Loader::__autoload() - ROOT/vendor/quickbooks-php-master/QuickBooks/Loader.php, line 104
spl_autoload_call - [internal], line ??
class_exists - [internal], line ??
QuickBooks_Driver_Factory::create() - ROOT/vendor/quickbooks-php-master/QuickBooks/Driver/Factory.php, line 95
QuickBooks_WebConnector_Queue::__construct() - ROOT/vendor/quickbooks-php-master/QuickBooks/WebConnector/Queue.php, line 73
App\Controller\ClientsController::add() - APP/Controller/ClientsController.php, line 271
Cake\Controller\Controller::invokeAction() - CORE/src/Controller/Controller.php, line 435
Cake\Http\ActionDispatcher::_invoke() - CORE/src/Http/ActionDispatcher.php, line 122
Cake\Http\ActionDispatcher::dispatch() - CORE/src/Http/ActionDispatcher.php, line 96
Cake\Routing\Dispatcher::dispatch() - CORE/src/Routing/Dispatcher.php, line 60
[main] - ROOT/webroot/index.php, line 36

Any nudges in the right direction would be most appreciated :)

  • 写回答

1条回答 默认 最新

  • duanping2809 2016-11-02 07:53
    关注

    This is the only thing you should be including:

    require_once(ROOT . DS . 'vendor' . DS . 'quickbooks-php-master' . DS . 'QuickBooks.php');

    In this code:

    $queue = new QuickBooks_WebConnector_Queue($dsn);

    You have not defined the $dsn variable. Please define it.

    As far as the namespace issue goes...

    This is telling you that you're in a namespace:

    2016-11-02 09:50:16 Error: [Error] Class 'App\Controller\QuickBooks_WebConnector_Queue' not found

    But that the class you're looking for isn't in the same namespace as you. The PHP lib you're using isn't namespaced, so you need it out of the global namespace (https://secure.php.net/manual/en/language.namespaces.global.php):

    $queue = new \QuickBooks_WebConnector_Queue($dsn);

    Take note of the leading \ which indicates the global namespace should be used when searching for the class.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 xshell无法连接提示ssh服务器拒绝密码
  • ¥15 AT89C52单片机C语言关于串口通信的位操作
  • ¥20 需要步骤截图(标签-服务器|关键词-map)
  • ¥50 gki vendor hook
  • ¥15 灰狼算法和蚁群算法如何结合
  • ¥15 这是一个利用ESP32自带按键和LED控制的录像代码,编译过程出现问题,请解决并且指出错误,指导如何处理 ,协助完成代码并上传代码
  • ¥20 stm32f103,hal库 hal_usart_receive函数接收不到数据。
  • ¥20 求结果和代码,sas利用OPTEX程序和D-efficiency生成正交集
  • ¥50 adb连接不到手机是怎么回事?
  • ¥20 抓取数据时发生错误: get_mooncake_data() missing 1 required positional argument: 'driver'的问题,怎么改出正确的爬虫代码?