Javascript Python POST请求相同的JS/PHP
我不擅长js/php,但我需要将下面的代码转换为Python Javascript版本:Javascript Python POST请求相同的JS/PHP,javascript,php,python,http-post,Javascript,Php,Python,Http Post,我不擅长js/php,但我需要将下面的代码转换为Python Javascript版本: function api_query(key,keyId,url,post,body,signature,cb){var method='POST'; var date=new Date(); var content_type='application/x-www-form-urlencoded; charset=UTF-8;'; var body_md5=CryptoJS.MD5(
function api_query(key,keyId,url,post,body,signature,cb){var method='POST';
var date=new Date();
var content_type='application/x-www-form-urlencoded; charset=UTF-8;';
var body_md5=CryptoJS.MD5(body);
var http= new XMLHttpRequest();http.onreadystatechange=function(){if (http.readyState===4){cb(JSON.parse(http.responseText));}};
http.open("POST",'http://'+url,true);http.setRequestHeader('x-pbx-date',date);
http.setRequestHeader('Accept','application/json');
http.setRequestHeader('Content-Type',content_type);
http.setRequestHeader('Content-MD5',body_md5);
http.setRequestHeader('x-pbx-authentication',keyId+':'+signature);
http.send(body);}
PHP版本:
$post = http_build_query($post);
$content_type = 'application/x-www-form-urlencoded';
$content_md5 = hash('md5', $post);
$signature = base64_encode(hash_hmac('sha1', $method."\n".$content_md5."\n".$content_type."\n".$date."\n".$url."\n", $secret_key, false));
$headers = array('Date: '.$date, 'Accept: application/json', 'Content-Type: '.$content_type, 'x-pbx-authentication: '.$key_id.':'.$signature, 'Content-MD5: '.$content_md5);
if (isset($opt['secure']) && $opt['secure']){
$proto = 'https';
}else{
$proto = 'http';
}
$ch = curl_init($proto.'://'.$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
$res = json_decode(curl_exec($ch), true);
if ($res){return $res;}else{return false;}
我已尝试请求库:
headers = {
'x-pbx-date': date,
'Content-Type': content_type,
'Content-MD5': body_md5_str,
'x-pbx-authentication': signature,
}
payload = {
'date_from': date_from,
'date_to': date_to,
}
r = requests.post(url, data=json.dumps(payload), headers=headers)
httlib2:
http = httplib2.Http()
response, content = http.request(url, 'POST', headers=headers, body=urllib.urlencode(payload))
urllib2:
req = urllib2.Request(url, data=urllib.urlencode(payload), headers=headers)
response = urllib2.urlopen(req).read()
什么都不管用。在每个重试服务器响应中:未验证。有什么想法吗 嗯,我想你的问题是身份验证。您没有在Python中演示如何做到这一点,但我想这是有点道理的,因为您在创建主体(
json.dumps
call)之前就以某种方式计算了body\u md5\u str
和signature
),所以它一定有问题。您是否确保您的代码生成与JS和PHP代码相同的值
就个人而言,我将实现一个身份验证类,该类将在请求触发之前添加必要的头。有关详细信息,请参阅,以下是我的(未经测试)尝试,如果我掌握了正确的详细信息:
import requests
import hashlib
import hmac
import base64
from wsgiref.handlers import format_date_time
import datetime
from time import mktime
CONTENT_TYPE_FORM_URLENCODED = "application/x-www-form-urlencoded"
class OnlinePBXAuth(requests.auth.AuthBase):
def __init__(self, key_id, secret):
self.key_id = key_id
self.secret = secret
def __call__(self, r):
content_type = r.headers.get("Content-Type", CONTENT_TYPE_FORM_URLENCODED)
body = r.body or ""
body_md5 = hashlib.md5(body).hexdigest()
date = format_date_time(mktime(datetime.datetime.now().timetuple()))
date = r.headers.get("Date", date)
r.headers["Date"] = date
r.headers["X-PBX-Date"] = date
sign = "\n".join([r.method, body_md5, content_type, date, r.url, ""])
signature = base64.b64encode(hmac.new(self.secret, sign, hashlib.sha1).hexdigest())
r.headers["Content-MD5"] = body_md5
r.headers["X-PBX-Authentication"] = "{0}:{1}".format(self.key_id, signature)
return r
这不是最漂亮的代码,但我想这应该能奏效
然后,像这样使用它:
auth = OnlinePBXAuth(KEY_ID, KEY_SECRET)
...
data = {"date_from": date_from, "date_to": date_to}
r = requests.post(url, data, auth=auth)
...
session = requests.Session(auth=OnlinePBXAuth(KEY_ID, KEY_SECRET))
...
r1 = session.post(url, data)
...
r2 = session.post(another_url, another_data)
或者甚至像这样:
auth = OnlinePBXAuth(KEY_ID, KEY_SECRET)
...
data = {"date_from": date_from, "date_to": date_to}
r = requests.post(url, data, auth=auth)
...
session = requests.Session(auth=OnlinePBXAuth(KEY_ID, KEY_SECRET))
...
r1 = session.post(url, data)
...
r2 = session.post(another_url, another_data)
我不确定它是否适用于空体请求(像大多数GET一样)和多部分分块体(因此请自行考虑或尽量避免这些),但我认为它适用于application/x-www-form-urlencoded和application/json编码的数据。是,我绝对确保我的代码生成与php/js等同等的值。我通过Chrome一步一步地调试找到了它。相同的md5哈希和签名。您的代码返回:
{“状态”:0,“注释”:“未验证”,“数据”:“}
Hmm。。。那我猜我错了。很抱歉不幸的是,我没有发现代码有任何问题。嗯,有一个服务可以显示向它发出的HTTP请求。也许值得尝试将PHP和Python程序(具有固定日期,因此请求将完全相同)都指向那里,并将请求与相同的数据进行比较?也许这会给Python版本带来一些线索。Ogh,在我的代码中生成的签名str中曾经有一个“\n”符号。包括你的工作在内的所有方法。我需要帮助。