I'm trying to get an O-Auth token from the Spotify API but when using cURL on Debian 8 I always get the error message POST requests require a Content-length header. while it works on my MacBook.
$authString = $spotifyId . ":" . $spotifySecret;
$encodedAuthString = base64_encode($authString);
$spotifyHeaders = array(
"Authorization: Basic " . $encodedAuthString,
"Content-Type: application/x-www-form-urlencoded",
);
$spotifyOauthCurl = curl_init();
curl_setopt($spotifyOauthCurl, CURLOPT_URL, "https://accounts.spotify.com/api/token");
curl_setopt($spotifyOauthCurl, CURLOPT_POST, true);
curl_setopt($spotifyOauthCurl, CURLOPT_HTTPHEADER, $spotifyHeaders);
curl_setopt($spotifyOauthCurl, POSTFIELDS, "grant_type=client_credentials");
curl_setopt($spotifyOauthCurl, CURLOPT_RETURNTRANSFER, true);
// curl_setopt($spotifyOauthCurl, CURLINFO_HEADER_OUT, true);
$result = curl_exec($spotifyOauthCurl);
echo curl_getinfo($spotifyOauthCurl, CURLINFO_HEADER_OUT);
Adding CURLOPT_VERBOSE as suggested by #hanshenrik returned the following output
Trying 35.186.224.25...
* TCP_NODELAY set
* Connected to accounts.spotify.com (35.186.224.25) port 443 (#0)
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:#STRENGTH
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use http/1.1
* Server certificate:
* subject: C=SE; L=Stockholm; O=Spotify AB; CN=*.spotify.com
* start date: May 3 00:00:00 2021 GMT
* expire date: May 3 23:59:59 2022 GMT
* subjectAltName: host "accounts.spotify.com" matched certs "*.spotify.com"
* issuer: C=US; O=DigiCert Inc; CN=DigiCert TLS RSA SHA256 2020 CA1
* SSL certificate verify ok.
> POST /api/token HTTP/1.1
/api/token?grant_type=client_credentials HTTP/1.1
Host: accounts.spotify.com
Accept: */ *
Authorization: Basic ...
Content-Type: application/x-www-form-urlencoded
Expect: 100-continue
* HTTP 1.0, assume close after body
< HTTP/1.0 411 Length Required
< Content-Type: text/html; charset=UTF-8
< Referrer-Policy: no-referrer
< Content-Length: 1564
< Date: Wed, 26 Jan 2022 17:36:23 GMT
<
* Curl_http_done: called premature == 0
* Closing connection 0
1: you're ignoring the error log, every time you run
curl_setopt($spotifyOauthCurl, POSTFIELDS, "grant_type: client_credentials");
your errorlog gets a message like
Warning: Use of undefined constant POSTFIELDS - assumed 'POSTFIELDS' (this will throw an Error in a future version of PHP) in /in/S9fsj on line 3
string(10) "POSTFIELDS"
Also you're running php 5/7, because in PHP8 this will throw an exception: https://3v4l.org/S9fsj
2: you're ignoring curl_setopt return errors, curl_setopt returns false on errors, which your code is ignoring. an easy way around that would be
function ecurl_setopt ( /*resource*/$ch , int $option , /*mixed*/ $value ){
$ret=curl_setopt($ch,$option,$value);
if($ret!==true){
//option should be obvious by stack trace
throw new RuntimeException ( 'curl_setopt() failed. curl_errno: ' . curl_errno ($ch) .'. curl_error: '.curl_error($ch) );
}
}
3: it's all caused by a typo! it's supposed to be CURLOPT_POSTFIELDS not just POSTFIELDS
Related
Well, I'm having troubles making requests to the Discord API, I'm not understanding how curl is working.
This is my code:
function make_request($mixed, $token, $get_json = true) {
$url = is_string($mixed) ? $mixed : getApiUrl($mixed);
// TODO: Check for valid url!
$log_file = __DIR__.'/../logs/request.txt';
if(!is_readable($log_file)) printError("File '$log_file' is not readable!");
if(!is_writable($log_file)) printError("File '$log_file' is not writable!");
$ch = curl_init();
$f = fopen($log_file, 'w+');
if($f === false) printError("There was an error opening '$log_file'!");
ftruncate($f, 0);
curl_setopt_array($ch, array(
CURLOPT_URL => $url,
CURLOPT_HTTPHEADER => array('Authorization: Bot ' . $token),
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_FOLLOWLOCATION => 1,
CURLOPT_VERBOSE => 1,
CURLOPT_SSL_VERIFYPEER => 0,
CURLOPT_STDERR => $f,
));
$response = curl_exec($ch);
fclose($f);
curl_close($ch);
$contents = file_get_contents($log_file);
if($contents != '')
{
// Censor bot key!
$contents = preg_replace("/^Authorization: Bot.+?$/", "Authorization: Bot xxx", $contents);
printError($contents);
}
if($get_json) {
$pretty = isset($_GET["pretty"]);
if($pretty) {
$json = json_decode($response);
return json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
}
return $response;
}
return json_decode($response, true);
}
And this is my output:
[OuterException] System.Exception: * Hostname in DNS cache was stale, zapped
* Trying 162.159.135.233...
* TCP_NODELAY set
* Connected to discordapp.com (162.159.135.233) port 443 (#0)
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:#STRENGTH
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* SSL connection using TLSv1.2 / ECDHE-ECDSA-AES128-GCM-SHA256
* ALPN, server accepted to use http/1.1
* Server certificate:
* subject: CN=ssl711320.cloudflaressl.com
* start date: Feb 13 00:00:00 2020 GMT
* expire date: Aug 21 23:59:59 2020 GMT
* subjectAltName: host "discordapp.com" matched cert's "discordapp.com"
* issuer: C=GB; ST=Greater Manchester; L=Salford; O=COMODO CA Limited; CN=COMODO ECC Domain Validation Secure Server CA 2
* SSL certificate verify ok.
> GET /api/guilds/479096180601782274 HTTP/1.1
Host: discordapp.com
Accept: */*
Authorization: Bot ...
< HTTP/1.1 200 OK
< Date: Thu, 20 Feb 2020 17:49:15 GMT
< Content-Type: application/json
< Transfer-Encoding: chunked
< Connection: keep-alive
< Set-Cookie: __cfduid=ddfc25d7448507e06474f24ff3e8352381582220955; expires=Sat, 21-Mar-20 17:49:15 GMT; path=/; domain=.discordapp.com; HttpOnly; SameSite=Lax
< Strict-Transport-Security: max-age=31536000; includeSubDomains
< Via: 1.1 google
< Alt-Svc: clear
< CF-Cache-Status: DYNAMIC
< Set-Cookie: __cfruid=66721d8d16cd42e4884dc62afe94705cbf1e21df-1582220955; path=/; domain=.discordapp.com; HttpOnly; Secure; SameSite=None
< Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
< Server: cloudflare
< CF-RAY: 568250ea9fe2a861-CDG
<
* Curl_http_done: called premature == 0
* Connection #0 to host discordapp.com left intact
en DiscordIdCrawler.Lib.Core.ApiWorker.CheckForErrors(Object response) en E:\PHP\discord-flooder-bot\client\DiscordIdCrawler\DiscordIdCrawler.Lib\Core\ApiWorker.cs:línea 152
en DiscordIdCrawler.Lib.Core.ApiWorker.GetServerName(Int64 serverId) en E:\PHP\discord-flooder-bot\client\DiscordIdCrawler\DiscordIdCrawler.Lib\Core\ApiWorker.cs:línea 312
en DiscordIdCrawler.Lib.Core.DriverWorker.GoToServer(IWebDriver web, Int32 serverNum, Boolean storeOnDB) en E:\PHP\discord-flooder-bot\client\DiscordIdCrawler\DiscordIdCrawler.Lib\Core\DriverWorker.cs:línea 141
My question is that maybe I'm printing an error when curl is just showing a verbosed log, but I'm not sure if the CURLOPT_STDERR is used to print errors or the entire log.
On the docs: https://www.php.net/manual/en/function.curl-setopt.php
An alternative location to output errors to instead of STDERR.
Maybe is because CURLOPT_VERBOSE is enabled.
TRUE to output verbose information. Writes output to STDERR, or the file specified using CURLOPT_STDERR.
On that case, I need to know when an error happens. Any tip here?
You're on the right track. If you want the diagnostic output, you have to arrange to capture it before you make your request. The usual way to do this is by storing it in RAM, checking for curl error, and handling appropriately.
That code looks like:
$ch = curl_init();
curl_setopt_array($ch, [
// ... other options here
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_VERBOSE => 1,
CURLOPT_STDERR => ($log = fopen('php://temp', 'w')),
]);
$response = curl_exec($ch);
if (false === $response) {
$errno = curl_error($ch);
$errmsg = curl_strerror($errno);
$logtext = stream_get_contents($log, -1, 0);
// ... log the info above, take action, etc.
} else {
// ... $response is your HTTP response
}
curl_close($ch);
How to get the raw HTTP request from a multipart/form-data request?
The request is not written to test.log.. Only Response: is saved?
The client can upload files etc. and I need to check if the user gzip the binary data parts.. If not I need to throw an error
request
$boundary = 'jlasdifj439';
$field1 = json_encode(['test' => 123]);
$body = '--'.$boundary."\r\n"
.'Content-Disposition: form-data; name="json"'."\r\n"
.'Content-Type: application/json'."\r\n"
.'Content-Length: '.strlen($field1)."\r\n\r\n"
.$field1."\r\n"
.'--'.$boundary.'--';
$socket = curl_init();
curl_setopt_array($socket, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_VERBOSE => true,
CURLOPT_ENCODING => '',
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2_0,
]);
curl_setopt($socket, CURLOPT_URL, 'https://my-url');
curl_setopt($socket, CURLOPT_HTTPHEADER, [
'Content-Type: multipart/form-data; boundary='.$boundary,
]);
curl_setopt($socket, CURLOPT_POSTFIELDS, $body);
if(!$response = curl_exec($socket)){
echo "ERROR!";
}
echo $response;
response
$body = file_get_contents('php://input');
file_put_contents('/var/www/test.log', "Response:\n".$body);
test.log
Response:
curl verbose
* Hostname was NOT found in DNS cache
* Trying xxx.xxx.xxx.xxx...
* Connected to test.com (xxx.xxx.xxx.xxx) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* Server certificate:
* subject: CN=*xxxxx
* start date: 2017-10-02 00:00:00 GMT
* expire date: 2018-12-01 23:59:59 GMT
* subjectAltName: test.com matched
* issuer: C=US; O=thawte, Inc.; OU=Domain Validated SSL; CN=thawte DV SSL SHA256 CA
* SSL certificate verify ok.
> POST / HTTP/1.1
Host: xxxxx
Accept: */*
Accept-Encoding: deflate, gzip
Content-Type: multipart/form-data; boundary=jlasdifj439
Content-Length: 143
* upload completely sent off: 143 out of 143 bytes
< HTTP/1.1 200 OK
* Server nginx is not blacklisted
< Server: nginx
< Date: Sun, 10 Jun 2018 20:49:43 GMT
< Content-Type: application/json
< Transfer-Encoding: chunked
< Connection: keep-alive
< content-encoding: gzip
<
* Connection #0 to host xxxxx left intact
When I try to open url1(https://www.google.co.in), url2(https://www.amazon.com), url5(https://www.instagram.com) its working fine that is I can load url1, url2 and url5 but when I try to open url3(https://www.facebook.com), url4(https://www.twitter.com), its printing my error message:"Error, Unable to open." as it can't open facebook, twitter page. I dont want to use API. Thank you in advance.
<?php
$curl = curl_init();
//url1 = https://www.google.co.in
//url2 = https://www.amazon.com
//url3 = https://www.facebook.com
//url4 = https://www.twitter.com
//url5 = https://www.instagram.com
$url ="https://www.facebook.com";
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
//curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec($curl);
if($output)
{
echo $output;
}
else
{
echo "Error, Unable to open.";
}
?>
when debugging issues like that, enable CURLOPT_VERBOSE. furthermore, when debugging, don't use echo, use var_dump. if you did that, you'd see something like
* Rebuilt URL to: https://www.facebook.com/
* Trying 157.240.20.35...
* TCP_NODELAY set
* Trying 2a03:2880:f10a:83:face:b00c:0:25de...
* TCP_NODELAY set
* Immediate connect fail for 2a03:2880:f10a:83:face:b00c:0:25de: Network is unreachable
* Connected to www.facebook.com (157.240.20.35) port 443 (#0)
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:#STRENGTH
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* SSL connection using TLSv1.2 / ECDHE-ECDSA-AES128-GCM-SHA256
* ALPN, server accepted to use http/1.1
* Server certificate:
* subject: C=US; ST=California; L=Menlo Park; O=Facebook, Inc.; CN=*.facebook.com
* start date: Dec 15 00:00:00 2017 GMT
* expire date: Mar 22 12:00:00 2019 GMT
* subjectAltName: host "www.facebook.com" matched cert's "*.facebook.com"
* issuer: C=US; O=DigiCert Inc; OU=www.digicert.com; CN=DigiCert SHA2 High Assurance Server CA
* SSL certificate verify ok.
> GET / HTTP/1.1
Host: www.facebook.com
Accept: */*
< HTTP/1.1 302 Found
< Strict-Transport-Security: max-age=15552000; preload
< Location: https://www.facebook.com/unsupportedbrowser
< Content-Type: text/html; charset=UTF-8
< X-FB-Debug: x3NeeaaJHxPQkX5Z9H7yMX3evzYJocXmZpzMV6GoWtacO8bXLL3O58vidPHZUvXTuP9iE9pHPEnbr/RvNsT23Q==
< Date: Mon, 19 Feb 2018 09:12:51 GMT
< Connection: keep-alive
< Content-Length: 0
<
* Connection #0 to host www.facebook.com left intact
string(0) ""
the problem being that facebook tried to issue a HTTP redirect (to https://www.facebook.com/unsupportedbrowser), and you didn't follow it. enable CURLOPT_FOLLOWLOCATION to have curl automatically handle redirects. why did facebook redirect you? because you didn't supply any user-agent header. set one that facebook will recognize as supported with CURLOPT_USERAGENT, for example Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:52.0) Gecko/20100101 Firefox/52.0 (aka Firefox 52 ESR running on Windows 7 x64)
as for twitter.com,
* Rebuilt URL to: https://www.twitter.com/
* Trying 104.244.42.193...
* TCP_NODELAY set
* Connected to www.twitter.com (104.244.42.193) port 443 (#0)
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:#STRENGTH
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use http/1.1
* Server certificate:
* subject: businessCategory=Private Organization; jurisdictionC=US; jurisdictionST=Delaware; serialNumber=4337446; C=US; ST=California; L=San Francisco; O=Twitter, Inc.; OU=tsa_o Point of Presence; CN=twitter.com
* start date: Jul 25 00:00:00 2017 GMT
* expire date: Jul 30 12:00:00 2018 GMT
* subjectAltName: host "www.twitter.com" matched cert's "www.twitter.com"
* issuer: C=US; O=DigiCert Inc; OU=www.digicert.com; CN=DigiCert SHA2 Extended Validation Server CA
* SSL certificate verify ok.
> GET / HTTP/1.1
Host: www.twitter.com
Accept: */*
< HTTP/1.1 301 Moved Permanently
< content-length: 0
< date: Mon, 19 Feb 2018 09:17:51 GMT
< location: https://twitter.com/
< server: tsa_o
< set-cookie: personalization_id="v1_ersTgWQIOjuJkjk6VFUlXw=="; Expires=Wed, 19 Feb 2020 09:17:51 UTC; Path=/; Domain=.twitter.com
< set-cookie: guest_id=v1%3A151903187127250514; Expires=Wed, 19 Feb 2020 09:17:51 UTC; Path=/; Domain=.twitter.com
< strict-transport-security: max-age=631138519
< x-connection-hash: aae827a6347e88db5f417a0c31bba366
< x-response-time: 101
<
* Connection #0 to host www.twitter.com left intact
string(0) ""
it tried to redirect you to the non-www url version of the site, and again, you didn't follow the redirect. enable CURLOPT_FOLLOWLOCATION to have curl automatically follow http redirects.
I'm trying to display the latest tweets of a Twitter account on my website, and I'm trying to fetch the data using cURL and PHP. When I use the OAuth tool (signature generator) on the Twitter Developers website. There is a cURL command that is generated and it runs just fine on my terminal. However, when I try to use cURL with the same parameters in my PHP code, I get the following error :
{
"errors": [
{
"code": 215,
"message": "Bad Authentication data."
}
]
}
Here is the cURL command :
curl --get 'https://api.twitter.com/1.1/statuses/user_timeline.json' --data 'count=2&screen_name=[my user name]' --header 'Authorization: OAuth oauth_consumer_key="[my key]", oauth_nonce="[my key]", oauth_signature="[the signature]", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1439736924", oauth_version="1.0"' --verbose
And here is my PHP code :
$ch = curl_init("https://api.twitter.com/1.1/statuses/user_timeline.json?count=2&screen_name=XXXXX");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Authorization' => 'OAuth',
'oauth_consumer_key' => '[my key]',
'oauth_nonce' => '[my key]',
'oauth_signature' => '[the signature]',
'oauth_signature_method' => 'HMAC-SHA1',
'oauth_timestamp' => '1439736924',
'oauth_version' => '1.0')
);
curl_setopt($ch, CURLOPT_POSTFIELDS, array(
'count' => 2,
'screen_name' => '[my username]')
);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
echo curl_exec($ch);
The values are exactly the same and I don't understand why it works with the curl command but not in the PHP code. Here are the two logs :
cURL command (works fine):
* Connected to api.twitter.com (199.16.156.199) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs/
* TLSv1.2, TLS handshake, Client hello (1):
* TLSv1.2, TLS handshake, Server hello (2):
* TLSv1.2, TLS handshake, CERT (11):
* TLSv1.2, TLS handshake, Server key exchange (12):
* TLSv1.2, TLS handshake, Server finished (14):
* TLSv1.2, TLS handshake, Client key exchange (16):
* TLSv1.2, TLS change cipher, Client hello (1):
* TLSv1.2, TLS handshake, Finished (20):
* TLSv1.2, TLS change cipher, Client hello (1):
* TLSv1.2, TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* Server certificate:
* subject: C=US; ST=California; L=San Francisco; O=Twitter, Inc.; OU=Twitter Security; CN=api.twitter.com
* start date: 2014-08-03 00:00:00 GMT
* expire date: 2016-12-31 23:59:59 GMT
* subjectAltName: api.twitter.com matched
* issuer: C=US; O=VeriSign, Inc.; OU=VeriSign Trust Network; OU=Terms of use at https://www.verisign.com/rpa (c)10; CN=VeriSign Class 3 Secure Server CA - G3
* SSL certificate verify ok.
> GET /1.1/statuses/user_timeline.json?count=2&screen_name=XXX HTTP/1.1
> User-Agent: curl/7.38.0
> Host: api.twitter.com
> Accept: */*
> Authorization: OAuth oauth_consumer_key="BBBBBB", oauth_nonce="CCCCCCCC", oauth_signature="DDDDDDDD", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1439736924", oauth_version="1.0"
>
< HTTP/1.1 200 OK
< cache-control: no-cache, no-store, must-revalidate, pre-check=0, post-check=0
< content-disposition: attachment; filename=json.json
< content-length: 7512
< content-type: application/json;charset=utf-8
< date: Sun, 16 Aug 2015 16:09:46 GMT
< expires: Tue, 31 Mar 1981 05:00:00 GMT
< last-modified: Sun, 16 Aug 2015 16:09:46 GMT
< pragma: no-cache
< server: tsa_b
< set-cookie: guest_id=v1%3A143974138658672554; Domain=.twitter.com; Path=/; Expires=Tue, 15-Aug-2017 16:09:46 UTC
< status: 200 OK
< strict-transport-security: max-age=631138519
< x-connection-hash: ae1b9fcc59bb90b767b246dfd06f6c94
< x-content-type-options: nosniff
< x-frame-options: SAMEORIGIN
< x-rate-limit-limit: 300
< x-rate-limit-remaining: 298
< x-rate-limit-reset: 1439741812
< x-response-time: 23
< x-transaction: 8515dfd151751885
< x-twitter-response-tags: BouncerCompliant
< x-xss-protection: 1; mode=block
<
PHP log (returns the error message):
* Hostname in DNS cache was stale, zapped
* Trying 199.16.156.199...
* Connected to api.twitter.com (199.16.156.199) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs/
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* Server certificate:
* subject: C=US; ST=California; L=San Francisco; O=Twitter, Inc.; OU=Twitter Security; CN=api.twitter.com
* start date: 2014-08-03 00:00:00 GMT
* expire date: 2016-12-31 23:59:59 GMT
* subjectAltName: api.twitter.com matched
* issuer: C=US; O=VeriSign, Inc.; OU=VeriSign Trust Network; OU=Terms of use at https://www.verisign.com/rpa (c)10; CN=VeriSign Class 3 Secure Server CA - G3
* SSL certificate verify ok.
> GET /1.1/statuses/user_timeline.json?count=2&screen_name=XXXX HTTP/1.1
Host: api.twitter.com
Accept: */*
Authorization: OAuth
oauth_consumer_key: BBBBBB
oauth_nonce: CCCCCCC
oauth_signature: DDDDDDD
oauth_signature_method: HMAC-SHA1
oauth_timestamp: 1439740787
oauth_version: 1.0
< HTTP/1.1 400 Bad Request
< content-length: 62
< content-type: application/json; charset=utf-8
< date: Sun, 16 Aug 2015 16:26:50 GMT
< server: tsa_b
< set-cookie: guest_id=v1%3A143974241022741403; Domain=.twitter.com; Path=/; Expires=Tue, 15-Aug-2017 16:26:50 UTC
< strict-transport-security: max-age=631138519
< x-connection-hash: abbabb47dc8a7d355f595f389f868de2
< x-response-time: 4
<
* Connection #0 to host api.twitter.com left intact
Any help would be appreciated. If possible, I really would like to use cURL instead of a third party library.
Thanks
EDIT : Michael's solution didn't work, but here is the updated PHP output :
Authorization: OAuth oauth_consumer_key="...", oauth_nonce="...", oauth_signature="...", oauth_signature_method="HMAC-SHA1" oauth_timestamp= "1439744503", oauth_version= "1.0"
The chief difference between these is that in the CLI curl command, the Authorization header is specified as a single string with multiple key=value pairs separated by commas. But in your PHP code you have specified those key=value pairs as multiple individual headers. You just need to add a single Authorization header with all of those values concatenated into one string.
The CLI request's header output:
Authorization: OAuth oauth_consumer_key="BBBBBB", oauth_nonce="CCCCCCCC", oauth_signature="DDDDDDDD", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1439736924", oauth_version="1.0"
The PHP request's header output differs:
Authorization: OAuth
oauth_consumer_key: BBBBBB
oauth_nonce: CCCCCCC
oauth_signature: DDDDDDD
oauth_signature_method: HMAC-SHA1
oauth_timestamp: 1439740787
oauth_version: 1.0
So the correct PHP to produce a comparable single-header string would be:
curl_setopt($ch, CURLOPT_HEADER, 0);
// All OAuth values in a single Authorization header string.
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Authorization' => 'OAuth oauth_consumer_key="[my key]", oauth_nonce="[my key]", oauth_signature="[the signature]", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1439736924", oauth_version="1.0"'
)
);
// etc... Everything else should be fine as you have it
I'm using the single file PHP library. I've got the store connecting, but I am getting no data back. Here is my script:
<?php
error_reporting(E_ALL);
ini_set('display_errors', True);
require 'bigcommerce.php';
use Bigcommerce\Api\Client as Bigcommerce;
$settings = array('store_url' => 'https://STORE_URL_REDACTED.mybigcommerce.com','username' => 'USERNAME_REDACTED', 'api_key' => 'API_KEY_REDACTED');
if(
(array_key_exists('store_url', (array)$settings)) &&
(array_key_exists('username', $settings)) &&
(array_key_exists('api_key', $settings))
) {
// Config Basic
Bigcommerce::configure(
array(
'store_url' => $settings['store_url'],
'username' => $settings['username'],
'api_key' => $settings['api_key']
)
);
Bigcommerce::setCipher('RC4-SHA');
Bigcommerce::verifyPeer(false);
}
$products = Bigcommerce::getProducts();
$orders = Bigcommerce::getOrders();
foreach($products as $product) {
echo $product->name;
echo $product->price;
}
?>
I've got output writing on the curl commands in bigcommerce.php, and I can see that I am actually connecting to the store:
About to connect() to STORE_ID_REDACTED.mybigcommerce.com port 443 (#0) * Trying REDACTED... * connected * Connected to STORE_ID_REDACTED.mybigcommerce.com (REDACTED) port 443 (#0) * successfully set certificate verify locations: * CAfile: cacert.pem CApath: /etc/ssl/certs * SSL connection using RC4-SHA * Server certificate: * subject: C=US; postalCode=49519; ST=Michigan; L=Wyoming; street=3343 Perry Ave SW; O=REDACTED; OU=InstantSSL; CN=REDACTED * start date: 2011-08-22 00:00:00 GMT * expire date: 2016-08-21 23:59:59 GMT * issuer: C=GB; ST=Greater Manchester; L=Salford; O=COMODO CA Limited; CN=COMODO High-Assurance Secure Server CA * SSL certificate verify ok. * Server auth using Basic with user 'USERNAME_REDACTED' > GET /api/v2/products HTTP/1.1 Authorization: Basic REDACTED Host: store-STORE_ID_REDACTED.mybigcommerce.com Accept: application/json < HTTP/1.1 200 OK < Date: Tue, 03 Dec 2013 16:32:57 GMT < Server: Apache < Last-Modified: Tue, 03 Dec 2013 06:25:44 +0000 < X-BC-ApiLimit-Remaining: 17167 < X-BC-Store-Version: 7.6.0 < X-Powered-By: PleskLin < Transfer-Encoding: chunked < Content-Type: application/json < * Connection #0 to host STORE_ID_REDACTED.mybigcommerce.com left intact * Re-using existing connection! (#0) with host STORE_ID_REDACTED.mybigcommerce.com * Connected to STORE_ID_REDACTED.mybigcommerce.com (REDACTED) port 443 (#0) * Server auth using Basic with user 'USERNAME_REDACTED' > GET /api/v2/orders HTTP/1.1 Authorization: Basic REDACTED Host: REDACTED Accept: application/json < HTTP/1.1 200 OK < Date: Tue, 03 Dec 2013 16:32:58 GMT < Server: Apache < Last-Modified: Thu, 18 Nov 2010 17:40:55 +0000 < X-BC-ApiLimit-Remaining: 17162 < X-BC-Store-Version: 7.6.0 < X-Powered-By: PleskLin < Transfer-Encoding: chunked < Content-Type: application/json < * Connection #0 to host STORE_ID_REDACTED.mybigcommerce.com left intact * Closing connection #0
I get the following error:
Warning: Invalid argument supplied for foreach() in /home/zetaphor/public_html/bigcommerce-api-php-master/coupons.php
My returned arrays contain no data.
I am running a LAMP stack using PHP 5.3.3, cURL enabled
I was facing that problem in php class, so i have done this using CURL,
You can get your stores products, orders and coupon.
here is the code.
$username = 'your username';
$password = 'your key';
$url = ' your store url';
$product_url = $url.'/api/v2/products.json';
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $product_url);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_USERPWD, $username . ":" . $password);
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($curl, CURLOPT_ENCODING, "");
$curlData = curl_exec($curl);
curl_close($curl);
//returning retrieved feed
$product_rec = json_decode($curlData);
echo '<pre>';
print_r($product_rec);
now for orders use
$order_url = $url.'/api/v2/orders.json';
There is normally another line below the setCipher line to "verify peer". Try adding that in so that it would look like:
Bigcommerce::setCipher('RC4-SHA');
Bigcommerce::verifyPeer(false);
Edit: to be clear, I think this is a key piece for the server to check that your certificate is valid.