2

我一直在使用下面的脚本通过欧洲银行免费远程 xml 文件自动转换货币值。我的问题是,有时http://www.ecb.europa.euxml 文件会出现问题,因此自动货币转换会出错。

<?php
/*

File: currencyexchange.php
Author: Gary White
Last modified: July 6, 2005

Copyright (C) 2005, Gary White

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
included GNU General Public License for more details. If you 
received this file without the gpl.txt file, you may view it at:
http://www.gnu.org/copyleft/gpl.html

See the readme.txt file for usage.

July 6, 2005 added the RON, Romania New Leu, to the currency list.

*/

// this simply gets an array of possible currency countries and names
$allCurrencies=getCurrencyNames();
class currencyExchange{
    /////////////////////////////////////////////////////////////////////////////////////////
    // Public Properties
    // Note that these properties are public, but the values are all generated internally.
    // You should consider them read only during normal usage.
    // The only one you may want to access would be the $localFile property, if you wanted
    // to change the name of the local file used to cache a copy of the data.
    /////////////////////////////////////////////////////////////////////////////////////////

    // $Supplier property will be the European Central Bank, assuming we get the data
    var $Supplier="";
    // $Date property is the date of the exchange rate publication
    var $Date="";
    // $Rates property is an associative array of rateobj objects with the three letter identifier as the array keys
    var $Rates=array();
    // $Source property will be either "Local" or "Remote" depending on where the data comes from
    var $Source="";
    // $Error property will contain any error messages generates along the way
    var $Error="";
    // $localFile property is the file name used to cache a local copy of the XML file
    var $localFile="currencies_local.xml";
    // $url property is the URL of the XML file at the European Central Bank
    var $url="http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml";

    /////////////////////////////////////////////////////////////////////////////////////////
    // Public Methods
    /////////////////////////////////////////////////////////////////////////////////////////
    function getData(){
        $olderr=error_reporting(0);
        $this->Source="Local";
        if(file_exists($this->localFile)){
            // load it
            $this->xml=@file_get_contents($this->localFile);
            $this->parse();

            // check if it's a weekend
            // what day of the week is it?
            $weekday=date("w");
            // if it's a Sunday or Saturday
            if($weekday==0 || $weekday==6){
                // go back to last Friday
                $date=date("Y-m-d",strtotime("last Friday"));
            } else {
                $date=date("Y-m-d");
            }
            // if the date in the local file is not the same
            // as our current date, or last Friday for weekends
            if($this->Date!=$date){

                // clear the data
                $this->clearData();

                // get the remote file
                $this->xml=$this->getRemoteFile($this->url);

                if($this->parse()){
                    $this->Source="Remote";
                    // write the remote file data to a local copy of the file
                    $this->saveLocalCopy();
                }
            } // if we have a local copy
        }else{
            $this->xml=$this->getRemoteFile($this->url);

            if($this->xml)
                // write the remote file data to a local copy of the file
                $this->saveLocalCopy();
        }
        if(!$this->xml)
            $this->error="Failed to get data";
        else{
            $this->parse();
        }
        // sort our rates on the keys
        ksort($this->Rates);
        error_reporting($olderr);
        return count($this->Rates);
    }

    function getRemoteFile($url){

        $curl_handle = curl_init();
        // Where should we get the data?
        curl_setopt ($curl_handle, CURLOPT_URL, $url);
        // This says not to dump it directly to the output stream, but instead
        // have it return as a string.
        curl_setopt ($curl_handle, CURLOPT_RETURNTRANSFER, 1);
        // the following is optional, but you should consider setting it
        // anyway. It prevents your page from hanging if the remote site is
        // down.
        curl_setopt ($curl_handle, CURLOPT_CONNECTTIMEOUT, 1);
        // Now, YOU make the call.
        $buffer = curl_exec($curl_handle);
        // And tell it to shut down (when your done. You can always make more
        // calls if you want.)
        curl_close($curl_handle);
        // This is where i�d probably do some extra checks on what i just got.
        // Paranoia pays dividends.

        return $buffer;
    }

    function Convert($from, $to, $amount=1){
        // Converts from one currency to another. The method expects at least two
        // parameters. The first param , $from, it the three letter identifier for
        // the currency you are converting from. The second param, $to, is the 
        // three letter identifier for the currency you are converting to. The final
        // param, $amount, is the amount of the $from currency to convert. If omitted
        // the amount defaults to 1 and the function will return the amount of $to
        // currency that corresponds with 1 unit of the $from currency.
        if(array_key_exists($from, $this->Rates) && array_key_exists($to, $this->Rates)){
            return ($amount * (($this->Rates[$to]->rate)/($this->Rates[$from]->rate)));
        }else{
            $this->Error->Error = "";
if (!array_key_exists($from, $this->Rates))
      $this->Error->Error.="$from is not a recognized currency identifier ";
if (!array_key_exists($from, $this->Rates))
      $this->Error->Error.="$to is not a recognized currency identifier";
            return false;
        }
    }

    function setBaseCurrency($currency){
        // This function converts all currencies to be based on one unit of
        // $base currency. It's only really useful if you want to output a 
        // table of conversion factors.

        // get a factor to do our conversion based on our base currency
        $factor=$this->Rates[$currency]->rate;
        // modify the rates based on the base currency
        foreach(array_keys($this->Rates) as $k){
            $rate=$this->Rates[$k]->rate / $factor;
            $this->Rates[$k]->rate=$rate;
        }
        return (count($this->Rates)>0);
    }

    /////////////////////////////////////////////////////////////////////////////////////////
    // Private Methods
    // You should not need to call any of the following methods.
    /////////////////////////////////////////////////////////////////////////////////////////
    function clearData(){
        $this->Supplier="";
        $this->Date="";
        $this->Rates=array();
        $this->Source="";
        $this->xml="";
    }

    function saveLocalCopy(){
        $fp=fopen($_SERVER['DOCUMENT_ROOT'].$this->localFile,"w") or die("failed to write file");
        fwrite($fp,$this->xml);
        fclose($fp);
        $this->parse();
        $this->Source="Remote";
    }

    function parse(){
        if($this->xml){
            $this->parser = xml_parser_create();
            @xml_set_object($this->parser, $this);
            @xml_set_element_handler($this->parser, "startElement", "endElement");
            @xml_set_character_data_handler($this->parser, "characterData");
            $this->Rates['EUR']=new rateobj();
            $this->Rates['EUR']->rate=1.00;
            $this->Rates['EUR']->currency="Euro";
            xml_parse($this->parser, $this->xml, true)
                or die(sprintf("XML error: %s at line %d", 
                    xml_error_string(xml_get_error_code($parser)), 
                    xml_get_current_line_number($parser)));
            xml_parser_free($this->parser);
        }
    }

    function currencyExchange(){
        $dir=pathinfo($_SERVER['PHP_SELF']);
        $dir=$dir['dirname'];
        $this->localFile="$dir/$this->localFile";
    }

    function startElement($parser, $name, $attrs) {
        global $allCurrencies;
        $this->temp="";
        $gwCurrencyExch=&$GLOBALS['gwCurrencyExch'];
        if($name=="CUBE"){
            if(array_key_exists("TIME",$attrs)){
                $this->Date=$attrs["TIME"];
            }
            if(array_key_exists("CURRENCY",$attrs)){
                $this->Rates[$attrs["CURRENCY"]]=new rateobj();
                $this->Rates[$attrs["CURRENCY"]]->rate=$attrs["RATE"];
                $this->Rates[$attrs["CURRENCY"]]->currency=$allCurrencies[$attrs["CURRENCY"]];
            }
        }
    }

    function characterData($parser, $data){
        $this->temp.=$data;
    }

    function endElement($parser, $name) {
        switch($name){
            case "GESMES:NAME":
                $this->Supplier=$this->temp;
                break;
            case "GESMES:SUBJECT":
                $this->Report=$this->temp;
                break;
        }
        $temp="";
    }

} // end of ratelist class

class gwSocket{
    var $ClassName="gwSocket";
    var $Version="0.6";

    var $error="";
    var $headers;
    var $maxRedirects=3;
    var $page="";
    var $result="";
    var $redirects=0;
    var $userAgent="Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)";

