本文是 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 应用摆脱了网络环境的依赖,成为能离线响应多方市场的应用。