0

Ich möchte nur Informationen mit der Quickbooks-API greifen (das scheint über die API möglich sein). Ich habe eine App auf ihrer Entwicklungssite eingerichtet, sie mit der von mir erstellten Quickbooks-Firma verknüpft und versuche, diesen Code auszuführen, um alles aus der CURL-Antwort zu erhalten, aber alles, was ich bekomme, sind Autorisierungsfehlermeldungen (401). Warum wird es nicht autorisiert? Studierte diese Seite für 12 Stunden und keines ihrer Beispiele, dass sie sogar Arbeit bieten. Bin mit dieser Seite als Referenz: https://developer.intuit.com/docs/0050_quickbooks_api/0010_your_first_request/rest_essentials_for_the_quickbooks_api und diese: https://developer.intuit.com/docs/0100_accounting/0300_developer_guides/0015_calling_data_services#/The_authorization_headerIntuit Quickbooks Buchhaltung API OAuth mit Entwickler überhaupt nicht funktioniert

Meine Datei index.php ist wie folgt:

<?php 

/** 
* QuickBooks PHP DevKit 
* 
* Copyright (c) 2010 Keith Palmer/ConsoliBYTE, LLC. 
* All rights reserved. This program and the accompanying materials 
* are made available under the terms of the Eclipse Public License v1.0 
* which accompanies this distribution, and is available at 
* http://www.opensource.org/licenses/eclipse-1.0.php 
* 
* @author Keith Palmer <[email protected]> 
* @license LICENSE.txt 
* 
* @package QuickBooks 
*/ 

class QuickBooks_IPP_OAuth 
{ 
    private $_secrets; 

    protected $_oauth_consumer_key; 
    protected $_oauth_consumer_secret; 

    protected $_oauth_access_token; 
    protected $_oauth_access_token_secret; 

    protected $_version = null; 
    protected $_signature = null; 
    protected $_keyfile; 

    /** 
    * 
    */ 
    const NONCE = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; 

    const METHOD_POST = 'POST'; 
    const METHOD_GET = 'GET'; 
    const METHOD_PUT = 'PUT'; 
    const METHOD_DELETE = 'DELETE'; 

    const DEFAULT_VERSION = '1.0'; 
    const DEFAULT_SIGNATURE = 'HMAC-SHA1'; 

    const SIGNATURE_PLAINTEXT = 'PLAINTEXT'; 
    const SIGNATURE_HMAC = 'HMAC-SHA1'; 
    const SIGNATURE_RSA = 'RSA-SHA1'; 

    /** 
    * Create our OAuth instance 
    */ 
    public function __construct($oauth_consumer_key, $oauth_consumer_secret) 
    { 
     $this->_oauth_consumer_key = $oauth_consumer_key; 
     $this->_oauth_consumer_secret = $oauth_consumer_secret; 

     $this->_version = QuickBooks_IPP_OAuth::DEFAULT_VERSION; 
     $this->_signature = QuickBooks_IPP_OAuth::DEFAULT_SIGNATURE; 
    } 

    /** 
    * Set the signature method 
    * 
    * 
    */ 
    public function signature($method, $keyfile = null) 
    { 
     $this->_signature = $method; 
     $this->_keyfile = $keyfile; 
    } 

    /** 
    * Sign an OAuth request and return the signing data (auth string, URL, etc.) 
    * 
    * 
    */ 
    public function sign($method, $url, $oauth_token = null, $oauth_token_secret = null, $params = array()) 
    { 
     /* 
     print('got in: [' . $method . '], ' . $url); 
     print_r($params); 
     print('<br /><br /><br />'); 
     */ 

     if (!is_array($params)) 
     { 
      $params = array(); 
     } 

     $params = array_merge($params, array(
      'oauth_consumer_key' => $this->_oauth_consumer_key, 
      'oauth_signature_method' => $this->_signature, 
      'oauth_nonce' => $this->_nonce(), 
      'oauth_timestamp' => $this->_timestamp(), 
      'oauth_version' => $this->_version, 
      )); 

     // Add in the tokens if they were passed in 
     if ($oauth_token) 
     { 
      $params['oauth_token'] = $oauth_token; 
     } 

     if ($oauth_token_secret) 
     { 
      $params['oauth_secret'] = $oauth_token_secret; 
     } 

     // Generate the signature 
     $signature_and_basestring = $this->_generateSignature($this->_signature, $method, $url, $params); 

     $params['oauth_signature'] = $signature_and_basestring[1]; 

     /* 
     print('<pre>'); 
     print('BASE STRING IS [' . $signature_and_basestring[0] . ']' . "\n\n"); 
     print('SIGNATURE IS: [' . $params['oauth_signature'] . ']'); 
     print('</pre>'); 
     */ 

     $normalized = $this->_normalize($params); 

     /* 
     print('NORMALIZE 1 [' . $normalized . ']' . "\n"); 
     print('NORMZLIZE 2 [' . $this->_normalize2($params) . ']' . "\n"); 
     */ 

     if (false !== ($pos = strpos($url, '?'))) 
     { 
      $url = substr($url, 0, $pos); 
     } 

     $normalized_url = $url . '?' . $normalized;   // normalized URL 

     return array (
      0 => $signature_and_basestring[0],  // signature basestring 
      1 => $signature_and_basestring[1],  // signature 
      2 => $normalized_url, 
      3 => $this->_generateHeader($params, $normalized), // header string 
      ); 
    } 

