package org.knowm.xchange.btcchina.service; import javax.crypto.Mac; import org.apache.commons.lang3.StringUtils; import org.knowm.xchange.btcchina.BTCChinaUtils; import org.knowm.xchange.btcchina.dto.BTCChinaRequest; import org.knowm.xchange.service.BaseParamsDigest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import si.mazi.rescu.BasicAuthCredentials; import si.mazi.rescu.RestInvocation; /** * @author David Yam */ public class BTCChinaDigest extends BaseParamsDigest { private final Logger log = LoggerFactory.getLogger(BTCChinaDigest.class); private final String exchangeAccessKey; /** * Constructor * * @param secretKeyBase64 * @throws IllegalArgumentException if key is invalid (cannot be base-64-decoded or the decoded key is invalid). */ private BTCChinaDigest(String exchangeAccessKey, String exchangeSecretKey) { super(exchangeSecretKey, HMAC_SHA_1); this.exchangeAccessKey = exchangeAccessKey; } public static BTCChinaDigest createInstance(String exchangeAccessKey, String exchangeSecretKey) { return exchangeSecretKey == null ? null : new BTCChinaDigest(exchangeAccessKey, exchangeSecretKey); } @Override public String digestParams(RestInvocation restInvocation) { String tonce = restInvocation.getHttpHeadersFromParams().get("Json-Rpc-Tonce"); BTCChinaRequest request = null; for (Object param : restInvocation.getUnannanotatedParams()) { if (param instanceof BTCChinaRequest) { request = (BTCChinaRequest) param; } } if (request == null) { throw new IllegalArgumentException("No BTCChinaRequest found."); } final long id = request.getId(); final String method = request.getMethod(); final String params = stripParams(request.getParams()); String signature = String.format("tonce=%s&accesskey=%s&requestmethod=%s&id=%d&method=%s¶ms=%s", tonce, exchangeAccessKey, "post", id, method, params); log.debug("signature message: {}", signature); Mac mac = getMac(); byte[] hash = mac.doFinal(signature.getBytes()); BasicAuthCredentials auth = new BasicAuthCredentials(exchangeAccessKey, BTCChinaUtils.bytesToHex(hash)); return auth.digestParams(restInvocation); } /** * Strip the {@code params} for signature message. * * @param params the value of {@link BTCChinaRequest#getParams()}. * @return the params string for signature message. * @see the note in <a href="http://btcchina.org/api-trade-documentation-en#faq">FAQ</a> 4.2(USING OPENONLY AS TRUE EXAMPLE) */ private String stripParams(String params) { final String[] original = params.substring(1, params.length() - 1).split(","); final String[] stripped = new String[original.length]; for (int i = 0; i < original.length; i++) { final String param = original[i]; if (param.startsWith("\"") && param.endsWith("\"")) { // string stripped[i] = param.substring(1, param.length() - 1); } else if (param.equals("true")) { // boolean: true stripped[i] = "1"; } else if (param.equals("false")) { // boolean: false stripped[i] = StringUtils.EMPTY; } else if (param.equals("null")) { stripped[i] = StringUtils.EMPTY; } else { // number, etc. stripped[i] = param; } } return StringUtils.join(stripped, ","); } }