發佈於

即時匯率換算系統的實作-帶入金額-及時換算匯率-的程式

#即時匯率換算系統的實作
帶入金額-及時換算匯率-的程式
===
我今天試用hackmd線上協作筆記本, 原創發表了一篇討論文 #即時匯率換算系統的實作 有興趣的朋友 歡迎共筆 https://hackmd.io/s/rJNm8WSFb

 

#即時匯率換算系統的實作
帶入金額-及時換算匯率-的程式

###帶入金額-和貨幣代碼 轉換成顯示出含貨幣前置符號的金額

D:\wamp\www\o03\system\library\cart\currency.php 這支

$this->currency->format($result['tax'], $this->config->get('config_currency')),//帶入金額-和貨幣代碼 轉換成顯示出含貨幣前置符號的金額
$this->currency->format(金額, 貨幣代碼一般是TWD) 	//帶入金額-轉換成顯示出含貨幣前置符號的金額
	//$this->currency->format(金額, 貨幣代碼一般是TWD,匯率=不輸入就是用資料庫的,是否不顯示貨幣符號)
currency

使用Yahoo API 抓取即時匯率

http://myskilltree.blogspot.tw/2016/03/yahoo-api.html

您可以在 http://www.xe.com/iso4217.php 找到完整的 ISO 貨幣代碼及設定。

http://download.finance.yahoo.com/d/quotes.csv?e=.csv&f=c4l1&s=TWDUSD=x,TWDJPY=x  2總幣的兌換比例
http://download.finance.yahoo.com/d/quotes.csv?e=.json&f=c4l1&s=TWDUSD=x,TWDJPY=x

其中URL裡的f=c4l1是只取下兌換幣別(美金)的代碼與匯率
如果想取下更詳細的資料可以換成f=sl1d1t1,分別指定了代碼(含原始幣別跟對換幣別)、匯率、日期、時間這四個欄位

而s=TWDUSD=x ,其中TWD (新台幣) 為原始幣別 USD (美金)為兌換幣別,可以依需求自行更換,如果要查詢多筆資料則在後在後接續即可。

後台一天抓一次匯率的程式

D:\wamp\www\o03\admin\controller\common\dashboard.php

// Run currency update
if ($this->config->get('config_currency_auto')) {
    $this->load->model('localisation/currency');

    $this->model_localisation_currency->refresh(false);//執行後台一天抓一次匯率的程式
}
 

D:\wamp\www\o03\admin\model\localisation\currency.php

	//抓取匯率資料-入資料庫 參數=false 是自己國家以外,更新資料抓取時間大於1天的 ,參數=true自己國家以外資料全更新
	public function refresh($force = false) {
		$data = array();

		if ($force) {
			$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "currency WHERE code != '" . $this->db->escape($this->config->get('config_currency')) . "'");
		} else {
			//SELECT * FROM oc_currency WHERE code != 'TWD' AND date_modified < '2017-08-30 14:20:18' 自己國家以外,更新資料抓取時間大於1天的
			$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "currency WHERE code != '" . $this->db->escape($this->config->get('config_currency')) . "' AND date_modified < '" .  $this->db->escape(date('Y-m-d H:i:s', strtotime('-1 day'))) . "'");
		}
		//組合文字把貨幣代碼加上=X
		foreach ($query->rows as $result) {
			$data[] = $this->config->get('config_currency') . $result['code'] . '=X';
		}
		$url='http://download.finance.yahoo.com/d/quotes.csv?s=' . implode(',', $data) . '&f=sl1&e=.csv';

		//去線上抓取資料
		$curl = curl_init();

		curl_setopt($curl, CURLOPT_URL,$url);
		curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($curl, CURLOPT_HEADER, false);
		curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 30);
		curl_setopt($curl, CURLOPT_TIMEOUT, 30);

		$content = curl_exec($curl);
		curl_close($curl);
		/*
		送出去的網址
			http://download.finance.yahoo.com/d/quotes.csv?s=TWDCNY=X,TWDHKD=X,TWDGBP=X,TWDUSD=X,TWDEUR=X&f=sl1&e=.csv"TWDCNY=X",0.2180
		抓回來資料
			"TWDHKD=X",0.2587
			"TWDGBP=X",0.0256
			"TWDUSD=X",0.0331
			"TWDEUR=X",0.0279
		echo $url,"<br>\n";print($content);	
		*/
		$lines = explode("\n", trim($content));
		/*把抓回來的資料處理*/
		foreach ($lines as $line) {
			$currency = utf8_substr($line, 4, 3);
			$value = utf8_substr($line, 11, 6);//匯率
			//更新全部匯率
			if ((float)$value) {
				$this->db->query("UPDATE " . DB_PREFIX . "currency SET value = '" . (float)$value . "', date_modified = '" .  $this->db->escape(date('Y-m-d H:i:s')) . "' WHERE code = '" . $this->db->escape($currency) . "'");
			}
		}
		//更新我國匯率為1.00000
		$this->db->query("UPDATE " . DB_PREFIX . "currency SET value = '1.00000', date_modified = '" .  $this->db->escape(date('Y-m-d H:i:s')) . "' WHERE code = '" . $this->db->escape($this->config->get('config_currency')) . "'");

		$this->cache->delete('currency');//刪除緩存檔案
	}
 

SELECT * FROM oc_currency WHERE code != ‘TWD’ AND date_modified < ‘2017-08-30 14:20:18’


#OPENCART 3.0 的匯率系統

