/gist:2396722 Secret
package com.mtgox.api; | |
import java.net.HttpURLConnection; | |
import java.net.URL; | |
import java.net.URLEncoder; | |
import java.util.HashMap; | |
import javax.crypto.Mac; | |
import javax.crypto.spec.SecretKeySpec; | |
import sun.misc.BASE64Decoder; | |
import sun.misc.BASE64Encoder; | |
public class Client { | |
protected final int BUFFER_SIZE = 8192; | |
protected String key; | |
protected String secret; | |
public Client(String key, String secret) { | |
this.key = key; | |
this.secret = secret; | |
} | |
public String query(String path, HashMap<String, String> args) throws Exception { | |
// small sanity check | |
if (args == null) { | |
args = new HashMap<>(); | |
} | |
// build URL, actually we may want to fallback to mtgox.com directly for | |
// private calls, but that should be fine for now | |
URL queryUrl = new URL("https://data.mtgox.com/api/" + path); | |
// create connection | |
HttpURLConnection connection = (HttpURLConnection)queryUrl.openConnection(); | |
// set user agent | |
connection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; Java Test client)"); | |
if (this.secret != null && this.key != null) { | |
// add nonce and build arg list, nonce is now converted to nanoseconds | |
// as some implementations uses that, allowing you to use the same value | |
// across languages. If you use any other library to call the API, make | |
// sure that you are using the same kind of nonce, or you will encounter | |
// issues | |
args.put("nonce", String.valueOf(System.currentTimeMillis() * 1000000)); | |
String sign_data = this.buildQueryString(args); | |
// api v2 now adds the path followed by a 0 byte in the signature | |
if (path.startsWith("2/")) { | |
sign_data = path.substring(2) + "\0" + sign_data; | |
} | |
// args signature | |
Mac mac = Mac.getInstance("HmacSHA512"); | |
SecretKeySpec secret_spec = new SecretKeySpec((new BASE64Decoder()).decodeBuffer(this.secret), "HmacSHA512"); | |
mac.init(secret_spec); | |
String signature = (new BASE64Encoder()).encode(mac.doFinal(sign_data.getBytes())); | |
// add signature headers | |
connection.setRequestProperty("Rest-Key", this.key); | |
connection.setRequestProperty("Rest-Sign", signature.replaceAll("\n", "")); | |
} | |
// write post | |
if (!args.isEmpty()) { | |
connection.setDoOutput(true); | |
connection.getOutputStream().write(this.buildQueryString(args).getBytes()); | |
} | |
// read info | |
String result = new String(); | |
byte buffer[] = new byte[this.BUFFER_SIZE]; | |
int len = 0; | |
// read until eof, no need to increment buffer size too much as the answer will | |
// most likely arrive in smaller chunks | |
while ((len = connection.getInputStream().read(buffer, 0, this.BUFFER_SIZE)) > 0) { | |
result += new String(buffer, 0, len, "UTF-8"); | |
} | |
return result; | |
} | |
protected String buildQueryString(HashMap<String, String> args) throws Exception { | |
String result = new String(); | |
for (String hashkey : args.keySet()) { | |
if (result.length() > 0) result += '&'; | |
result += URLEncoder.encode(hashkey, "UTF-8") + "=" | |
+ URLEncoder.encode(args.get(hashkey), "UTF-8"); | |
} | |
return result; | |
} | |
} |
The URL has changed, you need to change the base URL on line 55 to "https://data.mtgox.com/api/", and the example query URL on line 33 to "1/generic/merchant/order/create".
if you plan using the v2 of the api you can take a look here -> https://github.com/adv0r/mtgox-api-v2-java
Hopefully this new version should work better.
Changes are fairly simple:
- Key and secret can be left null when creating the Client for calling public APIs
- Support for API v2
- Support for data.mtgox.com
- Exceptions are now bubbled all the way to the top and are the user's responsability
Hi,
guys I am trying to run the new version mtgox-api-v2-java (UsageExample.java) , but again I am getting the following error:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
jun 06, 2013 8:32:33 PM com.mtgox.api.MtGox getBalance
SEVERE: null
Unexpected token END OF FILE at position 0.
at org.json.simple.parser.JSONParser.parse(JSONParser.java:257)
at org.json.simple.parser.JSONParser.parse(JSONParser.java:81)
at org.json.simple.parser.JSONParser.parse(JSONParser.java:75)
at com.mtgox.api.MtGox.getBalance(MtGox.java:254)
at com.mtgox.examples.UsageExample.main(UsageExample.java:43)
After investigating on the issue, I found out that I may need to download the certificate. So I downloaded and ran the InstallCert java program. But then I didnt know exactly what URL and port to use as argument so I just used the mtgox.com. However I bump into the same exception.
Anybody could help me out please??
does this API allow posting orders?
Hey , I tried your example but I am getting the following exception:
6-apr-2013 3:12:09 com.mtgox.api.Client query
SEVERE: null
java.io.IOException: Server returned HTTP response code: 400 for URL: https://mtgox.com/api/1/generic/private/merchant/order/create
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source)
at com.mtgox.api.Client.query(Client.java:61)
at com.mtgox.api.Client.main(Client.java:30)
I have double checked that my key and secret are the correct ones. Could please verify that the code is the correct one?