Swift 3, в Poloniex trade Api get - ошибка: Неверная команда

Мой код:

func testApi() {
        Alamofire.request("https://www.poloniex.com/tradingApi", withMethod: .post, parameters: ["command":"returnDepositAddresses","nonce":nonce()], encoding: .json, headers: ["Key":apiKey,"Sign":newSecret]).responseJSON() { (dataBack) in
            print(dataBack)
        }
    }
func nonce() -> Int {
        let date = "\(NSDate().timeIntervalSince1970)"
        let UnixInt = Double(date)!
        return Int(UnixInt)
    }

И я понимаю:

SUCCESS: {
error = "Invalid command.";}

Я не могу найти никакой информации о poloniex api с Swift или Objective C... Так что, если кто-то может помочь - буду очень благодарен


person VladyslavPG    schedule 05.09.2016    source источник
comment
Вы уверены, что «[ошибка: неверная команда.]» исходит именно из этой строки печати?   -  person pedrouan    schedule 05.09.2016
comment
@педруан Да. Я удалил команды печати, когда писал эту тему. Но уже редактировать.   -  person VladyslavPG    schedule 05.09.2016
comment
Что ж. ошибка не связана с API, так как ответ кажется правильным. Добавьте эту строку сразу после строки «print(dataBack.response)»: print(dataBack)   -  person pedrouan    schedule 05.09.2016
comment
@pedrouan хорошо, добавляю. Optional(<NSHTTPURLResponse: 0x600000031020> { URL: https://www.poloniex.com/tradingApi } { status code: 200, headers { "Cache-Control" = private; "Content-Encoding" = gzip; "Content-Type" = "application/json"; Date = "Mon, 05 Sep 2016 05:11:34 GMT"; Server = "cloudflare-nginx"; "cf-ray" = "2dd72e64b2dc30e4-SIN"; } }) SUCCESS: { error = "Invalid command."; } SUCCESS   -  person VladyslavPG    schedule 05.09.2016
comment
Я думаю, что что-то не так с параметрами, может быть... Потому что, если я изменю его на [команда: что-нибудь] - будет такая же ошибка.   -  person VladyslavPG    schedule 05.09.2016


Ответы (2)


Вот пример того, как сформировать NSURLRequest для poloniex.com.

Представьте, что ваш:

  1. API Key = @"апикей"
  2. Secret = @"секрет"
  3. nonce = @"1"

Начнем с самых простых вещей:

NSMutableURLRequest *theURLRequest = [NSMutableURLRequest new];
theURLRequest.URL = [NSURL URLWithString:@"https://poloniex.com/tradingApi"];
theURLRequest.HTTPMethod = @"POST";

NSString *theBodyString = @"command=returnBalances&nonce=1";

theURLRequest.HTTPBody = [theBodyString dataUsingEncoding:NSUTF8StringEncoding];
[theURLRequest setValue:@"apikey" forHTTPHeaderField:@"Key"];

А теперь самое сложное...

Что касается меня, то в документации Poloniex не очень понятно, что они хотят под значением поля заголовка "Sign", но в основном они хотят, чтобы вы передавали строку, которая должна быть результатом алгоритма шифрования HMAC SHA512, примененного к theBodyString и< /strong> Secret (в нашем примере это просто @"secret").

Вот функция, которая вернет вам HMAC SHA512 NSData:

#import <CommonCrypto/CommonHMAC.h>
NSData * getHMACSHA512FromSecretKeyStringAndBodyString(NSString *theSecretKeyString, NSString *theBodyString)
{
    const char *cSecret  = [theSecretKeyString cStringUsingEncoding:NSUTF8StringEncoding];
    const char *cBody = [theBodyString cStringUsingEncoding:NSUTF8StringEncoding];
    unsigned char cHMAC[CC_SHA512_DIGEST_LENGTH];
    CCHmac(kCCHmacAlgSHA512, cSecret, strlen(cSecret), cBody, strlen(cBody), cHMAC);
    return [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];
}

Итак, бег:

NSData *theData = getHMACSHA512FromSecretKeyStringAndBodyString(@"secret", @"command=returnBalances&nonce=1");
NSString *theString = [NSString stringWithFormat:@"%@", theData];

Дал бы нам почти то, что мы хотели.

Наш результат равен:

<c288f881 a6808d0e 78827ec6 ca9d6b9c 34ec1667 07716303 0d6d7abb 2b225456 31176f52 8347ab0f d6671ec5 3aec1f7d 3b6de8b8 e3ccc23d e62fd594 52d70db5>

Хотя то, что мы на самом деле хотим (согласно http://www.freeformatter.com/hmac-generator.html):

c288f881a6808d0e78827ec6ca9d6b9c34ec1667077163030d6d7abb2b22545631176f528347ab0fd6671ec53aec1f7d3b6de8b8e3ccc23de62fd59452d70db5

So, basically, just remove the <, > and symbols from your string;

theString = [theString stringByReplacingOccurrencesOfString:@"<" withString:@""];
theString = [theString stringByReplacingOccurrencesOfString:@">" withString:@""];
theString = [theString stringByReplacingOccurrencesOfString:@" " withString:@""];
[theURLRequest setValue:theString forHTTPHeaderField:@"Sign"];

Your theURLRequest is now ready and should succeed getting the tradingApi of poloniex.com.

person OlDor    schedule 17.04.2017
comment
Это круто! Вы все правильно поняли, и это мне очень помогло. Спасибо! :) - person Bob de Graaf; 22.12.2017

На самом деле это не проблема ни Swift, ни iOS. Это связано с тем, что вы обращаетесь к методам Trading API, и им могут потребоваться дополнительные параметры (кроме nonce) в вашем POST-запросе:

Проверь это:

Все вызовы торгового API отправляются через HTTP POST на https://poloniex.com/tradingApi и должны содержать следующие заголовки:

Ключ — ваш ключ API. Sign — данные POST запроса, подписанные «секретом» вашего ключа в соответствии с методом HMAC-SHA512. Кроме того, все запросы должны включать параметр POST "nonce". Параметр nonce представляет собой целое число, которое всегда должно быть больше предыдущего используемого одноразового номера.

Таким образом:

Все ответы от торгового API представлены в формате JSON. В случае ошибки ответ всегда будет иметь следующий формат:

{"ошибка":""}

https://temp.poloniex.com/support/api/

person pedrouan    schedule 05.09.2016
comment
Я уже добавляю ключ заголовков и код подписи (когда это неправильно - я получаю сообщение об ошибке: неверный ключ или код подписи), поэтому я не могу понять, какая команда недействительна - person VladyslavPG; 05.09.2016
comment
Я имею в виду, что ключ и знак точно верны. Это ошибка API или запроса. И моя тема здесь для устранения этой ошибки. Если его возможно... - person VladyslavPG; 05.09.2016
comment
ОК, я не понял ваш предыдущий комментарий, похоже, у вас проблемы с кодом подписи. Передавали ли вы какие-либо предыдущие команды раньше? Или это у вас первый пробег? И попробуйте это set the "account" POST parameter to "all" - person pedrouan; 05.09.2016
comment
Теперь ключ и знак верны. Когда я написал неправильный ключ, я получил ошибку = Неверная пара ключ/секрет API. И теперь решаю эту проблему. Но вторая проблема (почему я создаю эту тему) - это ошибка = Неверная команда. Я хочу понять, что мне теперь делать с этим... Я пробовал с разными параметрами, но получаю ту же ошибку. В примере кода Java они используют только returnBalances без каких-либо дополнительных команд или параметров... - person VladyslavPG; 05.09.2016
comment
Да. Но если я использую команду: returnDepositAddresses - я получаю ту же ошибку. Если я использую hello:hello - я получаю ту же ошибку... Для любых параметров я получаю ту же ошибку. - person VladyslavPG; 05.09.2016
comment
В этом случае я не могу помочь, так как это касается ваших секретных данных для входа. Вы говорите, что ваш java-запрос работает правильно? Разве для этого не требуется дополнительный заголовок или что-то в этом роде? - person pedrouan; 05.09.2016
comment
Например, простой запрос Python: urllib2.Request('https://poloniex.com/tradingApi', post_data, headers), где данные сообщения: req['command'] = 'returnDepositAddresses' req['nonce'] = int(time.time()*1000), а заголовки: headers = { 'Sign': sign, 'Key': self.APIKey }, это все, что нужно для правильного запроса... - person VladyslavPG; 05.09.2016
comment
Попробуйте также print(self.APIKey) и print(sign) прямо перед строкой Almofire.request. Не публикуйте, просто проверьте, есть ли они. - person pedrouan; 05.09.2016