    protected function _generateHeader($params, $normalized) 
    { 
     // oauth_signature="' . $this->_escape($params['oauth_signature']) . '", 
     $str = ''; 

     if (isset($params['oauth_token'])) 
      $str .= rawurlencode('oauth_token') . '="' . rawurlencode($params['oauth_token']) . '", '; 

     $nonce = rawurlencode(md5(mt_rand())); 

     $nonce_chars = str_split($nonce); 

     $formatted_nonce = ''; 
     foreach($nonce_chars as $n => $chr) 
     { 
      if (in_array($n, array(8, 12, 16, 20))) 
       $formatted_nonce .= '-'; 

      $formatted_nonce .= $chr; 
     } 

     $str .= rawurlencode('oauth_nonce') . '="' . $formatted_nonce . '", ' . 
      rawurlencode('oauth_consumer_key') . '="' . rawurlencode($params['oauth_consumer_key']) . '", ' . 
      rawurlencode(oauth_signature_method) . '="' . rawurlencode($params['oauth_signature_method']) . '", ' . 
      rawurlencode(oauth_timestamp) . '="' . rawurlencode($params['oauth_timestamp']) . '", ' . 
      rawurlencode(oauth_version) . '="' . rawurlencode($params['oauth_version']) . '", ' . 
      rawurlencode(oauth_signature) . '="' . $this->_escape($params['oauth_signature']) . '"'; 

     return str_replace(array(' ', ' ', ' '), '', str_replace(array("\r", "\n", "\t"), ' ', $str)); 
    } 

    /** 
    * 
    * 
    */ 
    protected function _escape($str) 
    { 
     if ($str === false) 
     { 
      return $str; 
     } 
     else 
     { 
      return str_replace('+', ' ', str_replace('%7E', '~', rawurlencode($str))); 
     } 
    } 

    protected function _timestamp() 
    { 
     //return 1326976195; 

     //return 1318622958; 
     return time(); 
    } 

    protected function _nonce($len = 5) 
    { 
     //return '1234'; 

     $tmp = str_split(QuickBooks_IPP_OAuth::NONCE); 
     shuffle($tmp); 

     //return 'kYjzVBB8Y0ZFabxSWbWovY3uYSQ2pTgmZeNu2VS4cg'; 
     return substr(implode('', $tmp), 0, $len); 
    } 

    protected function _normalize($params) 
    { 
     $normalized = array(); 

     ksort($params); 
     foreach ($params as $key => $value) 
     { 
      // all names and values are already urlencoded, exclude the oauth signature 
      if ($key != 'oauth_secret') 
      { 
       if (is_array($value)) 
       { 
        $sort = $value; 
        sort($sort); 
        foreach ($sort as $subkey => $subvalue) 
        { 
         $normalized[] = $this->_escape($key) . '=' . $this->_escape($subvalue); 
        } 
       } 
       else 
       { 
        $normalized[] = $this->_escape($key) . '=' . $this->_escape($value); 
       } 
      } 
     } 

     return implode('&', $normalized); 
    } 

