将 Python API 请求转换为 cURL PHP 请求

时间:2021-06-30 16:25:06

标签: python php curl

如果有人问过这个问题或有类似问题,我深表歉意;我已经使用不同的搜索词搜索了几天,结果都是空的。

我有一个 python 脚本,可以正常工作。我将它安装在我的 Windows 机器上并在本地运行脚本。我想要做的是以某种方式将其转换为 PHP 请求;我认为 cURL 将是选择的选项,但我愿意接受建议。我已经进行了几次尝试,但我不断收到身份验证错误。我相信这很简单;但也许不是。

这是我的python脚本:

import requests
from datetime import datetime
import hashlib
import hmac
import base64
import json
import time

def main():    
    api_key = 'abcd'
    secret_key = 'hashedSecret'
    host = 'https://myapidomain.com/'
    uri = 'api/1.0/Projects/8030854199/items'

    http_verb = 'GET'
    content_type = 'application/json'
    timestamp = gen_iso_timestamp()
    auth_header_value = gen_auth_string(api_key, secret_key, uri, http_verb, content_type, timestamp)
    full_url = f'{host}{uri}'
    headers = {'att-api-timestamp': timestamp, 'authorization': auth_header_value, 'Content-Type': content_type, 'Accept': content_type}
    
    r = requests.get(full_url, headers=headers)
    if r.status_code == 200:
        with open(f'data_dump/8030854199.json', 'w+') as json_file:
            json_file.write(r.text)
    elif r.status_code != 200:
        error_code = f'{r.status_code}'
        with open(f'data_dump/error.txt', 'w+') as json_file:
            json_file.write(error_code)


def gen_auth_string(api_key, secret_key, uri, http_verb, content_type, timestamp):
    message = f'{http_verb}\n{content_type}\n{uri}\n{timestamp}'
    canonical_request = bytes(message, 'ASCII')
    secret_bytes = bytes(secret_key, 'ASCII')
    digest = hmac.new(secret_bytes, msg=canonical_request, digestmod=hashlib.sha256).digest()
    signature = base64.b64encode(digest).decode()
    return f'AttAPI {api_key}:{signature}'


def gen_iso_timestamp():
    # generate a timestamp in this format 2018-12-31T23:55:55+00:00
    return f'{datetime.utcnow().replace(microsecond=0).isoformat()}+00:00'


if __name__ == "__main__":
    main()

这是我的测试 PHP 代码:

<?php

function genTimestamp(){ return gmdate(DATE_ATOM); }
function genAuthString($secret_key, $uri, $timestamp){ 
    $message = "GET"."\n"."application/json"."\n".$uri."\n".$timestamp;
    return hash_hmac('sha256',$message,$secret_key,true);
}

$api_key = 'abcd';
$secret_key = 'hashedSecret';
$host = 'https://myapidomain.com/';
$uri = 'api/1.0/Projects/8030854199/items';
$timestamp = genTimestamp();
// for testing: 
//    echo $timestamp."<br />";

$curl = curl_init();

curl_setopt($curl, CURLOPT_URL, $host.$uri);
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 0);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
// for testing: 
//    echo genAuthString($secret_key, $uri, $timestamp)."<br />"
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
    'att-api-timestamp: '.$timestamp,
    'authorization: '.genAuthString($secret_key, $uri, $timestamp),
    'Content-Type: application/json',
    'Accept: application/json'
));

// for testing: 
//    echo "Executing... <br />";
$result = curl_exec($curl);
if (curl_errno($curl)) {
    // for testing: 
    echo 'Error:' . curl_error($curl) . "<br />";
}
curl_close($curl);
echo $result;

?>

请注意,时间戳必须存储在一个变量中,以便在 HMAC 中散列并作为标头发送,否则肯定不会进行身份验证。

任何指导或建议将不胜感激!

谢谢

3 个答案:

答案 0 :(得分:1)

如果您只要求此 api 调用工作,那么我建议您只重新创建请求,而不是尝试翻译它。您可以设置环境变量等,然后使用 Postman 等工具下载 cURL 代码。

https://www.postman.com/

如果您要的是一种以编程方式进行切换的方法,我从未见过这样做的方法。

答案 1 :(得分:1)

我有一位同事指出了我的问题。对于任何有兴趣的人..

我有两个问题导致它失败。第一个是我在 cURL 标头中缺少授权字符串的前置部分:

loc

第二个问题是,根据python脚本和文档,它需要进行base64编码。所以 'authorization: AttAPI '.$api_key.':'.genAuthString($secret_key, $uri, $timestamp), 的返回行应该是:

genAuthString()

答案 2 :(得分:0)

我知道重新编码很难。如果你想在 PHP 中毫无问题地发出 http 请求,我建议你试试 Guzzle

https://docs.guzzlephp.org/en/stable/