Quickbooks WebConnector Обработчики на Laravel - PullRequest
0 голосов
/ 19 июня 2019

Я реализовал consolibyte / quickbooks-php для моего проекта laravel.Все в порядке, кроме обработчика крюка для успешного входа в систему.Большая часть моего кода основана на этом репо

Я хочу общаться с Quickbooks на хуке входа в систему.Теперь я получаю "QBWC1012: аутентификация не удалась из-за следующего сообщения об ошибке. Ответ не является правильно сформированным XML" , когда я добавляю эти обработчики для успешного входа в систему.Все работало нормально, когда я ставил в очередь действия над маршрутами, такими как "addCustomer" в этом репо.

Я использую Laravel V5.8.Ниже приведены некоторые файлы для логики Quickbooks:

- app / Quickbooks / Quickbooks.php (пользовательский класс quickbooks)

<?php

namespace App\Quickbooks;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Log;

class Quickbooks
{
    /**
   * User Configuration File Array
   */
  protected $dsn;
  protected $config;
  protected $map = [];

  public function __construct()
  {
    $this->config = config('quickbooks');
    $this->dsn    = $this->config['qb_dsn'];
  }

  public function connect()
  {
    // error_reporting(E_ALL | E_STRICT);
    date_default_timezone_set($this->config['qb_timezone']);

    // error_log(\QuickBooks_WebConnector_Handlers::HOOK_LOGINSUCCESS);
    // error_log(QuickBooks_WebConnector_Handlers::HOOK_LOGINSUCCESS);

    if(!$this->config['qb_dsn'])
    {
      $dbconf   = config('database');
      $db   =  $dbconf['connections'][$dbconf['default']];

      if($db['driver'] == 'mysql')
      {
        $db['driver'] = 'mysqli';
      }
      $this->dsn = $db['driver'] . '://' . $db['username'] . ':' .$db['password'] . '@' . $db['host'] . ':' . $db['port'] .'/'. $db['database'];
    }

    // Check to make sure our database is set up 
        if (!\QuickBooks_Utilities::initialized($this->dsn))
        {
            // Initialize creates the neccessary database schema for queueing up requests and logging
            \QuickBooks_Utilities::initialize($this->dsn);

            // This creates a username and password which is used by the Web Connector to authenticate
            \QuickBooks_Utilities::createUser($this->dsn, $this->config['qb_username'], $this->config['qb_password']);
        }

        // Set up our queue singleton
    \QuickBooks_WebConnector_Queue_Singleton::initialize($this->dsn);

    // 
    return \QuickBooks_Utilities::initialized($this->dsn);
  }

  public function initServer($return = true, $debug = false) 
  {
    // Create a new server and tell it to handle the requests 
    $Server = new \QuickBooks_WebConnector_Server(
      $this->dsn, 
      $this->config['actions'], 
      $this->config['error_map'], 
      $this->config['hooks'], 
      $this->config['qb_log_level'], 
      $this->config['soap']['server'], 
      QUICKBOOKS_WSDL, 
      $this->config['soap']['options'], 
      $this->config['handler_options'], 
      $this->config['driver_options'], 
      $this->config['callback_options']
    );

    return $Server->handle($return, $debug); 
    // if $return is turned-on, there is an error "Response is not well-formed XML". Probably because of whitespaces somewhere. I haven't figured out this yet
  } 

    // Generate and return a .QWC Web Connector configuration file 
    public function generateQWC()
    {
        $name = 'Metrony Admin';            // A name for your server (make it whatever you want)
        $descrip = 'Schwartz & Company';        // A description of your server 
        $appurl = 'https://' . $_SERVER['HTTP_HOST'] . dirname($_SERVER['REQUEST_URI']) . '/qbwc';      // This *must* be httpS:// (path to your QuickBooks SOAP server)
        $appsupport = $appurl;      // This *must* be httpS:// and the domain name must match the domain name above
        $username = $this->config['qb_username'];       // This is the username you stored in the 'quickbooks_user' table by using QuickBooks_Utilities::createUser()
        $fileid = \QuickBooks_WebConnector_QWC::fileID();       // Just make this up, but make sure it keeps that format
        $ownerid = \QuickBooks_WebConnector_QWC::ownerID();     // Just make this up, but make sure it keeps that format
        $qbtype = QUICKBOOKS_TYPE_QBFS; // You can leave this as-is unless you're using QuickBooks POS
        $readonly = false; // No, we want to write data to QuickBooks
    $run_every_n_seconds = 600; // Run every 600 seconds (10 minutes)

        // Generate the XML file
        $QWC = new \QuickBooks_WebConnector_QWC($name, $descrip, $appurl, $appsupport, $username, $fileid, $ownerid, $qbtype, $readonly, $run_every_n_seconds);
    $xml = $QWC->generate(); 

    return $xml;
  }

    // Queue up a request for the Web Connector to process
    public function enqueue($action, $ident, $priority = 0, $extra = null, $user = null)
    {
        $Queue = new \QuickBooks_WebConnector_Queue($this->dsn);
        Log::alert(print_r(array($action, $ident, $priority, $extra, $user), true));
        return $Queue->enqueue($action, $ident, $priority, $extra, $user);
  }

  // 
  // public function 

  /**
   * Get the last date/time the QuickBooks sync ran
   * 
   * @param string $user        The web connector username 
   * @return string         A date/time in this format: "yyyy-mm-dd hh:ii:ss"
   */
  function _quickbooks_get_last_run($user, $action)
  {
    $type = null;
    $opts = null;
    return \QuickBooks_Utilities::configRead(QB_QUICKBOOKS_DSN, $user, md5(__FILE__), QB_QUICKBOOKS_CONFIG_LAST . '-' . $action, $type, $opts);
  }

  /**
   * Set the last date/time the QuickBooks sync ran to NOW
   * 
   * @param string $user
   * @return boolean
   */
  function _quickbooks_set_last_run($user, $action, $force = null)
  {
    $value = date('Y-m-d') . 'T' . date('H:i:s');

    if ($force)
    {
      $value = date('Y-m-d', strtotime($force)) . 'T' . date('H:i:s', strtotime($force));
    }
    // error_log($action . ": " . $value);
    return \QuickBooks_Utilities::configWrite(QB_QUICKBOOKS_DSN, $user, md5(__FILE__), QB_QUICKBOOKS_CONFIG_LAST . '-' . $action, $value);
  }

  /**
   * 
   * 
   */
  function _quickbooks_get_current_run($user, $action)
  {
    $type = null;
    $opts = null;
    return \QuickBooks_Utilities::configRead(QB_QUICKBOOKS_DSN, $user, md5(__FILE__), QB_QUICKBOOKS_CONFIG_CURR . '-' . $action, $type, $opts);
  }

  /**
   * 
   * 
   */
  function _quickbooks_set_current_run($user, $action, $force = null)
  {
    $value = date('Y-m-d') . 'T' . date('H:i:s');
    if ($force)
    {
      $value = date('Y-m-d', strtotime($force)) . 'T' . date('H:i:s', strtotime($force));
    }
    return \QuickBooks_Utilities::configWrite(QB_QUICKBOOKS_DSN, $user, md5(__FILE__), QB_QUICKBOOKS_CONFIG_CURR . '-' . $action, $value);
  }


}

- app / Http / Controllers/QuickbooksController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\Response;
use App\Quickbooks\Quickbooks;
use Log;

class QuickbooksController extends Controller
{
    protected $qbd;

    public function __construct() 
    {
        $this->qbd = new Quickbooks;
        $this->qbd->connect();
    }

    // 
    public function initQBWC(Request $request) 
    {

        $response = $this->qbd->initServer(true, true); //$return,$debug

        $contentType = 'text/plain';

        if($request->isMethod('post'))
        {
            $contentType = 'text/xml';
        }
        else if($request->input('wsdl') !== null or $request->input('WSDL') !== null)
        {
            $contentType = 'text/xml';
        }

        if($contentType == 'text/xml')
        { 
            $tidy = new \tidy();
            $response = $tidy->repairString($response, ['input-xml'=> 1, 'indent' => 0, 'wrap' => 0]);
        }
        // Uncomment log if you want to see the request headers submitted from WebConnector

        return response($response,200)->header('Content-Type', $contentType);
    }

    public function generateQWC()
    {
        $xml = $this->qbd->generateQWC();
        // header('Content-type: text/xml');
        // print($xml);
        // exit;
        return response($xml,200)
            ->header('Content-Type', 'text/xml')
            ->header('Content-Disposition', 'attachment; filename="my-quickbooks-wc-file.qwc"'); // Send as a file download
    }

}

- config / quickbooks.php

<?php

return [
  'qb_dsn'            => env('QB_DSN'),
  'qb_username'   => env('QB_USERNAME'),
  'qb_password'   => env('QB_PASSWORD'),
  'qb_timezone'   => env('QB_TIMEZONE'), 
  'qb_log_level'  => constant(env('QB_LOGLEVEL')), 
  'qb_mem_limit'  => env('QB_MEMLIMIT'), 
  'error_map'     => array( 
    '*' => array(App\Quickbooks\ErrorHandler::class, '_quickbooks_error_catchall') 
  ), 
  'hooks'           => array( 
    \QuickBooks_WebConnector_Handlers::HOOK_LOGINSUCCESS => array(App\Quickbooks\HooksHandler::class, '_quickbooks_hook_loginsuccess') 
  ), // An array of callback hooks
  'soap'            => array( 
    'server'    => constant(env('QB_SOAPSERVER')), // A pure-PHP SOAP server (no PHP ext/soap extension required, also makes debugging easier)
    'options'   => [] // See http://www.php.net/soap
  ),
  'handler_options'=> array(
    '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. )
  'callback_options'=> array(),

  // Map QuickBooks actions to handle functions 
    'actions'   => [
        QUICKBOOKS_IMPORT_ACCOUNT => [
      [ App\Quickbooks\AccountImport::class, 'xmlRequest' ],
      [ App\Quickbooks\AccountImport::class, 'xmlResponse' ]
    ]
    // QUICKBOOKS_ADD_EMPLOYEE => [
    //   [ App\Quickbooks\EmployeeAdd::class, 'xmlRequest' ],
    //   [ App\Quickbooks\EmployeeAdd::class, 'xmlResponse' ]
    // ],
    // QUICKBOOKS_ADD_CUSTOMER => [
    //   [ App\Quickbooks\CustomerAdd::class, 'xmlRequest' ],
    //   [ App\Quickbooks\CustomerAdd::class, 'xmlResponse' ]
    // ],
    ]
];
...

- журнал веб-коннектора

20190619.18:17:12 UTC   : QBWebConnector.WebServiceManager.DoUpdateSelected() : updateWS() for application = 'Metrony Admin' has STARTED
20190619.18:17:12 UTC   : QBWebConnector.RegistryManager.getUpdateLock() : HKEY_CURRENT_USER\Software\Intuit\QBWebConnector\UpdateLock = FALSE
20190619.18:17:12 UTC   : QBWebConnector.RegistryManager.setUpdateLock() : HKEY_CURRENT_USER\Software\Intuit\QBWebConnector\UpdateLock has been set to True
20190619.18:17:12 UTC   : QBWebConnector.RegistryManager.setUpdateLock() : ********************* Update session locked *********************
20190619.18:17:12 UTC   : QBWebConnector.SOAPWebService.instantiateWebService() : Initiated connection to the following application.
20190619.18:17:12 UTC   : QBWebConnector.SOAPWebService.instantiateWebService() : AppName: Metrony Admin
20190619.18:17:12 UTC   : QBWebConnector.SOAPWebService.instantiateWebService() : AppUniqueName (if available): Metrony Admin
20190619.18:17:12 UTC   : QBWebConnector.SOAPWebService.instantiateWebService() : AppURL: http://localhost/schwartz/public/qbd-connector/qbwc
20190619.18:17:12 UTC   : QBWebConnector.SOAPWebService.do_serverVersion() : *** Calling serverVersion().
20190619.18:17:12 UTC   : QBWebConnector.SOAPWebService.do_serverVersion() : Actual error received from web service for serverVersion call: <Response is not well-formed XML.>. For backward compatibility of all webservers, QBWC will catch all errors under app-not-supporting-serverVersion.
20190619.18:17:12 UTC   : QBWebConnector.SOAPWebService.do_serverVersion() : This application does not contain support for serverVersion. Allowing update operation for backward compatibility.
20190619.18:17:12 UTC   : QBWebConnector.SOAPWebService.do_clientVersion() : *** Calling clientVersion() with following parameter:<productVersion="2.3.0.25">
20190619.18:17:12 UTC   : QBWebConnector.SOAPWebService.updateWS() : Actual error received from web service for clientVersion call: <Response is not well-formed XML.>. For backward compatibility of all webservers, QBWC will catch all errors under app-not-supporting-clientVersion.
20190619.18:17:12 UTC   : QBWebConnector.SOAPWebService.do_clientVersion() : This application does not contain support for clientVersion. Allowing update operation for backward compatibility.
20190619.18:17:12 UTC   : QBWebConnector.SOAPWebService.do_authenticate() : Authenticating to application 'Metrony Admin', username = 'quickbooks'
20190619.18:17:12 UTC   : QBWebConnector.SOAPWebService.do_authenticate() : *** Calling authenticate() with following parameters:<userName="quickbooks"><password=<MaskedForSecurity>
20190619.18:17:12 UTC   : QBWebConnector.SOAPWebService.do_authenticate() : QBWC1012: Authentication failed due to following error message.
Response is not well-formed XML.
More info:
StackTrace =    at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
   at QBWebConnector.localhost.WCWebServiceDoc.authenticate(String strUserName, String strPassword)
   at QBWebConnector.localhost.WCWebService.authenticate(String strUserName, String strPassword)
   at QBWebConnector.SOAPWebService.authenticate(String UserName, String Password)
   at QBWebConnector.WebService.do_authenticate(String& ticket, String& companyFileName)
Source = System.Web.Services
20190619.18:17:12 UTC   : QBWebConnector.RegistryManager.setUpdateLock() : HKEY_CURRENT_USER\Software\Intuit\QBWebConnector\UpdateLock has been set to False
20190619.18:17:12 UTC   : QBWebConnector.RegistryManager.setUpdateLock() : ********************* Update session unlocked *********************
20190619.18:17:12 UTC   : QBWebConnector.WebServiceManager.DoUpdateSelected() : Update completed with errors. See log (QWClog.txt) for details.

- Журнал ошибок Laravel

[2019-06-19 15:05:39] local.ERROR: Array
(
    [0] => 
    [1] => -4
    [2] => Callback does not exist: [function] App\Quickbooks\HooksHandler(...)
)
...