    protected function _generateSignature($signature, $method, $url, $params = array()) 
    { 
     /* 
     print('<pre>params for signing'); 
     print_r($params); 
     print('</pre>'); 
     */ 

     //if (false !== strpos($url, 'get_access')) 
     /*if (true) 
     { 
      print($url . '<br />' . "\r\n\r\n"); 
      die('NORMALIZE MINE [' . $this->_normalize($params) . ']'); 
     }*/ 

     /* 
     print('<pre>'); 
     print('NORMALIZING [' . "\n"); 
     print($this->_normalize($params) . "]\n\n\n"); 
     print('SECRET KEY FOR SIGNING [' . $secret . ']' . "\n"); 
     print('</pre>'); 
     */ 

     if (false !== ($pos = strpos($url, '?'))) 
     { 
      $tmp = array(); 
      parse_str(substr($url, $pos + 1), $tmp); 

      // Bad hack for magic quotes... *sigh* stupid PHP 
      if (get_magic_quotes_gpc()) 
      { 
       foreach ($tmp as $key => $value) 
       { 
        if (!is_array($value)) 
        { 
         $tmp[$key] = stripslashes($value); 
        } 
       } 
      } 

      $params = array_merge($tmp, $params); 

      $url = substr($url, 0, $pos); 
     } 

     //print('url [' . $url . ']' . "\n"); 
     //print_r($params); 

     $sbs = $this->_escape($method) . '&' . $this->_escape($url) . '&' . $this->_escape($this->_normalize($params)); 

     //print('sbs [' . $sbs . ']' . "\n"); 

     // Which signature method? 
     switch ($signature) 
     { 
      case QuickBooks_IPP_OAuth::SIGNATURE_HMAC: 
       return $this->_generateSignature_HMAC($sbs, $method, $url, $params);  
      case QuickBooks_IPP_OAuth::SIGNATURE_RSA: 
       return $this->_generateSignature_RSA($sbs, $method, $url, $params); 
     } 

     return false; 
    } 


    /* 
     // Pull the private key ID from the certificate 
     $privatekeyid = openssl_get_privatekey($cert); 

     // Sign using the key 
     $sig = false; 
     $ok = openssl_sign($base_string, $sig, $privatekeyid); 

     // Release the key resource 
     openssl_free_key($privatekeyid); 

     base64_encode($sig) 
    */ 


    protected function _generateSignature_RSA($sbs, $method, $url, $params = array()) 
    { 
     // $res = ... 
     $res = openssl_pkey_get_private('file://' . $this->_keyfile); 

     /* 
     print('key id is: ['); 
     print_r($res); 
     print(']'); 
     print("\n\n\n"); 
     */ 

     $signature = null; 
     $retr = openssl_sign($sbs, $signature, $res); 

     openssl_free_key($res); 

     return array(
      0 => $sbs, 
      1 => base64_encode($signature), 
      ); 
    } 



    /* 
    $key = $request->urlencode($consumer_secret).'&'.$request->urlencode($token_secret); 
    $signature = base64_encode(hash_hmac("sha1", $base_string, $key, true)); 
    */ 

    protected function _generateSignature_HMAC($sbs, $method, $url, $params = array()) 
    { 
     $secret = $this->_escape($this->_oauth_consumer_secret); 

     $secret .= '&'; 

     if (!empty($params['oauth_secret'])) 
     { 
      $secret .= $this->_escape($params['oauth_secret']); 
     } 

     //print('generating signature from [' . $secret . ']' . "\n\n"); 

     return array(
      0 => $sbs, 
      1 => base64_encode(hash_hmac('sha1', $sbs, $secret, true)), 
      ); 
    } 
} 
?> 

$request['headers']:

<?php 

define('IS_SANDBOX', 1); 

require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'oAuth.php'); 

// GET baseURL/v3/company/companyID/resourceName/entityID 
// consumer and consumer_secret 
$oAuth = new QuickBooks_IPP_OAuth('qyprdwX21R3klmiskW3AaYLnDRGNLn', 'FDPpxScC6CIgoA07Uc2NYtZJk45CqNDI1Gw4zntn'); 

$request = array(
    'url' => array(
     'base_request_uri' => IS_SANDBOX == 1 ? 'https://sandbox-quickbooks.api.intuit.com' : 'https://quickbooks.api.intuit.com', 
     'version' => 'v3', 
     'company' => 'company', 
     'companyID' => '123145768959777' 
    ), 
    'query' => 'SELECT * FROM ESTIMATE', 
    'headers' => array(
     'Host' => IS_SANDBOX == 1 ? 'sandbox-quickbooks.api.intuit.com' : 'quickbooks.api.intuit.com', 
     'Accept' => 'application/json', 
     'User-Agent' => 'APIExplorer' 
    ) 
); 

