linux curl -F к php curl - обратитесь к каждому API - PullRequest
0 голосов
/ 05 сентября 2018

Я пытаюсь использовать следующий API для автоматического вызова аудиофайлов: https://contact -everyone.orange-business.com / api / docs / guides / index.html? Shell # cr-er-une -Vocale-диффузии

Код 'linux cURL' следующий (справа в предыдущей ссылке):

    curl -X POST https://[SERVER_URL]/api/v1.2/groups/[id_group]/diffusion-requests \
-H 'Authorization: Bearer [Access-Token]' \
-H 'Content-Type: multipart/form-data' \
-F audio-intro=@/path/to/myintro.wav \
-F audio-body=@/path/to/mybody.wav \
-F audio-outro=@/path/to/myoutro.wav \
-F 'diffusion={
           "name":"diffusion vocale via API REST",
           "contactIds":["id_contact_1", "id_contact_2", ...],
           "mailingListIds":["id_mailing_list_1","id_mailing_list_2", ...],
           "excludedContactIds":[],
           "msisdns":["0612327745"],
           "landlines":["0522331155"],
           "voiceParam":{
              "locale": "fr_FR"
           }
        };type=application/json'

Я ищу то же самое, но в PHP. Я перепробовал много таких вещей:

    $diffusion_params = '"diffusion"={
           "name":"diffusion vocale via API REST",
           "contactIds":[],
           "mailingListIds":[],
           "excludedContactIds":[],
           "msisdns":["0612345678"],
           "landlines":[],
           "voiceParam":{
              "locale": "fr_FR"
           }
        };type=application/json' ;

    $audio_intro_param = '"audio-intro"="@/path/to/file/sound.wav"';
    $audio_body_param = '"audio-body"="@/path/to/file/sound.wav"';
    $audio_outro_param = '"audio-outro"="@/path/to/file/sound.wav"';

    $post_field_params = array($audio_intro_param, $audio_body_param, $audio_outro_param, $diffusion_params);
    $ch = curl_init();

    curl_setopt( $ch,CURLOPT_URL, 'https://'.$URL.'/api/v1.2/groups/'.$group_id.'/diffusion-requests');
    curl_setopt( $ch,CURLOPT_POST, true );
    curl_setopt( $ch,CURLOPT_HTTPHEADER, array("Authorization: Bearer ".$token, "Content-Type: multipart/form-data") );
    curl_setopt( $ch,CURLOPT_RETURNTRANSFER, true );
    curl_setopt( $ch,CURLOPT_SSL_VERIFYPEER, false );
    curl_setopt( $ch,CURLOPT_POSTFIELDS, $post_field_params );

    $result = curl_exec($ch);// Retourne un résultat de la forme suivante : 

    curl_close($ch);

Моя проблема касается всех опций -F. Как «конвертировать» его в PHP?

[ОБНОВЛЕНО] Проблема заключалась в внутренней ошибке маршрутизации в сети Orange.

Я использую этот сервис в php, используя "shell_exec ($ cmd)", где $ cmd - это команда raw bash curl, и она отлично работает.

Ответы [ 2 ]

0 голосов
/ 11 сентября 2018

Спасибо, @hanshenrik. Следуя вашим инструкциям, я получаю следующие отличия:

- разница заголовка (тип контента):
¤ curl = application/json ;
¤ php-curl = multipart/form-data

- разница в содержании:
¤ curl = Content-Disposition: form-data; name="audio-body"; filename="Test.wav"
¤ php-curl = Content-Disposition: form-data; name="audio-body"; filename=""

- тип контента:
¤ curl = Content-Type: application/octet-stream
¤ php-curl = Content-Type:

- для атрибута audio-outro существует та же проблема: нет файла и нет типа контента.

- и, наконец, значение msisdns не одного типа (легко исправить, уже опробовано):
¤ curl = "msisdns":["0612327745"]
¤ php-curl = "msisdns":[["0612345678"]]

Если я исправлю msisdns, чтобы он был массивом с одним диммером, я получу следующую ошибку, вызвав API (файлы отсутствуют): [{"code":"NotNull","message":"A field is missing or blank, ensure that all mandatory fields are specified."}]

Проблема, похоже, связана со способом добавления файлов. Любое предложение?