1.它用curl抓取了yahoo的關於匯率的數據,
D:\wamp\www\o06\admin\model\localisation\currency.php 這只有首頁 才會讀取

	$curl = curl_init();
	//就是這裡了,看到木有
	curl_setopt($curl, CURLOPT_URL, 'http://download.finance.yahoo.com/d/quotes.csv?s=' . implode(',', $currency_data) . '&f=sl1&e=.json');
	curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);

它用curl抓取了yahoo的關於匯率的數據,結合這2段代碼可以看出,其實它的功能就是打開這個頁面的時候自動更新數據庫中匯率數據。
到此問題找到原因了,那麼解決的方法總結一下:
可以關閉自動更新匯率(Dashboard>System>Setting>Your Store>edit>local>Auto Update Currency 選擇No)
系統管理=>商店管理.編輯=>本地化設定=>匯率自動更新
系統管理=>在地化管理=>幣別管理


-----------------------------------------------
詳細實驗
送出值是先抓SELECT * FROM `oc_currency` 的資料
-----------------------------------------------

Array
(
    [0] => TWDCNY=X
    [1] => CNYTWD=X
    [2] => TWDHKD=X
    [3] => HKDTWD=X
    [4] => TWDGBP=X
    [5] => GBPTWD=X
    [6] => TWDUSD=X
    [7] => USDTWD=X
    [8] => TWDEUR=X
    [9] => EURTWD=X
)
http://download.finance.yahoo.com/d/quotes.csv?s=&f=sl1&e=.json	目標 結果抓一個空值
http://download.finance.yahoo.com/d/quotes.csv?s=TWDCNY=X,CNYTWD=X,TWDHKD=X,HKDTWD=X,TWDGBP=X,GBPTWD=X,TWDUSD=X,USDTWD=X,TWDEUR=X,EURTWD=X&f=sl1&e=.json 正常抓資料
結論:慢的原因不是這個-這一天只會抓一次而且只在你登入後台首頁時抓

帶入金額-及時換算匯率-的程式

D:\wamp\www\o03\system\library\cart\currency.php 是這支

<?php
namespace Cart;
class Currency {
	private $currencies = array();

	public function __construct($registry) {
		$this->db = $registry->get('db');
		$this->language = $registry->get('language');

		$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "currency");//資料庫查出數據

		foreach ($query->rows as $result) {
			$this->currencies[$result['code']] = array(
				'currency_id'   => $result['currency_id'],//貨幣代號
				'title'         => $result['title'],//貨幣名稱
				'symbol_left'   => $result['symbol_left'],//貨幣符號金額左邊顯示(eg:$32、¥45、)
				'symbol_right'  => $result['symbol_right'],//貨幣符號金額右邊顯示
				'decimal_place' => $result['decimal_place'],//保留小數點後幾位有效數字
				'value'         => $result['value']//匯率
			);
		}
	}
	//帶入金額-轉換成顯示出含貨幣前置符號的金額$this->currency->format(金額, 貨幣代碼一般是TWD)
	//$this->currency->format(金額, 貨幣代碼一般是TWD,匯率=不輸入就是用資料庫的,是否不顯示貨幣符號)
	public function format($number, $currency, $value = '', $format = true) {
		$symbol_left = $this->currencies[$currency]['symbol_left'];
		$symbol_right = $this->currencies[$currency]['symbol_right'];
		$decimal_place = $this->currencies[$currency]['decimal_place'];

		if (!$value) {
			$value = $this->currencies[$currency]['value'];
		}
		//金額浮點數*匯率
		$amount = $value ? (float)$number * $value : (float)$number;
		
		$amount = round($amount, (int)$decimal_place);//金額取到小數幾位
		//是否不顯示貨幣符號
		if (!$format) {
			return $amount;
		}
		//以下顯示貨幣符號
		$string = '';

		if ($symbol_left) {
			$string .= $symbol_left;
		}
        //千進位加標點函式
		$string .= number_format($amount, (int)$decimal_place, $this->language->get('decimal_point'), $this->language->get('thousand_point'));

		if ($symbol_right) {
			$string .= $symbol_right;
		}

		return $string;//返回有貨幣符號的金額
	}

	public function convert($value, $from, $to) {
		if (isset($this->currencies[$from])) {
			$from = $this->currencies[$from]['value'];
		} else {
			$from = 1;
		}

		if (isset($this->currencies[$to])) {
			$to = $this->currencies[$to]['value'];
		} else {
			$to = 1;
		}

		return $value * ($to / $from);
	}
	//返回貨幣代號
	public function getId($currency) {
		if (isset($this->currencies[$currency])) {
			return $this->currencies[$currency]['currency_id'];
		} else {
			return 0;
		}
	}
	//返回貨幣符號
	public function getSymbolLeft($currency) {
		if (isset($this->currencies[$currency])) {
			return $this->currencies[$currency]['symbol_left'];
		} else {
			return '';
		}
	}

	public function getSymbolRight($currency) {
		if (isset($this->currencies[$currency])) {
			return $this->currencies[$currency]['symbol_right'];
		} else {
			return '';
		}
	}

	public function getDecimalPlace($currency) {
		if (isset($this->currencies[$currency])) {
			return $this->currencies[$currency]['decimal_place'];
		} else {
			return 0;
		}
	}

	public function getValue($currency) {
		if (isset($this->currencies[$currency])) {
			return $this->currencies[$currency]['value'];
		} else {
			return 0;
		}
	}
	//返回貨幣資料
	public function has($currency) {
		return isset($this->currencies[$currency]);
	}
}

 

 

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *