我正在尝试使用 python 和
httpx
对 Xero Invoice Api 进行 API 调用。我使用以下api方法:
async def create_invoice(
invoice_detail: InvoiceCreateRequest,
token_manager=Depends(oauth_manager)
) -> InvoiceCreateResponse:
base_url = 'https://api.xero.com/api.xro/2.0/Invoices'
headers = {
'Xero-Tenant-Id': get_settings().TENANT_ID,
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': f'Bearer {await token_manager.access_token}'
}
data = invoice_request_to_dict(invoice_detail)
async with httpx.AsyncClient() as client:
response = await client.request(
method='POST',
url=base_url,
headers=headers,
data=data
)
data
对象看起来像这样:
{
"Type": "ACCREC",
"Contact": {
"ContactID": "3ed357da-0988-4ea1-b1b7-96829e0dde69"
},
"DueDate": r"\/Date(1518685950940+0000)\/",
"LineItems": [
{
"Description": "Services as agreed",
"Quantity": "4",
"UnitAmount": "100.00",
"AccountCode": "200"
}
],
"Status": "AUTHORISED"
}
这给我留下了以下错误:
b'{\r\n "ErrorNumber": 14,\r\n "Type": "PostDataInvalidException",\r\n "Message": "Invalid Json data"\r\n}'
据我所知,这与
DueDate
传递给 Xero API 的方式有关。他们使用 MS .NET 日期格式,但 python 在 \
之前添加转义字符以给出以下内容:
'\\/Date(1518685950940+0000)\\/'
我已经通过 Postman 设置了一个本地 API 调用,以相同的负载对相同的 Xero 端点进行调用,并且工作正常。将
DueDate
对象更改为与上面的对象类似会生成相同类型的错误:
JSON for post data was invalid,Could not convert string to DateTime: \/Date(1518685950940+0000)\/. Path 'DueDate', line 6, position 45.</Message>
我还没有找到一种方法来重新格式化字符串以消除额外的转义字符。有没有具体的方法可以做到这一点? 我在开发文档中找不到任何与此相关的内容。
原来是编码问题。对于
httpx
,如果 data
是一个简单的 Dict
对象,例如:
{
"Type": "ACCREC",
"Contact": {
"ContactID": "3ed357da-0988-4ea1-b1b7-96829e0dde69"
},
"DueDate": r"\/Date(1518685950940+0000)\/",
"LineItems": [
{
"Description": "Services as agreed",
"Quantity": "4",
"UnitAmount": "100.00",
"AccountCode": "200"
}
],
"Status": "AUTHORISED"
}
首先应使用
json.dumps(data)
进行序列化。
更新代码:
data = json.dumps(invoice_request_to_dict(invoice_detail))
async with httpx.AsyncClient() as client:
response = await client.request(
method='POST',
url=base_url,
headers=headers,
data=data
)