如何在 PHP 中使用 NIMLAB Crypto Exchange API 实现身份验证?

问题描述 投票:0回答:1

我正在尝试按照其官方文档实施身份验证以连接 NIMLAB 加密货币交易所:NIMLAB API 文档

但是,我不断遇到身份验证和签名生成问题。不幸的是,到目前为止我尝试过的解决方案都不起作用。

NIMLAB 支持团队提供了一个 Python 示例,他们声称该示例完美运行:

import json
import hashlib
import asyncio
import aiohttp
import logging

from aiohttp.client_exceptions import ContentTypeError, ClientConnectorError
from urllib.parse import urlencode, quote

class NIMLABAPI:
    def __init__(self, apiUrl, apiKey, apiSecret):
        if not apiUrl:
            raise ValueError('apiUrl is required in class ExchangerAPI')
        if not apiKey:
            raise ValueError('apiKey is required in class ExchangerAPI')
        if not apiSecret:
            raise ValueError('apiSecret is required in class ExchangerAPI')

        self.config = {
            "apiUrl": apiUrl,
            "apikey": apiKey,
            "secret": apiSecret
        }

        self.session = aiohttp.ClientSession()

    def generate_hash(self, get_params, post_params):

        for key in get_params:
            if isinstance(get_params[key], list):
                get_params[key] = [str(value) for value in get_params[key]]
            else:
                get_params[key] = str(get_params[key])

        params = {**get_params, **post_params}
        checksum_params = hashlib.sha256(json.dumps(params, ensure_ascii=False, separators=(',', ':')).encode()).hexdigest()
        HASH = hashlib.sha256((checksum_params + self.config['secret']).encode()).hexdigest()
        return HASH

    async def call(self, method, param=None, rewriteConfig=None):
        if param is None:
            param = {}
        get = param.get('get', {})
        post = param.get('post', {})
        post_out =  json.dumps(post, ensure_ascii=False)

        if not isinstance(get, dict):
            return {"errorCode": 20, "message": 'Error invalid "get" params must be object'}
        if not isinstance(post, dict):
            return {"errorCode": 21, "message": 'Error invalid "post" params must be object'}

        configService = {**self.config, **(rewriteConfig or {})}
        method_parts = method.split(':')
        typeMethod = 'POST'

        if len(method_parts) == 2:
            typeMethod, method = method_parts[0].upper(), method_parts[1]
        else:
            method = method_parts[0]

        if typeMethod == 'GET':
            get['time'] = int(1000 * asyncio.get_event_loop().time())

        url_params = "&".join(f"{key}={value}" if not isinstance(value, list) else "&".join(f"{key}[]={item}" for item in value) for key, value in get.items())

        url = f"{configService['apiUrl']}{method}?{url_params}" if url_params else f"{configService['apiUrl']}{method}"

        HASH = self.generate_hash(get, post)
        print(f"URL: {url}")
        async with self.session.request(typeMethod, url, headers={
            'cache-control': 'no-cache',
            'apikey': configService['apikey'],
            'hash': HASH,
            'Content-Type': 'application/json'
        }, data=post_out) as response:
            while True:
                try:
                    if response.status in [502, 504, 409]:
                        logging.warning(f"Error {response.status}: {response.reason}. Retrying in a while...")
                        await asyncio.sleep(15)
                        continue

                    if response.status != 200:
                        cf_mitigated = response.headers.get('cf-mitigated')
                        if cf_mitigated:
                            ray_id = response.headers.get('cf-ray', 'unknown')
                            raise Exception(f'CloudFlare mitigation required "{cf_mitigated}". RayID: {ray_id}. '
                                            'Ask support to whitelist your IP.')

                        reason = response.reason or 'Unknown error'
                        raise Exception(f'Error API: {response.status} - {reason}')

                    if 'application/json' not in response.headers.get("content-type", ""):
                        text = await response.text()
                        raise Exception(f'Error: Response not JSON: {text}')

                    text = await response.text()
                    response_data = json.loads(text)
                    if not response_data.get('success') or not response_data.get('data'):
                        error_msg = response_data.get('error', 'Unknown error')
                        raise Exception(f'Error API: {error_msg}')

                    return json.dumps(response_data.get('data', {}))

                except aiohttp.ClientError as error:
                    logging.exception("API call error", exc_info=error)

    async def close(self):
        await self.session.close()

