
在将python脚本转换为php时,尤其涉及与外部api交互的post请求,一个常见的陷阱是对请求体(request body)格式的误解。python的requests库在处理data参数时,默认将其作为application/x-www-form-urlencoded类型发送,即使data参数的值本身是一个json字符串。而如果使用json参数,则会将整个请求体序列化为json,并设置content-type: application/json。
原始Python脚本通过requests.post('...', data={...})发送请求。关键在于,data字典中的'data'键对应的值是通过json.dumps()函数序列化后的JSON字符串。这意味着整个POST请求的结构是:
POST /trackingCal/track HTTP/1.1 Content-Type: application/x-www-form-urlencoded data=%7B%22TrackPackagesRequest%22%3A%7B...%7D%7D&action=trackpackages&locale=en_US&format=json&version=99
可以看到,外层是一个URL编码的表单数据,其中一个字段data的值是经过JSON编码的字符串。
初次尝试将Python逻辑转换为PHP时,开发者可能会倾向于将整个请求参数数组进行JSON编码,并设置Content-Type: application/json。例如:
<?php
// ...
$headers = ['Content-Type' => 'application/json'];
$data = [
'data' => [ /* ... 完整的请求结构 ... */ ],
'action' => 'trackpackages',
'locale' => 'en_US',
'format' => 'json',
'version' => 99
];
$response = Requests::post($url, $headers, json_encode($data));
// ...
?>这种做法会导致整个请求体被发送为一个单一的JSON对象,例如:
立即学习“PHP免费学习笔记(深入)”;
{
"data": {
"TrackPackagesRequest": { /* ... */ }
},
"action": "trackpackages",
"locale": "en_US",
"format": "json",
"version": 99
}这与FedEx API所期望的application/x-www-form-urlencoded格式(其中data字段的值是JSON字符串)不符。因此,API会返回{"CALError": {"code":"UNSUPPORTED.ACTION", "message":" is not a supported action", ...}}错误,表明它无法解析这种格式的请求。
要正确地将Python脚本转换为PHP,我们需要模拟Python requests库的行为:将外层参数作为application/x-www-form-urlencoded发送,但其中data字段的值需要是JSON编码的字符串。
PHP的Requests库(或cURL)在发送POST请求时,如果第三个参数是一个关联数组,它会默认将其作为application/x-www-form-urlencoded类型发送。因此,我们只需要确保data数组中的data键对应的值是经过json_encode()处理的字符串即可。
以下是修正后的PHP代码示例:
<?php
// 引入Composer自动加载文件,确保Requests库可用
$dir = __DIR__;
include $dir .'/vendor/autoload.php';
// 示例追踪号
$tracking_number = '123456789'; // 请替换为实际的追踪号
// FedEx追踪API的URL
$url = 'https://www.fedex.com/trackingCal/track';
// 请求头:对于application/x-www-form-urlencoded,通常不需要显式设置Content-Type,
// Requests库会根据$data参数的类型自动处理。
$headers = [];
// 构建POST请求的数据体
$data = [
// 'data' 字段的值必须是JSON编码的字符串
"data" => json_encode([
"TrackPackagesRequest" => [
"appType" => "wtrk",
"uniqueKey" => "",
"processingParameters" => [
"anonymousTransaction" => true,
"clientId" => "WTRK",
"returnDetailedErrors" => true,
"returnLocalizedDateTime" => false
],
"trackingInfoList" => [[
"trackNumberInfo" => [
"trackingNumber" => $tracking_number,
"trackingQualifier" => "",
"trackingCarrier" => ""
]
]]
]
]),
"action" => "trackpackages",
"locale" => "en_US",
"format" => "json",
"version" => 99
];
// 发送POST请求
// Requests::post() 方法会将 $data 数组自动编码为 application/x-www-form-urlencoded
$response = Requests::post($url, $headers, $data);
// 打印响应内容,通常需要进一步解析JSON
print_r($response->body); // 访问响应体内容
// 示例:解析JSON响应
// $decoded_response = json_decode($response->body, true);
// if (isset($decoded_response['TrackPackagesResponse']['packageList'][0])) {
// $fedex_status = $decoded_response['TrackPackagesResponse']['packageList'][0]['keyStatus'];
// $fedex_details = $decoded_response['TrackPackagesResponse']['packageList'][0]['statusWithDetails'];
// $delivery_date = $decoded_response['TrackPackagesResponse']['packageList'][0]['displayActDeliveryDt'];
// $delivery_time = $decoded_response['TrackPackagesResponse']['packageList'][0]['displayActDeliveryTm'];
// echo "FedEx Status: " . $fedex_status . "\n";
// echo "Details: " . $fedex_details . "\n";
// echo "Delivery Date: " . $delivery_date . "\n";
// echo "Delivery Time: " . $delivery_time . "\n";
// } else {
// echo "Error or no tracking information found.\n";
// print_r($decoded_response);
// }
?>代码解析:
通过以上修正,PHP脚本将能够以与原始Python脚本完全相同的请求格式与FedEx API进行交互,从而成功获取包裹追踪信息。这个案例也强调了在跨语言移植API调用逻辑时,深入理解HTTP请求协议和各语言HTTP客户端库的细节是多么重要。
以上就是Python FedEx追踪脚本PHP转换:正确处理POST请求体格式的详细内容,更多请关注php中文网其它相关文章!
PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号