Parse XML File that is Dyanamically Generated - php

I am integrating the API from our monitoring software (PRTG) into our website and attempting to use a function that generates a list of data in XML format. As it is generated as needed, the URL doesn't point to an existing file.
I tried using "simplexml_load_file" and "simplexml_load_string" and passing the URL with no luck. I've also tried use "file_put_contents" to first save the file, but it also fails since the URL doesn't actually point to a file.
How can this be made to work?
<?php
$prtg_url = "http://prtg.domain.net:8080/";
$prtg_user = "username";
$prtg_hash = "passwordhash";
function getSensorData($deviceid)
{
$sensor_xml_file = $GLOBALS['prtg_url'] . "api/table.xml?content=sensors&output=xml&columns=objid,type,device,sensor,status&id=" . $deviceid . "&username=" . $GLOBALS['prtg_user'] . "&passhash=" . $GLOBALS['prtg_hash'];
file_put_contents("sensor.xml", fopen($sensor_xml_file, 'r'));
$sensors = simplexml_load_file("sensor.xml");
foreach ($sensors->item as $sensor)
{
$sensor_ping = $sensor->ping;
$sensor_id = $sensor->objid;
$sensor_type = $sensor->type;
$sensor_typeraw = $sensor->type_raw;
echo $sensor_ping . "</br>";
echo $sensor_id . "</br>";
echo $sensor_type . "</br>";
echo $sensor_typeraw . "</br>";
}
}
getSensorData("3401");
?>

It may be something to do with the file handler. You could try using simplexml_load_file() with your URL. For example:
$url = $GLOBALS['prtg_url']
. "api/table.xml?content=sensors&output=xml&columns=objid,type,device,sensor,status&id="
. $deviceid . "&username=" . $GLOBALS['prtg_user']
. "&passhash=" . $GLOBALS['prtg_hash']);
$xml = simplexml_load_file($url);

try this:
$c = curl_init();
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($c, CURLOPT_URL, $sensor_xml_file);
$xmlString = curl_exec($c);
curl_close($c);
$sensors = simplexml_load_string($xmlString);

$opts = array('http' =>
array(
'method' => 'GET',
'header' => "Content-Type: text/xml\r\n",
'timeout' => 60
)
);
$context = stream_context_create($opts);
$url = $GLOBALS['prtg_url']
. "api/table.xml?content=sensors&output=xml&columns=objid,type,device,sensor,status&id="
. $deviceid . "&username=" . $GLOBALS['prtg_user']
. "&passhash=" . $GLOBALS['prtg_hash']);
$result = file_get_contents($url, false, $context);
echo $results;
This forces a 60 second timeout on the operation, that way you can see if it actually fetches any results. If it does return incomplete results, switch to using XMLReader for your parser.

Related

Download a folder from azure blob storage which is not compressed in any format

