advanced
|
|
April 15, 2013, 03:52:03 PM |
|
Thanks, as always! I've found out about that method by reading through the pdfs @ https://github.com/MtGox/mtgox-doc/tree/master/api , it seems quite useful. BTCUSD/money/info isn't technically the method, the actual method is money/info, but it can be accessed with a currency context as well. money/info gives your account details, including all the currency wallets you have, so if you have an EUR wallet, it will show up, as well as your BTC wallet, and any other currencies Are you sure? I tried removing the BTCUSD from the ticker ending with (money/ticker) and I get a http 500. Do you know what the response is that comes with the 403 error? Your function should still generate and return the answer, right? Actually I'm afraid that I can't get the answer as the instruction to read the http inputstream throws the IOException... I'll try to go back to the buffer example to be able to read the answer from there
|
Bitmessage : BM-NAx31aEiqeq5zKUtxhKscXQ7Dwn1jJfR
|
|
|
nitrous (OP)
|
|
April 15, 2013, 03:57:46 PM |
|
I also recommend making sure you join your arguments to your nonce properly using the following, and updating it wherever necessay: my $post_data = $nonce . ($args == '' ? '' : '&' . $args); my $hash_data = $method . chr(0) . $post_data; I think it's ok as it is - the ? doesn't seem to be required in post data and I'm supplying the args in full: print Dumper __request('BTCUSD/money/order/add', "&type=$type&amount_int=$amount"); I've created and cancelled orders with it anyway so seems fine. Oh sorry, yeah if you pass it with a leading ampersand it's most definitely fine, yeah that works great then 403 probably means failed authentication - I don't think the post data should contain the method should it? (as shown above)
mine works with just nonce + any other arguments.
The API can return 403 for quite a few different reasons (wrong API key, bad nonce, etc), but it usually hints in the JSON the specific reason for the error. post_data_mac is the equivalent of your $hash_data
|
|
|
|
nitrous (OP)
|
|
April 15, 2013, 04:03:49 PM |
|
Thanks, as always! I've found out about that method by reading through the pdfs @ https://github.com/MtGox/mtgox-doc/tree/master/api , it seems quite useful. BTCUSD/money/info isn't technically the method, the actual method is money/info, but it can be accessed with a currency context as well. money/info gives your account details, including all the currency wallets you have, so if you have an EUR wallet, it will show up, as well as your BTC wallet, and any other currencies Are you sure? I tried removing the BTCUSD from the ticker ending with (money/ticker) and I get a http 500. Do you know what the response is that comes with the 403 error? Your function should still generate and return the answer, right? Actually I'm afraid that I can't get the answer as the instruction to read the http inputstream throws the IOException... I'll try to go back to the buffer example to be able to read the answer from there With money/ticker, a currency context is required as it returns information specific to a given currency, but money/info does not require a context as it is independent of the currency - it just returns an informative overview of your entire account (all wallets inclusive), so you can call BTCUSD/money/info if you want, but it's really just redirecting to money/info. Could you catch the exception or is the response data completely blocked from you? The JSON response should contain an error key pointing to the problem, although it can be somewhat cryptic.
|
|
|
|
advanced
|
|
April 15, 2013, 04:24:06 PM |
|
All right, I'll try to get that JSON right away. In the meantime another question: is it correct that the HTTP requests are GETs, right?
|
Bitmessage : BM-NAx31aEiqeq5zKUtxhKscXQ7Dwn1jJfR
|
|
|
nitrous (OP)
|
|
April 15, 2013, 04:27:51 PM |
|
All right, I'll try to get that JSON right away. In the meantime another question: is it correct that the HTTP requests are GETs, right?
I should have spotted that! No, it's POST. I'm surprised you managed to get money/ticker working without POST but yes, you need to send the post_data by POST during the connection.
|
|
|
|
advanced
|
|
April 15, 2013, 04:42:00 PM |
|
ah, really? :\ Writing this client is driving me nuts. This is the behaviour at the moment : Doing nothing or specifing the request method with this line : connection.setRequestMethod("GET"); allows me to read the ticker and gives me the 403 on my info. Using post, on the other hand, stars giving me a HTTP 500 on the ticker! (and still 403 on the info) connection.setRequestMethod("POST"); /code] This is everything I was able to get so far... unfortunately not any JSON. Failed : HTTP error code : 403 - Server returned HTTP response code: 403 for URL: https://data.mtgox.com/api/2/money/info Forbidden("java.net.SocketPermission" "data.mtgox.com:80" "connect,resolve") Apr 15, 2013 6:39:36 PM io.botcoin.api.MtGox query
|
Bitmessage : BM-NAx31aEiqeq5zKUtxhKscXQ7Dwn1jJfR
|
|
|
MikeH
|
|
April 15, 2013, 05:06:30 PM |
|
if only the world would settle on 1 language.
|
|
|
|
bittencoin
Member
Offline
Activity: 83
Merit: 10
|
|
April 15, 2013, 05:30:52 PM Last edit: April 15, 2013, 05:56:36 PM by bittencoin |
|
Hi Nitrous, I tried to read and follow your guide to try to pull up some data, but I am getting errors in the response when I just try to get the ticker info. array(3) { ["result"]=> string(5) "error" ["error"]=> string(20) "Chosen API not found" ["token"]=> string(13) "unknown_error" } Basically, all I did was taking the example php template and put in my api key and secret (not shown here), and changed the base URL to https://data.mtgox.com/api/2/ and changed the path to but the var dump says Chosen API not found. I tested with many new api key/secret codes, but that appears not to be the source of the problem. Any insight is appreciated. Thank you. Hi bittencoin, You are correct that the API code and secret are not the problem, the problem is with this part of your code: $prefix = ''; if (substr($path, 0, 2) == '2/') { $prefix = substr($path, 2)."\0"; } // generate the extra headers $headers = array( 'Rest-Key: '.$key, 'Rest-Sign: '.base64_encode(hash_hmac('sha512', $prefix.$post_data, base64_decode($secret), true)), ); Your prefix is empty in a normal scenario, instead, you should change this code to the following: $prefix = $path; if (substr($path, 0, 2) == '2/') { $prefix = substr($path, 2); } // generate the extra headers $headers = array( 'Rest-Key: '.$key, 'Rest-Sign: '.base64_encode(hash_hmac('sha512', $prefix."\0".$post_data, base64_decode($secret), true)), );
I have made sure your prefix variable contains the path, and I've moved the null character into the rest-sign to make sure it's always included. This code worked for me after doing those fixes Thank you Nitrous. I will test it out and report back. But by looking at the original template code from mtgox, I can see why it does not work now. This block of code is suppose to check if the "path" is api version 2 $prefix = ''; if (substr($path, 0, 2) == '2/') { $prefix = substr($path, 2)."\0"; } the check is supposed to look for the "2/" at end of the string, but in this case the $path variable is "BTCUSD/money/ticker" and does not contain the "2/". If I am correct, the original code tried to look for the "2/" in the wrong string, it should be looking for the version in the base url https://data.mtgox.com/api/2/ using the code substr($path, -2, 2) == '2/' . So if that is fixed, then you don't need to hard code the null character into the REST sign. UPDATE: Here is my fix of that block of code $prefix = ''; $baseurl = 'https://data.mtgox.com/api/2/'; if (substr($baseurl, -2, 2) == '2/') { $prefix = $path."\0"; }
|
|
|
|
nitrous (OP)
|
|
April 15, 2013, 06:22:56 PM |
|
Thank you Nitrous. I will test it out and report back. But by looking at the original template code from mtgox, I can see why it does not work now. This block of code is suppose to check if the "path" is api version 2 $prefix = ''; if (substr($path, 0, 2) == '2/') { $prefix = substr($path, 2)."\0"; } the check is supposed to look for the "2/" at end of the string, but in this case the $path variable is "BTCUSD/money/ticker" and does not contain the "2/". If I am correct, the original code tried to look for the "2/" in the wrong string, it should be looking for the version in the base url https://data.mtgox.com/api/2/ using the code substr($path, -2, 2) == '2/' . So if that is fixed, then you don't need to hard code the null character into the REST sign. UPDATE: Here is my fix of that block of code $prefix = ''; $baseurl = 'https://data.mtgox.com/api/2/'; if (substr($baseurl, -2, 2) == '2/') { $prefix = $path."\0"; } Ok, let me know how it goes, your code is very close to working, the error you received was simply not signing the request properly, which the above should fix
|
|
|
|
nitrous (OP)
|
|
April 15, 2013, 06:31:52 PM |
|
ah, really? :\ Writing this client is driving me nuts. This is the behaviour at the moment : Doing nothing or specifing the request method with this line : connection.setRequestMethod("GET"); allows me to read the ticker and gives me the 403 on my info. Using post, on the other hand, stars giving me a HTTP 500 on the ticker! (and still 403 on the info) connection.setRequestMethod("POST"); /code] This is everything I was able to get so far... unfortunately not any JSON. Failed : HTTP error code : 403 - Server returned HTTP response code: 403 for URL: https://data.mtgox.com/api/2/money/info Forbidden("java.net.SocketPermission" "data.mtgox.com:80" "connect,resolve") Apr 15, 2013 6:39:36 PM io.botcoin.api.MtGox query Your code is so close to working, which makes it that much more frustrating. It must be some small, easy to miss, error. Anyway, I quickly wrote this using my own basic API as a reference: http://pastebin.com/SmrxuJQjI was able to get it to work, so if you compare each line hopefully you'll finally find whatever's causing the problem Also, I found a way to get the JSON even with the IOException: declare the query function as throwing java.io.Exception, then you can check the response code of the connection - if it is >= 400, use getErrorStream instead of getInputStream, hopefully this will help you debug. Note: I added "000" to the nonce because my api uses miroseconds, and otherwise I would be rejected by the server, feel free to remove them as your nonces are milliseconds.
|
|
|
|
MikeH
|
|
April 15, 2013, 06:47:53 PM |
|
not sure if it's an issue with v2 but others have had probs with their nonce not being long enough, something to keep in mind - but remember if you fiddle with it, you can't make it shorter again don't know the requirement but mine's working at 16 chars.
|
|
|
|
nitrous (OP)
|
|
April 15, 2013, 07:13:13 PM |
|
not sure if it's an issue with v2 but others have had probs with their nonce not being long enough, something to keep in mind - but remember if you fiddle with it, you can't make it shorter again don't know the requirement but mine's working at 16 chars. Yeah I noticed that recently, but testing today with a separate API key I found 13 also seems to work, so millisecond time should also be ok. I'll put it on my todo list to find the minimum length at some point
|
|
|
|
advanced
|
|
April 16, 2013, 09:58:28 AM |
|
Thanks! My today's resolution is : don't go to sleep unless it works. So, lets try to capture exceptions and errors: if (connection.getResponseCode() != 200) { BufferedReader errBr = new BufferedReader(new InputStreamReader((connection.getErrorStream()))); System.err.println("Failed : HTTP error code : " + connection.getResponseCode() + " \n Response message:" + connection.getResponseMessage() + " \n Permission :" + connection.getPermission()); String output; System.out.println("Error Stream: : \n"); //TODO Remove while ((output = errBr.readLine()) != null) { System.err.println(output);
} } And here we go baby : Failed : HTTP error code : 403 Response message:Forbidden Permission :("java.net.SocketPermission" "data.mtgox.com:80" "connect,resolve") Error Stream: {"result":"error","error":"Identification required to access private API","token":"login_error_missing_nonce"} missing nonce?
|
Bitmessage : BM-NAx31aEiqeq5zKUtxhKscXQ7Dwn1jJfR
|
|
|
advanced
|
|
April 16, 2013, 10:09:34 AM |
|
update : the call to the ticker works only via GET
|
Bitmessage : BM-NAx31aEiqeq5zKUtxhKscXQ7Dwn1jJfR
|
|
|
MikeH
|
|
April 16, 2013, 10:14:00 AM |
|
works via POST for me - should paste the rest of the code in question.
|
|
|
|
advanced
|
|
April 16, 2013, 10:23:32 AM Last edit: April 16, 2013, 10:36:35 AM by advanced |
|
Spotted new difference between your code HttpsURLConnection c = (HttpsURLConnection)query.openConnection(); and my code HttpURLConnection connection = (HttpURLConnection)query.openConnection(); still missing_nonce_error. Plus, I don't understand howcome it works for you without specifying the keystore file .... :\ To make your code work I had to add the keystore to it! (And yes, it works with the same api keys I'm try to use)
|
Bitmessage : BM-NAx31aEiqeq5zKUtxhKscXQ7Dwn1jJfR
|
|
|
advanced
|
|
April 16, 2013, 10:25:14 AM |
|
works via POST for me - should paste the rest of the code in question.
I receive this error when "POSTing" it : {"result":"error","error":"Invalid request method for this API","token":"invalid_request_method"}
|
Bitmessage : BM-NAx31aEiqeq5zKUtxhKscXQ7Dwn1jJfR
|
|
|
MikeH
|
|
April 16, 2013, 10:50:53 AM |
|
I've only posted perl code.. is that what you ran? paste your java equivalent of the following: my $nonce = 'nonce=' . sprintf "%d", gettimeofday * 1e6; my $hash_data = $method . chr(0) . $nonce . $args; my $req = HTTP::Request->new(POST => ' https://data.mtgox.com/api/2/' . $method ); $req->content_type('application/x-www-form-urlencoded'); $req->content($nonce . $args); $req->header('Rest-Key' => $key); $req->header('Rest-Sign' => encode_base64( hmac_sha512( $hash_data, decode_base64($secret) ) )); my $result = $lwp->request($req);
|
|
|
|
advanced
|
|
April 16, 2013, 10:52:30 AM |
|
I've only posted perl code.. is that what you ran? paste your java equivalent of the following: my $nonce = 'nonce=' . sprintf "%d", gettimeofday * 1e6; my $hash_data = $method . chr(0) . $nonce . $args; my $req = HTTP::Request->new(POST => ' https://data.mtgox.com/api/2/' . $method ); $req->content_type('application/x-www-form-urlencoded'); $req->content($nonce . $args); $req->header('Rest-Key' => $key); $req->header('Rest-Sign' => encode_base64( hmac_sha512( $hash_data, decode_base64($secret) ) )); my $result = $lwp->request($req); Hi Mike, thanks for your support. However, if you go back in this conversation you can follow the track of the java discussion .
|
Bitmessage : BM-NAx31aEiqeq5zKUtxhKscXQ7Dwn1jJfR
|
|
|
advanced
|
|
April 16, 2013, 11:02:57 AM Last edit: April 16, 2013, 11:32:16 AM by advanced |
|
I ran your code, inspected it line by line, tried to go back to deprecated Base64 functions, but nothing. The only difference I was able to spot is the way you (don't) encode the post data arguments. I'm trying to use this function to add the arguments, which maybe does something weird to the request . I don't see how anyway : Here is how I call the query and add the argument : String urlPath = "money/info"; HashMap<String, String> query_args = new HashMap<>(); String queryResult = query(urlPath, query_args);
public String query(String path, HashMap<String, String> args) { .//here args should be empty . . args.put("nonce", nonce); //here the nonce is added to the args String hash_data = path + "\0" + this.buildQueryString(args); //here the nonce should be added to hash_data: indeed if I print I have money/info◙nonce=1366110562837 . . . }
And below is the function buildQueryString //Build the query string given a set of query parameters protected String buildQueryString(HashMap<String, String> args) { String result = new String(); for (String hashkey : args.keySet()) { if (result.length() > 0) result += '&'; try { result += URLEncoder.encode(hashkey, "UTF-8") + "=" + URLEncoder.encode(args.get(hashkey), "UTF-8"); } catch (Exception ex) { Logger.getLogger(MtGox.class.getName()).log(Level.SEVERE, null, ex); } } return result; } I wonder if is something related to the ◙ symbol, but I see it in your hash_data as well! EDIT: nope, I tried to build the string manually and I get the same damn 'missing nonce' error.
|
Bitmessage : BM-NAx31aEiqeq5zKUtxhKscXQ7Dwn1jJfR
|
|
|
|