ok so I have been trying to reproduce the functionality of this PHP script:

我一直在尝试复制这个PHP脚本的功能:

<?php

function api_query($method, array $req = array()) {
    // API settings
    $key = ''; // your API-key
    $secret = ''; // your Secret-key

    $req['method'] = $method;
    $mt = explode(' ', microtime());
    $req['nonce'] = $mt[1];

    // generate the POST data string
    $post_data = http_build_query($req, '', '&');

    $sign = hash_hmac("sha512", $post_data, $secret);

    // generate the extra headers
    $headers = array(
            'Sign: '.$sign,
            'Key: '.$key,
    );

    // our curl handle (initialize if required)
    static $ch = null;
    if (is_null($ch)) {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; Cryptsy API PHP client; '.php_uname('s').'; PHP/'.phpversion().')');
    }
    curl_setopt($ch, CURLOPT_URL, 'https://www.cryptsy.com/api');
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);

    // run the query
    $res = curl_exec($ch);

    if ($res === false) throw new Exception('Could not get reply: '.curl_error($ch));
    $dec = json_decode($res, true);
    if (!$dec) throw new Exception('Invalid data received, please make sure connection is working and requested API exists');
    return $dec;
}

I have (at least I believe I have) taken care of creating the http_build_query call that C does not have just by constructing the query myself. I have the $mt variable in mtStr by using gettimeofday() and I am using the HMAC function from openSSL to sign the post_data with my secret key.

我有(至少我相信我已经)负责创建http_build_query调用,而C不只是通过自己构造查询。通过使用gettimeofday(),我在mtStr中有$mt变量,而我使用的是openSSL的HMAC函数,用我的秘钥在post_data上签名。

I figured out that the CURLOPT_HTTPHEADER option in C needs a curl_slist linked lists instead of just an array like in PHP, but where I seem to be having problems is in the Post Data. The request will go through but there is an error return saying "check your POST Data". So i went back to the libcurl documentation and found that CURLOPT_POSTFIELDS requires a void* to the data you want to post. So i create void *pData = post_data (where post_data is just a char array, not a pointer so I dont see a probem here) but it still says that it can not valid my identify please check POST data. So if you could take a look at this and tell me where I am going wrong it would be appreciated...

我发现C中的CURLOPT_HTTPHEADER选项需要一个curl_list链接列表,而不是像PHP那样的数组,但是在Post数据中我似乎遇到了问题。请求将会被执行,但是有一个错误的返回说“检查你的POST数据”。因此,我返回到libcurl文档,发现CURLOPT_POSTFIELDS需要对您想要发布的数据使用一个void*。所以我创建了void *pData = post_data(这里post_data只是一个char数组,而不是一个指针,所以我在这里看不到一个问题)但是它仍然说它不能有效地识别我的身份请检查POST数据。所以,如果你能看一下这个,告诉我哪里出错了,我会很感激……

Note that I am not showing my API and secret keys, since I cant change them on my own I would rather not give them out but I know this makes it hard to check my stuff by compiling yourself without a cryptsy account but I'd like to keep it secret for now but there are some dummy keys in there so that there is something to hash that is the proper length etc.

注意,我不显示我的API密钥,因为我不能改变我自己我宁愿不给他们出,但我知道这很难检查我的东西通过编译自己没有cryptsy账户但是我想保守这个秘密,但有一些假钥匙,这样有一些散列,适当的长度等。