我需要使这个逻辑适应 PHP。我已经尝试过使用 hash_hmac 和各种方法来创建签名,但似乎没有任何效果。

任何人都可以帮我将此代码转换为 PHP 或指导我如何通过签名生成正确实现身份验证吗?

API 文档:https://nimlab.eu/service/api-docs/#/

提前谢谢您!

是的,我忘了添加代码:

<?php

class NIMLABAPI {
    private $apiUrl;
    private $apiKey;
    private $apiSecret;

    public function __construct($apiUrl, $apiKey, $apiSecret) {
        if (empty($apiUrl)) {
            throw new InvalidArgumentException('apiUrl is required');
        }
        if (empty($apiKey)) {
            throw new InvalidArgumentException('apiKey is required');
        }
        if (empty($apiSecret)) {
            throw new InvalidArgumentException('apiSecret is required');
        }

        $this->apiUrl = $apiUrl;
        $this->apiKey = $apiKey;
        $this->apiSecret = $apiSecret;
    }

    private function generateHash($getParams, $postParams) {
        foreach ($getParams as $key => &$value) {
            if (is_array($value)) {
                $value = array_map('strval', $value);
            } else {
                $value = strval($value);
            }
        }

        $params = array_merge($getParams, $postParams);
        $checksumParams = hash('sha256', json_encode($params, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
        $hash = hash('sha256', $checksumParams . $this->apiSecret);
        return $hash;
    }

    public function call($method, $params = [], $rewriteConfig = []) {
        $get = $params['get'] ?? [];
        $post = $params['post'] ?? [];

        if (!is_array($get)) {
            return ["errorCode" => 20, "message" => 'Error: "get" params must be an array'];
        }
        if (!is_array($post)) {
            return ["errorCode" => 21, "message" => 'Error: "post" params must be an array'];
        }

        $configService = array_merge([
            'apiUrl' => $this->apiUrl,
            'apikey' => $this->apiKey,
            'secret' => $this->apiSecret
        ], $rewriteConfig);

        $methodParts = explode(':', $method);
        $typeMethod = count($methodParts) === 2 ? strtoupper($methodParts[0]) : 'POST';
        $method = count($methodParts) === 2 ? $methodParts[1] : $methodParts[0];

        if ($typeMethod === 'GET') {
            $get['time'] = intval(microtime(true) * 1000);
        }

        $urlParams = http_build_query($get);
        $url = $configService['apiUrl'] . $method . ($urlParams ? '?' . $urlParams : '');

        $hash = $this->generateHash($get, $post);

        $headers = [
            'cache-control: no-cache',
            'apikey: ' . $configService['apikey'],
            'hash: ' . $hash,
            'Content-Type: application/json'
        ];

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $typeMethod);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        if ($typeMethod === 'POST') {
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post, JSON_UNESCAPED_UNICODE));
        }

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);

        if ($httpCode !== 200) {
            $error = "Error: HTTP $httpCode";
            if (strpos($contentType, 'application/json') !== false) {
                $responseData = json_decode($response, true);
                $error = $responseData['error'] ?? $error;
            }
            curl_close($ch);
            throw new Exception($error);
        }

        curl_close($ch);
        $responseData = json_decode($response, true);

        if (empty($responseData['success']) || empty($responseData['data'])) {
            throw new Exception('API Error: ' . ($responseData['error'] ?? 'Unknown error'));
        }

        return $responseData['data'];
    }
}

?>

python php api cryptography http-headers
1个回答
0
投票

尝试使用chatgpt,它总能帮助我解决此类问题!

© www.soinside.com 2019 - 2024. All rights reserved.