Мне нужна помощь в преобразовании генератора сигнатур API Walmart из PHP в Python. Я все еще немного новичок в PHP и Python (хотя я быстро учусь), но чтобы использовать API разработчика Walmart (НЕ открытый API), вам, очевидно, нужно знать, как работает криптография, поэтому я немного застрял.
Вот оригинальный код PHP от https://developer.walmart.com/#/apicenter/contentProvider#introduction:
$URL = //Walmart API URL along with path and query parameters
$RequestMethod = //Request method type i.e GET, POST
$Timestamp = round(microtime(true) * 1000); //Current system timestamp
function _GetWalmartAuthSignature($URL, $RequestMethod, $Timestamp) {
$WalmartPrivateKey = //Your Walmart Private Key;
$WalmartConsumerID = //Your Walmart Comsumer Id;
// CONSTRUCT THE AUTH DATA WE WANT TO SIGN
$AuthData = $WalmartConsumerID."\n";
$AuthData .= $URL."\n";
$AuthData .= $RequestMethod."\n";
$AuthData .= $Timestamp."\n";
// GET AN OPENSSL USABLE PRIVATE KEY FROMM THE WARMART SUPPLIED SECRET
$Pem = _ConvertPkcs8ToPem(base64_decode($WalmartPrivateKey));
$PrivateKey = openssl_pkey_get_private($Pem);
// SIGN THE DATA. USE sha256 HASH
$Hash = defined("OPENSSL_ALGO_SHA256") ? OPENSSL_ALGO_SHA256 : "sha256";
if (!openssl_sign($AuthData, $Signature, $PrivateKey, $Hash))
{
// IF ERROR RETURN NULL
return null;
}
//ENCODE THE SIGNATURE AND RETURN
return base64_encode($Signature);
}
function _ConvertPkcs8ToPem($der)
{
static $BEGIN_MARKER = "-----BEGIN PRIVATE KEY-----";
static $END_MARKER = "-----END PRIVATE KEY-----";
$key = base64_encode($der);
$pem = $BEGIN_MARKER . "\n";
$pem .= chunk_split($key, 64, "\n");
$pem .= $END_MARKER . "\n";
return $pem;
}
Я не совсем верю в PHP-код Walmart, так как они случайно закомментировали строку, в которой находится оператор if. Кроме того, они base64_decode закрытый ключ Walmart, а затем сразу base64_encode его снова ... какой смысл в этом?
В любом случае, вот что я придумал в Python:
import base64
import time
# Request URL
url = 'https://developer.walmart.com/orderProxy/order-api-doc-app/rest/v3/orders?createdStartDate=2018-12-01&createdEndDate=2018-12-07&limit=10'
request_method = 'GET'
timestamp = int(time.time() * 1000)
walmart_private_key = '**redacted**'
walmart_consumer_id = '**redacted**'
# Construct auth_data for signature.
auth_data = walmart_consumer_id + "\n"
auth_data += url + "\n"
auth_data += request_method + "\n"
auth_data += str(timestamp) + "\n"
# Convert private key from PKCS8 to PEM (without using a new function)
# The original PHP says to decode, and then immediately re-encode the private key ... so I'm skipping that ...?
pem_start = "-----BEGIN PRIVATE KEY-----\n"
key_chunk = [walmart_private_key[i:i+64] for i in range(0,len(walmart_private_key), 64)]
pem_end = "\n-----END PRIVATE KEY-----\n"
pem = pem_start + "\n".join(key_chunk) + pem_end
# openssl_pkey_get_private, but with Python ...?
# openssl_sign, but with Python ...?
У меня проблемы с поиском / пониманием Python-эквивалента openssl_pkey_get_private и openssl_sign.
Часть кода $ Hash выглядит так, будто она просто проверяет, знает ли PHP, что такое sha256, или проверяет, какое имя оно использует? Правильно?
Должен ли я понять, что openssl_pkey_get_private берет ключ (который я только что вручную преобразовал в определенный формат) и возвращает закрытый ключ, который сопряжен с этим исходным ключом (поэтому Walmart может, при наличии того же ключа, получить тот же ключ и подтвердите, кто запрашивает данные)?
openssl_sign Я думаю, я понимаю. Он генерирует подпись, когда ему передаются указанные данные (те же данные, которые будут отправлены в заголовке с запросом API, в сочетании с закрытым ключом, так как именно они проверяют, кто запрашивает данные?). Опять же, я все еще не уверен, как это сделать в Python.
Любая помощь будет принята с благодарностью. Спасибо.