I searched and found a few questions that sort of addressed what I am trying to accomplish, but I can't seem to quite put my finger on this. I'm new to programming and am trying to replicate a bit of code that's available to me by the vendor in a handful of languages (PHP, Ruby, Perl, C#). I've taken the PHP code and tried my best to replicate it in Python and have gotten everything working except this signature function. Basically, I have to take an array of data that's being passed in by a user via web form, sign it, and send it to the web services listener to process. Try as I might, I can't get the signature values to match. The vendor unfortunately does not provide code-level support for anything other than their samples, so I'm out of luck there. Here's the PHP sample:
<?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);
}
?>
which is invoked as such:
<?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";
?>
This is what I've used in Python to attempt to replicate:
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')
Here's a sample of the data I'm trying to sign (reduced into the object that's being returned via the sign_data() method in the Python code:
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
I realize it's a long-shot, but does anyone see anything that's obviously incorrect about my signature method in Python vs. the provided method in PHP? I thought it could be a way that the PHP function is encoding the key-value pairs so I tried messing around with that in the Python code but it doesn't seem to have worked. Thanks in advance!