$request_url = implode('/', $request['url']) . '/query?query=' . str_replace('+', ' ', str_replace('%7E', '~', rawurlencode($request['query']))) . '&minorversion=4'; 

// token, and token_secret 
$headers = $oAuth->sign('GET', $request_url, 'qyprdaiy37CxGCuB8ow8XK76FYii3rnRU4AIQrHsZDcVFNnV', 'wWcpmPffdPABp6LNNyYgnraTft7bgdygAmTML0aB'); 

$request['headers']['Authorization'] = 'OAuth ' . array_pop($headers); 

$response = curl($request_url, $request['headers']); 

echo '<pre>', var_dump($response), '</pre>'; 
echo '<pre>', var_dump($request['headers']), '</pre>'; 


function curl($url, $headers) { 
    try { 
     $request_headers = array(); 
     $ch = curl_init(); 

     if (FALSE === $ch) 
      throw new Exception('failed to initialize'); 

     curl_setopt($ch, CURLOPT_URL, $url); 
     curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 

     if (!empty($headers)) { 

      foreach($headers as $key => $value) 
      { 
       if ($key == 'GET') 
       { 
        $request_headers[] = $key . ' ' . $value; 
        continue; 
       } 

       $request_headers[] = $key . ': ' . $value; 
      } 

      curl_setopt($ch, CURLOPT_HTTPHEADER, $request_headers); 
      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Disable SSL Verfication, so we can get all info from non-SSL site! 
     } 

     $data = curl_exec($ch); 
     $header = curl_getinfo($ch); 

     echo '<h2>Curl Get Info</h2>'; 
     echo '<pre>', var_dump($header), '</pre>'; 

     if (FALSE === $data) 
      throw new Exception(curl_error($ch), curl_errno($ch)); 
     else 
      return $data; 

     curl_close($ch); 
    } catch(Exception $e) { 
     trigger_error(sprintf(
       'Curl failed with error #%d: %s', 
       $e->getCode(), $e->getMessage()), E_USER_ERROR); 
    } 
} 

echo '<pre>', var_dump($request_url), '</pre>'; 


?> 

Meine oAuth.php Datei sieht wie folgt aus sieht so aus:

array(4) { 
    ["Host"]=> 
    string(33) "sandbox-quickbooks.api.intuit.com" 
    ["Accept"]=> 
    string(16) "application/json" 
    ["User-Agent"]=> 
    string(11) "APIExplorer" 
    ["Authorization"]=> 
    string(306) "OAuth oauth_token="qyprdaiy37CxGCuB8ow8XK76FYii3rnRU4AIQrHsZDcVFNnV",oauth_nonce="189f7f21-6dd9-c136-e208-0f33141feea5",oauth_consumer_key="qyprdwX21R3klmiskW3AaYLnDRGNLn",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1462545676",oauth_version="1.0",oauth_signature="BIpYveqCxlfVT4Ps4qJypS%2BXHh8%3D"" 
} 

Die Antwort l ooks wie folgt aus:

message=ApplicationAuthenticationFailed; errorCode=003200; statusCode=401 
      SignatureBaseString: GET&https%3A%2F%2Fsandbox-quickbooks.api.intuit.com%2Fv3%2Fcompany%2F123145768959777%2Fquery&minorversion%3D4%26oauth_consumer_key%3DqyprdwX21R3klmiskW3AaYLnDRGNLn%26oauth_nonce%3D189f7f21-6dd9-c136-e208-0f33141feea5%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1462545676%26oauth_token%3Dqyprdaiy37CxGCuB8ow8XK76FYii3rnRU4AIQrHsZDcVFNnV%26oauth_version%3D1.0%26query%3DSELECT%2520%252A%2520FROM%2520ESTIMATE 

Die $request_url sieht wie folgt aus:

https://sandbox-quickbooks.api.intuit.com/v3/company/123145768959777/query?query=SELECT%20%2A%20FROM%20ESTIMATE&minorversion=4

Bin ich etwas vergessen, hier zu tun? Oder ist vielleicht etwas nicht in Ordnung? Ich sollte alle Schätzungen aus der Quickbook Company mit der ID 123145768959777 bekommen, aber alles, was ich bekomme, ist 401 Authorization Failure messages.

