成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

商品價格的多幣種方案

wpw / 2141人閱讀

摘要:主要遇到的問題如下涉及商品價格的系統(tǒng)眾多各上層系統(tǒng)調(diào)用商品價格接口繁多商品價格相關(guān)字段較多為了實現(xiàn)快速上線,我們在原人民幣的商品價格基礎(chǔ)架構(gòu)上,只能進(jìn)行少量且合適的改造??尚行哉{(diào)研改造商品中心,商品價格支持盧比。

首發(fā)于 樊浩柏科學(xué)院

假若,你是某個國內(nèi)電商平臺的商品中心項目負(fù)責(zé)人。突然今天,接到了一個這樣的需求:商品在原人民幣價格的基礎(chǔ)架構(gòu)上,須支持盧比(印度)價格。

需求

需求點,可以描述為:

購買的用戶,商品價格需要支持盧比;

營運人員,商品管理系統(tǒng)依然使用人民幣價格;

同樣這個需求,定了以下兩個硬指標(biāo):

必須實現(xiàn)需求;

必須快速上線;

問題

首先,我們必須承認(rèn)的是,這確實是個簡單的需求,但這也是個夠坑爹的需求。主要遇到的問題如下:

涉及商品價格的系統(tǒng)眾多;

各上層系統(tǒng)調(diào)用商品價格接口繁多;

商品價格相關(guān)字段較多;

為了實現(xiàn)快速上線,我們在原人民幣的商品價格基礎(chǔ)架構(gòu)上,只能進(jìn)行少量且合適的改造。所以,最后我們的改造方向為:盡量只改造商品價格源頭系統(tǒng),即商品中心,其他上層系統(tǒng)盡量不改動。

可行性調(diào)研

改造商品中心,商品價格支持盧比??尚械母脑旆桨赣?2 種:

1、數(shù)據(jù)表價格字段存盧比

將原人名幣價格相關(guān)的數(shù)據(jù)表字段,存盧比值,數(shù)據(jù)表并新增人名幣字段。

2、接口輸出數(shù)據(jù)時轉(zhuǎn)化為盧比

原人名幣相關(guān)的數(shù)據(jù)表字段依然存人民幣值,在接口輸出數(shù)據(jù)時,將價格相關(guān)字段值轉(zhuǎn)化為盧比。

針對以上方案,我們需要注意 2 個問題:

匯率會每天變化,所以商品價格也會變化;

后續(xù)商品價格,可能須支持多幣種;

上述 方案 ①,商品中心只需改造數(shù)據(jù)表。然后每天根據(jù)匯率刷新商品價格,原價格字段就都變成了盧比。方案相對簡單,也容易操作,但缺點是:對任然需要人民幣價格的系統(tǒng),即商品管理系統(tǒng)須改造。
方案 ②,需要改造商品中心業(yè)務(wù)邏輯。由于涉及的價格字段較多,改造較復(fù)雜,主要優(yōu)點是:匯率變動對商品價格影響較小,且可拓展支持多幣種價格(可以根據(jù)地區(qū)標(biāo)識,獲取相應(yīng)的商品價格)。

解決方案

最終,為了系統(tǒng)的可擴(kuò)展性,我們選擇了方案 ②。

這里主要改造了商品中心,主要解決 透傳地區(qū)標(biāo)識 和 支持多幣種價格 這 2 個問題。

透傳地區(qū)標(biāo)識

我們的業(yè)務(wù)系統(tǒng)主要分為 API 和 Service 項目,API 暴露出 HTTP 接口,API 與 Service 和 Service 與 Service 之前使用 RPC 接口通信。由于商品中心涉及到價格的接口繁多,不可能對每個接口都增加地區(qū)標(biāo)識的參數(shù)。所以我們弄了一套調(diào)用鏈路透傳地區(qū)標(biāo)識的機(jī)制。

機(jī)制原理

思路就是,先將地區(qū)標(biāo)識放在全局上下文中,API 接口通過 Header 頭X-Location攜帶地區(qū)標(biāo)識;而對于 RPC 接口,我們的 RPC 框架已支持了 Context,不需要改造。

代碼實現(xiàn)
傳遞全局上下文

由于 RPC 框架已支持了 Context,所以 API 和 RPC 接口透傳全局上下文略有不同。實現(xiàn)如下:

class Location
{
    public static function init()
    {
        global $context;

        if (empty($context["location"])) {
            return;
        }

        // API在這里直接獲取X-Location頭
        if (!empty($_SERVER["HTTP_X_LOCATION"])) {
            $context["location"] = $_SERVER["HTTP_X_LOCATION"];
        }
        // RPC Server會自動獲取Context
    }
}
上述init()方法,需要在項目入口位置初始化。

其中,RPC 接口不需要操作全局上下文。因為 RPC Client 在調(diào)用時會自動獲取全局變量$context值并在 RPC 協(xié)議數(shù)據(jù)中追加 Context,同時 RPC Server 在收到請求時會自動獲取 RPC 協(xié)議數(shù)據(jù)中的 Context 值并設(shè)置全局變量$context

RPC Client 傳遞 Context 實現(xiàn)如下:

protected function addGlobalContext($data)
{
    global $context;

    $context = !is_array($context) ? array() : $context;
    
    // data為待請求的RPC協(xié)議數(shù)據(jù)
    $data["Context"] = $context;
    return $data;
}

RPC Server 獲取 Context 實現(xiàn)如下:

public function getGlobalContext($packet)
{
    global $context;
    
    $context = array();
    // packet為接收的RPC協(xié)議數(shù)據(jù)
    if(isset($packet["Context"])) {
        $context = $packet["Context"];
    }
}

當(dāng)設(shè)置了 Context 后,RPC 通信時協(xié)議數(shù)據(jù)會攜帶location字段,內(nèi)容如下:

RPC
325
{"data":"{"version":"1.0","user":"xxx","password":"xxx","timestamp":1553225486.5455,"class":"xxx","method":"xxx","params":[1]}","signature":"xxx","Context":{"location":"india"}}
設(shè)置地區(qū)標(biāo)識

到這里,我們只需要在全局上下文設(shè)置地區(qū)標(biāo)識即可。一旦我們設(shè)置了地區(qū)標(biāo)識,所有業(yè)務(wù)系統(tǒng)就會在本次的調(diào)用鏈路中透傳這個地區(qū)標(biāo)識。實現(xiàn)如下:

class Location
{
    public static function set($location)
    {
        global $context;

        $context["location"] = $location;
        // API需要在這里多帶帶設(shè)置X-Location頭
        header("X-Location: " . $context["location"]);
    }
}
獲取地區(qū)標(biāo)識

設(shè)置了地區(qū)標(biāo)識后,就可以在本次調(diào)用鏈路的所有業(yè)務(wù)系統(tǒng)中直接獲取。實現(xiàn)如下:

class Location
{
    public static function get()
    {
        global $context;

        if (!isset($context["location"])) {
            return "china";
        }

        return $context["location"];
    }
}
支持多幣種價格 商品中心

有了地區(qū)標(biāo)識后,商品中心服務(wù)就可以根據(jù)地區(qū)標(biāo)識對價格字段進(jìn)行轉(zhuǎn)化了。因為設(shè)計到價格的數(shù)據(jù)表和價格字段較多,這里直接從數(shù)據(jù)層(Model)進(jìn)行改造。

改造獲取數(shù)據(jù)方法

下述的ReadBase類是所有數(shù)據(jù)表 Model 的基類,所有獲取數(shù)據(jù)表數(shù)據(jù)的方法都繼承或調(diào)用自getOne()getAll()方法,所以我們只需要改造這兩個方法。

class ReadBase
{
    public function getOne(array $cond, $fields)
    {
        $data = $this->getReader()->select($this->getFields($fields))->from($this->getTableName())->where($cond)->queryRow();
        
        return $this->getExchangePrice($data);
    }
    
    public function getAll(array $cond, $fields)
    {
        $data = $this->getReader()->select($this->getFields($fields))->from($this->getTableName())->where($cond)->queryAll();
        
        if ($data) {
            foreach ($data as &$one) {
                 $this->getExchangePrice($one);
            }
        }
        
        return $data;
    }
}
后綴匹配價格字段

由于涉及到價格字段名字較多,且具有不確定性,所以這里使用后綴方式匹配。為了防止一些字段命名不規(guī)范,這里引入了黑名單機(jī)制。

protected function isExchangeField($field)
{
    $priceSuffix = array("cost", "_price");
    $black = array();
    $len = strlen($field) ;

    foreach ($priceSuffix as $suffix) {
        $lastPos = $len - strlen($suffix);
        // 非黑名單且非is_
        if (!in_array($field, $black)
            && false === strpos($field, "is_")
            && $lastPos === strpos($field, $suffix)
        ) {
            return true;
        }
    }

    return false;
}
前綴為is_的字段一般定義為標(biāo)識字段,默認(rèn)為非價格字段。
計算地區(qū)價格

上述getExchangePrice()方法,用來根據(jù)地區(qū)標(biāo)識轉(zhuǎn)化價格覆蓋到原價格字段,并自增以_origin后綴的人民幣價格字段。

public function getExchangePrice(&$data)
{
    if (empty($data)) {
        return $data;
    }

    $originPrice = array();
    foreach ($data as $field => &$value) {
        // 是否是價格字段
        if ($this->isExchangeField($field)) {
            $originField = $field . "_origin";
            $originPrice[$originField] = $value;
            // 獲取對應(yīng)地區(qū)的價格
            $value = $this->getExchangePrice($value);
        }
    }
    
    $data = array_merge($originPrice, $data);

    return $data;
}

public static function getExchangePrice($price)
{
    // 獲取地區(qū)標(biāo)識
    $location = Location::get();
    // 匯率
    $exchangeRateConfig = Config::$exchangeRate;
    if ($location === "china") {
        return $price;
    } else if (isset($exchangeRateConfig[$location])) {
        $exchangeRate = $exchangeRateConfig[$location];
    } else {
        throw new BusinessException("not found $location exchange rate");
    }
    // 向上取值并保留兩位小數(shù)
    $exchangePrice = bcmul($price, $exchangeRate, 3);

    return number_format(ceil($exchangePrice * 100) / 100, 2, ".", "");
}

其中,getExchangePrice()方法會調(diào)用Location::get()獲取地區(qū)標(biāo)識,并根據(jù)匯率計算實時價格。

最終,商品中心改造后,得到的部分商品價格信息,如下:

# 人民幣價格10,匯率10.87
market_price: 108.7
market_price_origin: 10
API系統(tǒng)

對于所有 API 的項目,我們只需要讓客戶端在所有的請求中增加X-Location頭即可。

GET /product/detail/1 HTTP/1.1

Request Headers
  X-Location: india

API 項目需在入口文件處,初始化地區(qū)標(biāo)識。如下:

Location::init();
商品管理系統(tǒng)

對于商品管理系統(tǒng),我們?yōu)榱朔奖氵\營操作,所有商品價格都應(yīng)以人民幣。因此,我們只需要初始化地區(qū)標(biāo)識為中國,如下:

