I only want to grab information using the Quickbooks API (that seems like this should be possible via their API). I setup an App on their Development site, linked it to the Quickbooks Company I created, and am trying to run this code to get anything from the curl response, but all I am getting are Authorization Failure (401) Messages. Why is it not being authorized? Been studying this site for 12 hours and none of their examples that they provide even work. Am using this page as a reference: https://developer.intuit.com/docs/0050_quickbooks_api/0010_your_first_request/rest_essentials_for_the_quickbooks_api and this: https://developer.intuit.com/docs/0100_accounting/0300_developer_guides/0015_calling_data_services#/The_authorization_header
My index.php file is as follows:
<?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>';
?>
My oAuth.php file looks like this:
<?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 <keith#consolibyte.com>
* #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 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
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'] looks like this:
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""
}
The response looks like this:
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
The $request_url looks like this:
https://sandbox-quickbooks.api.intuit.com/v3/company/123145768959777/query?query=SELECT%20%2A%20FROM%20ESTIMATE&minorversion=4
Am I forgetting to do something here? Or perhaps something is not correct somehow? I should be getting All Estimates from within the Quickbook Company with ID of 123145768959777, but all I'm getting is 401 Authorization Failure messages.
Am I forgetting to do something here? Or perhaps something is not correct somehow?
Yes, definitely. See below for specifics:
$headers = $oAuth->sign(null, ...
null is not a valid HTTP request method. Valid HTTP request methods are things like GET, POST, etc. Please refer to the HTTP spec and the OAuth spec.
$headers = $oAuth->sign(null, $_SERVER['REQUEST_URI'],
Why are you signing the server request URI? You should be signing the URL that you are sending your curl request to and not the URL the user is visiting on your own website.
$headers = $oAuth->sign(null, $_SERVER['REQUEST_URI'], 'qyprdaiy37CxGCuB8ow8XK76FYii3rnRU4AIQrHsZDcVFNnV', 'wWcpmPffdPABp6LNNyYgnraTft7bgdygAmTML0aB');
You can not hard-code the OAuth access token and secret. They change every 6 months, and thus have to be stored in a database/file somewhere so that you can change them without editing your code every 6 months.
$request_url = implode('/', $request['url']) . '/query?query=' . str_replace('+', ' ', str_replace('%7E', '~', rawurlencode($request['query']))) . '&minorversion=4';
This is the URL you should be signing.
I should be getting All Estimates from within the Quickbook Company with ID of 123145768959777, but all I'm getting is 401 Authorization Failure messages.
If you need further help, it would make a lot of sense to post your actual HTTP requests and responses. There's not a lot anyone will be able to tell you without really seeing the requests being sent, and the responses being received.
Also... you realize that all of this hard work has already been done for you, using the library you've grabbed code from, right? e.g. You don't need to do any of what you're doing - it's just re-inventing the wheel. 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");
}
Helpful links:
https://github.com/consolibyte/quickbooks-php
https://github.com/consolibyte/quickbooks-php/blob/master/docs/partner_platform/example_app_ipp_v3/
https://github.com/consolibyte/quickbooks-php/blob/master/docs/partner_platform/example_app_ipp_v3/example_invoice_query.php
I'm building a HMAC API and I have issues testing the hashing with Paw.
On Paw I have this payload:
GET:/hello/world:"":9a6e30f2016370b6f2dcfb6880501d7f2305d69bout
and a custom HMAC-SHA256 variable (actually function like this that sets it in the X-Hash header.
X-Hash: 4Cq2yehWumDcUk1dYyfhm6qWjJVBkOCB8o12f5l0WGE=
In my PHP API I have the same thing:
GET:/hello/world:"":9a6e30f2016370b6f2dcfb6880501d7f2305d69bout
and used:
hash_hmac('sha256', $this->getPayload(), '9a6e30f2016370b6f2dcfb6880501d7f2305d69bout', false);
So when comparing the hashes:
Paw: 4Cq2yehWumDcUk1dYyfhm6qWjJVBkOCB8o12f5l0WGE=
PHP: 6961b9d1f6e986c49d963cbebd691fa68dfa59b4ce3b7f05320c2d43eae3c7c3
They are very different. Any idea why is that?
Update
Paw Code:
function evaluate(context){
var loc = getLocation(context.getCurrentRequest().url);
var payload = "";
payload += context.getCurrentRequest().method + ':';
payload += loc.pathname + ':';
payload += JSON.stringify(context.getCurrentRequest().body) + ':';
payload += "9a6e30f2016370b6f2dcfb6880501d7f2305d69bout"; // Private key
return payload;
};
function getLocation(href) {
var match = href.match(/^(https?\:)\/\/(([^:\/?#]*)(?:\:([0-9]+))?)(\/[^?#]*)(\?[^#]*|)(#.*|)$/);
return match && {
protocol: match[1],
host: match[2],
hostname: match[3],
port: match[4],
pathname: match[5],
search: match[6],
hash: match[7]
}
}
PHP Code (with lots of comments):
if (strpos(strtoupper($authHeader), 'HMAC') !== 0) {
echo 'out';
throw new HttpForbiddenException();
}
else {
$hmacSignature = $app->request->headers()->get('X-Hash');
$publicKey = $app->request->headers()->get('X-Public');
if ( empty($hmacSignature) || empty($publicKey) ) {
echo 'out2';
throw new HttpForbiddenException();
}
else {
$this->hmacManager->setPublicKey($publicKey);
print '$publickey = ' . $publicKey . '<br>';
// Validate if base64_encoded or not
if( base64_decode($hmacSignature, true) !== FALSE ) {
$binaryString = base64_decode($hmacSignature);
$hmacSignature = bin2hex($binaryString);
print 'decoding ' . '<br>';
}
$this->hmacManager->setHmacSignature($hmacSignature);
print '$hmacSignature = ' . $hmacSignature . '<br>';
$this->hmacManager->setRequestMethod($app->request->getMethod());
print 'method = ' . $app->request->getMethod() . '<br>';
$this->hmacManager->setRequestResourceUri($app->request->getResourceUri());
print 'uri = ' . $app->request->getResourceUri() . '<br>';
$requestBody = $app->request()->getBody();
if (Utils::isJson($requestBody)) {
$requestBody = json_decode($requestBody);
}
$this->hmacManager->setRequestBody(json_encode($requestBody));
print 'body = ' . json_encode($requestBody) . '<br>';
print 'private key = ' . $this->hmacManager->getPrivateKey() . '<br>';
$payload = '';
$payload .= $this->hmacManager->getRequestMethod() . ":";
$payload .= $this->hmacManager->getRequestResourceUri() . ":";
$payload .= $this->hmacManager->getRequestBody() . ":";
$payload .= $this->hmacManager->getPrivateKey();
print 'PHP payload [' . $payload . ']';
$this->hmacManager->setPayload($payload);
$hmacValue = $this->hmacManager->generateHmac();
$isValid = $this->hmacManager->isValid($this->hmacManager->generateHmac(), $hmacSignature);
if ($isValid !== true) {
echo 'out3';
throw new HttpForbiddenException();
}
}
}
generateHmac from another class:
public function generateHmac()
{
print 'Generating HMAC' . '<br>';
$algorithm = $this->getAlgorithm();
print 'algo ' . $algorithm . '<br>';
$privateKey = $this->getPrivateKey();
print 'privk ' . $privateKey . '<br>';
if (empty($algorithm)) {
throw new \RuntimeException('Algorithm must be set and not empty');
} elseif (empty($privateKey)) {
throw new \RuntimeException('Private key must be set and not empty');
}
print 'payload ' . $this->getPayload() . '<br>';
$hash = hash_hmac($this->getAlgorithm(), $this->getPayload(), $this->getPrivateKey(), false);
print 'php hasj: ' . $hash . '<br>';
return $hash;
}
Finally, here's the output statements:
$publickey = 95f97b93560f951b4cae46c86d03d9b1a81d4ae8
decoding
$hmacSignature = e02ab6c9e856ba60dc524d5d6327e19baa968c954190e081f28d767f99745861
method = GET
uri = /hello/world
body = ""
private key = 9a6e30f2016370b6f2dcfb6880501d7f2305d69bout
PHP payload [GET:/hello/world:"":9a6e30f2016370b6f2dcfb6880501d7f2305d69bout]
Generating HMAC
algo sha256
privk 9a6e30f2016370b6f2dcfb6880501d7f2305d69bout
payload GET:/hello/world:"":9a6e30f2016370b6f2dcfb6880501d7f2305d69bout
php hash: 6961b9d1f6e986c49d963cbebd691fa68dfa59b4ce3b7f05320c2d43eae3c7c3
Hope it helps!
The paw hash is base64 encoded while the PHP one is in hexadecimal. So decode the paw hash first:
$binary = base64_decode($pawHash);
$hex = bin2hex($binary);
And then compare this to your own hash.
We've just added new Base 64 to Hex conversion dynamic values, this should solve your problem.
Wrap your HMAC signature dynamic value inside the new Base 64 to Hex one, and you'll get a valid hexadecimal signature:
You can install this new dynamic value here: Base 64 to Hex Dynamic Value
I'm using Amazon MWS API in creating my own web site that will Import my products from Amazon..
but I don't how to fetch my products in Amazon using my seller ID..
require_once('config.inc.php');
$serviceUrl = "https://mws.amazonservices.com/Products/2011-10-01";
$config = array (
'ServiceURL' => $serviceUrl,
'ProxyHost' => null,
'ProxyPort' => -1,
'ProxyUsername' => null,
'ProxyPassword' => null,
'MaxErrorRetry' => 3,
);
$service = new MarketplaceWebServiceProducts_Client(
AWS_ACCESS_KEY_ID,
AWS_SECRET_ACCESS_KEY,
APPLICATION_NAME,
APPLICATION_VERSION,
$config);
$request = newMarketplaceWebServiceProducts_Model_ListMatchingProductsRequest();
$request->setSellerId(A1234V999SASDF);
invokeListMatchingProducts($service, $request);
functioninvokeListMatchingProducts(MarketplaceWebServiceProducts_Interface $service, $request)
{
try {
$response = $service->ListMatchingProducts($request);
echo ("Service Response\n");
echo ("=============================================================================\n");
$dom = new DOMDocument();
$dom->loadXML($response->toXML());
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
echo $dom->saveXML();
echo("ResponseHeaderMetadata:".$response->getResponseHeaderMetadata() . "\n");
} catch (MarketplaceWebServiceProducts_Exception $ex) {
echo("Caught Exception: " . $ex->getMessage() . "\n");
echo("Response Status Code: " . $ex->getStatusCode() . "\n");
echo("Error Code: " . $ex->getErrorCode() . "\n");
echo("Error Type: " . $ex->getErrorType() . "\n");
echo("Request ID: " . $ex->getRequestId() . "\n");
echo("XML: " . $ex->getXML() . "\n");
echo("ResponseHeaderMetadata: " . $ex->getResponseHeaderMetadata() . "\n");
}
it has an error
PHP Fatal error: Class 'MarketplaceWebServiceProducts_Client' not found in /var/www/html/amazon/src/MarketplaceWebServiceProducts/Samples/listMatching.php on line 16
I am using PAYPAL API.
I success calling the setExpressCheckout (after calling this method I got ACK=Success) and therefore get a full link that I can proceed with.
After getting the full link (https://www.paypal.com/cgi-bin/webscr?cmd=_flow&SESSION=[SESSION_TOKEN]), the full link represent a page, that includes error.
The error:
This transaction is invalid. Please return to the recipient's website to complete your transaction using their regular checkout flow.
Return to merchant
At this time, we are unable to process your request. Please return to and try another option
Here is my Code:
<?php
/*.
require_module 'standard';
require_module 'standard_reflection';
require_module 'spl';
require_module 'mysqli';
require_module 'hash';
require_module 'session';
require_module 'streams';
.*/
//turn php errors on
//ini_set('track_errors', true);
require_once __DIR__ . "/stdlib/all.php";
require_once __DIR__ . "/SqlManager.php";
/*. array .*/ $body_data = null;
$body_data_txt = "";
/*. string .*/ $htmlpage = "";
/*. array .*/ $keyAr = array();
/*. array .*/ $tokenAr = array();
$response = "";
/*. SqlManager .*/ $sqlm = null;
session_start();
$url = trim('https://api-3t.paypal.com/nvp');
$urlRun = trim('https://www.paypal.com/cgi-bin/webscr');
$body_data = array( 'USER' => *****",
'PWD' => "******",
'SIGNATURE' => "*****",
'VERSION' => "95.0",
'PAYMENTREQUEST_0_PAYMENTACTION' => "Sale",
'PAYMENTREQUEST_0_AMT' => (string)$_SESSION["AMOUNT"],
'PAYMENTREQUEST_0_CURRENCYCODE' => 'USD',
'RETURNURL' => "******",
'CANCELURL' => "******",
'METHOD' => "SetExpressCheckout"
);
$body_data_txt = http_build_query($body_data, '', chr(38));
try
{
$sqlm = new SqlManager(true);
//create request and add headers
$params = array(
'http' => array(
'protocol_version' => "1.1",
'method' => "POST",
'header' => "".
"Connection: close\r\n".
"Content-Length: ".strlen($body_data_txt)."\r\n".
"Content-type: "."application/x-www-form-urlencoded"."\r\n",
'content' => $body_data_txt
));
//create stream context
$ctx = stream_context_create($params);
//open the stream and send request
try {
$fp = fopen($url, 'r', false, $ctx);
} catch(ErrorException $e) {
throw new ErrorException("cannot open url" . $url . " error:" . $e->getMessage());
}
//get response
$response = (string)stream_get_contents($fp);
//check to see if stream is open
if ($response === "") {
throw new Exception("php error message = " . "$php_errormsg");
}
//close the stream
fclose($fp);
$key = explode("&", $response);
$keyAr = array();
foreach ($key as $i => $value) {
$tmpAr = explode("=", $value);
if(sizeof($tmpAr) > 1) {
$keyAr[$tmpAr[0]] = $tmpAr[1];
}
}
if (substr($response, 0, 1) === "<") {
echo $response;
} else {
// Extract the response details.
if((0 == sizeof($keyAr)) || !array_key_exists('ACK', $keyAr) || (string)$keyAr["ACK"] !== "Success") {
if (array_key_exists('L_ERRORCODE0', $keyAr) && array_key_exists('L_LONGMESSAGE0', $keyAr)) {
echo cast("string", htmlspecialchars(urldecode((string)$keyAr["L_ERRORCODE0"]))) . ',' .
cast("string", htmlspecialchars(urldecode((string)$keyAr["L_LONGMESSAGE0"])));
} else {
echo "Unkown server response!";
}
} else {
// ********************************************
$htmlpage = $urlRun . "?cmd=_express-checkout&". "TOKEN=" . (string)$keyAr["TOKEN"]; // ******************* IS THIS LINE OK????
// ********************************************
echo "ok," . $htmlpage;
}
}
}
catch(Exception $e)
{
echo 'Message: ||' .cast("string", str_replace('"', '\\"', $e->getMessage())).'||';
}
?>
the $htmlpage got the full link (see the line with the asterisks remark 'IS THIS LINE OK')
My account is business account.
What may be the cause for the problem?
Seem kind of configuration problem - are there any setups I shall check?
Thanks :)
The problem is that I have opened the paypal page with 'TOKEN=', and I should open by 'token='
(capitalized letter matter).
The line:
$htmlpage = $urlRun . "?cmd=_express-checkout&". "TOKEN=" . (string)$keyAr["TOKEN"];
should be:
$htmlpage = $urlRun . "?cmd=_express-checkout&". "token=" . (string)$keyAr["TOKEN"];
Thanks, anyway :)
I am trying to download all my listings from ebay into my database using following code:
$client = new eBaySOAP($session);
$ebay_items_array = array();
try {
$client = new eBaySOAP($session);
$params = array(
'Version' => $Version,
'GranularityLevel' => "Fine",
'OutputSelector' => "ItemID,SKU,Title",
'EndTimeFrom' => date("c", mktime(date("H"), date("i")+10, date("s"), date("n"), date("j"), date("Y"))),
'EndTimeTo' => date("c", mktime(date("H"), date("i"), date("s"), date("n"), date("j")+120, date("Y"))),
'Pagination' => array(
'PageNumber' => $_GET['linkebaynum'],
'EntriesPerPage' => "20"
)
);
$results = $client->GetSellerList($params);
if($results->Ack == "Success")
{
$c = 0;
if(is_array($results->ItemArray->Item))
{
foreach($results->ItemArray->Item as $key => $value)
{
array_push($ebay_items_array, $value->ItemID);
$Qcheck = tep_db_query('select ebay_productstoitems_items_id from ' . TABLE_EBAY_PRODUCTS_TO_ITEMS . ' where ebay_productstoitems_items_id = ' . $value->ItemID);
$check = tep_db_fetch_array($Qcheck);
if($check == 0) {
if($check['ebay_productstoitems_items_id'] = $value->ItemID) {
echo 'Not in Database - Inserting ' . $value->ItemID . '<br>';
tep_db_query("insert ebay_productstoitems set ebay_productstoitems_items_id = '" . $value->ItemID . "'");
}
}else{
echo 'Found - ' . $value->ItemID . ' Nothing to Change<br>';
tep_db_query("update ebay_productstoitems set ebay_productstoitems_items_id = '" . $value->ItemID . "' where ebay_productstoitems_items_id = '" . $value->ItemID . "'");
}
}
$c++;
}
}
} catch (SOAPFault $f) {
print "error<br>";
}
print "Request:<br>".ebay_formatxmlstring($client->__getLastRequest())."<br><br>";
print "Response:<br>".ebay_formatxmlstring($client->__getLastResponse())."<br><br>";
But it will not recover the SKU (or CustomLabel).
Can anyone explain what I am missing to get the SKU into the database along with the ItemID.
Or would I have to recover lists of ItemID and then do a second call to recover the SKU or CustomLabel?
Found out what the problem was the Sandbox does not appear to pass the SKU back. I switched to the live site and hey presto the SKU is being retrieved along with the Itemid.