[EDIT] @hanshenrik: я использовал следующий код PHP для получения этих результатов:

function sendCallFromFile($URL, $token, $group_id, $file_path, $my_mobile_phone_number)
{
$ch = curl_init();

    curl_setopt_array ( $ch, array (
            CURLOPT_URL => 'https://'.$URL.'/api/v1.2/groups/'.$group_id.'/diffusion-requests',
            CURLOPT_POST => 1 
    ) );

    echo (file_exists($file_path)) ? "The file exists.\n" : "ERROR : The file does not exist !!!\n"; // print "The file exists"

    shitty_multipart_form_data_generator ( $ch, array (
            'Authorization: Bearer '.$token 
    ), array (
            "audio-intro" => new CURLFile ( $file_path ),
            "audio-body" => new CURLFile ( $file_path ),
            "audio-outro" => new CURLFile ( $file_path ),
            "diffusion" => new CURLMultiPart ( array (
                    'Content-Type: application/json' 
            ), json_encode ( array (
                    "name" => "diffusion vocale via API REST",
                    "contactIds" => array (                 ),
                    "mailingListIds" => array (),
                    "excludedContactIds" => array (),
                    "msisdns" => array (
                                $my_mobile_phone_number
                    ),
                    "landlines" => array (/*"0412345678"*/),
                    "voiceParam" => array (
                            "locale" => "fr_FR" 
                    ) 
            ) ) ) 
    ) );


    $result = curl_exec($ch);// Retourne un résultat de la forme suivante : 

    curl_close($ch);

    return $result;
}


class CURLMultiPart {
    /** @var string[] $headers */
    public $headers;
    /** @var string $value */
    public $value;
    /**
     *
     * @param string $value
     * @param string[] $headers
     */
    function __construct(array $headers, string $value) {
        // todo: verify that all $headers are strings.
        $this->headers = $headers;
        $this->value = $value;
    }
}
/**
 *
 * @param curl_resource $ch
 * @param string[] $additional_headers
 * @param array $post_data
 * @throws \InvalidArgumentException
 */
function shitty_multipart_form_data_generator($ch, array $additional_headers = [], array $post_data) {
    $bon = '------------------------' . bin2hex ( random_bytes ( 8 ) );
    $global_header = 'Content-Type: multipart/form-data; boundary=' . $bon;
    $body = '';
    foreach ( $post_data as $post_name => $post_value ) {
        $body .= "$bon\r\n";
        if (is_string ( $post_value )) {
            $body .= "Content-Disposition: form-data; name=\"$post_name\"\r\n";
            $body .= "\r\n$post_value\r\n";
        } elseif (is_a ( $post_value, 'CURLMultiPart', false )) {
            /** @var CURLMultiPart $post_value */
            $has_content_disposition = false;
            foreach ( $post_value->headers as $header ) {
                if (0 === stripos ( $header, 'Content-Disposition' )) {
                    $has_content_disposition = true;
                    break;
                }
            }
            if (! $has_content_disposition) {
                $body .= "Content-Disposition: form-data; name=\"$post_name\"\r\n";
            }
            foreach ( $post_value->headers as $header ) {
                $body .= "$header\r\n";
            }
            $body .= "\r\n{$post_value->value}\r\n";
        } elseif (is_a ( $post_value, 'CURLFile' )) {
            /** @var CURLFile $post_value */
            // Content-Disposition: form-data; name="file"; filename="myPostName"
            // Content-Type: myMime
            $body .= "Content-Disposition: form-data; name=\"$post_name\"; filename=\"" . $post_value->getPostFilename () . "\"\r\n";
            $body .= "Content-Type: " . $post_value->getMimeType () . "\r\n\r\n";
            $body .= file_get_contents ( $post_value->getFilename () );
            $body .= "\r\n";
        } else {
            // error, invalid argument.
            ob_start ();
            var_dump ( [ 
                    $post_name => $post_value 
            ] );
            $debug = ob_get_clean ();
            throw new \InvalidArgumentException ( "every member of \$post_data must be either a string, CURLMultiPart, or CURLFile - but contains something else: " . $debug );
        }
        // unreachable
    }
    $body .= "{$bon}--\r\n";
    // var_dump ( $body );
    $additional_headers [] = $global_header;
    curl_setopt_array ( $ch, array (
            CURLOPT_POSTFIELDS => $body,
            CURLOPT_HTTPHEADER => $additional_headers 
    ) );
}
0 голосов
/ 05 сентября 2018

