Я искал и нашел несколько вопросов, которые были адресованы тем, что я пытаюсь выполнить, но я не могу сказать, что это не так. Я новичок в программировании и пытаюсь реплицировать немного кода, доступного мне продавцом на нескольких языках (PHP, Ruby, Perl, C#). Я взял PHP-код и попытался изо всех сил реплицировать его на Python и получил все, кроме этой функции подписи. В принципе, я должен взять массив данных, которые передаются пользователем через веб-форму, подписывать ее и отправлять ее слушателю веб-сервисов для обработки. Попытайтесь, как я мог, я не могу получить значения подписи для соответствия. Поставщик, к сожалению, не предоставляет поддержку уровня кода для чего-либо другого, кроме своих образцов, поэтому мне там не повезло. Вот PHP пример:Подпись Python HMAC-SHA256 отличается от подписи PHP
<?php
define ('HMAC_SHA256', 'sha256');
define ('SECRET_KEY', 'secret_key_redacted');
function sign ($params) {
return signData(buildDataToSign($params), SECRET_KEY);
}
function signData($data, $secretKey) {
return base64_encode(hash_hmac('sha256', $data, $secretKey, true));
}
function buildDataToSign($params) {
$signedFieldNames = explode(",",$params["signed_field_names"]);
foreach ($signedFieldNames as &$field) {
$dataToSign[] = $field . "=" . $params[$field];
}
return commaSeparate($dataToSign);
}
function commaSeparate ($dataToSign) {
return implode(",",$dataToSign);
}
?>
, который вызывается так:
<?php
foreach($params as $name => $value) {
echo "<input type=\"text\" id=\"" . $name . "\" name=\"" . $name . "\" value=\"" . $value . "\"/>\n";
}
echo "<input type=\"text\" id=\"signature\" name=\"signature\" value=\"" . sign($params) . "\"/>\n";
?>
Это то, что я использовал в Python, чтобы попытаться повторить:
def payment_confirmation(self, *args, **kw):
vars = cherrypy.request.params #takes POST parameters from previous page
del vars['submit'] #removed so it doesnt get signed - part of POST from prev. page
def sign_data(vars):
for key, value in vars.iteritems():
yield "%s=%s," % (key, value)
sign_payload = ''.join(sign_data(vars)).rstrip(',')
sign_signature = hashlib.sha256(sign_payload + secret_key).digest().encode('base64')
Вот образец данные, которые я пытаюсь подписать (сведены в объект, возвращаемый с помощью метода sign_data() в коде Python:
access_key=12345,reference_number=123456789,currency=USD,locale=en,profile_id=1234567,transaction_type=authorization,signed_date_time=2013-07-22T16:30:43Z,amount=25.00,transaction_uuid=0dc4a151-f2ec-11e2-bb29-005056c00008,payment_method=card,signed_field_names=access_key,profile_id,transaction_uuid,payment_token,signed_field_names,signed_date_time,locale,payment_method,transaction_type,amount,reference_number,currency,payment_token=0000000000000000
Я понимаю, что это длинный снимок, но кто-нибудь видит что-то, что явно не соответствует моему методу подписи в Python и предоставленному методу в PHP? Я думал, что это может быть способ, которым PHP-функция кодирует пары ключ-значение, поэтому я попытался объединиться с этим в коде Python, но он, похоже, не сработал. Заранее спасибо!
Почему b64encode hexdigest? Facebook не хочет, чтобы вы, для одного. См https://github.com/pythonforfacebook/facebook-sdk/commit/157799da3bb725b6b2f8698f7ee53b4d0e2abf2c, который использует hmac.new (app_secret.encode ('ASCII'), тзд = access_token.encode ('ASCII'), digestmod = hashlib.sha256) .hexdigest() – drewp