我搜索并发现了一些问题,这些问题解决了我想要实现的目标,但我似乎无法完全理解这一点。我是编程的新手,并且正在尝试复制供应商以少数几种语言(PHP,Ruby,Perl,C#)提供的一些代码。我已经使用了PHP代码,并尽我所能在Python中复制它,除了这个签名函数之外,它已经完成了所有工作。基本上,我必须获取一组数据,这些数据由用户通过Web表单传递,签名并将其发送给Web服务侦听器进行处理。尽我所能,我无法获得匹配的签名值。遗憾的是,供应商不为其他样品提供代码级支持,所以我在那里运气不好。这是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')
以下是我正在尝试签名的数据示例(缩减为通过Python代码中的sign_data()方法返回的对象:
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代码中弄乱它,但它似乎没有用。提前谢谢!
答案 0 :(得分:1)
如果你仍然坚持这个问题,你可能想尝试使用:
sign_signature = base64.b64encode(hmac.new(secret_key, sign_payload, hashlib.sha256).hexdigest())
此处的关键是使用hexdigest()
代替digest()
。
在我的情况下,我失去了2个小时,发现为什么Python在尝试使用新的“app secret proof”签署Facebook API请求时没有产生与PHP相同的结果。