-X POST примерно переводится в CURLOPT_POST=>1 (на самом деле точный перевод будет с CURLOPT_CUSTOMREQUEST, но не используйте это, используйте вместо этого CURLOPT_POST.)

https://[SERVER_URL]/api/v1.2/groups/[id_group]/diffusion-requests переводится как CURLOPT_URL => 'https://[SERVER_URL]/api/v1.2/groups/[id_group]/diffusion-requests'

The

-H 'Authorization: Bearer [Access-Token]' \

переводится как

CURLOPT_HTTPHEADER=>array('Authorization: Bearer [Access-Token]')

что касается -H 'Content-Type: multipart/form-data' - вообще не добавляйте этот заголовок вручную, curl сделает это за вас. (если вы добавите его вручную, вы можете испортить граничную строку, полный заголовок будет выглядеть примерно так: Content-Type: multipart/form-data; boundary=------------------------82442bc797f0)

-F audio-intro=@/path/to/myintro.wav \
-F audio-body=@/path/to/mybody.wav \
-F audio-outro=@/path/to/myoutro.wav \

переводится как

CURLOPT_POSTFIELDS=>array(
"audio-intro"=>new CURLFile("/path/to/myintro.wav"),
"audio-body"=> new CURLFile("/path/to/mybody.wav"),
"audio-outro"=>new CURLFile("/path/to/myoutro.wav"),
)

но следующие 1,

-F 'diffusion={
           "name":"diffusion vocale via API REST",
           "contactIds":["id_contact_1", "id_contact_2", ...],
           "mailingListIds":["id_mailing_list_1","id_mailing_list_2", ...],
           "excludedContactIds":[],
           "msisdns":["0612327745"],
           "landlines":["0522331155"],
           "voiceParam":{
              "locale": "fr_FR"
           }
        };type=application/json'

проблематично, обертка phl curl_ api не поддерживает добавление заголовков к отдельным параметрам запросов multipart/form-data, но если вам повезет, вы можете сделать это без заголовка Content-Type, поэтому, кроме этого заголовка, он переводится в

/*...,*/
"diffusion"=>json_encode(array(
"name"=>"diffusion vocale via API REST",
"contactIds"=>array("id_contact_1", "id_contact_2", ...),
"mailingListIds"=>array("id_mailing_list_1","id_mailing_list_2", ...),
"excludedContactIds"=>array(),
"msisdns"=>array(0=>array("0612327745")),
"landlines"=>array("0522331155"),
"voiceParam"=>array("locale"=>"fr_FR")
)
));

так вкратце:

curl_setopt_array ( $ch, array (
        CURLOPT_URL => 'https://[SERVER_URL]/api/v1.2/groups/[id_group]/diffusion-requests',
        CURLOPT_HTTPHEADER => array (
                'Authorization: Bearer [Access-Token]' 
        ),
        CURLOPT_POSTFIELDS => array (
                "audio-intro" => new CURLFile ( "/path/to/myintro.wav" ),
                "audio-body" => new CURLFile ( "/path/to/mybody.wav" ),
                "audio-outro" => new CURLFile ( "/path/to/myoutro.wav" ),
                "diffusion" => json_encode ( array (
                        "name" => "diffusion vocale via API REST",
                        "contactIds" => array (
                                "id_contact_1",
                                "id_contact_2",
                                (...) 
                        ),
                        "mailingListIds" => array (
                                "id_mailing_list_1",
                                "id_mailing_list_2",
                                (...) 
                        ),
                        "excludedContactIds" => array (),
                        "msisdns" => array (
                                0 => array (
                                        "0612327745" 
                                ) 
                        ),
                        "landlines" => array (
                                "0522331155" 
                        ),
                        "voiceParam" => array (
                                "locale" => "fr_FR" 
                        ) 
                ) ) 
        ) 

) );

edit: если вам абсолютно необходим заголовок, вы не можете использовать генератор multipart / form-data для PHP curl_ api, вы должны свернуть свой собственный, см. https://bugs.php.net/bug.php?id=76847 - вот довольно непроверенный пример:

