如何使用php curl使用multipart / form-data body创建HTTP POST请求

I need to generate a HTTP post request accordingly to documentation found here.

Here is an example of how the request body should look like

Content-Type: multipart/form-data; boundary=---------------------------7d54b1fee05aa

-----------------------------7d54b1fee05aa
Content-Disposition: form-data; name="Username"

5556090455
-----------------------------7d54b1fee05aa
Content-Disposition: form-data; name="Password"

qwerty
-----------------------------7d54b1fee05aa
Content-Disposition: form-data; name="Attachment"; filename="C:\example.doc" 
<Document content is here>
-----------------------------7d54b1fee05aa
Content-Disposition: form-data; name="Recipient"

5556465589|John Doe
-----------------------------7d54b1fee05aa
Content-Disposition: form-data; name="Recipient"

5555568552|John Smith
-----------------------------7d54b1fee05aa
Content-Disposition: form-data; name="Coverpagetext"

This is a test fax from web
-----------------------------7d54b1fee05aa--

Here is the PHP code that I have so far

$postURL = 'https://service.ringcentral.com/faxapi.asp';
$ch  = curl_init($postURL);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.13) Gecko/20101206 Ubuntu/10.10 (maverick) Firefox/3.6.13');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_REFERER, 'http://www.google.com/');

$hiddens = '';
$hiddens .= 'Username'.'='.'8558415124'.'&';
$hiddens .= 'Password'.'='.'Champion92'.'&';
$hiddens .= 'Recipient'.'='.'8882466583'.'&';
$hiddens .= 'Coverpage'.'='.'NONE'.'&';
$hiddens .= 'Coverpagetext'.'='.'asdf asdf'.'&';
$hiddens .= 'Attachment'.'='.'C:\example.doc'.'&';
$hiddens = substr($hiddens, 0, strlen($hiddens)-1);

curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,  $hiddens);

$page = curl_exec($ch);
echo $page;// output result
if ($page === FALSE) {
  var_dump(curl_getinfo($ch));
  exit( "Post: FAILED = ".curl_error($ch) );
}
curl_close($ch); // close the connection

I am getting a response of 1 (which means Authorization failed). I have the feeling that I am doing a normal post request and the authorization fails because the request is not well formatted.

How can I turn this as Multipart request? And how can I troubleshoot the HTTP header I am sending, not the one I receive?

Try using urlencode on the POST values like this:

$hiddens = urlencode(substr($hiddens, 0, strlen($hiddens)-1));

curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,  $hiddens);

Without URL encoding the string it looks like this:

Username=8558415124&Password=Champion92&Recipient=8882466583&Coverpage=NONE&Coverpagetext=asdf asdf&Attachment=C:\example.doc1

With URL encoding the string looks like this:

Username%3D8558415124%26Password%3DChampion92%26Recipient%3D8882466583%26Coverpage%3DNONE%26Coverpagetext%3Dasdf+asdf%26Attachment%3DC%3A%5Cexample.doc1

Also, I am not too sure about how you are handling the file you are sending itself, because this does not look correct:

Attachment=C:\example.doc1

How exactly would a remote service have access to your C:\ drive? The file itself would have to be form encoded to be sent. Or perhaps the service requires that the file be on a publicly accessible URL?

Looking at the documentation you link to it says it should be a binary stream:

Description: Document to be faxed.
Possible values: Original document file name must be passed in the filename field of the body-part header.
Format: Binary stream.
Number of occurrences: any.

So you need to get that ironed out as well.

For the Username try appending 1 before the fax number and also @ before the Attachment, ie

$hiddens .= 'Username'.'='.'18558415124'.'&';
$hiddens .= 'Password'.'='.'Champion92'.'&';
$hiddens .= 'Recipient'.'='.'8882466583'.'&';
$hiddens .= 'Coverpage'.'='.'NONE'.'&';
$hiddens .= 'Coverpagetext'.'='.'asdf asdf'.'&';
$hiddens .= 'Attachment'.'='.'@realpathC:\example.doc'.'&';
$hiddens = substr($hiddens, 0, strlen($hiddens)-1);