char *handle_url( char *url )
{
CURL *curl;

struct url_data data;
data.size = 0;
data.data = malloc( 4096 );
if ( NULL == data.data )
{
    fprintf( stderr, "failed to allocate memory.\n" );
    return NULL;
}

data.data[0] = '\0';

CURLcode res;

// API settings, API key and secret key for your account
char key[] = "9498fbb723961a42816a10bc559cgda7ded2ed8e";
char secret[] = "687cd29def08a7861446c3b4b9c97996c8472e7dd8922da147d3b1343e52e99125d24ace90729fbb";

// method to use against the API, will make changable later
char *method = "mytrades";

// This is required to replace the microtime()/explode methods to
// generate the nonce value required to use the cryptsy API
struct timeval time;
gettimeofday( &time, NULL );
long mt = ( (unsigned long long)time.tv_sec * 1000000 ) + time.tv_usec;
// C is much morer strict than PHP about types so we create a buffer for the
// string representation of the nonce
char mtStr[ 128 ];

sprintf( mtStr, "%lu", mt );

// C does not have a build_http_query as PHP does so
// we just create the string neccessary with strcpy
// and strcat
char post_data[ strlen("method=") + strlen(method) + strlen("&nonce=") + strlen(mtStr) + 1];
strcpy( post_data, "method=" );
strcat( post_data, method );
strcat( post_data, "&" );
strcat( post_data, "nonce=" );
strcat( post_data, mtStr );

printf( "%s", post_data);
printf( "\n");

void *pData = post_data;

//sha512 needs 128 characters
unsigned char *result;
unsigned int len = 128;

result = (unsigned char *)malloc( sizeof(char) * len );

HMAC_CTX ctx;
HMAC_CTX_init( &ctx );

// using sha512
HMAC_Init_ex( &ctx, secret, strlen(secret), EVP_sha512(), NULL );
HMAC_Update( &ctx, (unsigned char *)&post_data, strlen(post_data) );
HMAC_Final( &ctx, result, &len );
HMAC_CTX_cleanup( &ctx );
/*
printf( "\nHMAC digest: " );

for ( int i = 0; i != len; i++ )
{
    printf( "%02x", (unsigned int)result[i] );
} */
printf("\n");

// This is the start of setting up the $headers array as in the PHP script
const char *header1 = "Sign: ";
size_t PrefixL = strlen(header1);
char resBuffer[PrefixL + 2 * len + 1];
strcpy( resBuffer, header1);
char *p = &resBuffer[PrefixL];

for ( unsigned int i = 0; i < len; i++ )
{
    sprintf( p, "%02x", (unsigned int)result[i]);
    p += 2;
}

printf( "%s\n", resBuffer );

const char *header2 = "Key: ";
size_t PrefixR = strlen(header2);
char keyBuffer[PrefixR + 2 * strlen(key) + 1];
strcpy( keyBuffer, header2);
strcat( keyBuffer, key);

printf( "\n%s\n", keyBuffer );


// So now resBuffer is Sign: <128 character sha512 hash here>
// and keyBuffer is Key: <API key here>

free(result);

//struct curl_httppost *chttppostlist = NULL; //a possibility about sending chunked post data not currently used

// originally I set this up so that Sign and Key would be in the array in the same
// manner as the PHP script but libcurl in C needs a curl_slist 
const char *headerArray[2];
headerArray[0] = resBuffer;
headerArray[1] = keyBuffer;

// So then we just create a curl_slist and add the resBuffer and keyBuffer (headerArray
// [0] and headerArray[1] respectively) to the curl_slist.
struct curl_slist *cslist= NULL;
curl_slist_append(cslist, headerArray[0]);
curl_slist_append(cslist, headerArray[1]);

curl = curl_easy_init();
if ( curl )
{
    curl_easy_setopt( curl, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible Cryptsy API C Client)");
    curl_easy_setopt( curl, CURLOPT_URL, url );
    curl_easy_setopt( curl, CURLOPT_POST, 1 ); // is this necessary? isnt in PHP
    curl_easy_setopt( curl, CURLOPT_POSTFIELDS, pData ); // <--- something wrong here?
    curl_easy_setopt( curl, CURLOPT_HTTPHEADER, cslist );
    curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, write_data );
    curl_easy_setopt( curl, CURLOPT_WRITEDATA, &data );
    curl_easy_setopt( curl, CURLOPT_SSL_VERIFYPEER, 0 );
    res = curl_easy_perform( curl );
    if ( res != CURLE_OK )
    {
        fprintf( stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
    }
    curl_slist_free_all( cslist );
    curl_easy_cleanup( curl );
}
return data.data;
}

1 个解决方案

#1


0

#include <iostream>
#include <cstdlib>
#include <cstring>
#include "json_parsers.h"
extern "C" {
#include <curl/curl.h>
#include <sys/time.h>
#include <limits.h>
#include <openssl/hmac.h>
#include <openssl/sha.h>
}

#define OK  0
#define NO_INPUT 1
#define TOO_LONG 2

using namespace std;

struct url_data {
size_t size;
char *data;
};

size_t write_data( void *ptr, size_t size, size_t nmemb, struct url_data *data )
{
    size_t index = data->size;
    size_t n = ( size * nmemb );
    char *tmp;

    data->size += ( size * nmemb );

#ifdef DEBUG
    fprintf( stderr, "data at %p size=%ld nmemb=%ld\n", ptr,
        size, nmemb );
#endif

tmp = (char *)realloc( data->data, data->size + 1); // + 1 for \n

if ( tmp )
{
    data->data = tmp;
}
else
{
    if ( data->data )
    {
        free( data->data );
    }
    fprintf( stderr, "Failed to allocate memory.\n" );
    return 0;
}

memcpy( ( data->data + index ), ptr, n );
data->data[ data->size ] = '\0';

return size * nmemb;
}

