【问题标题】:converting curl call to python requests将 curl 调用转换为 python 请求
【发布时间】:2016-08-24 22:13:08
【问题描述】:

我在将 curl 请求转换为 Python 请求调用时遇到问题:

这是 curl 调用的样子:(取自:http://developers.payu.com/en/restapi.html#creating_new_order_api

curl -X POST https://secure.payu.com/api/v2_1/orders \
-H "Content-Type: application/json" \
-H "Authorization: Bearer 3e5cac39-7e38-4139-8fd6-30adc06a61bd" \
-d '{
    "notifyUrl": "https://your.eshop.com/notify",
    "customerIp": "127.0.0.1",
    "merchantPosId": "145227",
    "description": "RTV market",
    "currencyCode": "PLN",
    "totalAmount": "21000",
    "products": [
        {
            "name": "Wireless Mouse for Laptop",
            "unitPrice": "15000",
            "quantity": "1"
        },
        {
            "name": "HDMI cable",
            "unitPrice": "6000",
            "quantity": "1"
        }
    ]
}'

这是我在请求中写的:

import json
import requests
headers = {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer 3e5cac39-7e38-4139-8fd6-30adc06a61bd',
}

data = {
    "notifyUrl": "https://your.eshop.com/notify",
    "customerIp": "127.0.0.1",
    "merchantPosId": "145227",
    "description": "RTV market",
    "currencyCode": "PLN",
    "totalAmount": "21000",
    "products": [
        {
            "name": "Wireless Mouse for Laptop",
            "unitPrice": "15000",
            "quantity": "1"
        },
        {
             "name": "HDMI cable",
             "unitPrice": "6000",
             "quantity": "1"
        }
    ]
}

resp2 = requests.post('https://secure.payu.com/api/v2_1/orders', headers=headers, json=data)
print(resp2.json())

卷曲作为响应打印出来:

{"orderId":"V6GRPMNRLR160429GUEST000P01","status":{"statusCode":"SUCCESS"},"redirectUri":"https://secure.payu.com/pl/standard/co/summary?sessionId=HtnLqVtBJ5tcOKG2nX03TKwAXOYtXPHe&merchantPosId=145227&timeStamp=1461948331350&showLoginDialog=false&apiToken=9f31fcd1d0d1c5fde8aa57c2b16b5d6bbdfe81543a5f6a12cd39955a487fdaab"}

而 python 请求:

/usr/local/lib/python2.7/dist-packages/requests/packages/urllib3/util/ssl_.py:315: SNIMissingWarning: An HTTPS request has been made, but the SNI (Subject Name Indication) extension to TLS is not available on this platform. This may cause the server to present an incorrect TLS certificate, which can cause validation failures. For more information, see https://urllib3.readthedocs.org/en/latest/security.html#snimissingwarning.        
  SNIMissingWarning                                                                                                                                                                                                       
/usr/local/lib/python2.7/dist-packages/requests/packages/urllib3/util/ssl_.py:120: InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. For more information, see https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning.                                                                           
  InsecurePlatformWarning                                                                                                                                                                                                 
Traceback (most recent call last):                                                                                                                                                                                        
  File "/home/ubuntu/workspace/src/billing/testapi.py", line 30, in <module>                                                                                                                                              
    print(resp2.json())                                                                                                                                                                                                   
  File "/usr/local/lib/python2.7/dist-packages/requests/models.py", line 808, in json                                                                                                                                     
    return complexjson.loads(self.text, **kwargs)                                                                                                                                                                         
  File "/usr/lib/python2.7/dist-packages/simplejson/__init__.py", line 488, in loads                                                                                                                                      
    return _default_decoder.decode(s)                                                                                                                                                                                     
  File "/usr/lib/python2.7/dist-packages/simplejson/decoder.py", line 370, in decode                                                                                                                                      
    obj, end = self.raw_decode(s)                                                                                                                                                                                         
  File "/usr/lib/python2.7/dist-packages/simplejson/decoder.py", line 389, in raw_decode                                                                                                                                  
    return self.scan_once(s, idx=_w(s, idx).end())                                                                                                                                                                        
simplejson.scanner.JSONDecodeError: Expecting value: line 8 column 1 (char 7)   

有谁知道为什么它不适用于 requests ?谢谢

【问题讨论】:

  • 定义“不工作”,会报错吗?
  • 当我调用请求时,它不会打印出 curl 响应:它应该类似于 "{"orderId":"V6GRPMNRLR160429GUEST000P01","status":{"statusCode":"SUCCESS"} ,"redirectUri":"secure.payu.com/pl/standard/co/…"}" 。当我提出请求时,我得到“simplejson.scanner.JSONDecodeError: Expecting value: line 8 column 1 (char 7)”
  • 你得到的是一个堆栈跟踪。将其添加到问题中。
  • 您得到的响应不是 json。调用返回 html。
  • 所以你得到一个不同的响应。而不是print(resp.json())print(resp.text),也许看看标题和状态码。

标签: python curl python-requests


【解决方案1】:

网站以 302 状态码进行响应,包括 Location 标头:

>>> resp = requests.post('https://secure.payu.com/api/v2_1/orders', headers=headers, json=data)
>>> resp.history
[<Response [302]>, <Response [302]>]
>>> resp.history[0].headers['location']
'https://secure.payu.com/pl/standard/co/summary?sessionId=rrQ97fR2bxQJhUqCDORCbRa0uA4WlxJi&merchantPosId=145227&timeStamp=1461950205252&showLoginDialog=false&apiToken=f3599eca78ad55a16d84608e69f3ac7458b782598b064b337be07e8bd6c2c1d5'
>>> resp.history[0].text
u'{"orderId":"Z9W2H77TVD160429GUEST000P01","status":{"statusCode":"SUCCESS"},"redirectUri":"https://secure.payu.com/pl/standard/co/summary?sessionId=rrQ97fR2bxQJhUqCDORCbRa0uA4WlxJi&merchantPosId=145227&timeStamp=1461950205252&showLoginDialog=false&apiToken=f3599eca78ad55a16d84608e69f3ac7458b782598b064b337be07e8bd6c2c1d5"}'

您可以通过查看包含先前请求的response.history 列表来查看重定向历史记录(就像我在上面所做的那样)。 resp.history[0] 是这里的初始回复。请参阅文档中的Redirection and History

请注意,初始响应中的数据就在那里

当您使用 any Accept-Encoding 标头时,网站会执行此操作;如果你添加,你会得到相同的结果

-H "Accept-Encoding: gzip, deflate"

curl 命令,或通过将相同的标题(具有任何值)添加到supplied payu.apiari.io console(单击标题,然后添加Accept-Encoding 标题并为标题)。

您应该将其视为网站中的错误,因为指定标题是非常正常的事情。事实上,Python httplib 库(由 requests 间接使用)会为该标头设置一个 默认值,如果您自己省略它,那么 requests 甚至无法关闭它。因此,我已将此作为错误报告给 PayU。

作为一种变通方法,您可以使用response.history[0] 引用,或者更好的是,告诉请求不要首先遵循重定向:

>>> resp = requests.post('https://secure.payu.com/api/v2_1/orders', headers=headers, json=data, allow_redirects=False)
>>> resp.json()
{u'orderId': u'NBWTP5WNKK160429GUEST000P01', u'status': {u'statusCode': u'SUCCESS'}, u'redirectUri': u'https://secure.payu.com/pl/standard/co/summary?sessionId=PcvceJHf5En60Dier5gKxCyExiva4qh0&merchantPosId=145227&timeStamp=1461950329704&showLoginDialog=false&apiToken=5962ef901010ca4f8ef6491619217c060f4d53ed0d8e4eadb513d4e0811fc992'}

但请注意忽略 302 可能会干扰正常的状态代码,我看到 a 302 may indicate that additional security info is required

【讨论】:

  • 感谢 Martijn 指出,这解决了我的问题。
猜你喜欢
  • 1970-01-01
  • 2016-01-30
  • 2020-03-18
  • 2023-04-02
  • 1970-01-01
  • 2019-08-17
相关资源
最近更新 更多