    function getUrl( $url ) {
        $retVal="";
        $url_parsed = parse_url($url);
        $scheme = $url_parsed["scheme"];
        $host = $url_parsed["host"];
        $port = $url_parsed["port"]?$url_parsed["port"]:"80";
        $user = $url_parsed["user"];
        $pass = $url_parsed["pass"];
        $path = $url_parsed["path"]?$url_parsed["path"]:"/";
        $query = $url_parsed["query"];
        $anchor = $url_parsed["fragment"];

        if (!empty($host)){

            // attempt to open the socket
            if($fp = fsockopen($host, $port, $errno, $errstr, 2)){

                $path .= $query?"?$query":"";
                $path .= $anchor?"$anchor":"";

                // this is the request we send to the host
                $out = "GET $path ".
                    "HTTP/1.0\r\n".
                    "Host: $host\r\n".
                    "Connection: Close\r\n".
                    "User-Agent: $this->userAgent\r\n";
                if($user)
                    $out .= "Authorization: Basic ".
                        base64_encode("$user:$pass")."\r\n";
                $out .= "\r\n";

                fputs($fp, $out);
                while (!feof($fp)) {
                    $retVal.=fgets($fp, 128);
                }
                fclose($fp);
            } else {
                $this->error=$errstr;
            }
            $this->result=$retVal;
            $this->headers=$this->parseHeaders(trim(substr($retVal,0,strpos($retVal,"\r\n\r\n"))));
            $this->page=trim(stristr($retVal,"\r\n\r\n"))."\n";
            if(isset($this->headers['Location'])){
                $this->redirects++;
                if($this->redirects<$this->maxRedirects){
                    $location=$this->headers['Location'];
                    $this->headers=array();
                    $this->result="";
                    $this->page="";
                    $this->getUrl($location);
                }
            }
        }
        return (!$retVal="");
    }

    function parseHeaders($s){
        $h=preg_split("/[\r\n]/",$s);
        foreach($h as $i){
            $i=trim($i);
            if(strstr($i,":")){
                list($k,$v)=explode(":",$i);
                $hdr[$k]=substr(stristr($i,":"),2);
            }else{
                if(strlen($i)>3)
                    $hdr[]=$i;
            }
        }
        if(isset($hdr[0])){
            $hdr['Status']=$hdr[0];
            unset($hdr[0]);
        }
        return $hdr;
    }

} // end of gwSocket class

class rateobj{
    var $currency="";
    var $rate=0;
}

