使用嵌套json发布请求

时间:2017-10-17 22:20:32

标签: php python json python-requests

php curl to python request

尝试向API发出请求以订购产品。似乎我无法弄清楚如何以API正确接收它的方式实际发送带有后请求的json-payload。

该服务仅提供php示例:

PHP-示例:

$params = array();
$params['access_token']             = '123abc';
$params['product_total']            = 2; 
$params['product_list'] = array(
    array(
        'product_id' => 111
    ),
    array(
        'product_id' => 222
    ),
);

到目前为止这是我的python代码:

import requests

payload = {
            "access_token": "123abc",
            "product_total": 2,
            "product_list":[
                {
                    "product_id": 111,
                    ...
                },
                {
                    "product_id": 222,
                    ...
                }]
           }

r = requests.post(url, data=payload, verify=False)
r.text
> u'{"code":123,"msg":"product_id is empty"}'

我发送product_list的方式出了问题。

我也尝试过:

import json
r = requests.post(url, data=json.dumps(payload), verify=False)
> u'{"code":456,"msg":"access_token is empty"}'

r = requests.post(url, json=json.dumps(payload), verify=False)
> u'{"code":456,"msg":"access_token is empty"}'

但是它不能再读access_token了。

我正在使用python 2.7.9requests 2.18.4

更新 也失败了......

r = requests.post(url, json=payloal, verify=False)
> u'{"code":456,"msg":"access_token is empty"}'

更新2:

我深入研究了我从API文档中获得的php示例,我发现了这个:

curl_setopt($this->__ch, CURLOPT_URL, $apiUrl );
curl_setopt($this->__ch, CURLOPT_HEADER, 0);
curl_setopt($this->__ch, CURLOPT_USERAGENT, $_SERVER ['HTTP_USER_AGENT']);
curl_setopt($this->__ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($this->__ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($this->__ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($this->__ch, CURLOPT_POST, 1 ); 
curl_setopt($this->__ch, CURLOPT_POSTFIELDS, http_build_query($this->__params));

也许有人可以发现我错过的这些内容。

更新3:

我可以毫无问题地运行php-example并以此方式创建订单。但仍然无法用python做到这一点。

2 个答案:

答案 0 :(得分:1)

我找到了解决方案:

payload = {
            "access_token": "123abc",
            "product_total": 2,
            "product_list[0][product_id]": 111,
            "product_list[1][product_id]": 222,
           }

r = requests.post(url, data=payload, verify=False)

我是如何解决的:

我通过打开一个本地端口并将工作的php请求发送到此端口来重新设计python函数应该具有的最终发布请求,以便查看其有效负载。

(mac terminal)
user$ nc -l localhost 11111 # to open port
POST / HTTP/1.1
Host: localhost:11111
Accept: */*
Content-Length: 115
Content-Type: application/x-www-form-urlencoded

access_token=123abc&product_total=2&product_list%5B0%5D%5Bproduct_id%5D=111&product_list%5B1%5D%5Bproduct_id%5D=22

只需要解码有效载荷:

from urllib import parse
parse.unquote("access_token=123abc&product_total=2&product_list%5B0%5D%5Bproduct_id%5D=111&product_list%5B1%5D%5Bproduct_id%5D=22")
'access_token=123abc&product_total=2&product_list[0][product_id]=111&product_list[1][product_id]=22'

现在有效负载的结构清晰可见,只需复制它就可以进行python post请求。

这就是有效载荷查找我的初始python post请求的方式:

'access_token=123abc&product_total=2&product_list=product_id&product_list=product_id'

你可以清楚地看到它为什么不起作用......

如果有人有解释为什么带有json-payload的帖子请求不起作用 - 我仍然对此非常感兴趣。到目前为止我唯一能想到的是,API根本不支持json-payload?

答案 1 :(得分:0)

根据之前类似问题的经验,您应该尝试在发布之前将product_list中的JSON(实际上是您的Python序列列表)转换为相同JSON的字符串表示形式:

import requests
import json

payload = {
            "access_token": "123abc",
            "product_total": 2,
            "product_list": json.dumps([
                {
                    "product_id": 111,
                    ...
                },
                {
                    "product_id": 222,
                    ...
                }])
           }

r = requests.post(url, data=payload, verify=False)
r.text