python和php中的hmac签名不同

python和php中的hmac签名不同,php,python,hmacsha1,Php,Python,Hmacsha1,我不需要什么帮助来解决phphash\hmac的问题。我正在将一个现有的python脚本转换为php,该脚本为流程数据调用api。Python脚本运行良好 几乎没有类似的问题,其中之一就是 但这对我没有帮助。我已经尝试了很多方法,但每次我都发现错误,你的签名不匹配 这是我的php代码 $session_id = xxxxxxxxxxxxxxxxxxxxx; $accessKey = xxxxxxxxxxxxxxxxxxxxxx; $url = '/APIENDPOINT?action=mobil

我不需要什么帮助来解决php
hash\hmac
的问题。我正在将一个现有的
python
脚本转换为
php
,该脚本为流程数据调用api。Python脚本运行良好

几乎没有类似的问题,其中之一就是 但这对我没有帮助。我已经尝试了很多方法,但每次我都发现错误,你的签名不匹配

这是我的
php
代码

$session_id = xxxxxxxxxxxxxxxxxxxxx;
$accessKey = xxxxxxxxxxxxxxxxxxxxxx;
$url = '/APIENDPOINT?action=mobileAccess&autoJoin=true';
$timestamp = date('r');
$body = '{"expireTime": "20160322T2359", "doorOperations": [{"operation": "guest", "doors": ["103"]}], "endPointID": "enpointID", "format": "rfid48"}';

$params["action"] = "mobileAccess";
$params["override"] = "true";

$canonicalized_query = array();
foreach ($params as $param => $value) {
    $param = str_replace("%7E", "~", rawurlencode($param));
    $value = str_replace("%7E", "~", rawurlencode($value));
    $canonicalized_query[] = $param . "=" . $value;
}
ksort($canonicalized_query);
$canonicalized_query = implode("&", $canonicalized_query);

$string_to_sign = "POST\n";
$string_to_sign .= base64_encode(md5($body, true))."\n";
$string_to_sign .="application/json;charset=utf-8\n";
$string_to_sign .= $timestamp."\n";
$string_to_sign .= 'APIEDNPOINT?'.$canonicalized_query;
echo strlen($string_to_sign);
$header=array(
    'Date: '.$timestamp,
    'Content-Type: application/json;charset=utf-8', 
    'Content-MD5: '.base64_encode(md5($body, true)),    
    'Authorization: Basic '.$session_id.':'.base64_encode(hash_hmac('sha1', iconv(mb_detect_encoding($string_to_sign, mb_detect_order(), true), "UTF-8", $string_to_sign), iconv(mb_detect_encoding($accessKey, mb_detect_order(), true), "UTF-8", $accessKey), true))
url=self._basepath+url
        headers={}

        if body:
            # Encode request body as JSON
            body=json.dumps(body)
            headers['Content-Type']='application/json;charset=utf-8'

            # Compute MD5 digest
            h=hashlib.new('md5')
            h.update(body)
            headers['Content-MD5']=base64.b64encode(h.digest())

        # Format the date correctly, after applying the client/server skew
        headers['Date']=email.Utils.formatdate(time()+self._time_skew)

        if sign and 'id' in self._session:
            # Canonicalize the URL
            (canonicalized_resource,q,query_string)=url.partition('?')
            canonicalized_resource+=q+'&'.join(sorted(query_string.split('&')))

            # Build the string to be signed
            string_to_sign=method+"\n"
            if 'Content-MD5' in headers:
                string_to_sign+=headers['Content-MD5']
            string_to_sign+="\n"
            if 'Content-Type' in headers:
                string_to_sign+=headers['Content-Type']
            string_to_sign+="\n"+headers['Date']+"\n"+canonicalized_resource

            # Create the signature
            h=hmac.new(self._session['accessKey'].encode('utf-8'),\
                           string_to_sign.encode('utf-8'),hashlib.sha1)
            headers['Authorization']='Basic %s:%s'\
                %(self._session['id'],base64.b64encode(h.digest()))
下面是正在工作的
python
code

$session_id = xxxxxxxxxxxxxxxxxxxxx;
$accessKey = xxxxxxxxxxxxxxxxxxxxxx;
$url = '/APIENDPOINT?action=mobileAccess&autoJoin=true';
$timestamp = date('r');
$body = '{"expireTime": "20160322T2359", "doorOperations": [{"operation": "guest", "doors": ["103"]}], "endPointID": "enpointID", "format": "rfid48"}';

$params["action"] = "mobileAccess";
$params["override"] = "true";

$canonicalized_query = array();
foreach ($params as $param => $value) {
    $param = str_replace("%7E", "~", rawurlencode($param));
    $value = str_replace("%7E", "~", rawurlencode($value));
    $canonicalized_query[] = $param . "=" . $value;
}
ksort($canonicalized_query);
$canonicalized_query = implode("&", $canonicalized_query);

$string_to_sign = "POST\n";
$string_to_sign .= base64_encode(md5($body, true))."\n";
$string_to_sign .="application/json;charset=utf-8\n";
$string_to_sign .= $timestamp."\n";
$string_to_sign .= 'APIEDNPOINT?'.$canonicalized_query;
echo strlen($string_to_sign);
$header=array(
    'Date: '.$timestamp,
    'Content-Type: application/json;charset=utf-8', 
    'Content-MD5: '.base64_encode(md5($body, true)),    
    'Authorization: Basic '.$session_id.':'.base64_encode(hash_hmac('sha1', iconv(mb_detect_encoding($string_to_sign, mb_detect_order(), true), "UTF-8", $string_to_sign), iconv(mb_detect_encoding($accessKey, mb_detect_order(), true), "UTF-8", $accessKey), true))
url=self._basepath+url
        headers={}

        if body:
            # Encode request body as JSON
            body=json.dumps(body)
            headers['Content-Type']='application/json;charset=utf-8'

            # Compute MD5 digest
            h=hashlib.new('md5')
            h.update(body)
            headers['Content-MD5']=base64.b64encode(h.digest())

        # Format the date correctly, after applying the client/server skew
        headers['Date']=email.Utils.formatdate(time()+self._time_skew)

        if sign and 'id' in self._session:
            # Canonicalize the URL
            (canonicalized_resource,q,query_string)=url.partition('?')
            canonicalized_resource+=q+'&'.join(sorted(query_string.split('&')))

            # Build the string to be signed
            string_to_sign=method+"\n"
            if 'Content-MD5' in headers:
                string_to_sign+=headers['Content-MD5']
            string_to_sign+="\n"
            if 'Content-Type' in headers:
                string_to_sign+=headers['Content-Type']
            string_to_sign+="\n"+headers['Date']+"\n"+canonicalized_resource

            # Create the signature
            h=hmac.new(self._session['accessKey'].encode('utf-8'),\
                           string_to_sign.encode('utf-8'),hashlib.sha1)
            headers['Authorization']='Basic %s:%s'\
                %(self._session['id'],base64.b64encode(h.digest()))
在python中调用
端点

ws.send_request("POST","APIENDPOINT",\
                                         {"doorOperations": [{"doors": ["101"],"operation": "guest"}],"expireTime": "20150522T2359","format": "rfid48","endPointID":"endpointid"})
我已经检查了两个脚本的
body content md5和string to sign
输出是否相同