function getCurrencyNames(){
    $retVal['AED']="United Arab Emirates Dirham";
    $retVal['AFA']="Afghanistan Afghani";
    $retVal['ALL']="Albania Leke";
    $retVal['ARS']="Argentina Peso";
    $retVal['ATS']="Austria Schilling*";
    $retVal['AUD']="Australia Dollar";
    $retVal['BBD']="Barbados Dollar";
    $retVal['BDT']="Bangladesh Taka";
    $retVal['BEF']="Belgium Franc*";
    $retVal['BGN']="Bulgaria Leva";
    $retVal['BHD']="Bahrain Dinar";
    $retVal['BMD']="Bermuda Dollar";
    $retVal['BRL']="Brazil Reai";
    $retVal['BSD']="Bahamas Dollar";
    $retVal['CAD']="Canada Dollar";
    $retVal['CHF']="Switzerland Franc";
    $retVal['CLP']="Chile Peso";
    $retVal['CNY']="China Yuan Renminbi";
    $retVal['COP']="Colombia Peso";
    $retVal['CRC']="Costa Rica Colone";
    $retVal['CYP']="Cyprus Pound";
    $retVal['CZK']="Czech Republic Koruny";
    $retVal['DEM']="Germany Deutsche Mark*";
    $retVal['DKK']="Denmark Kroner";
    $retVal['DOP']="Dominican Republic Peso";
    $retVal['DZD']="Algeria Dinar";
    $retVal['EEK']="Estonia Krooni";
    $retVal['EGP']="Egypt Pound";
    $retVal['ESP']="Spain Peseta*";
    $retVal['EUR']="Euro";
    $retVal['FIM']="Finland Markkaa*";
    $retVal['FJD']="Fiji Dollar";
    $retVal['FRF']="France Franc*";
    $retVal['GBP']="United Kingdom Pound";
    $retVal['GRD']="Greece Drachmae*";
    $retVal['HKD']="Hong Kong Dollar";
    $retVal['HRK']="Croatia Kuna";
    $retVal['HUF']="Hungary Forint";
    $retVal['IDR']="Indonesia Rupiahs";
    $retVal['IEP']="Ireland Pounds*";
    $retVal['ILS']="Israel New Shekel";
    $retVal['INR']="India Rupee";
    $retVal['IQD']="Iraq Dinar";
    $retVal['IRR']="Iran Rial";
    $retVal['ISK']="Iceland Kronur";
    $retVal['ITL']="Italy Lire*";
    $retVal['JMD']="Jamaica Dollar";
    $retVal['JOD']="Jordan Dinar";
    $retVal['JPY']="Japan Yen";
    $retVal['KES']="Kenya Shilling";
    $retVal['KRW']="South Korea Won";
    $retVal['KWD']="Kuwait Dinar";
    $retVal['LBP']="Lebanon Pound";
    $retVal['LKR']="Sri Lanka Rupee";
    $retVal['LTL']="Lithuanian Lita";
    $retVal['LVL']="Latvian Lat";
    $retVal['LUF']="Luxembourg Franc*";
    $retVal['MAD']="Morocco Dirham";
    $retVal['MTL']="Malta Liri";
    $retVal['MUR']="Mauritius Rupee";
    $retVal['MXN']="Mexico Peso";
    $retVal['MYR']="Malaysia Ringgit";
    $retVal['NLG']="Dutch (Netherlands) Guilder*";
    $retVal['NOK']="Norway Kroner";
    $retVal['NZD']="New Zealand Dollar";
    $retVal['OMR']="Oman Rial";
    $retVal['PEN']="Peru Nuevos Sole";
    $retVal['PHP']="Philippines Peso";
    $retVal['PKR']="Pakistan Rupee";
    $retVal['PLN']="Poland Zlotych";
    $retVal['PTE']="Portugal Escudo*";
    $retVal['QAR']="Qatar Riyal";
    $retVal['ROL']="Romania Lei";
    $retVal['RON']="Romania New Leu";
    $retVal['RUB']="Russia Ruble";
    $retVal['SAR']="Saudi Arabia Riyal";
    $retVal['SDD']="Sudan Dinar";
    $retVal['SEK']="Sweden Kronor";
    $retVal['SGD']="Singapore Dollar";
    $retVal['SIT']="Slovenia Tolar";
    $retVal['SKK']="Slovakia Koruny";
    $retVal['THB']="Thailand Baht";
    $retVal['TND']="Tunisia Dinar";
    $retVal['TRL']="Turkey Lira*";
    $retVal['TRY']="Turkey New Lira";
    $retVal['TTD']="Trinidad and Tobago Dollar";
    $retVal['TWD']="Taiwan New Dollar";
    $retVal['USD']="United States Dollar";
    $retVal['VEB']="Venezuela Bolivare";
    $retVal['VND']="Vietnam Dong";
    $retVal['XAF']="CFA BEAC Franc";
    $retVal['XAG']="Silver Ounce";
    $retVal['XAU']="Gold Ounce";
    $retVal['XCD']="Eastern Caribbean Dollar";
    $retVal['XDR']="IMF Special Drawing Right";
    $retVal['XOF']="CFA BCEAO Franc";
    $retVal['XPD']="Palladium Ounce";
    $retVal['XPF']="CFP Franc";
    $retVal['XPT']="Platinum Ounce";
    $retVal['ZAR']="South Africa Rand";
    $retVal['ZMK']="Zambia Kwacha";
    return $retVal;
}
?>

我想修改此代码以首先检查 var $url="http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml";(远程 URL)是否存在(站点或链接在线),如果不存在(站点或链接离线),然后使用var $localFile="currencies_local.xml";(本地文件)代替..

4

1 回答 1

2

我会使用:

$http_status = curl_getinfo($curl_handle, CURLINFO_HTTP_CODE);

检查状态码。任何 >= 400 都可能是坏消息,所以使用缓存。

于 2012-06-11T09:25:19.993 回答