本文是 Uber 的客戶端工程師團隊講述瞭如何開發最新版本司機端系列文章中的第四篇,該系列代號 Carbon ,是咱們共享出行業務的核心。包括其它功能在內,Uber 司機端使得超過 300 萬名司機能夠查看費用、里程以及收益狀況。2017 年咱們結合司機的反饋開始對司機端進行從新設計,並在 2018 年 9 月份啓動了該項目。react
Uber 做爲全球性公司,努力使其服務保證可用。因此要利用技術作到功能本地化。其中關鍵的一項工做是使用戶能夠選擇最有效的付款方式,不管是信用卡,借記卡,或者是當地特殊的支付方式,例如現金支付。git
對於 Uber 的大部分市場來講,其出行業務和外賣業務所使用的廣泛支付方式並非信用卡和借記卡。直到 2016 年,這些線上支付方式是主要支持的類型,這使得那些只用現金支付的用戶很難去使用咱們的服務。首次支持現金支付是在孟買,這裏的乘客只有少部分有信用卡。因此他們很歡迎使用現金支付,接着咱們在印度,拉丁美洲,非洲也支持了這種方式。後端
然而,直到 2017 年 9 月,外賣服務才支持現金支付,首次支持的城市也是孟買。遲到 2 年的緣由是: 外賣三方市場的複雜性,它包括餐廳,配送員和食客。react-native
克服這項挑戰,即要改變操做流程又要支持新的技術。尤爲咱們新的司機端( Carbon )支持擴展示金支付的能力。經過這些創新服務,咱們可以給全球更多的用戶提供外賣服務。緩存
在出行業務支持現金支付的城市,司機留下現金,而後從線上支付的訂單中去支付 Uber 的費用。這種狀況下,智能派單系統保證司機接到足夠的線上支付訂單,以此來支付以前屬於 Uber 的現金單費用。司機很是樂意在行程結束時可以及時收取現金,同時這項功能對那些沒有信用卡的用戶也是很是重要的。網絡
對於擁有三方市場的外賣業務來講,大部分屬於餐廳的現金須要配送員去收取。而且,對於信用卡,借記卡使用率不高的地區,派發足夠多線上支付的訂單去抵消未收付的現金是不太現實的。比起讓配送員把現金送回餐廳,咱們須要一個可持續的方法在食客和餐廳之間進行現金轉移。app
首先咱們嘗試了第三方的現金收款服務,例若有合做關係的便利店,傳統的銀行存款,轉帳。這種方法的問題在於:支持 Uber 外賣的城市並不都支持這些服務,而且限制了現金支付的地方,須要配送員停下來去完成那些不屬於配送過程當中的任務。框架
理想中的現金收款方法須要適用於如今和未來全部支持外賣服務的地區,而且方便於配送員操做。更進一步,當現金支付的地區不具有可靠的網絡環境,現金交換操做可以徹底離線完成。分佈式
產品方案很新穎:利用全部餐廳做爲一個現金流動的分佈式網絡。配送員帶着以前訂單的現金去往有合做關係的餐廳,而後用現金去支付訂單,這與食客的支付方式無關。爲了不取餐過程當中沒必要要的衝突,支付金額與訂單金額相等,由於收到不等的金額會給餐廳的出納形成混亂。餐廳仍是能保持全部現金收入,而且樂於看到及時付款。 Uber 將會從後續的線上訂單中扣除配送和預定。ide
這個機制運行的不錯,它在當前和將來的外賣市場都能進行擴展,而且操做集成到了每次配送中,使現金支付成爲配送過程當中的常規組成部分。咱們下一個挑戰是:確保餐廳欠款的收集可以離線完成.幸運的是,新司機端中的離線功能可以覆蓋一些 Case,例如司機在網絡狀況差的地方結束訂單。這個功能與咱們現金支付的需求很吻合。
在 Uber 運營的許多新興市場,可靠的網絡環境是不能保障的。以前的司機應用在整個行程中須要可靠的網絡環境,這給咱們的司機和配送員帶來了使人沮喪的體驗。例如,司機必須將乘客帶到一個網絡環境良好的地方纔能結束訂單。對於配送員來講,狀況可能更糟,地下或建築物內的交付和配送受網絡環境影響更大。
新司機端的衆多新功能中有一個是樂觀模式(Optimistic Mode),它容許功能在無網狀況下使用。當開啓的時候,不管網絡請求是否成功,應用的狀態會立馬更新並保持響應。失敗的請求會被記錄,緩存,並在網絡恢復鏈接後進行重試。無論實際網絡延時狀況,應用能快速響應,用戶可以正常操做。使用樂觀模式,行程能夠在弱網或無網狀況下開始和結束。對於外賣服務,配送員能夠在無網狀況下完成整個餐廳現金收付流程。
若是但願餐廳能無縫從配送員那收集欠款,須要新版的 Android/iOS 司機端和餐廳端(使用 React Native 編寫 ),以及新版的後端服務。咱們構建了一個新的微服務( microservice )去支持餐廳的現金流服務,它的客戶端( clients )有如下幾個職責:
如圖 1 所示,現金流包含如下幾個狀態:
圖 1: 映射現實世界中配送員如何在餐廳結算現金欠款機制的現金流狀態機模型。
在調度中時,配送員會默認選擇完成現金支付的操做,以後的主動操做是須要網絡鏈接時完成。如圖 2,在配送開始時,會認爲配送員是處於網絡狀態良好的環境中,不然,他們不會收到派送信息。以後咱們會把流程結束的完整信息發送過去,這樣後續操做不須要網絡一直鏈接,而且會提醒餐廳多是現金支付,如圖 3 所示。配送員可能會退出現金支付頁面並繼續以後的派送流程,這時樂觀模式( Optimistic Mode )會把失敗請求存儲到磁盤上。網絡恢復鏈接後,會通知後端有臨時跳過現金支付的決定。
圖 2:配送應用上顯示須要支付的金額和暫時跳過的選項,
圖 3:取餐時餐廳收到可選現金支付的信息
服務支持配送員設置他們能支付的金額,若是配送員手上沒有足夠支付的金錢或者但願以後派送時再支付,這個功能會很是有用。然而,咱們沒有開啓此功能,更多考慮的是餐廳會收到現金總額與訂單總額不符的體驗。在當前實踐中,若是配送員選擇完成現金支付,以後會進入支付狀態交換,這時現金總額會自動設置爲訂單總額。
離線狀況下咱們如何進行現金支付交換呢?須要餐廳和配送員都能認可現金支付是使人安心的,能夠預防潛在的欺詐。在雙方確認後,不能依賴網絡請求來提供及時通訊,所以咱們利用四位數驗證碼。
調度過程當中,咱們同時給司機端和餐廳端提供完成流程所須要的全部信息。如圖 4,餐廳獲得了一個隨機生成的驗證碼,在現金交換時配送員會被提示去請求它。
圖 4:在調度時,餐廳獲得一個四位驗證碼。
相反地,發給手機端的是此驗證碼SHA256加鹽後的 Hash 值,而後在輸入餐廳獲得的驗證碼時,會和該驗證碼的加鹽 hash 值進行比對。一旦成功,配送員能夠繼續完成現金交換流程,並開始下一次配送。hash 值相等性驗證發生在線下。爲了不做弊,會限制頻率和最大嘗試次數。 此外,若是現金支付操做沒有完成,驗證碼會在合理時間內到期。若是發現事務不一致,Uber 會進一步調查,可能會禁止平臺內任何有不良行爲的用戶。
圖 5: 配送員輸入驗證碼進行hash和驗證。
如上圖 5 所示,一旦驗證碼輸入成功,配送員和餐廳應用會同時顯示一個預填充確認的頁面。若是網絡又出現錯誤,樂觀模式( Optimistic Mode )會緩存失敗請求到磁盤,並在網絡恢復時重試。配送員支付行爲被記錄爲可信,餐廳的餘額根據以後的線上收益進行調整,至此現金支付結束。
雖然樂觀模式( Optimistic Mode )設計的初衷是爲了 Carbon 的核心出行流程,可是它爲這套全新功能的實現提供了可能。Uber 的工程師和設計師團隊在開發新功能時擺脫了網絡環境的限制。因爲現金交接須要多方的高度信任,因此僅依靠餐廳去核實現金交易是行不通的。同時,配送員網絡鏈接狀態可能阻塞行程的進行,從而停留在驗證的流程中。樂觀模式( Optimistic Mode )完美解決了這個問題,它容許現金交接操做在離線環境中進行,並稍後在網絡鏈接恢復時通知後端事務。
認識到離線操做的價值後,其餘的 Carbon 開發團隊都是用了樂觀模式( Optimistic Mode ),並且 Uber 的移動端網絡組在框架中拓展了此功能。這些努力使得 Uber 應用擺脫了網絡環境的依賴,成爲能離線響應多方市場的應用。