class CURLMultiPart {
    /** @var string[] $headers */
    public $headers;
    /** @var string $value */
    public $value;
    /**
     *
     * @param string $value
     * @param string[] $headers
     */
    function __construct(array $headers, string $value) {
        // todo: verify that all $headers are strings.
        $this->headers = $headers;
        $this->value = $value;
    }
}
/**
 *
 * @param curl_resource $ch
 * @param string[] $additional_headers
 * @param array $post_data
 * @throws \InvalidArgumentException
 */
function shitty_multipart_form_data_generator($ch, array $additional_headers = [], array $post_data) {
    $bon = '------------------------' . bin2hex ( random_bytes ( 8 ) );
    $global_header = 'Content-Type: multipart/form-data; boundary=' . $bon;
    $body = '';
    foreach ( $post_data as $post_name => $post_value ) {
        $body .= "$bon\r\n";
        if (is_string ( $post_value )) {
            $body .= "Content-Disposition: form-data; name=\"$post_name\"\r\n";
            $body .= "\r\n$post_value\r\n";
        } elseif (is_a ( $post_value, 'CURLMultiPart', false )) {
            /** @var CURLMultiPart $post_value */
            $has_content_disposition = false;
            foreach ( $post_value->headers as $header ) {
                if (0 === stripos ( $header, 'Content-Disposition' )) {
                    $has_content_disposition = true;
                    break;
                }
            }
            if (! $has_content_disposition) {
                $body .= "Content-Disposition: form-data; name=\"$post_name\"\r\n";
            }
            foreach ( $post_value->headers as $header ) {
                $body .= "$header\r\n";
            }
            $body .= "\r\n{$post_value->value}\r\n";
        } elseif (is_a ( $post_value, 'CURLFile' )) {
            /** @var CURLFile $post_value */
            // Content-Disposition: form-data; name="file"; filename="myPostName"
            // Content-Type: myMime
            $body .= "Content-Disposition: form-data; name=\"$post_name\"; filename=\"" . $post_value->getPostFilename () . "\"\r\n";
            $body .= "Content-Type: " . $post_value->getMimeType () . "\r\n\r\n";
            $body .= file_get_contents ( $post_value->getFilename () );
            $body .= "\r\n";
        } else {
            // error, invalid argument.
            ob_start ();
            var_dump ( [ 
                    $post_name => $post_value 
            ] );
            $debug = ob_get_clean ();
            throw new \InvalidArgumentException ( "every member of \$post_data must be either a string, CURLMultiPart, or CURLFile - but contains something else: " . $debug );
        }
        // unreachable
    }
    $body .= "{$bon}--\r\n";
    // var_dump ( $body );
    $additional_headers [] = $global_header;
    curl_setopt_array ( $ch, array (
            CURLOPT_POSTFIELDS => $body,
            CURLOPT_HTTPHEADER => $additional_headers 
    ) );
}

с этим ваши аргументы curl будут переводиться, вкратце:

curl_setopt_array ( $ch, array (
        CURLOPT_URL => 'https://[SERVER_URL]/api/v1.2/groups/[id_group]/diffusion-requests',
        CURLOPT_POST => 1 
) );
shitty_multipart_form_data_generator ( $ch, array (
        'Authorization: Bearer [Access-Token]' 
), array (
        "audio-intro" => new CURLFile ( "/path/to/myintro.wav" ),
        "audio-body" => new CURLFile ( "/path/to/mybody.wav" ),
        "audio-outro" => new CURLFile ( "/path/to/myoutro.wav" ),
        "diffusion" => new CURLMultiPart ( array (
                'Content-Type: application/json' 
        ), json_encode ( array (
                "name" => "diffusion vocale via API REST",
                "contactIds" => array (
                        "id_contact_1",
                        "id_contact_2" 
                    // (...)
                ),
                "mailingListIds" => array (
                        "id_mailing_list_1",
                        "id_mailing_list_2" 
                    // (...)
                ),
                "excludedContactIds" => array (),
                "msisdns" => array (
                        0 => array (
                                "0612327745" 
                        ) 
                ),
                "landlines" => array (
                        "0522331155" 
                ),
                "voiceParam" => array (
                        "locale" => "fr_FR" 
                ) 
        ) ) ) 
) );
...