I'm trying to build a payment form that integrates with Firstdata's api. I need to post an XML string to their server. They also require a client side certificate and http authentication. My CURL set up currently looks like this:
function firstdata_send($config_param, $data) {
$config_default = array(
'test' => FALSE,
);
// settings in $config_param will overwrite settings in $config_default
$config = (object)array_merge($config_default, $config_param);
if($config->test) {
$url = 'https://ws.merchanttest.firstdataglobalgateway.com/fdggwsapi/services/order.wsdl';
}
else {
$url = 'https://ws.firstdataglobalgateway.com/fdggwsapi/services/order.wsdl';
}
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, "{$config->username}:{$config->password}");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSLCERT, $config->pemfile);
curl_setopt($ch, CURLOPT_SSLKEY, $config->keyfile);
curl_setopt($ch, CURLOPT_SSLKEYPASSWD, $config->keypass);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HEADER, TRUE);
curl_setopt($ch, CURLOPT_VERBOSE, TRUE);
$result = curl_exec($ch);
$result .= curl_error($ch);
return $result;
}
Their server responds with HTTP/1.1 401 Unauthorized
. But if I comment out the post options:
//curl_setopt($ch, CURLOPT_POST, TRUE);
//curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
I get HTTP/1.1 200 OK
. Unless I'm completely misunderstanding whats going on it seems like using post somehow interferes with the auth headers. I don't know what I'm missing.
Solved:
Turns out the ssl certificates the test account had generated were bad. I had to call their tech support and they had to regenerate the certs 3 times before the system would accept them. Sorry for wasting your time. I should have called them first. If anybody is interested the tech support number I called was (888) 477-3611. I think NomikOS was closest to being correct so I'll mark his as the answer and up vote the rest of you. Thanks again.
Check you access credentials (username, password)
401 Unauthorized
The request requires user authentication. The response MUST include a WWW-Authenticate header field (section 14.47) containing a challenge applicable to the requested resource. The client MAY repeat the request with a suitable Authorization header field (section 14.8). If the request already included Authorization credentials, then the 401 response indicates that authorization has been refused for those credentials. If the 401 response contains the same challenge as the prior response, and the user agent has already attempted authentication at least once, then the user SHOULD be presented the entity that was given in the response, since that entity might include relevant diagnostic information. HTTP access authentication is explained in "HTTP Authentication: Basic and Digest Access Authentication" [43].
source: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2
==
OBS: I recommend you this code to check for errors
// check for errors before close
$result = curl_exec($ch);
if ($result === false)
{
echo curl_error($ch);
}
curl_close($ch);
Just checked First Datas API is a SOAP based API...
The url to the wsdl only accepts GET because the wsdl is just the xml instruction set for sending soap calls.
Form what i see you need a certificate
in pem
format to use this service ....
A. Download the API https://www.firstdata.com/downloads/customerservice/30006_api_php.zip
B. You would see so many examples
Example Sales Info
include"lphp.php";
$mylphp=new lphp;
$myorder["host"] = "secure.linkpt.net";
$myorder["port"] = "1129";
$myorder["keyfile"] = "./YOURCERT.pem"; # Change this to the name and location of your certificate file
$myorder["configfile"] = "1234567"; # Change this to your store number
$myorder["ordertype"] = "SALE";
$myorder["result"] = "LIVE"; # For a test, set result to GOOD, DECLINE, or DUPLICATE
$myorder["cardnumber"] = "4111-1111-1111-1111";
$myorder["cardexpmonth"] = "01";
$myorder["cardexpyear"] = "05";
$myorder["chargetotal"] = "9.99";
$myorder["addrnum"] = "123"; # Required for AVS. If not provided, transactions will downgrade.
$myorder["zip"] = "12345"; # Required for AVS. If not provided, transactions will downgrade.
// $myorder["debugging"] = "true"; # for development only - not intended for production use
# Send transaction. Use one of two possible methods #
// $result = $mylphp->process($myorder); # use shared library model
$result = $mylphp->curl_process($myorder); # use curl methods
if ($result["r_approved"] != "APPROVED") // transaction failed, print the reason
{
print "Status: $result[r_approved]
";
print "Error: $result[r_error]
";
}
else
{ // success
print "Status: $result[r_approved]
";
print "Code: $result[r_code]
";
print "OID: $result[r_ordernum]
";
}