Authenticated Java Jersey REST call to Bitstamp

2019-04-01 22:01发布

问题:

I am trying to make a private REST call to Bitstamp (see https://www.bitstamp.net/api/).

However, I am getting the following resonse:

{"error":"Missing key, signature and nonce parameters"}

In the API specification they write the following:

All private API calls require authentication. You need to provide 3 parameters to authenticate a request:

  • API key
  • Nonce
  • Signature

API KEY

To get an API key, go to "Account", "Security" and then "API Access". Set permissions and click "Generate key".

NONCE

Nonce is a regular integer number. It must be increasing with every request you make. Read more about it here. Example: if you set nonce to 1 in your first request, you must set it to at least 2 in your second request. You are not required to start with 1. A common practice is to use unix time for that parameter.

SIGNATURE

Signature is a HMAC-SHA256 encoded message containing: nonce, client ID and API key. The HMAC-SHA256 code must be generated using a secret key that was generated with your API key. This code must be converted to it's hexadecimal representation (64 uppercase characters).

I have been trying to solve this for some time and everything seems to be in order: the creation of the signature using encryption and convertion to HEX, API access being activated on the server, API keys being in order etc. When contacting Bitstamp they tell me that the API is working properly and that the error I receive usually happens when my key, signature and parameters aren't reaching their API. After being stuck with this for some time now I have no clues left on how to solve this. Please help.

My code is as follows

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import org.codehaus.jettison.json.JSONObject;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.ws.rs.core.MediaType;
import javax.xml.bind.DatatypeConverter;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException


public class Connection {

private static WebResource baseResource;

private static final MediaType responseType = MediaType.APPLICATION_JSON_TYPE;


public Connection() throws NoSuchAlgorithmException {

    Client client = Client.create();
    baseResource = client.resource("https://www.bitstamp.net/api/");

}


public void test() throws NoSuchAlgorithmException, InvalidKeyException {

    String nonce_unixTime = String.valueOf(System.currentTimeMillis() / 1000L);
    String clientID = "xxx";
    String key = "yyy";
    String secret = "zzz";
    String message = nonce_unixTime + clientID + key;

    Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
    SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
    sha256_HMAC.init(secret_key);
    byte[] hash = sha256_HMAC.doFinal(message.getBytes());
    String signature = DatatypeConverter.printHexBinary(hash).toUpperCase();

    // Fetch the resource.
    JSONObject json = baseResource.path("balance/")
            .queryParam("key", key)
            .queryParam("signature", signature)
            .queryParam("nonce", nonce_unixTime)
            .accept(responseType).post(JSONObject.class);

    System.out.println(json.toString());
}
}

回答1:

It's because bitstamp waiting for params in POST's body instead of params in url, so the type of POST-message must be MediaType.APPLICATION_FORM_URLENCODED instead of JSONObject.class.

See How are parameters sent in an HTTP POST request?

How to do it in Jersey: Using the Jersey client to do a POST operation