The only outright error I see upon inspection is not related to the success or failure of curl_exec, but it is that you are using the string concatenation with assignment operator .= on a non-defined variable ($fields_string). This should show up on screen (but never in production environment) and/or in error log. If it shows in neither, you should check your php.ini settings and change how error reporting is dealt with. Relevant php.ini settings: error_reporting, log_errors, display_errors.
While not wrong, I'd recommend not doing the extra work you do to turn an array into an ampersand separated name/value pair string, since
CURLOPT_POSTFIELDS
This parameter can either be passed as a urlencoded string or as an array with the field name as key and field data as value.
However, you cannot be certain of success, even if your code would be "flawless". Your server may not be connected to the internet, or the remote server may not be. Their server may be so busy that it fails to respond within the allowable timeframe, etc. As such, you should always check if you're request is a success or failure.
# success
if (curl_errno($ch) === 0)
{
# do stuff
}
else
{
# retry? inform user of failure? log curl_errno() and curl_error() someplace?
# etc...
}
One last thing which also has nothing to do with why this may fail. You never set a timeout value for the connection and/or response, which means that your server may wait for a long time. Iirc, 30 seconds is the default value for these. You may wish to lower your connection timeout to less than a second and the timeout for the entire response to some sensible value of not too many seconds.
As php.net's documentation shows you for curl_setopt, there are 2 ways of setting each timeout value, one for ms, one for s.
CURLOPT_CONNECTIONTIMEOUT_MS, CURLOPT_CONNECTTIMEOUT
CURLOPT_TIMEOUT_MS, CURLOPT_TIMEOUT