如果有人用java设计安卓程序的就可以用到这个了
It was the Bitcointalk forum that inspired us to create Bitcointalksearch.org - Bitcointalk is an excellent site that should be the default page for anybody dealing in cryptocurrency, since it is a virtual gold-mine of data. However, our experience and user feedback led us create our site; Bitcointalk's search is slow, and difficult to get the results you need, because you need to log in first to find anything useful - furthermore, there are rate limiters for their search functionality.
The aim of our project is to create a faster website that yields more results and faster without having to create an account and eliminate the need to log in - your personal data, therefore, will never be in jeopardy since we are not asking for any of your data and you don't need to provide them to use our site with all of its capabilities.
We created this website with the sole purpose of users being able to search quickly and efficiently in the field of cryptocurrency so they will have access to the latest and most accurate information and thereby assisting the crypto-community at large.
/**
* JAVA RMBTB SECURE API CLASS
*
* 版权和限制
* (c)2013人盟比特币公布以下的代码遵循BSD条款。您可以按您的意愿使用或修改,用于个人或商业用途。
*
* 然而您不可以以 "RMBTB", "人盟比特币"来标识您的程序,也不可以有意或无意示意您的软件或服务是由人盟比特币提供的。
*
* 你可以使用默认的浮点型或者整数型的.
* 请仔细阅读下面的设置和安全建议
*
* 使用示例
* This class relies on the Apache commons codec and the json-simple modules.
*
* RmbtbSecureApi r = new RmbtbSecureApi("pubkey", "passphrase", "BTCCNY");
* Sytem.out.print(r.addOrder("bid", 1.1, 600.0));
*
* Full documentation is at https://www.rmbtb.com/help-secureapi-en/
*
*/
import java.util.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import javax.net.ssl.HttpsURLConnection;
import java.net.ProtocolException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
// http://commons.apache.org/proper/commons-codec/
import org.apache.commons.codec.binary.Base64;
// json-simple http://code.google.com/p/json-simple/
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
/**
* The RMBTB Secure API class. Set the constants here.
*/
interface RmbtbApi {
// Set this to the location you want to store temporary secrets
public static final String StorLocation = "rmbtb-secret-data.dat";
public static final String urlBaseLoc = "https://www.rmbtb.com/api/secure/";
/**
* Gets useful information about your account
* Authentication required.
* @return JSONObject account details
*/
public JSONObject getInfo() throws Exception;
/**
* Gets your wallet balances
* Authentication required.
* @return JSONObject account balances
*/
public JSONObject getFunds() throws Exception;
/**
* Gets your wallet balances
* Authentication required.
* @return JSONObject account balances
*/
public JSONObject ticker() throws Exception;
/**
* Gets useful market information
* @return JSONObject market info
*/
public JSONObject getOrders() throws Exception;
/**
* Adds an order -- double params
* @param String type bid | ask
* @param double amount the amount to buy/sell
* @param souble price the price to buy/sell at
* @return JSONObject containing the Order ID
*/
public JSONObject addOrder(String type, double amount, double price) throws Exception;
/**
* Adds an order -- long integer params
* @param String type bid | ask
* @param long amount the amount to buy/sell
* @param long price the price to buy/sell at
* @return JSONObject containing the Order ID
*/
public JSONObject addOrder(String type, long amount, long price) throws Exception;
/**
* Cancels an order
* @param long orderId the Order ID to cancel
* @return JSONObject containing the Order ID
*/
public JSONObject cancelOrder(long orderId) throws Exception;
/**
* fetches info about an order
* @param long orderId the Order ID to cancel
* @return JSONObject of info
*/
public JSONObject fetchOrder(long orderId) throws Exception;
/**
* Gets your 50 most recent trades
* @return JSONObject of info
*/
public JSONObject getTrades() throws Exception;
/**
* returns the most recent market transactions
* @return JSONObject of info
*/
public JSONObject lastTrades() throws Exception;
/**
* returns the market depth
* @return JSONObject showing bids and asks
*/
public JSONObject getDepth() throws Exception;
}
public class RmbtbSecureApi implements RmbtbApi {
private String currPair;
private String pubkey;
private String passphrase;
private String secret;
private Calendar expires;
public RmbtbSecureApi(String pubkey, String passphrase) {
this(pubkey, passphrase, "BTCCNY");
}
public RmbtbSecureApi(String pubkey, String passphrase, String currPair) {
this.currPair = currPair;
this.pubkey = pubkey;
this.passphrase = passphrase;
this.secret = "";
this.expires = Calendar.getInstance();
}
public JSONObject getInfo() throws Exception {
return doRequest("getinfo", "GET", true);
}
public JSONObject getFunds() throws Exception {
return doRequest("wallets", "GET", true);
}
public JSONObject ticker() throws Exception {
return doRequest("ticker", "GET", false);
}
public JSONObject getOrders() throws Exception {
return doRequest("orders", "GET", true);
}
public JSONObject addOrder(String type, double amount, double price) throws Exception {
HashMapparams = new HashMap ();
params.put("type", type == "ask" ? "ask" : "bid");
params.put("amount", new DecimalFormat("00000000.00000000").format(amount));
params.put("price", new DecimalFormat("00000000.00000000").format(price));
return doRequest("order/add", "POST", true, params);
}
public JSONObject addOrder(String type, long amount, long price) throws Exception {
HashMapparams = new HashMap ();
params.put("type", type == "ask" ? "ask" : "bid");
params.put("amount_int", String.valueOf(amount));
params.put("price_int", String.valueOf(price));
return doRequest("order/add", "POST", true, params);
}
public JSONObject cancelOrder(long orderId) throws Exception {
HashMapparams = new HashMap ();
params.put("oid", String.valueOf(orderId));
return doRequest("order/cancel", "POST", true, params);
}
public JSONObject fetchOrder(long orderId) throws Exception {
HashMapparams = new HashMap ();
params.put("oid", String.valueOf(orderId));
return doRequest("order/fetch", "GET", true, params);
}
public JSONObject getTrades() throws Exception {
return doRequest("trades/mine", "GET", true);
}
public JSONObject lastTrades() throws Exception {
return doRequest("trades/all", "GET", false);
}
public JSONObject getDepth() throws Exception {
return doRequest("depth", "GET", false);
}
private JSONObject doRequest(String api, String httpMethod, boolean auth) throws Exception {
HashMapparams = new HashMap ();
return doRequest(api, httpMethod, auth, params);
}
private JSONObject doRequest(String api, String httpMethod, boolean auth, HashMapparams) throws Exception {
if(auth) {
Calendar maxAge = Calendar.getInstance();
maxAge.add(Calendar.MINUTE, -1);
if((this.secret == "") || this.expires.before(maxAge)) {
this.loadSecret();
}
params.put("nonce", String.valueOf(System.nanoTime())+"000");
}
String paramStr = "";
int i = 0;
for(Map.Entryentry : params.entrySet()) {
paramStr += entry.getKey() + "=" + URLEncoder.encode(entry.getValue(), "UTF-8");
i++;
if(i < params.size()) {
paramStr += "&";
}
}
HashMapheaders = new HashMap ();
if(auth) {
headers.put("Rest-Key", this.pubkey);
headers.put("Rest-Sign", this.getRequestSig(paramStr));
}
JSONObject data = this.doHttpRequest(api, httpMethod, paramStr, headers);
return data;
}
private void loadSecret() throws UnsupportedEncodingException, IOException, ParseException {
File dat = new File(this.StorLocation);
// Load secret from file
if(dat.exists()) {
this.expires.setTimeInMillis(dat.lastModified());
this.expires.add(Calendar.HOUR, 2);
Calendar maxAge = Calendar.getInstance();
maxAge.add(Calendar.MINUTE, -1);
if(this.expires.after(maxAge)) {
StringBuilder datContents = new StringBuilder((int)dat.length());
Scanner scanner = null;
try {
scanner = new Scanner(dat);
while(scanner.hasNextLine()) {
datContents.append(scanner.nextLine());
}
} catch (FileNotFoundException e) {
} finally {
scanner.close();
}
this.secret = datContents.toString();
this.expires = Calendar.getInstance();
this.expires.add(Calendar.HOUR, 2);
return;
}
}
// Need to fetch a new secret
HashMapheaders = new HashMap ();
headers.put("Rest-Key", this.pubkey);
String params = "api_passphrase=" + URLEncoder.encode(this.passphrase, "UTF-8");
JSONObject data = this.doHttpRequest("getsecret", "POST", params, headers);
this.secret = (String)data.get("secret");
this.expires = Calendar.getInstance();
this.expires.add(Calendar.HOUR, 2);
FileWriter fw = new FileWriter(dat);
try {
fw.write(this.secret);
} catch(IOException e) {
System.out.println(e);
} finally {
fw.close();
}
}
// Perform the request
private JSONObject doHttpRequest(String api, String httpMethod, String params, HashMapheaders) throws IOException, ProtocolException, ParseException {
api = (httpMethod == "GET") ? api += "?" + params : api;
URL uObj = new URL(this.urlBaseLoc + this.currPair + "/" + api);
HttpsURLConnection conn = (HttpsURLConnection) uObj.openConnection();
conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; RMBTB Java client)");
for(Map.Entryentry : headers.entrySet()) {
conn.setRequestProperty(entry.getKey(), entry.getValue());
}
if(httpMethod == "POST") {
conn.setRequestMethod("POST");
conn.setDoOutput(true);
DataOutputStream out = new DataOutputStream(conn.getOutputStream());
out.writeBytes(params);
out.flush();
out.close();
} else {
conn.setRequestMethod("GET");
}
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String inLine;
StringBuffer response = new StringBuffer();
while((inLine = in.readLine()) != null) {
response.append(inLine);
}
in.close();
JSONParser parser = new JSONParser();
JSONObject respJSON = (JSONObject)(parser.parse(response.toString()));
if(respJSON.get("error").getClass().getName() != "java.lang.Boolean") {
String strErr = (String)(respJSON.get("error"));
throw new RuntimeException(strErr);
}
JSONObject data = (JSONObject)respJSON.get("data");
return data;
}
// Signs using HMAC
private String getRequestSig(String data) throws NoSuchAlgorithmException, InvalidKeyException {
Mac mac = Mac.getInstance("HmacSHA512");
SecretKeySpec secret_spec = new SecretKeySpec(this.secret.getBytes(), "HmacSHA512");
mac.init(secret_spec);
return Base64.encodeBase64String(mac.doFinal(data.getBytes())).toString();
}
}
#!/usr/bin/env ruby
#
# coding: utf-8
#
# Ruby wrapper for the RMBTB.com Secure API
# (c) RMBTB.com. Released under the BSD license. Modification & redistribution allowed, but you may not use the RMBTB brand or name.
#
# Example usage:
# rmbtb = RmbtbSecureApi.new(pubkey, passphrase, 'BTCCNY')
# p rmbtb.add_order('bid', 3.1, 570.2)
#
require 'base64'
require 'openssl'
require 'time'
require 'uri'
require 'cgi'
require 'net/http'
require 'net/https'
require 'rubygems'
require 'json'
# RMBTB API layer
class RmbtbSecureApi
def initialize(key, passphrase, currpair = 'BTCCNY')
@base = 'https://www.rmbtb.com/api/secure/'
@storloc = 'rmbtb-store.dat'
@key = key
@passphrase = passphrase
@currpair = currpair
@secret = nil
@expiry = nil
end
# Public: Retrieve account information
#
# Returns a JSON object
def get_info
return prepare_request('getinfo', :httpMethod => 'GET', :auth => true)
end
# Public: Retrieve wallet balances
#
# Returns a JSON object of wallet balances
def get_funds
return prepare_request('wallets', :httpMethod => 'GET', :auth => true)
end
# Public: Retrieve market information
#
# Returns a JSON object
def ticker
return prepare_request('ticker', :httpMethod => 'GET')
end
# Public: Retrieve my last 50 orders
#
# Returns a JSON object of orders
def get_orders
return prepare_request('ticker', :httpMethod => 'GET', :auth => true)
end
# Public: Add an order, using floats
#
# type - String, 'bid' or 'ask'
# amount - Float, amount to buy or sell
# price - Float, the price
#
# Returns a JSON object containing the Order ID
def add_order(type, amount, price)
params = { :type => type, :amount => amount, :price => price }
return prepare_request('order/add', :params => params, :httpMethod => 'POST', :auth => true)
end
# Public: Add an order, using integers
#
# type - String, 'bid' or 'ask'
# amount - Float, amount to buy or sell
# price - Float, the price
#
# Returns a JSON object containing the Order ID
def add_order_int(type, amount, price)
params = { :type => type, :amount_int => amount, :price_int => price }
return prepare_request('order/add', :params => params, :httpMethod => 'POST', :auth => true)
end
# Public: Cancel an order
#
# orderid - Integer, the order ID to cancel
#
# Returns a JSON object containing the Order ID
def cancel_order(orderid)
params = { :oid => orderid }
return prepare_request('order/cancel', :params => params, :httpMethod => 'POST', :auth => true)
end
# Public: Fetch information about an order
#
# orderid - Integer, the order ID to cancel
#
# Returns order information
def fetch_order(orderid)
params = { :oid => orderid }
return prepare_request('order/fetch', :params => params, :httpMethod => 'GET', :auth => true)
end
# Public: Get my trades
#
# Returns my latest trades
def get_trades
return prepare_request('trades/mine', :httpMethod => 'GET', :auth => true)
end
# Public: Get all market trades
#
# Returns the latest market trades
def last_trades
return prepare_request('trades/all', :httpMethod => 'GET')
end
# Public: Get depth
#
# Returns the market depth
def get_depth
return prepare_request('depth', :httpMethod => 'GET')
end
private
# Prepares the request
def prepare_request(api, options = { })
httpMethod = (options[:httpMethod] == 'GET') && 'GET' || 'POST'
auth = options[:auth] ||= false
params = options[:params] ||= { }
if auth
load_secret if !@secret || !@expiry || (@expiry < (Time.now - 60))
# Add nonce
params = params.merge(:nonce => (Time.now.to_f * 1e6).to_i.to_s)
sendParams = params.map{ |k,v| "#{ CGI::escape(k.to_s) }=#{ CGI::escape(v.to_s) }" }.join('&')
mac = Base64.encode64(OpenSSL::HMAC.digest('sha512', @secret, sendParams)).gsub(/\n/, '')
headers = { 'Rest-Key' => @key, 'Rest-Sign' => mac }
else
sendParams = params.map{ |k,v| "#{CGI::escape(k.to_s) }=#{ CGI::escape(v.to_s)}" }.join('&')
headers = { }
end
return send_request(api, :paramStr => sendParams, :httpMethod => httpMethod, :headers => headers)
end
# fetch or load/refresh the temporary secret
def load_secret
if !@secret && File.exists?(@storloc)
@expiry = File.mtime(@storloc) + 7200
if @expiry > (Time.now - 60)
@secret = File.open(@storloc).read
return
end
end
result = send_request('getsecret', :paramStr => "api_passphrase=#{ CGI::escape(@passphrase) }", :httpMethod => 'POST', :headers => { 'Rest-Key' => @key })
@secret = result['secret']
File.open(@storloc, 'w') { |f| f.write(@secret) }
@expiry = Time.now + 7200
end
# Send the request out
def send_request(api, options={ })
httpMethod = (options[:httpMethod] == 'GET') && 'GET' || 'POST'
headers = options[:headers] ||= { }
data = options[:paramStr] ||= ''
url = "#{ @base }#{ @currpair }/#{ api }"
if httpMethod == 'POST'
headers.merge({'Content-Type' => 'application/x-www-form-urlencoded'})
elsif data != ''
url = "#{ url }?#{ data }"
end
headers.merge({'User-Agent' => 'Mozilla/4.0 (compatible); RMBTB Ruby API Client'})
url = URI.parse(url)
https = Net::HTTP.new(url.host, url.port)
https.use_ssl = true
result = nil
begin
req, body = ((httpMethod == 'POST') ? https.post(url.path, data, headers) : https.get(url.request_uri, headers))
result = JSON.parse(body)
rescue
raise 'Could not communicate with server'
end
raise "Error: #{ result['error'] }" if result['error']
return result['data']
end
end
/**
*
* JavaScript (Node.js) secure API wrapper
*
* 版权和限制 (c) 2013人盟比特币公布以下的代码遵循BSD条款。您可以按您的意愿使用或修改,用于个人或商业用途。
*
* 然而您不可以以 "RMBTB", "人盟比特币"来标识您的程序,也不可以有意或无意示意您的软件或服务是由人盟比*特币提供的。
*
* Usage:
* All functions are fully asynchronous, so you need to provide a callback function.
*
* var rmbtb = new rmbtbSecureApi('BTCCNY', myPubKey, myPassPhrase);
*
* rmbtb.addOrder('bid', 3, 591, function(result) {
* console.log('Result: %j', result);
* });
*
*/
// Location where you will store temporary secrets:
var rmbtbStoreLocation = 'rmbtb-secret.dat';
// Node.js dependencies
var
fs = require('fs'),
https = require('https'),
querystring = require('querystring'),
crypto = require('crypto');
function rmbtbSecureApi(currPair, pubKey, passphrase) {
this.currPair = currPair;
this.pubKey = pubKey;
this.passphrase = passphrase;
this.storeLoc = rmbtbStoreLocation;
this.apiHost = 'www.rmbtb.com';
this.apiPath = '/api/secure/' + currPair + '/';
this.secret = false;
this.secretExpiryTime = false;
var that = this;
var twoHrs = 7200000;
// fetches a new secret if necessary, before performing the main request
this.apiCall = function(api, params, httpMethod, auth, callback) {
var cb = function() {
prepRequest(api, params, httpMethod, auth, callback);
};
if(auth) {
if((this.secret === false) || (this.secretExpiryTime === false)) {
loadSecret(cb);
} else if((this.secretExpiryTime.getTime() - 60000) > (new Date()).getTime()) {
rereshSecret(cb);
} else {
cb.call(this);
}
} else {
cb.call(this);
}
};
// prepares the request
function prepRequest(api, params, httpMethod, auth, callback) {
var data = '',
headers = {};
if(this.secret === false) {
throw 'No valid secret!';
}
if(auth) {
params.nonce = (new Date()).getTime() * 1000;
data = querystring.stringify(params);
var hmac = crypto.createHmac("sha512", that.secret);
hmac.update(data);
headers['Rest-Key'] = that.pubKey;
headers['Rest-sign'] = hmac.digest('base64');
} else {
data = querystring.stringify(params);
}
if(httpMethod == 'POST') {
headers['Content-Type'] = 'application/x-www-form-urlencoded';
headers['Content-Length'] = data.length;
}
headers['User-Agent'] = 'Mozilla/4.0 (compatible; RMBTB JavaScript client)';
var opts = {
method: httpMethod,
headers: headers
};
if(httpMethod == 'GET') {
api += '?' + data;
}
doRequest(api, data, opts, callback);
}
// sends a prepared request to the API
function doRequest(api, data, opts, callback) {
opts.host = that.apiHost;
opts.path = that.apiPath + api;
var req = https.request(opts, function(response) {
var resultStr = '';
response.setEncoding('utf8');
response.on('data', function(chunk) {
resultStr += chunk;
});
response.on('error', function(err) {
throw err;
});
response.on('end', function() {
try {
var obj = JSON.parse(resultStr);
} catch(e) {
throw 'Could not understand response';
}
if(obj.error !== false) {
throw 'API returned an error: ' + obj.error;
}
var result = obj.data;
callback.call(that, result);
});
});
req.on('error', function(err) {
throw 'Error communicating: ' + err;
});
if(opts.method == 'POST') {
req.write(data);
}
req.end();
}
// refreshes the temporary secret
function refreshSecret(cb) {
var data = querystring.stringify({'api_passphrase': that.passphrase});
var opts = {
method: 'POST',
headers: {
'Rest-Key': that.pubKey,
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': data.length,
}
};
doRequest('getsecret', data, opts, function(result) {
that.secret = result.secret;
that.secretExpiryTime = new Date((new Date()).getTime() + twoHrs);
fs.writeFile(that.storeLoc, that.secret, 'utf8', function() {
cb.call(that)
});
});
}
// loads the stored secret from the save file
function loadSecret(cb) {
fs.stat(that.storeLoc, function(err, stat) {
if(!err) {
that.secretExpiryTime = new Date(stat.mtime.getTime() + twoHrs);
if((new Date()).getTime() < that.secretExpiryTime.getTime()) {
fs.readFile(that.storeLoc, 'utf8', function(err, data) {
if(!err) {
that.secret = data;
cb.call(that);
} else {
refreshSecret(cb);
}
});
} else {
refreshSecret(cb);
}
} else {
refreshSecret(cb);
}
});
}
}
/**
*
* The public, callable methods:
*
*/
rmbtbSecureApi.prototype.getInfo = function(callback) {
this.apiCall('getinfo', {}, 'GET', true, callback);
};
rmbtbSecureApi.prototype.getFunds = function(callback) {
this.apiCall('wallets', {}, 'GET', true, callback);
};
rmbtbSecureApi.prototype.ticker = function(callback) {
this.apiCall('ticker', {}, 'GET', false, callback);
};
rmbtbSecureApi.prototype.getOrders = function(callback) {
this.apiCall('orders', {}, 'GET', true, callback);
};
rmbtbSecureApi.prototype.addOrder = function(type, amount, price, callback) {
var params = {
'type': type,
'amount': amount,
'price': price
};
this.apiCall('order/add', params, 'POST', true, callback);
};
rmbtbSecureApi.prototype.addOrderInt = function(type, amount, price, callback) {
var params = {
'type': type,
'amount_int': amount,
'price_int': price
};
this.apiCall('order/add', params, 'POST', true, callback);
};
rmbtbSecureApi.prototype.cancelOrder = function(orderid, callback) {
var params = {
'oid': orderid,
};
this.apiCall('order/cancel', params, 'POST', true, callback);
};
rmbtbSecureApi.prototype.fetchOrder = function(orderid, callback) {
var params = {
'oid': orderid,
};
this.apiCall('order/fetch', params, 'POST', true, callback);
};
rmbtbSecureApi.prototype.getTrades = function(callback) {
this.apiCall('trades/mine', {}, 'GET', true, callback);
};
rmbtbSecureApi.prototype.lastTrades = function(callback) {
this.apiCall('trades/all', {}, 'GET', false, callback);
};
rmbtbSecureApi.prototype.getDepth = function(callback) {
this.apiCall('depth', {}, 'GET', false, callback);
};
< ? php
/**
* PHP RMBTB SECURE API WRAPPER
* 版权和限制
* (c) 2013人盟比特币公布以下的代码遵循BSD条款。您可以按您的意愿使用或修改,用于个人或商业用途。
*
* 然而您不可以以 "RMBTB", "人盟比特币"来标识您的程序,也不可以有意或无意示意您的软件或服务是由人盟比特币提供的。
*
* 你可以使用默认的浮点型或者整数型的.
* 请仔细阅读下面的设置和安全建议
*
* 使用示例
* $rmbtbApi = new Rmbtb_Secure_API('BTCCNY', RMBTB_API_PUBKEY, RMBTB_API_PASSPHRASE);
* print_r($rmbtbApi->get_info());
* print_r($rmbtbApi->add_order('bid', 5, 650));
*
* // 或...
* $rmbtbApiInt = new Rmbtb_Secure_API_Integer('BTCCNY', RMBTB_API_PUBKEY, RMBTB_API_PASSPHRASE);
* print_r($rmbtbApiInt->add_order('ask', 500000000, 65000000));
*/
/**
* 配置
*
* 于此设置您的配置选项
* 建议您将这些文件存在另一个文件里,在服务器一个更安全的地方上。要包含将() 在文件中
*
* e.g. require('/path/to/rmbtb/config.php');
*/
// 你的API用户名和口令
define('RMBTB_API_PUBKEY', 'r-api-e888a-1111d-181818-6fafa7-fa18fa-8888a-9fsx');
define('RMBTB_API_PASSPHRASE', 'n4ajpX/df*2A%%xxT>Pq<_24pxcpH|^Q5nhQab==!=IIh%/x-');
/*
* 存放人盟比特币SSL证书副本的地方。用此来确定您不是和冒名者在沟通。你可以下载此文件并导到你的浏览器内。
*/
define('RMBTB_CERT_LOC', 'rmbtb-cert.pem');
/*
* 一个安全,可写的地方来存放你零时的API 密钥。文件未必需要存在,但是文件夹必须存在,并且可写。
* 不要将其放在很容易找到的地方!
*/
define('RMBTB_LOCAL_STORAGE_LOC', 'rmbtb-store.dat');
/**
* 配置部分结束
*/
/**
*
* The base API class. This is extended below if you need to deal with integers rather than floats.
*/
class Rmbtb_Secure_API {
private
$urlBase = 'https://www.rmbtb.com/api/secure/',
$currencyPair,
$key,
$passphrase,
$secret,
$secretExpiryTime,
$debug;
/**
* Constructor
* @param string $key your RMBTB Secure API public key
* @param string $passphrase the passphrase given to you with your key
*/
public function __construct($currencyPair, $key, $passphrase, $debug = false) {
$this->debug = $debug;
$this->currencyPair = $currencyPair;
$this->key = $key;
$this->passphrase = $passphrase;
$this->load_secret(RMBTB_LOCAL_STORAGE_LOC);
}
/**
* get_info()
* Get useful information about your account
* Authentication required.
* @return Array representation of JSON object
*/
public function get_info() {
return $this->request('getinfo', array(), 'GET');
}
/**
* get_funds()
* Get balance information
* Authentication required.
* @return Array representation of JSON object
*/
public function get_funds() {
return $this->request('wallets', array(), 'GET');
}
/**
* ticker()
* Get market information
* @return Array representation of JSON object
*/
public function ticker() {
return $this->request('ticker', array(), 'GET', false);
}
/**
* get_orders()
* Get your 50 most recent orders
* Authentication required.
* @return Array representation of JSON object
*/
public function get_orders() {
return $this->request('orders', array(), 'GET');
}
/**
* add_order()
* Place a new order
* Authentication required.
* @param string bid|ask $type
* @param float $amount amount of BTC to buy/sell
* @param float $price bid or ask price
* @return Array representation of JSON object
*/
public function add_order($type, $amount, $price) {
return $this->request('order/add', array('type' => $type, 'amount' => $amount, 'price' => $price), 'POST');
}
/**
* add_order()
* Cancel an order
* Authentication required.
* @param integer $orderid the Order ID to cancel
* @return Array representation of JSON object
*/
public function cancel_order($orderid) {
return $this->request('order/cancel', array('oid' => $orderid), 'POST');
}
/**
* fetch_order()
* Fetch order details
* Authentication required.
* @param integer $orderid the Order ID to fetch
* @return Array representation of JSON object
*/
public function fetch_order($orderid) {
return $this->request('order/fetch', array('oid' => $orderid), 'GET');
}
/**
* get_trades()
* Get your 50 most recent trades
* Authentication required.
* @return Array representation of JSON object
*/
public function get_trades() {
return $this->request('trades/mine', array(), 'GET');
}
/**
* last_trades()
* View the last 80 public trades
* @return Array representation of JSON object
*/
public function last_trades() {
return $this->request('trades/all', array(), 'GET', false);
}
/**
* get_depth()
* View the market depth
* @return Array representation of JSON object
*/
public function get_depth() {
return $this->request('depth', array(), 'GET', false);
}
/**
* Performs the request.
* @param string $method the API address
* @param array $params the API method parameters
* @param string GET|POST $http_method the HTTP method
* @param bool $auth whether to sign the request
* @return array with the returned data
* @access protected
*/
protected function request($method, $params = array(), $http_method = 'GET', $auth = true) {
$http_method = ($http_method == 'GET') ? 'GET' : 'POST';
if($auth) {
// refresh secret if necessary
$secretExpires = $this->secretExpiryTime - time();
if($secretExpires < 60) {
$this->refresh_secret(RMBTB_LOCAL_STORAGE_LOC);
}
// generate an always-increasing nonce using microtime
$mt = explode(' ', microtime());
$params['nonce'] = $mt[1].substr($mt[0], 2, 6);
// generate the POST data string
$data = http_build_query($params, '', '&');
// generate the extra headers for message verification
$headers = array(
'Rest-Key: ' . $this->key,
'Rest-Sign: '. base64_encode(hash_hmac('sha512', $data, $this->secret, true))
);
} else {
$data = http_build_query($params, '', '&');
$headers = array();
}
$data = $this->do_curl($method, $data, $headers, $http_method);
return $data;
}
/**
* Loads the last API secret from your local storage file.
* Secrets expire every two hours, so we only use the secret if it was stored less than two hours ago.
* If it has expired, we load a new one.
* @param string $loc the location where the last secret was stored.
* @return bool false on failure
* @access private
*/
private function load_secret($loc) {
$this->secret = false;
$this->secretExpiryTime = false;
if(file_exists($loc)) {
$storTime = @filemtime($loc);
// Account for a bug in Windows where daylight saving is not reflected correctly
$isDST = (date('I', $storTime) == 1);
$systemDST = (date('I') == 1);
$adjustment = 0;
if($isDST == false && $systemDST == true) {
$adjustment = 3600;
} else if($isDST == true && $systemDST == false) {
$adjustment = -3600;
}
$storTime += $adjustment;
$elapsed = time() - $storTime;
if($elapsed < 7200) {
// secret has not yet expired
$this->secret = trim(file_get_contents($loc));
$this->secretExpiryTime = $storTime + 7200;
return true;
}
}
// secret has expired or we've never created one before
return $this->refresh_secret($loc);
}
/**
* Fetch a new secret from the API
* @param string $loc the location to store the secret
* @return bool true on success
* @access private
*/
private function refresh_secret($loc) {
if($this->secret = $this->obtain_new_secret()) {
file_put_contents($loc, $this->secret);
$this->secretExpiryTime = time() + 7200;
return true;
}
return false;
}
/**
* Requests a new API secret, which will be tied to our IP and will
* last for 2 hours.
* @return string our new secret, or false on error.
* @access private
*/
private function obtain_new_secret() {
$postData = 'api_passphrase=' . urlencode($this->passphrase);
$headers = array(
'Rest-Key: ' . $this->key
);
$data = $this->do_curl('getsecret', $postData, $headers, 'POST');
return $data['data']['secret'];
}
/**
* Performs the request
* @param string $path the API method path
* @param string $data the GET url string, or the POST body
* @param array $headers headers to send -- e.g. our Rest-Key and Rest-Sign
* @param string GET|POST $http_method the HTTP method to use
* @return array representation of JSON response, or an error.
* @access private
*/
private function do_curl($path, $data, $headers, $http_method) {
static $ch = null;
$url = $this->urlBase . $this->currencyPair . '/' . $path;
if($this->debug) {
echo "Sending request to $url\n";
}
if (is_null($ch)) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; RMBTB PHP client; '.php_uname('s').'; PHP/'.phpversion().')');
}
if($http_method == 'GET') {
$url .= '?' . $data;
} else {
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
curl_setopt($ch, CURLOPT_CAINFO, RMBTB_CERT_LOC);
// run the query
$response = curl_exec($ch);
if($this->debug) {
echo "Response: $response\n";
}
if (empty($response)) {
throw new Exception('Could not get reply: ' . curl_error($ch));
}
$data = json_decode($response, true);
if (!is_array($data)) {
throw new Exception('Invalid data received, please make sure connection is working and requested API exists');
}
$this->quit_on_error($data);
return $data;
}
/**
* Parses the returned data, and bails if it contains an error.
* @param array $data an array representation of returned JSON data
* @return void
* @access private
*/
private function quit_on_error($data) {
if($data['error'] !== false) {
throw new Exception("\n\nError received from API: {$data['code']}\n-----------------------------------\n{$data['error']}\n\n");
exit();
}
}
}
/**
*
* Use this if you prefer to use integers to order.
*/
class Rmbtb_Secure_API_Integer extends Rmbtb_Secure_API {
/**
* add_order()
* Place a new order
* Authentication required.
* @param string bid|ask $type
* @param integer $amount_int amount of BTC to buy/sell
* @param integer $price_int bid or ask price
* @return Array representation of JSON object
*/
public function add_order($type, $amount_int, $price_int) {
return $this->request('order/add', array('type' => $type, 'amount_int' => $amount_int, 'price_int' => $price_int));
}
}
# -*- coding: utf-8 -*-
#
# PYTHON RMBTB SECURE API WRAPPER
#
# 版权和限制
# (c) 2013人盟比特币公布以下的代码遵循BSD条款。您可以按您的意愿使用或修改,用于个人或商业用途。
#
# 然而您不可以以 "RMBTB", "人盟比特币"来标识您的程序,也不可以有意或无意示意您的软件或服务是由人盟比特币提供的。
#
#
# 使用示例
# >>> rmbtb = RmbtbSecureAPI("API_KEY_HERE", "API_PASSPHRASE_HERE", "BTCCNY")
# >>> rmbtb.ticker()
# >>> rmbtb.add_order(type="ask", amount=3.1, price=650.00)
#
# // 或...
# >>> rmbtb = RmbtbSecureAPIInt("API_KEY_HERE", "API_PASSPHRASE_HERE", "BTCCNY")
# >>> rmbtb.add_order(type="bid", amount=310000000, price=65000000)
#
import time, datetime, json, urllib, urllib2, base64, hmac, gzip
from hashlib import sha512
from os import path
class RmbtbSecureAPI(object):
"""The base RMBTB class"""
#Set the following to a local, secure, writeable location to store temporary secrets.
RMBTB_LOCAL_STORAGE_LOC = "rmbtb-store.dat"
RMBTB_BASE_URL = "https://www.rmbtb.com/api/secure/"
def __init__(self, key, passphrase, currencyPair="BTCCNY"):
self.key = key
self.passphrase = passphrase
self.currencyPair = currencyPair
self._load_secret(self.RMBTB_LOCAL_STORAGE_LOC)
def get_info(self):
"""Get account information"""
return self._request(api="getinfo", httpMethod="GET")
def get_funds(self):
"""Get wallet balances"""
return self._request(api="wallets", httpMethod="GET")
def ticker(self):
"""Get ticker data"""
return self._request(api="ticker", httpMethod="GET", auth=False)
def get_orders(self):
"""Get my orders"""
return self._request(api="orders", httpMethod="GET")
def add_order(self, type, amount, price):
"""Place an order"""
params = {
'type': type,
'amount': amount,
'price': price
}
return self._request(api="order/add", params=params, httpMethod="POST")
def cancel_order(self, orderid):
"""Cancel an order"""
params = {
'oid': orderid
}
return self._request(api="order/cancel", params=params, httpMethod="POST")
def fetch_order(self, orderid):
"""Get order details"""
params = {
'oid': orderid
}
return self._request(api="order/fetch", params=params, httpMethod="GET")
def get_trades(self):
"""Get your recent trades"""
return self._request(api="trades/mine", httpMethod="GET")
def last_trades(self):
"""Get recent market trades data"""
return self._request(api="trades/all", httpMethod="GET", auth=False)
def get_depth(self):
"""Get market depth"""
return self._request(api="depth", httpMethod="GET", auth=False)
def _load_secret(self, loc):
"""Private method; loads secret from storage"""
self.secret = False
self.secretExpiryTime = False
if path.exists(loc):
storTime = datetime.datetime.fromtimestamp(path.getmtime(loc))
timeNow = datetime.datetime.now()
self.secretExpiryTime = storTime + datetime.timedelta(hours=2)
if (datetime.datetime.now() < self.secretExpiryTime):
# secret has not expired
self.secret = open(loc).read().strip()
return True
#secret has expired or we've never created one before
return self._refresh_secret(loc)
def _refresh_secret(self, loc):
"""Private method; refreshes the secret"""
self.secret = str(self._obtain_new_secret(loc))
if self.secret != False:
f = open(loc, 'w')
f.write(self.secret)
f.close()
self.secretExpiryTime = datetime.datetime.now() + datetime.timedelta(hours=2)
return self.secret
def _obtain_new_secret(self, loc):
"""Private method; Gets the new secret"""
postData = "api_passphrase=" + urllib2.quote(self.passphrase)
headers = {
"Rest-Key": self.key
}
data = self._curl_call(api="getsecret", paramStr=postData, headers=headers, httpMethod="POST")
return data["data"]["secret"]
def _request(self, api, params={}, httpMethod="GET", auth=True):
"""Private method; creates the API request parameters / auth headers"""
'GET' if (httpMethod == 'GET') else 'POST'
if auth:
#refresh secret if necessary
if (self.secret == False) or (datetime.datetime.now() > (self.secretExpiryTime - datetime.timedelta(seconds=60))):
self._refresh_secret(self.RMBTB_LOCAL_STORAGE_LOC)
params[u"nonce"] = str(int(time.time()*1e6))
sendParams = urllib.urlencode(params)
mac = hmac.new(self.secret, str(sendParams), sha512)
sig = base64.b64encode(str(mac.digest()))
headers = {
"Rest-Key": self.key,
"Rest-Sign": sig,
"Content-Type": "application/x-www-form-urlencoded",
}
else:
sendParams = urllib.urlencode(params)
headers = {}
data = self._curl_call(api=api, paramStr=sendParams, headers=headers, httpMethod=httpMethod)
return data
def _curl_call(self, api, paramStr=None, httpMethod="GET", headers={}, timeout=8):
"""Private method; performs the request"""
url = self.RMBTB_BASE_URL + self.currencyPair + "/" + api
headers.update({
'User-Agent': "Mozilla/4.0 (compatible; RMBTB Python client)",
'Accept-Encoding': 'GZIP',
})
if httpMethod == "POST":
headers["Content-Type"] = "application/x-www-form-urlencoded"
sendParams = paramStr
else:
url = url + "?" + paramStr
sendParams = False
if sendParams:
request = urllib2.Request(url, sendParams, headers=headers)
else:
request = urllib2.Request(url, headers=headers)
response = urllib2.urlopen(request, timeout=timeout)
data = json.loads(response.read())
if not(u"data" in data):
if(u"error" in data):
raise Exception(u"Error received: " + data[u"error"])
else:
raise Exception("An error occurred")
return data
class RmbtbSecureAPIInt(RmbtbSecureAPI):
"""Use this class if you prefer to deal with integers"""
def add_order(self, type_int, amount_int, price):
"""Place an order"""
params = {
'type': type,
'amount_int': amount_int,
'price_int': price_int
}
return self._request(api="order/add", params=params, httpMethod="POST")