4

I've successfully used the example here https://gist.github.com/tonefolder/44191a29454f9059c7e6 to authenticate a user and to store the oauth_token and oauth_token_secret. I can then make authenticated GET requests using cURL.

I don't know how to make authenticated POST requests though.

I have tried using the $result['header'] from the signed oauthObject in this way:

$discogs_username = "'XXXX'";

$result = mysql_query("SELECT * FROM discogs WHERE username = $discogs_username;", $link);
if (mysql_num_rows($result)) {
    $discogs_details = mysql_fetch_array($result, MYSQL_ASSOC);
}


$signatures = array(
    'consumer_key'     => 'MyKey',
    'shared_secret'    => 'MySecret',
  'oauth_token'    => $discogs_details['oauth_token'],
  'oauth_token_secret'    => $discogs_details['oauth_token_secret']
);


$jsonquery = json_encode(array(
        'release_id' => '7608939',
        'price' => '18.00',
        'condition' => 'Mint',
        'sleeve_condition' => 'Mint',
        'status' => 'For Sale'
    )
);


$result = $oauthObject->sign(array(
        'path'      => $scope.'/marketplace/listings',
        'signatures'=> $signatures
    )
);


$ch = curl_init();
curl_setopt($ch, CURLOPT_USERAGENT, 'MyDiscogsClient/0.1 +http://me.com');
curl_setopt($ch, CURLOPT_URL, $result['signed_url']);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json','Authorization:' . $result['header'])); 
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonquery);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$output = json_decode(curl_exec($ch), true);
curl_close($ch);

But I get '[message] => You must authenticate to access this resource.'

I'm not sure if i'm doing the CURLOPT_POSTFIELDS part correctly, but I can figure that out once i'm actually able to send an authenticated POST! Sorry if there is also loads more wrong with this - I don't use cURL that often!

Ashley
  • 251
  • 5
  • 19
  • I've asked this question on the Discogs API forum too [link](http://www.discogs.com/forum/thread/703535) but nobody has responded. Am I asking for something really obscure here? – Ashley Jan 25 '16 at 09:36
  • I see that discogs has well api documentation here: http://www.discogs.com/developers and there under quick start: http://www.discogs.com/developers/#page:home,header:home-quickstart, is present PHP Client API library: https://github.com/ricbra/php-discogs-api , you can try to use it for communicating with them instead creating costume methods – Armen Jan 25 '16 at 11:59
  • Thanks but that client only appears to support GET requests rather than POST requests – Ashley Jan 25 '16 at 15:05
  • You have posted only a part of your code or this is the full code you are using? – Pradeep Sambandam Jan 26 '16 at 20:47
  • There's not that much extra missing, just creating the signatures array, i'll edit it. – Ashley Jan 27 '16 at 08:24
  • Are you sure the Authentication header is set correctly? It should be like `Authorization: Discogs token=abcxyz123456`, you can construct it manually with the authentication token to see if that works. – Niki van Stein Jan 27 '16 at 12:53
  • $result['header'] contains this: `OAuth oauth_nonce="TXf7B", oauth_timestamp="1453899705", oauth_consumer_key="xxx", oauth_token="xxx", oauth_signature_method="HMAC-SHA1", oauth_version="1.0", oauth_signature="xxx"` – Ashley Jan 27 '16 at 13:04

1 Answers1

2

Background

After reproducing all your steps and fiddling around a bit, I found the following. As a side node, I presumed that the $scope variable just contains the API url, namely https://api.discogs.com.

As it turns out, signing the OAuth request does also need to know the proper request method you are going to use. You can find that by var_dump()ing the $result you are getting from the sign() call:

array(5) {
/// ... snip ...
    'sbs' =>
  string(269) "GET&https%3A%2F%2Fapi.discogs.com%2Fmarketplace%2Flistings&oauth_consumer_key%XXXXX%26oauth_nonce%3DMOtWK%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1453937109%26oauth_token%XXXXX%26oauth_version%3D1.0"
}

So I digged a bit into the code of the "OAuthSimple" library that you are using, and it turns out you can just pass the method under an index called "action".

Solution

Based on the findings, you will have to change this:

$result = $oauthObject->sign(
    array(
        'path' => $scope . '/marketplace/listings',
        'signatures' => $signatures,
    )
);

to this:

$result = $oauthObject->sign(
    array(
        'path' => $scope . '/marketplace/listings',
        'signatures' => $signatures,
        'action' => 'POST',
    )
);

Side notes

I actually tried that solution and was able to create a listing through the API. The only other change I had to make is the condition and sleeve_condition values Mint are not allowed by their API so you actually have to use Mint (M).

Also, I got an error at first that said I have to complete my "seller settings". So you might want to catch that case in your application.

Further thoughts

As you mentioned in the comments to your original post, you presume that the suggested library just allows GET requests also. However, as you can see here, it just returns a Guzzle Client, so firing POST requests via this should not be a problem at all, and actually using this would probably save you a lot of pain. I did however not try that, so, just as thought.

Hope that helps :)

ArSeN
  • 5,133
  • 3
  • 19
  • 26