char *cryptsy_api( char *url, char *method_in, char *marketid, int limit, char *ordertype, char *quantity, char *price, char *orderid ) {

char *cryptsy_api(char *url, char *method_in, char *marketid, int limit, char *ordertype, char *quantity, char *price, char *orderid) {

CURL *curl;

struct url_data data;
data.size = 0;
data.data = (char *)malloc(4096);
if (data.data == NULL)
{
    cerr << "Failed to allocate memory.\n" << endl;
    return NULL;
}

data.data[0] = '\0';

CURLcode res;

char strInt[5];
if (limit != NULL)
{
    sprintf(strInt, "%d", limit);
}

// API settings, API key and secret key for your account
char key[] = "9498fbb723961a42816a10bc559cfda7ded2ed8f";
char secret[] =  "687cd29def08a7861446c3b4b9c97996c8472e7dd8922da147d3b1346e52e99125d24ace90729fb3";

char *method = method_in;

// This is required to replace the microtime()/explode methods to
// generate the nonce value required to use the cryptsy API
struct timeval time;
gettimeofday(&time, NULL);
long mt = (unsigned long long)time.tv_sec;

char mtStr[10];
sprintf(mtStr, "%ul", mt);


// C does not have a build_http_query as PHP does so
// we just create the string neccessary with strcpy
// and strcat
char post_data[ strlen("method=") + strlen(method) + strlen("&nonce=") + strlen(mtStr) + strlen("&marketid=110") + strlen("&limit=1000") + strlen("&ordertype=sell&quantity=1000000&price=0.00000000")+ 1];
strcpy(post_data, "method=");
strcat(post_data, method);
strcat(post_data, "&nonce=");
strcat(post_data, mtStr);
if (marketid != NULL)
{
    strcat(post_data, "&marketid=");
    strcat(post_data, marketid);
}
if (limit != NULL)
{
    strcat(post_data, "&limit=");
    strcat(post_data, strInt);
}
if (ordertype != NULL)
{
    strcat(post_data, "&ordertype=");
    strcat(post_data, ordertype);
}
if (quantity != NULL)
{
    strcat(post_data, "&quantity=");
    strcat(post_data, quantity);
}
if (price != NULL)
{
    strcat(post_data, "&price=");
    strcat(post_data, price);
}
if (orderid != NULL)
{
    strcat(post_data, "&orderid=");
    strcat(post_data, orderid);
}

unsigned char *result;
unsigned int len = SHA512_DIGEST_LENGTH;

result = (unsigned char *)malloc(sizeof(char) * len);

HMAC_CTX ctx;
HMAC_CTX_init( &ctx );

// using SHA512
HMAC_Init_ex( &ctx, secret, strlen(secret), EVP_sha512(), NULL);
HMAC_Update( &ctx, (unsigned char *)&post_data, strlen(post_data));
HMAC_Final( &ctx, result, &len);
HMAC_CTX_cleanup( &ctx );

const char *header1 = "Sign: ";
size_t PrefixL = strlen(header1);
char resBuffer[PrefixL + 2 * len + 1];
strcpy(resBuffer, header1);
char *p = &resBuffer[PrefixL];

for (unsigned int i = 0; i < len; i++)
{
    sprintf(p, "%02x", (unsigned int)result[i]);
    p += 2;
}

const char *header2 = "Key: ";
size_t PrefixR = strlen(header2);
char keyBuffer[PrefixR + 2 * strlen(key) + 1];
strcpy(keyBuffer, header2);
strcat(keyBuffer, key);

free(result);

struct curl_slist *cslist = NULL;
cslist = curl_slist_append(cslist, resBuffer);
cslist = curl_slist_append(cslist, keyBuffer);

curl = curl_easy_init();
if (curl)
{
    curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible Cryptsy API C Client)");
    curl_easy_setopt(curl, CURLOPT_URL, url);
    curl_easy_setopt(curl, CURLOPT_POST, 1L);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(post_data));
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, cslist);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
    res = curl_easy_perform(curl);
    if (res != CURLE_OK)
    {
        cerr << "curl_easy_perform() failed " << curl_easy_strerror(res) << "\n" <<   endl;
    }
    curl_slist_free_all(cslist);
    curl_easy_cleanup(curl);
}
return data.data;
}

sorry couldn't get that last bit formatted but you got the idea, and yes i changed my API keys :)

抱歉不能格式化最后一个位,但你明白了,是的,我更改了API键:)

更多相关文章

  1. 如何将PHP数组的关联数组转移到javascript?
  2. PHP:在类中使用数据库
  3. 如何在不更改其键值的情况下删除数组的第一个元素?
  4. 纯真ip数据库查询的php实现(补充分组查询)
  5. 添加到数据库后,保持在同一页面而不刷新它
  6. PHP 导出 万级别数据 时间测试
  7. 以完整二叉树,数组格式获取所有节点
  8. php 写一个算法,查寻数组里第一个大于某数的值。
  9. 插入PHP数组作为MYSQL列

随机推荐

  1. thinkphp执行删除操作然后成功success后
  2. 从数组中回显键和值
  3. 架构比MVC更适合Web应用程序?
  4. PHP中 应该如何写 无符号右移
  5. php删除指定目录下的的文件/文件夹-用PHP
  6. 或者不使用Laravel的有说服力的关系查询
  7. thinkphp3.2【空操作和空控制器使用】
  8. python django 基本测试 及调试 201812
  9. phpcms v9访问单网页一级栏目自动跳转到
  10. eclipse 编写php错误