I am trying to download a folder which is not compressed in any format like .zip,7-zip. I took code from Get azure blob files from inside Sub Directories using php.
My Folder structure on azure blob storage like that parentFolder>childFolder>1.pdf,2.pdf,3.pdf.
I am trying to download childFolder. I am using below code But I am getting error BlobNotFoundThe specified blob does not exist.
<?php
$storageAccount = 'XXXXXXX';
$containerName = 'XXXXXXX';
$blobName = 'parentFolder/childFolder';
$account_key = 'XXXXXXXXXXXXXXXXXXXXX';
$date = gmdate('D, d M Y H:i:s \G\M\T');
$version = "2019-12-12";
$stringtosign = "GET\n\n\n\n\n\n\n\n\n\n\n\nx-ms-date:". $date . "\nx-ms-version:".$version."\n/".$storageAccount."/".$containerName."/".$blobName;
$signature = 'SharedKey'.' '.$storageAccount.':'.base64_encode(hash_hmac('sha256', $stringtosign, base64_decode($account_key), true));
echo "\n\n" . $signature;
$header = array (
"x-ms-date: " . $date,
"x-ms-version: " . $version,
"Authorization: " . $signature
);
$url="https://$storageAccount.blob.core.windows.net/$containerName/$blobName";
$ch = curl_init ();
curl_setopt ( $ch, CURLOPT_URL, $url );
curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, false );
curl_setopt ( $ch, CURLOPT_CUSTOMREQUEST, 'GET' );
curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt ( $ch, CURLOPT_HTTPHEADER, $header);
curl_exec ( $ch );
$result = curl_exec($ch);
echo "\n\n" . $result;
if(curl_errno($ch)){
throw new Exception(curl_error($ch));
}
file_put_contents('C://demo//childFolder', $result); // save the string to a file
curl_close($ch);
Just try the code below that using sasToken and cURL to download all blobs under a folder:
<?php
function generateSharedAccessSignature($accountName,
$storageKey,
$signedPermissions,
$signedService,
$signedResourceType,
$signedStart,
$signedExpiry,
$signedIP,
$signedProtocol,
$signedVersion){
if(empty($accountName)){
trigger_error("The account name is required.");
return;
}
if(empty($storageKey)){
trigger_error("The account key is required.");
return;
}
if(empty($signedPermissions)){
trigger_error("The permissions are required.");
return;
}
if(empty($signedService)){
trigger_error("The services are required.");
return;
}
if(empty($signedResourceType)){
trigger_error("The resource types are required.");
return;
}
if(empty($signedExpiry)){
trigger_error("The expiration time is required.");
return;
}
if(empty($signedVersion)){
trigger_error("The service version is required.");
return;
}
// generate the string to sign
$_toSign = urldecode($accountName) . "\n" .
urldecode($signedPermissions) . "\n" .
urldecode($signedService) . "\n" .
urldecode($signedResourceType) . "\n" .
urldecode($signedStart) . "\n" .
urldecode($signedExpiry) . "\n" .
urldecode($signedIP) . "\n" .
urldecode($signedProtocol) . "\n" .
urldecode($signedVersion) . "\n";
// sign the string using hmac sha256 and get a base64 encoded version_compare
$_signature = base64_encode(hash_hmac("sha256", utf8_encode($_toSign), base64_decode($storageKey), true));
return $_signature;
}
$key= "";
$storageAccount = "";
$containerName = "";
$directoryName = "";
$destDir = "d:/temp/";
$_signedPermissions = "rl"; //read and list permission
$_signedService = "b"; // for blob service
$_signedResourceType = "oc"; //only for access container and object
$_signedStart = "2021-05-31T00:00:00Z"; //sas token start time
$_signedExpiry = "2021-06-10T00:00:00Z"; //sas token expairy time
$_signedIP = NULL; // no IP limit
$_signedProtocol = "https";
$_signedVersion = "2020-02-10";
$_signature = generateSharedAccessSignature($storageAccount,
$key,
$_signedPermissions,
$_signedService,
$_signedResourceType,
$_signedStart,
$_signedExpiry,
$_signedIP,
$_signedProtocol,
$_signedVersion);
$sig = urlencode($_signature);
$sasToken = "sp=$_signedPermissions&srt=$_signedResourceType&ss=$_signedService&st=$_signedStart&se=$_signedExpiry&sv=$_signedVersion&spr=$_signedProtocol&sig=$sig";
$destinationURL = "https://$storageAccount.blob.core.windows.net/$containerName?restype=container&comp=list&prefix=$directoryName&$sasToken";
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, $destinationURL);
$content = curl_exec($ch);
$xml = simplexml_load_string($content);
foreach ($xml->Blobs->Blob as $i) {
$url ="https://$storageAccount.blob.core.windows.net/$containerName/$i->Name";
//Use basename() function to return the base name of file
$file_name = $destDir.basename($url) ;
//Use file_get_contents() function to get the file
//from url and use file_put_contents() function to
//save the file by using base name
if(file_put_contents( $file_name,file_get_contents($url."?".$sasToken ))) {
echo "$url:File downloaded successfully\n";
}
else {
echo "File downloading failed.";
}
}
?>
I have tested on my side, see result below:
my blobs :
Your approach will not work because the folders in Azure Blob Storage are not real folders. They are virtual folders. Your blob names are parentFolder/childFolder/1.pdf and so on.
To download blobs from a virtual folder, here's what you would need to do:
List blobs in your blob container. Since you only want to download blobs from parentFolder/childFolder, you will have to do prefix search. That will list all the blobs in the desired folder.
Once you have the list, then you can download each blob from that list.
Unfortunately I am not that much knowledgeable about PHP thus I am only giving you some guidance (and not code).
I would also recommend using Azure Storage SDK for PHP instead of consuming the REST API directly. That will make your job much easier. You can find more information about the SDK here: https://github.com/Azure/azure-storage-php.

Discord oAuth2 API ratelimit triggered without any (known) cause

First question! Woho!
I'm currently coding a Dashboard for a Discord bot in PHP.
Recently, when trying to select a server, it would only display 3 malfunctioning items. So I checked the complete array using print_r() and it turned out it rate-limited me.
Now, I got no idea why that happened, as I'm the only person on the server. So what am I doing wrong? Here is the code for listing the selection page:
$all = DiscordAPI("/users/#me/guilds");
foreach ($all as $guild) {
echo "<a href='/?server=" . $guild['id'] . "'><p>";
if ($guild['icon']) {
if (substr($guild['icon'], 0, 2) == "a_") {
echo "<img class='server-icon' src='https://cdn.discordapp.com/icons/" . $guild['id'] . "/" . $guild['icon'] . ".gif?size=64'>";
} else {
echo "<img class='server-icon' src='https://cdn.discordapp.com/icons/" . $guild['id'] . "/" . $guild['icon'] . ".webp?size=64'>";
}
} else {
$words = explode(" ", $guild['name']);
$acronym = "";
foreach ($words as $w) {
$acronym .= $w[0];
}
echo "<img class='server-icon' src='https://cdn.statically.io/avatar/s=64/" . $acronym . "'>";
}
echo $guild['name'];
echo "</p></a>";
}
And here is the code for the DiscordAPI() function:
function DiscordAPI($endpoint)
{
if (!$_SESSION['token']) {
die("No token provided");
}
$ch = curl_init("https://discord.com/api" . $endpoint);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"Authorization: Bearer " . $_SESSION['token']
));
$data = curl_exec($ch);
curl_close($ch);
return json_decode($data, true);
}
There are 2 API calls before this code to verify that there is a valid token.
Quick sidenote: I got Autism, so I might understand stuff a bit differently. Don't be scared to ask if I worded something hard to understand. Thank you for trying to understand me.

How to stream or send the first 5 seconds of a wav from S3 to IBM watson for speech to text conversion?

I am trying to convert .wav files into text so that we can do speech analysis for the calls answered by my company. I got a working prototype up but its slow and takes a long time to just transcribe 100 files. I need to be able to do about 30k files a day.
Here is my code so far. Its in steps ie a user has to start one after the other.
First Step get the file from S3 server
S3.php
<?php
require 'aws-autoloader.php';
include 'db.php'; // my DB connection file
set_time_limit(0);
ignore_user_abort(true);
ini_set('max_execution_time', 0); // setting timer to so the script does not time out
$credentials = new Aws\Credentials\Credentials('', '');
$s3Client = new Aws\S3\S3Client([ // S3 client connection
'version' => 'latest',
'region' => 'us-east-1',
'credentials' => $credentials
//'debug' => true
]);
echo "<br>";
$objects = $s3Client->getIterator('ListObjects', array(
"Bucket" => 'bucker_name',
"Prefix" => "folder1/folder2/folder3/2017/10/05/"
));
$i = 0;
foreach ($objects as $object) {
try {
if ($i == 140) break; // This is the counter I set to get only 140 files
if ($object['Size'] > 482000 and $object['Size'] < 2750000) { // get only objects that are not too small nor too big or consider it file filerting
echo $object['Key'] . "<br>";
$i++;
$cmd = $s3Client->getCommand('GetObject', [
'Bucket' => 'bucket_name',
'Key' => $object['Key']
]);
// Create a signed URL from a completely custom HTTP request that
// will last for 10 minutes from the current time
$signedUrl = $s3Client->createPresignedRequest($cmd, '+10 minutes');
ob_start();
echo $url = (string)$signedUrl->getUri();
ob_end_flush();
ob_flush();
flush();
$filename = parse_url($url, PHP_URL_PATH);
$arr = explode("_", basename($filename));
$filename = $arr[0] . ".wav";
file_put_contents('uploads/' . basename($filename), fopen($url, 'r')); // Storing the files in uploads folder on my Linux server
$sql = "INSERT INTO `audioFiles` (`audioFile`) VALUES ('" . basename($filename) . "')"; // Inserting the file name into DB to keep track of it
$STH = $DBH->prepare($sql);
$STH->execute();
}
//print_r($object);
} catch (Exception $e) {
print_r($e);
}
}
Once the files are downloaded I need to split the recording into left and right and use the first 5 seconds of the right side. I am doing this cause its expensive to transcribe the entire call and this is more of a initializing app that needs to scale for thousands of files before we can rationalize doing it for the entire duration of each file.
Here is part of the script used to split and extract the first 5 seconds. I get the files names from the DB which have a marker as 0 and to the split and then update the DB file marker with the new name and marker as 1.
Split.php
$sql = "SELECT audioFile FROM audioFiles WHERE split = 0"; // SQL to get file names
$sql_update = "UPDATE audioFiles SET split = 1 WHERE audioFile IN ("; // SQL to update split files
.
.
while ($fileName = $STH->fetch()) {
echo $output = shell_exec("sox --i " . $location . " | grep Channels | sed 's/^.*: //'"); // to check if the file has stereo or mono recording
if ($output == 2) {
$left = substr($location, 0, $extension_pos) . '.CALLER' . substr($location, $extension_pos);
$right = substr($location, 0, $extension_pos) . '.AGENT' . substr($location, $extension_pos);
$ap = substr($location, 0, $extension_pos) . '.AGENT.AP' . substr($location, $extension_pos);
exec("sox $location $left remix 1 ");
exec("sox $location $right remix 2 ");
exec("sox $location $ap trim 0 5");
$sql_update .= "'" . $fileName[0] . "',";
$sql_update_agentTranscript = "UPDATE audioFiles SET agentFile ='" . $right . "', agentAP ='".$ap ."' WHERE audioFile ='" . $fileName[0] . "'";
$STH1 = $DBH->prepare($sql_update_agentTranscript);
$STH1->execute();
} else if ($output == 1) {
$right = substr($location, 0, $extension_pos) . '.AGENT' . substr($location, $extension_pos);
$ap = substr($location, 0, $extension_pos) . '.AGENT.AP' . substr($location, $extension_pos);
exec("cp $location $right");
exec("sox $location $ap trim 0 5");
$sql_update .= "'" . $fileName[0] . "',";
$sql_update_agentTranscript = "UPDATE audioFiles SET agentFile ='" . $right . "', agentAP ='".$ap ."' WHERE audioFile ='" . $fileName[0] . "'";
$STH1 = $DBH->prepare($sql_update_agentTranscript);
$STH1->execute();
} else {
echo "Something is wrong. The file did not have 1 or 2 channel or code is wrong - ".$fileName[0];
echo "<br>";
$ap = substr($location, 0, $extension_pos) . '.AGENT.AP' . substr($location, $extension_pos);
}
$sql_update = substr($sql_update, 0, -1);
$sql_update .= ")";error_log($sql_update, 0);
$STH = $DBH->prepare($sql_update);
$STH->execute();
Here is the script use to convert the 5 second files into text.
IBM.php
<?php
.
//get file name from DB with marker set as 1 from previous script.
$url = 'https://stream.watsonplatform.net/speech-to-text/api/v1/recognize?model=en-US_NarrowbandModel&profanity_filter=false';
$headers = array(
"Content-Type: audio/wav",
"Transfer-Encoding: chunked");
.
if($STH->rowCount() > 0) {
while ($fileName = $STH->fetch()) {
$file = fopen($fileName[0], 'r');
$size = filesize($fileName[0]);
$fileData = fread($file, $size);
// CURL start to send via IBM API and conver it.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fileData);
curl_setopt($ch, CURLOPT_INFILE, $file);
curl_setopt($ch, CURLOPT_INFILESIZE, $size);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$executed = curl_exec($ch);
curl_close($ch);
$result = json_decode($executed);
$match = "thank you for calling"; // The text to see if they are present in the converted text
$transcript = $result->results[0]->alternatives[0]->transcript;
if(strpos($transcript,$match) !== false){
//Update DB with STH1->execute() to say that matching text is found.
} else {
//Update DB with STH2->execute() to say that matching text is not found.
}
}
}
else{
echo "No more files to convert.";
}
?>
The above can be used to convert speech to text using IBM Watson. Just adding it if any one wants to use it.
The whole three step process, what I assume, would work for hundreds of calls but will not work or be too expensive to run for thousands of calls.
The steps can be listed as follows.
Download files from S3 to server // Extremely slow
Split files // Reasonably fast based on server power
Transcribe with IBM Watson // moderate, I can not think of a way to speed this up, unless I figure out how to do huge batch conversion.
I need help optimizing this flow and making it faster than it is now. I was hoping there will be a way to send the file from S3 to IBM Watson directly as a stream with a 5 second time limit for each file. I think this might be possible but I don't have the slightest idea how to do that.
Do I need to recreate it completely? if so what other option is there?
Any suggestions or ideas will help.
Ps - I apologize for my code indenting

Etsy API Pagination with PHP

So, I'm fairly new to working with APIs, and am just trying to play around with using the Etsy API to display a certain set of listings.
By default, the API returns a set of 25 results, and can do a max of 100 at a time. I'd like to show more than that, so I'm trying to add pagination to my call. Here's what I've got so far:
<?php
//setting API key
define("API_KEY", XXX);
//setting request url
$url = "https://openapi.etsy.com/v2/listings/active?keywords=unicorn,unicorns&includes=Images:1:0&api_key=" . API_KEY;
while (isset($url) && $url != '') {
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$response_body=curl_exec($curl);
curl_close($curl);
$response = json_decode($response_body);
foreach ($response->results as $listing) {
echo "<li>" . $listing->title . " ~*~ " . $listing->price . " " . $listing->currency_code . " ~*~ " . 'View on Etsy!' . "</li>" . "<br>";
}
$url = $response->pagination->next_page;
}
?>
I thought this would loop through and return the next set of 25 results, but it didn't. Anyone have experience working with this? Is there somewhere I'm getting tripped up?
Thanks!
In your while block, you are assigning the value of the next_page property to $url.
But the actual value is an int, 2, not an url.
Instead append the next_page to the initial url, as a query string variable.
$url .= "&page=" . $response->pagination->next_page;
See below an example on how you can isolate each process to a function.
We move the curl operation into its own function where it returns an object from json_decode.
We move the whole processing of the listings into a separate function, where for now, it just prints out the listings.
This second function is recursive, meaning, that if the next page exists it will call the first function, get the response, then process it.
<?php
//setting API key
define("API_KEY", 'br4j52uzdtlcpp6qxb6we3ge');
function get_listings($page=1){
$url = "https://openapi.etsy.com/v2/listings/active?keywords=unicorn,unicorns&includes=Images:1:0&api_key=" . API_KEY;
$url .= "&page=$page";
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$response_body=curl_exec($curl);
curl_close($curl);
$responseObject = json_decode($response_body);
return $responseObject;
}
function process_listings($responseObject){
foreach ($responseObject->results as $listing) {
echo "Title: " . $listing->title . PHP_EOL .
"Price " . $listing->price . PHP_EOL .
"Currency code " . $listing->currency_code . PHP_EOL .
'URL ' . $listing->url . PHP_EOL;
}
print PHP_EOL . "Pagination " . $responseObject->pagination->next_page . PHP_EOL;
$next_page = $responseObject->pagination->next_page;
if ($next_page) {
$nextPageResponse = get_listings($next_page);
process_listings($nextPageResponse);
}
}
$firstPage = get_listings(); // page 1 is default
process_listings($firstPage);

Barclaycard ePDQ MPI using PHP & CURL just doesn't want to work, no repsonse, not sure CURL is working?

I've been putting this off for a while as I just don't seem to have a clue with what I'm doing. I'm trying to use PHP and Curl to talk to the Barclaycard ePDQ MPI. I've done this before using the HSBC XML API but the Barclaycard ePDQ MPI seems to be giving me a few headaches. I have a form which posts card details/address details and the to a page that contains the following functions Please note that I have SSL set up on the domain, CURL is installed on the server, I had the HSBC XML API working just fine on the same box/URL.
<?php
function process_card($users_ip, $Temp_Order_ID, $User_NameX, $First_Name, $Surname, $Address_Line1, $Address_Line2, $Town, $Country, $Postcode, $CardNumber, $CardExpiryDate, $issue_node, $CardCVV, $totalCost ) {
if ($CardCVV == "")
$cvvindicator = 0;
else
$cvvindicator=1;
global $status;
//$amount = $amount * 100;
$xml = '
<?XML version="1.0" encoding="UTF-8"?>
<EngineDocList>
<DocVersion>1.0</DocVersion>
<EngineDoc>
<IPAddress>' . $users_ip . '</IPAddress>
<ContentType>OrderFormDoc</ContentType>
<User>
<Name>XXXXX</Name>
<Password>XXXXXXX</Password>
<ClientId DataType="S32">12345</ClientId>
</User>
<Instructions>
<Pipeline>Payment</Pipeline>
</Instructions>
<OrderFormDoc>
<Mode>T</Mode>
<Id>' . $Temp_Order_ID. '</Id>
<Consumer>
<Email>' . $User_NameX . '</Email>
<BillTo>
<Location>
<Address>
<FirstName>' . $First_Name . '</FirstName>
<LastName>' . $Surname .'</LastName>
<Street1>' . $Address_Line1 . '</Street1>
<Street2>' . $Address_Line2 . '</Street2>
<Street3></Street3>
<City>' . $Town . '</City>
<StateProv>' . $Country . '</StateProv>
<PostalCode>' . $Postcode . '</PostalCode>
<Country>' . getCuntCode($Country) . '</Country>
</Address>
</Location>
</BillTo>
<ShipTo>
<Location>
<Address>
<FirstName>' . $First_Name . '</FirstName>
<LastName>' . $Surname .'</LastName>
<Street1>' . $Address_Line1 . '</Street1>
<Street2>' . $Address_Line2 . '</Street2>
<Street3></Street3>
<City>' . $Town . '</City>
<StateProv>' . $Country . '</StateProv>
<PostalCode>' . $Postcode . '</PostalCode>
<Country>' . getCuntCode($Country) . '</Country>
</Address>
</Location>
</ShipTo>
<PaymentMech>
<CreditCard>
<Type DataType="S32">1</Type>
<Number>' . $CardNumber . '</Number>
<Expires DataType="ExpirationDate" Locale="826">' . $CardExpiryDate . '</Expires>
' . $issue_node . '
<Cvv2Indicator>' . $cvvindicator . '</Cvv2Indicator>
<Cvv2Val>' . $CardCVV . '</Cvv2Val>
</CreditCard>
</PaymentMech>
</Consumer>
<Transaction>
<Type>Auth</Type>
<CurrentTotals>
<Totals>
<Total DataType="Money" Currency="826">' . $totalCost . '</Total>
</Totals>
</CurrentTotals>
<CardholderPresentCode DataType="S32"></CardholderPresentCode>
<PayerSecurityLevel DataType="S32"></PayerSecurityLevel>
<PayerAuthenticationCode></PayerAuthenticationCode>
<PayerTxnId></PayerTxnId>
</Transaction>
</OrderFormDoc>
</EngineDoc>
</EngineDocList>';
$url = "https://secure2.epdq.co.uk:11500";
$params = array("CLRCMRC_XML" => $xml);
$params = formatData($params);
$response = post_to_epdq($url, $xml);
$auth_code = strstr($response, "<AuthCode>");
echo "auth_code=" . $auth_code;
if ($auth_code <> "") {
$splt = split("</AuthCode>", $auth_code);
$status = strip_tags($splt[0]);
return $xml . "<hr/>" . $response . "Good";
} else {
$error = strstr($response, "<Text>");
$splt = split("</Text>", $error);
$status = strip_tags($splt[0]);
return $xml . "<hr/>" . $response . "Bad";
}
}
function post_to_epdq($url, $data) {
set_time_limit(120);
$output = array();
$curlSession = curl_init();
curl_setopt($curlSession, CURLOPT_URL, $url);
curl_setopt($curlSession, CURLOPT_PORT, 443);
curl_setopt($curlSession, CURLOPT_HEADER, 0);
curl_setopt($curlSession, CURLOPT_POST, 1);
curl_setopt($curlSession, CURLOPT_POSTFIELDS, $data);
curl_setopt($curlSession, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curlSession, CURLOPT_TIMEOUT, 60);
#$response = split(chr(10),curl_exec ($curlSession));
$response = curl_exec($curlSession);
if (curl_error($curlSession)) {
$this->error = curl_error($curlSession);
return "ERROR";
}
curl_close($curlSession);
return $response;
}
function formatData($data) {
$output = "";
foreach ($data as $key => $value)
$output .= "&" . $key . "=" . urlencode($value);
$output = substr($output, 1);
return $output;
}
Needless to say I validate the user input, generate their IP and determine a country code, I then call the above function:
process_card($users_ip,$Temp_Order_ID,$User_NameX,$First_Name,$Surname,$Address_Line1,$Address_Line2,$Town,$Country,$Postcode,$CardNumber, $CardExpiryDate, $issue_node, $CardCVV, $totalCost );
I don't get a response? I'm unsure if the port and url items are incorrect or if the whole CURL request is wrong. Nothing is returned from the request.
Sorry about this being a long post but this is really doing my head in!
Has anyone done this before?
I've managed to fix my problem now. It turned out that the CURL connection to the Barclays website was blocked by a firewall on the server which was why I was getting no error message back.
I modified the CURL code a bit to check for errors:
$data = curl_exec($ch);
if(curl_errno($ch)) {
print curl_error($ch);
}
curl_close ($ch);
This then says: couldn't connect to host at which point I tried it on another server and it got past this error.
The error I am getting now is: "Insufficient permissions to perform requested operation." I have tried all the accounts I have been given but if I log into the EPDQ control panel I seem to only be able to assign up to EPDQ Level 4 and CPI access with no mention of MPI and even though it says technical support is available from 8AM until 12PM, it is not. It is really just office hours for anything but the most basic queries.
Is there any advantage to using this over SagePay? SagePay allows you to send through the individual transaction details as well where Barclays only lets you send the total amount payable and they really do offer support out of office hours.
The only reason I am changing the site to MPI is the fact that with CPI the customer can close the browser before returning to the website so the order details and invoice are not sent so there is no way of knowing what has been purchased.
Thanks
Robin
Howdy, after some playing around here's the correct CURL set up you have to do...
I realise that the variables could be better and I should make this as an object but I just want to get a quick answer up there. The script also needs to sift through the different accept and error messages but this is what I've got so far...
$ch = curl_init();
$url = "https://secure2.epdq.co.uk:11500"; // Don't need to add curl_setopt($curlSession, CURLOPT_PORT, 443); as port is included
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $vars); // $vars is your XML
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 120);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$data = curl_exec($ch);
curl_close ($ch);
$xml = new domDocument;
$xml->loadXML($data);
if (!$xml) {
echo 'Error while parsing the document - Please Contact to determine if payment has gone though';
exit;
}
$x = $xml->getElementsByTagName( "CcErrCode" );
$approved = $x->item(0)->nodeValue;
$xx = $xml->getElementsByTagName( "CcReturnMsg" );
$CcReturnMsg = $xx->item(0)->nodeValue;
if($approved) {
// the card is valid.
$y = $xml->getElementsByTagName( "Id" );
$BCardId = $y->item(1)->nodeValue;
$z = $xml->getElementsByTagName( "MessageList" );
$MessageList = $z->item(0)->nodeValue;
$zz = $xml->getElementsByTagName( "AvsRespCode" );
$AvsRespCode = $zz->item(0)->nodeValue;
$zzz = $xml->getElementsByTagName( "AvsDisplay" );
$AvsDisplay = $zzz->item(0)->nodeValue;
$zzzz = $xml->getElementsByTagName( "ProcReturnMsg" );
$ProcReturnMsg = $zzzz->item(0)->nodeValue;
if($approved == "1"){
echo "approved!<br />";
echo "BCardId: " . $BCardId . ", MessageList=" . $MessageList . ", " . $AvsRespCode . ", " . $AvsDisplay . ", " . $ProcReturnMsg;
die();
}else{
// raise that it's been partially accepted,
echo "partially approved";
echo "BCardId: " . $BCardId . ", MessageList=" . $MessageList . ", " . $AvsRespCode . ", " . $AvsDisplay . ", " . $ProcReturnMsg;
die();
}
}else{
echo "you have been completely knocked back";
$zzzzz = $xml->getElementsByTagName( "Text" );
$BCard_Text = $zzzzz->item(0)->nodeValue;
echo "The reason:" . $BCard_Text;
die();
}
hope this helps other people who have to set this up!

Categories