Antwort

1

Vergesse ich hier etwas zu tun? Oder ist vielleicht etwas nicht in Ordnung?

Ja, definitiv. Siehe unten für Einzelheiten.

$ headers = $ oAuth-> Zeichen (null, ...

null ist keine gültige HTTP-Request-Methode gültige HTTP-Request-Methoden sind Dinge wie GET, POST Bitte, etc. an die HTTP-Spezifikation beziehen und die OAuth spec.

$ headers = $ oAuth-> Zeichen (null, $ _SERVER [ 'REQUEST_URI'],

Warum signieren Sie die Serveranforderungs-URI? Sie sollten die URL unter signieren, unter der Sie Ihre Curl-Anfrage an senden und nicht die URL, die der Nutzer auf Ihrer eigenen Website besucht.

$ headers = $ oAuth-> Zeichen (null, $ _SERVER [ 'REQUEST_URI'], 'qyprdaiy37CxGCuB8ow8XK76FYii3rnRU4AIQrHsZDcVFNnV', 'wWcpmPffdPABp6LNNyYgnraTft7bgdygAmTML0aB');

Sie können das OAuth-Zugriffstoken und -geheimnis nicht fest codieren. Sie ändern sich alle 6 Monate und müssen daher irgendwo in einer Datenbank/Datei gespeichert werden, so dass Sie sie ändern können, ohne Ihren Code alle 6 Monate zu bearbeiten.

$ request_url = implode ('/', $ anfrage ['url']). '/ query? query ='. str_replace ('+', '', str_replace ('% 7E', '~', rawurlencode ($ anfrage ['query']))). '& Nebenversion = 4';

Dies ist die URL, die Sie signieren sollten.

Ich sollte alle Schätzungen aus der Quickbook Company mit ID 123145768959777 bekommen, aber alles, was ich bekomme, ist 401 Authorization Failure Nachrichten.

Wenn Sie weitere Hilfe benötigen, wäre es sehr sinnvoll, Ihre tatsächlichen HTTP-Anfragen und Antworten zu veröffentlichen. Es gibt nicht viel, was jemand Ihnen sagen kann, ohne wirklich zu sehen, dass die Anfragen gesendet werden und die Antworten empfangen werden.

Auch ... merkt man, dass all diese harte Arbeit bereits für Sie erledigt wurde, indem Sie die Bibliothek benutzen, aus der Sie Code geholt haben, richtig? z.B. Du brauchst nichts von dem, was du tust - es ist nur das Rad neu erfinden. Just do:

require_once dirname(__FILE__) . '/config.php'; 

$EstimateService = new QuickBooks_IPP_Service_Estimate(); 
$estimates = $EstimateService->query($Context, $realm, "SELECT * FROM Estimate STARTPOSITION 1 MAXRESULTS 10"); 

foreach ($estimates as $Estimate) 
{ 
    print('Estimate # ' . $Estimate->getDocNumber() . "\n"); 
} 

Hilfreiche Links:

+0

Danke für Ihre Hilfe, hier ist meine Antwort vom curl Anfrage: 'message = ApplicationAuthenticationFailed; errorCode = 003200; status = 401 SignatureBaseString: GET & https% 3A% 2F% 2Fsandbox-quickbooks.api.intuit.com% 2Fv3% 2Fcompany% 2F123145768959777% 2Fquery & Minorversion% 3D4% 26oauth_consumer_key% 3DqyprdwX21R3klmiskW3AaYLnDRGNLn% 26oauth_nonce% 3Ddbc677e1-3992-0ae4-0063-9b861998c265% 26oauth_signature_method% 3DHMAC-SHA1% 26oauth_timestamp% 3D1462545469% 26oauth_token% 3Dqyprdaiy37CxGCuB8ow8XK76FYii3rnRU4AIQrHsZDcVFNnV% 26oauth_version% 3D1.0% 26Query% 3DSELECT% 2520% 252A% 2520FROM% 2520ESTIMATE' –

+0

Die Änderungen wurden gemäß Ihren Empfehlungen vorgenommen, aber immer noch keine Würfel. –

+0

Aber du hast deinen aktualisierten Code oder die HTTP-Anfrage/Antwort von deinem aktualisierten Code nicht hochgeladen, damit ich dir nicht weiterhelfen kann ... –