OK, I have this php file for my HSBC bank processing using the API, I have this working fine on 2 of my other websites, however the SAME file is failing on the other two sites, I have no idea why. My web developer is stumped and decided to create a test file, Here is the code from the test file:
<?php
echo "payment processing...";
$amount = 100;// round($_POST["realamount"], 2) * 100;
$fullName = "test";//$_POST['name'];
$Address1 = "test";//$_POST['address1'];
$Address2 = "test";//$_POST['address2'];
$city ="test";// $_POST['city'];
$county = $city;
$postcode = "test";//$_POST['zipcode'];
$country = "GRB";//$_POST['country'];
$phone = "test";//$_POST['telephone'];
$email = "a#a.com";//$_POST['emailaddress'];
$cardNumber = "337877666233434";//$_POST['cardNumber'];
$cardExp = "03/2011";//$_POST['ccmonth'] . "/" . substr($_POST["ccyear"],2,2);
$cvdIndicator = "111";//$_POST['cvdIndicator'];
$cvdValue = "111";//$_POST['cvdValue'];
$issueNumber = "111";//$_POST['issueNumber'];
$cardType = "VI";//$_POST['cardType'];
$testRead = "<?xml version='1.0' encoding='UTF-8'?>
<EngineDocList>
<DocVersion>1.0</DocVersion>
<EngineDoc>
<ContentType>OrderFormDoc</ContentType>
<User>
<Name>xxx</Name>
<Password>xxx</Password>
<ClientId>xxx</ClientId>
</User>
<Instructions>
<Pipeline>PaymentNoFraud</Pipeline>
</Instructions>
<OrderFormDoc>
<Mode>P</Mode>
<Comments/>
<Consumer>
<Email/>
<PaymentMech>
<CreditCard>
<Number>".$cardNumber."</Number>
<Expires DataType='ExpirationDate' Locale='840'>".$cardExp."</Expires>
<Cvv2Val>".$cvdValue."</Cvv2Val>
<Cvv2Indicator>".$cvdIndicator."</Cvv2Indicator>
<IssueNum>".$issueNumber."</IssueNum>
</CreditCard>
</PaymentMech>
</Consumer>
<Transaction>
<Type>Auth</Type>
<CurrentTotals>
<Totals>
<Total DataType='Money' Currency='826'>".$amount."</Total>
</Totals>
</CurrentTotals>
</Transaction>
</OrderFormDoc>
</EngineDoc>
</EngineDocList>";
?>
<?php
//$url = "https://www.uat.apixml.netq.hsbc.com";
$url = "https://www.secure-epayments.apixml.hsbc.com/";
$ch = curl_init();
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_POSTFIELDS,$testRead);
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
$result_tmp = curl_exec ($ch);
curl_close ($ch);
///////////////////////////////////////
// use XML Parser result
$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser,XML_OPTION_CASE_FOLDING,0);
xml_parser_set_option($xml_parser,XML_OPTION_SKIP_WHITE,1);
xml_parse_into_struct($xml_parser, $result_tmp, $vals, $index);
xml_parser_free($xml_parser);
//print_r($vals); // print all the arrays.
//print_r($vals[29]); // print only the selected array.
$val1 = $vals[21];
// ProcReturnMsg
$paymentResult = $val1[value];
$result_tmp = "";
$k=0;
$findthis = false;
$findthis2 = false;
foreach ($vals as $val) {
$result_tmp.= $k."{";
foreach($val as $d => $a) {
$result_tmp.="[".$d."]".$a;
if($d=="tag" && $a=="TransactionStatus"){
$findthis = true;
}
if($d=="value" && $findthis){
$tResult = $a;
$findthis = false;
}
if($d=="tag" && $a=="Text"){
$findthis2 = true;
}
if($d=="value" && $findthis2){
$tResult2 = $a;
$findthis2 = false;
}
}
$result_tmp.= "}";
$k++;
}
echo $tResult2.$tResult;
?>
Here is an example of one of the sites not working gs.net
The output is:
payment processing... The HTTP method received is not valid. Only POST is accepted.
Whereas when I upload this exact same file to some of my other web hosts such as:
HGL working example
The output here is payment processing... Unable to determine card type. ('length' is '15')E
This sounds like an error message, but basically that error is not important, so the latter is what we are trying to achieve in the first link.
I have even uploaded this file to some really basic hosting accounts of mine, sometimes it will work sometimes it won't, so I'm guessing it's something to do with what the hosting company are allowing or have switched On/Off.
Any ideas please?
Thank you
This seems to have been caused by a PHP upgrade applied to the server and it was driving me crazy.
The solution is to set the following SSL options when specifying the CURL connection.
curl_setopt($ch, CURLOPT_SSLVERSION, 3);
curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, 'RC4-MD5');
check if curl is enabled on those servers that don't work for starters. use phiinfo() function to check.
Related
I have spent a couple of hours reading up on this but as so yet I find no clear solutions....I am using WAMP to run as my Local server. I have a successful API call set up to return data.
I would like to store that data locally, thus reducing the number of API call being made.
For simplicity I have created a cache.json file in the same folder as my PHP scripts and when I run the process I can see the file has been accessed as the time stamp updates.
But the file remains empty.
Based on research I suspect the issue may come down to a permission issue; I have gone through the folders and files and unchecked read only etc.
Appreciate if someone could validate that my code is correct and if it is hopefully point me in the the direction of a solution.
many thanks
<?php
$url = 'https://restcountries.eu/rest/v2/name/'. $_REQUEST['country'];
$cache = __DIR__."/cache.json"; // make this file in same dir
$force_refresh = true; // dev
$refresh = 60; // once an min (set short time frame for testing)
// cache json results so to not over-query (api restrictions)
if ($force_refresh || ((time() - filectime($cache)) > ($refresh) || 0 == filesize($cache))) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL,$url);
$result=curl_exec($ch);
curl_close($ch);
$decode = json_decode($result,true);
$handle = fopen($cache, 'w');// or die('no fopen');
$json_cache = $decode;
fwrite($handle, $json_cache);
fclose($handle);
}
} else {
$json_cache = file_get_contents($cache); //locally
}
echo json_encode($json_cache, JSON_UNESCAPED_UNICODE);
?>
I managed to solve this by using file_put_contents(), not being an expert I do not understand why this works and the code above doesn't, but maybe this helps someone else.
adjusted code:
<?php
$url = 'https://restcountries.eu/rest/v2/name/'. $_REQUEST['country'];
$cache = __DIR__."/cache.json"; // make this file in same dir
$force_refresh = false; // dev
$refresh = 60; // once an min (short time frame for testing)
// cache json results so to not over-query (api restrictions)
if ($force_refresh || ((time() - filectime($cache)) > ($refresh) || 0 == filesize($cache))) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL,$url);
$result=curl_exec($ch);
curl_close($ch);
$decode = json_decode($result,true);
$handle = fopen($cache, 'w');// or die('no fopen');
$json_cache = $result;
file_put_contents($cache, $json_cache);
} else {
$json_cache = file_get_contents($cache); //locally
$decode = json_decode($json_cache,true);
}
echo json_encode($decode, JSON_UNESCAPED_UNICODE);
?>
<?php
if(isset($_POST["submit"]))
{
$adm=$_POST["admno"];
$phn=$_POST["phn1"];
include("model.php");
$db = new database;
$r=$db->register($adm);
while($row=mysql_fetch_array($r))
{
if($row["phn_no1"]==$phn || $row["phn_no2"]==$phn || $row["phn_no3"]==$phn)
{
$formatted = "".substr($phn,6,10)." ";
$password = $formatted + $adm;
echo $password;
$db->setpassword($adm,$password);
$pre = 'PREFIX';
$suf = '%20ThankYou';
$sms = $pre.$password.$suf;
session_start();
$ch = curl_init("http://www.perfectbulksms.in/Sendsmsapi.aspx? USERID=ID&PASSWORD=PASS&SENDERID=SID&TO=$phn&MESSAGE=$sms");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_AUTOREFERER, true);
$result = curl_exec($ch);
curl_close($ch);
header("Location:password.php?msg=new");
}
else
{
header("Location:register.php?msg=invalid");
}
}
}
?>
this code is working perfect on my local host .. but when i put it on server ... it takes lots of time but the code in curl command is not working it only refers to next page ... i checked that curl is enabled .. if i use only sms api without curl command it sends sms immidiately.... but i want to run both header and also want to hide my sms api.... is there any alternate of this ???
so my issue is according to the documentation (wich is pretty slim and not the greatest) the xml i have is everything that is required, but im getting this error code back
<?xml version="1.0" encoding="UTF-8"?>
<Error><Number>80040B19</Number><Description>XML Syntax Error: Please check the XML request to see if it can be parsed.</Description><Source>USPSCOM::DoAuth</Source></Error>
this doesnt make much sense to me because my account is in production mode, and as i said according to the documentation i have everything that is required, i have spent the last 2 days trying to get this to work and nothing.
the VerifyAddress function works fine, but the RateCheck function does not work.
class USPS
{
protected $Endpoint = 'http://production.shippingapis.com/ShippingAPI.dll';
protected $SecureEndpoint = 'https://secure.shippingapis.com/ShippingAPI.dll';
protected $TestEndpoint = 'http://stg-production.shippingapis.com/ShippingAPI.dll';
protected $TestSecureEndpoint = 'https://stg-secure.shippingapis.com/ShippingAPI.dll';
private $username = 'example’;
function VerifyAddress($address1, $address2, $city, $state, $zip)
{
$xml = '<AddressValidateRequest%20USERID="'.$this->username.'">
<Address>
<Address1>'.$address1.'</Address1>
<Address2>'.$address2.'</Address2>
<City>'.$city.'</City>
<State>'.$state.'</State>
<Zip5>'.$zip.'</Zip5>
<Zip4></Zip4>
</Address>
</AddressValidateRequest>';
//build the data
$data = $this->AddressVerify . $xml;
//send for the request
$verified = $this->Request($data);
//return he results
return $verified;
}
function RateCheck($packages, $zipDest, $service='PRIORITY', $zipOrigin='93274', $pounds='3', $ounces='0',
$container='RECTANGULAR', $size='LARGE', $width='13', $length='14', $height='6', $girth='38')
{
$packageIDS = array('1ST'=>1, '2ND'=>2, '3RD'=>3, '4TH'=>4, '5TH'=>5, '6TH'=>6, '7TH'=>7, '8th'=>8,'9TH'=>9,
'10th'=>10);
$packagexml = array();
for($i=1;$i<=$packages;$i++)
{
$PackageID = array_search($i, $packageIDS);
$packagexml[] = '<Package ID="'.$PackageID.'">
<Service>'.$service.'</Service>
<ZipOrigination>'.$zipOrigin.'</ZipOrigination>
<ZipDestination>'.$zipDest.'</ZipDestination>
<Pounds>'.$pounds.'/Pounds>
<Ounces>'.$ounces.'</Ounces>
<Container>'.$container.'</Container>
<Size>'.$size.'</Size>
<Width>'.$width.'</Width>
<Length>'.$length.'</Length>
<Height>'.$height.'</Height>
<Girth>'.$girth.'</Girth>
</Package>';
}
$xml2 = '';
foreach($packagexml as $package)
{
$xml2 .= $package;
}
$data = 'API=RateV4&XML=<RateV4Request USERID="'.$this->username.'"><Revision>2</Revision>'.$xml2.'</RateV4Request>';
$RateResult = $this->Request($data);
return $RateResult;
}
function Request($data)
{
$ch = curl_init();
// set the target url
curl_setopt($ch, CURLOPT_URL,$this->Endpoint);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
//curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
// parameters to post
curl_setopt($ch, CURLOPT_POST, 1);
// send the POST values to usps
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
//curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
$result=curl_exec ($ch);
curl_close($ch);
$Parseresult = $this->parseResult($result);
return $Parseresult;
}
function parseResult($responce)
{
$data = strstr($responce, '<?');
echo '<!-- '. $data. ' -->'; // Uncomment to show XML in comments
$xml_parser = xml_parser_create();
xml_parse_into_struct($xml_parser, $data, $vals, $index);
xml_parser_free($xml_parser);
$params = array();
$level = array();
foreach ($vals as $xml_elem) {
if ($xml_elem['type'] == 'open') {
if (array_key_exists('attributes',$xml_elem)) {
list($level[$xml_elem['level']],$extra) = array_values($xml_elem['attributes']);
} else {
$level[$xml_elem['level']] = $xml_elem['tag'];
}
}
if ($xml_elem['type'] == 'complete') {
$start_level = 1;
$php_stmt = '$params';
while($start_level < $xml_elem['level']) {
$php_stmt .= '[$level['.$start_level.']]';
$start_level++;
}
$php_stmt .= '[$xml_elem[\'tag\']] = $xml_elem[\'value\'];';
eval($php_stmt);
}
}
return $params;
}
}
The reason I was getting this was because I had unescaped ampersands in my XML that I was posting to the USPS API. Before you POST the XML, print the XML out on your screen just to see exactly what is being posted. I'm not sure how to do this in php (maybe echo?) but in python I would do print(my_xml_string).
Like I said, my generated xml had ampersand characters in it &, I fixed the problem by replacing those with &. Again, I'm not way familiar with php but python would be my_xml_string.replace('&', '&'). This is because an ampersand in XML needs to be 'closed' with a ;.
soultion form Viable works .. by adding the following code in appropriate format
'.$pounds.'
i have demonstrated at usps tracking site and its now works well
I got following error to my site usps tracking : when i manually entered field i got result . but through the form i got that error mentioned below.
80040B19XML Syntax Error: Please check the XML request to see if it can be parsed.(B)USPSCOM::DoAuth
Finally revising quote . i got solution.
DONOT defin the value in the loop or xml tag
right <Pounds>'.$pounds.'</Pounds>
wrong <Pounds>'if($_POST['unit']=="Pounds"){ ...'</Pounds> This is creating xml VALIDATION ISSUE ..
Sorry for the long code, I'm really losing it.
This code is supposed to get a list of urls through POST, in a textarea with breaklines between each url. The script should download each url, go through the html and take some links, then go in those links, get some data and echo it out.
For some reason, visually it looks as if I'm running getDetails() only once, as I'm getting only one set of results.
I have checked multiple times if the foreach loop takes each url separately and that part is working
Can anyone spot the problem?
require_once('simple_html_dom.php');
function getDetails($html) {
$dom = new simple_html_dom;
$dom->load($html);
$title = $dom->find('h1', 0)->find('a', 0);
foreach($dom->find('span[style="color:#333333"]') as $element) {
$address = $element->innertext;
}
$address = str_replace("<br>"," ",$address);
$address = str_replace(","," ",$address);
$title->innertext = str_replace(","," ",$title->innertext);
if ($address == "") {
$exp = explode("<strong><strong>",$html);
$exp2 = explode("</strong>",$exp[1]);
$address = $exp2[0];
}
echo $title->innertext . "," . $address . "<br>";
}
function getHtml($Url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $Url);
curl_setopt($ch, CURLOPT_REFERER, "http://www.google.com/");
curl_setopt($ch, CURLOPT_USERAGENT, "MozillaXYZ/1.0");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$output = curl_exec($ch);
curl_close($ch);
return $output;
}
function getdd($u) {
$html = getHtml($u);
$dom = new simple_html_dom;
$dom->load($html);
foreach($dom->find('a') as $element) {
if (strstr($element->href,"display_one.asp")) {
$durls[] = $element->href;
}
}
return $durls;
}
if (isset($_POST['url'])) {
$urls = explode("\n",$_POST['url']);
foreach ($urls as $u) {
$durls2 = getdd($u);
$durls2 = array_unique($durls2);
foreach ($durls2 as $durl) {
$d = getHtml("http://www.example.co.il/" . $durl);
getDetails($d);
}
}
}
You're only assigning the last element in the loop, it looks like. You'll need to concatenate. Something like $address .= $element->innertext; inside the loop (note the .= instead of =).
edit: unless I'm mistaking what it's supposed to be doing. I think I may've been focusing on the wrong part of the code.
When you use DOMDocument on html you load it with $dom->loadHTMLFile() or $dom->loadHTML() you should also call libxml_use_internal_errors(true) before hand so that it will not crash because of improperly formatted html.
Could you please tell me , is there any limitation to send a request using multi_curl.
When I tried to send a request more than 200 , it was getting timeout.
see the below code ..............
.........................................
foreach($newUrlArry as $url){
$gatherUrl[] = $url['url'];
}
/*...................Array slice----------------------*/
$totalUrlRequest = count($gatherUrl);
if($totalUrlRequest > 10){
$offset = 10;
$index = 0;
$matchedAnchors = array();
$dom = new DOMDocument;
$NoOfTilesRequest = ceil($totalUrlRequest/$offset);
for($sl = 0; $sl<$NoOfTilesRequest;$sl++){
$output = array_slice($gatherUrl, $index, $offset);
$index = $offset+$index;
$responseAction = $this->multiRequestAction($output);
$k=0;
foreach($responseAction as $responseHtml){
#$dom->loadHTML($responseHtml);
$documentLinks = $dom->getElementsByTagName("a");
$chieldFlag = false;
for($i=0;$i<$documentLinks->length;$i++) {
$documentLink = $documentLinks->item($i);
if ($documentLink->hasAttribute('href') AND substr($documentLink->getAttribute('href'), 0, strlen($match)) == $match) {
$description = $documentLink->childNodes;
foreach($description as $words) {
$name = trim($words->nodeName);
if($name == 'em' || $name == 'b' || $name=="span" || $name=="p") {
if(!empty($words->nodeValue)) {
$matchedAnchors[$sl][$k]['anchor'] = trim($words->nodeValue);
$matchedAnchors[$sl][$k]['img'] = 0;
if($documentLink->hasAttribute('rel'))
$matchedAnchors[$sl][$k]['rel'] = 'Y';
else
$matchedAnchors[$sl][$k]['rel'] = 'N';
$chieldFlag = true;
break;
}
}
elseif($name == 'img' ) {
$alt= $words->getAttribute('alt');
if(!empty($alt)) {
$matchedAnchors[$sl][$k]['anchor'] = trim($words->getAttribute('alt'));
$matchedAnchors[$sl][$k]['img'] = 1;
if($documentLink->hasAttribute('rel'))
$matchedAnchors[$sl][$k]['rel'] = 'Y';
else
$matchedAnchors[$sl][$k]['rel'] = 'N';
$chieldFlag = true;
break;
}
}
}
if(!$chieldFlag){
$matchedAnchors[$sl][$k]['anchor'] = $documentLink->nodeValue;
$matchedAnchors[$sl][$k]['img'] = 0;
if($documentLink->hasAttribute('rel'))
$matchedAnchors[$sl][$k]['rel'] = 'Y';
else
$matchedAnchors[$sl][$k]['rel'] = 'N';
}
}
}$k++;
}
}
}
Both #Phliplip & #lunixbochs have mentioned common cURL pitfalls (max execution time & denied by the target server.)
When sending that many cURL requests to the same server I try to "be nice" and place voluntarily sleep periods so I don't bombard the host. For a low-end site, 1000+ requests could be like a mini DDOS!
Here's code that's worked for me. I it used to scrape a client's product data from their old site, since the data was locked in a proprietary database system with NO export function.
<?php
header('Content-type: text/html; charset=utf-8', true);
set_time_limit(0);
$urls = array(
'http://www.example.com/cgi-bin/product?id=500',
'http://www.example.com/cgi-bin/product?id=501',
'http://www.example.com/cgi-bin/product?id=502',
'http://www.example.com/cgi-bin/product?id=503',
'http://www.example.com/cgi-bin/product?id=504',
);
$i = 0;
foreach($urls as $url){
echo $url."\n";
$curl = curl_init($url);
$userAgent = 'Googlebot/2.1 (http://www.googlebot.com/bot.html)';
curl_setopt($curl, CURLOPT_USERAGENT, $userAgent);
curl_setopt($curl, CURLOPT_AUTOREFERER, true);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt($curl, CURLOPT_TIMEOUT, 25 );
$html = curl_exec($curl);
$html = #mb_convert_encoding($html, 'HTML-ENTITIES', 'utf-8');
curl_close($curl);
// now do something with info returned by curl
$i++;
if($i%10==0){
sleep(20);
} else {
sleep(2);
}
}
?>
The main features are:
no max execution time
voluntary sleep-ing
new curl init & exec for each request.
In my experience, going to sleep() will stop servers from denying you.
However if by "different different server" you mean that you are sending a small number of requests a large number of servers, for example:
$urls = array(
'http://www.example-one.com/',
'http://www.example-two.com/',
'http://www.example-three.com/',
'http://www.example-four.com/',
'http://www.example-five.com/',
'http://www.example-six.com/'
);
And you are using set_time_limit(0); then something then an error may be causing your code to die; try
ini_set('display_errors',1);
error_reporting(E_ALL);
And tell us the error message you are getting.
PHP doesn't place a restriction on the number of connections using curl_multi_init, but memory usage and time limits will be an issue.
Check your memory_limit setting in your php.ini and try to increase it to see if that helps you.