Location::init();
// 地區(qū)設(shè)置為中國
Location::set("china");
總結(jié)

為了實現(xiàn)需求很容易,但是要做到合理且快速卻不簡單。本文的實現(xiàn)的方案,避免了很多坑,但同時也可能又埋下了一些坑。沒有一套方案是萬能的,慢慢去優(yōu)化吧!

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/11987.html

相關(guān)文章

  • 商品價格的多幣種方案

    摘要:主要遇到的問題如下涉及商品價格的系統(tǒng)眾多各上層系統(tǒng)調(diào)用商品價格接口繁多商品價格相關(guān)字段較多為了實現(xiàn)快速上線,我們在原人民幣的商品價格基礎(chǔ)架構(gòu)上,只能進(jìn)行少量且合適的改造??尚行哉{(diào)研改造商品中心,商品價格支持盧比。 首發(fā)于 樊浩柏科學(xué)院 假若,你是某個國內(nèi)電商平臺的商品中心項目負(fù)責(zé)人。突然今天,接到了一個這樣的需求:商品在原人民幣價格的基礎(chǔ)架構(gòu)上,須支持盧比(印度)價格。 showIm...

    Chao 評論0 收藏0
  • SegmentFault 在杭成功舉辦黑客馬拉松,發(fā)布區(qū)塊鏈創(chuàng)新基金

    摘要:上周,在杭州歐美金融城創(chuàng)投中心啟動全球黑客馬拉松,本次活動吸引了眾多長三角開發(fā)者的關(guān)注,有多位嘉賓出席活動進(jìn)行項目交流討論,現(xiàn)場更有幣圈大佬現(xiàn)場撒幣。 showImg(https://segmentfault.com/img/bVbbQCS); 上周,SegmentFault 在杭州歐美金融城 G5 創(chuàng)投中心啟動全球黑客馬拉松,本次活動吸引了眾多長三角開發(fā)者的關(guān)注,有多位嘉賓出席活動進(jìn)...

    Lorry_Lu 評論0 收藏0
  • koa2開發(fā)微信公眾號: 不定期推送最新幣圈消息

    摘要:背景比特幣說好的分叉最后卻分叉不成,如今算力又不夠,于是比特現(xiàn)金想篡位沒一個星期就漲了快倍,錯過這趟快車甚是后悔,于是打算寫一個可不定期推送最新消息的微信公眾號。既然是利用微信這個平臺載體,當(dāng)然要熟悉微信的,遂封裝了一下。 背景:比特幣說好的segwit2x分叉最后卻分叉不成,如今算力又不夠,于是比特現(xiàn)金想篡位? 沒一個星期就漲了快10倍,錯過這趟快車甚是后悔,于是打算寫一個可不定期推...

    xi4oh4o 評論0 收藏0
  • 小牛市啟示錄:有價值何必等風(fēng)來

    摘要:很多人將這一波的上漲解讀為比特幣小牛市的到來,無論從技術(shù)層面還是從消息層面來看,比特幣都有逐步回暖的跡象。到日,關(guān)于英雄鏈網(wǎng)絡(luò)詐騙案被破獲的報道便鋪天蓋地地傳播開來。 摘要:不在風(fēng)口上,長了翅膀的項目同樣可以起飛,價值終究會超越時間。 showImg(https://segmentfault.com/img/bVbrS0N?w=4096&h=3575); 自四月初以來,比特幣就開啟了起...

    xiaoqibTn 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<