This article is the fourth in a series covering how Uber’s mobile engineering team developed the newest version of our driver app, codenamed Carbon, a core component of our ridesharing business. Among other new features, the app lets our population of over three million driver-partners find fares, get directions, and track their earnings. We began designing the new app in conjunction with feedback from our driver-partners in 2017 and began rolling it out for production in September 2018.
As a global company, Uber strives to make its services accessible everywhere it operates. That effort involves understanding regional customs and adapting our technology to them. Critical in this pursuit is letting customers pay in the method that makes the most sense for them, whether that be credit, debit, or region-specific payment types such as cash.
In many markets where Uber’s ridesharing service and Uber Eats are available, credit and debit cards are not commonplace nor the payment method of choice. Yet until 2016, such digital methods were the primary supported payment type, making it difficult for users that preferred to and or could only pay in cash to leverage our services. We addressed this limitation by first accepting cash payments for Uber rides in Mumbai where a small percentage of the city’s population has credit cards. As customers welcomed this new choice in payment type, we expanded cash payments for rides throughout India, Latin America, and Africa.
However, it was not until September 2017 that we began accepting cash payments for Uber Eats delivery orders, an offering originating again in Mumbai. This two-year delay came down to tackling the payments complexity of Uber Eats’ three-sided marketplace, comprised of restaurant-partners, delivery-partners, and eaters.
Overcoming this challenge involved a mix of operational changes and new technology. In particular, our new driver app (codenamed Carbon) gave us new features that helped support scaling a cash-based economy. With these innovations, we are able to bring Uber Eats to more customers worldwide.
The challenge of collecting cash
In cities where we support cash payments for our ridesharing service, driver-partners keep the money paid to them in cash and pay Uber’s fees for those trips automatically from the proceeds of digitally-paid trips. In these circumstances, our intelligent dispatch system guarantees that driver-partners receive enough trips paid with a digital payment type to cover fees owed to Uber from previous cash trips. Drivers benefit from an immediate payment while Uber enables riders to pay with physical cash, an important feature in regions where some people do not have access to credit cards.
With the three-sided marketplace of Uber Eats, the majority of cash received by a delivery-partner from an eater is owed to the restaurant-partner. Moreover, in markets with low credit or debit card usage, it is not possible to dispatch enough digitally-paid deliveries to offset the outstanding cash collected. Rather than asking our delivery-partners to go back to the restaurants they just came from to drop off cash paid for an order, we needed a sustainable means of transferring cash payments between the eater and the restaurant-partner.
We first tried using third-party cash collection services that leverage participating locations, such as convenience stores, as well as traditional bank deposits and transfers. The problem we found with this approach was that these services were not available in all Uber Eats cities, limiting where we could support cash payments, and required our delivery-partners to make stops that were not part of the traditional delivery trip experience.
Our ideal cash collection mechanism needed to work in all current and future Uber Eats markets as well as be convenient for delivery-partners. Moreover, as many cash payment-enabled markets have unreliable network connectivity, the cash exchange operation needed to be able to function entirely offline.
Our new approach
The product proposal was novel: leverage our restaurant-partners as a distributed network of cash drop-off locations. Delivery-partners with an outstanding cash balance from previous trips would be dispatched to participating restaurants and pay for the order in cash, agnostic to the eater’s payment type. To avoid unnecessary friction during pick-up, the payment amount would equal the order amount, as receiving an amount that differed could create confusion for a restaurant cashier. Restaurants would keep all cash earnings and benefit from the immediate payment. Uber would cover its delivery booking fees by deducting them from subsequent digital orders.
This mechanism works well because it scales in present and future Uber Eats markets and makes cash payments a regular part of the delivery experience by integrating them with each trip. Our next challenge was to ensure that restaurant arrears collection could function offline. Fortunately, we built offline support into our new driver app to cover a number of use cases, such as when a driver ends a trip in an area with limited network coverage. This feature dovetailed nicely with our requirements for cash payments.
Leveraging Optimistic Mode
In many emerging markets where Uber operates, reliable network connectivity is not a guarantee. Our previous driver app required network connectivity throughout the entire trip, which could result in incredibly frustrating experiences for both our driver- and delivery-partners. For example, a driver may have to drive to an area with connectivity after dropping off a customer in order to end the trip on the app. This issue can be worse for delivery-partners, where underground and in-building pickups and deliveries further interfere with network connections.
Amongst the many new features of our redesigned driver app is Optimistic Mode, which allows features to function and progress without the need for a network connection. When enabled, the app state will immediately update and remain responsive regardless of whether or not network requests succeed. Failed requests will be noted, cached, and reattempted when connectivity is restored. Regardless of actual network latency, the app responds quickly, letting the user interact with it normally. With Optimistic Mode, trips can immediately start and end in low or no connectivity areas. For Uber Eats, delivery-partners can progress through the entire restaurant cash collection flow without a network connection.
The restaurant arrears collection feature
Enabling restaurants to seamlessly collect arrears from delivery-partners required updates to our new Android and iOS driver apps and our Restaurant Dashboard app, written with React Native, as well as new back-end functionality. We built a new microservice to support restaurant cash drops and its clients with the following responsibilities:
- Determine trip eligibility for restaurant cash payments.
- Calculate the suggested amounts of cash to pay.
- Maintain the state of ongoing restaurant cash payment trips with a state machine.
- Format and provide display data to the mobile clients as well as our restaurant app.
With this paradigm, a cash drop has several possible states, visualized in Figure 1, below:
At dispatch, delivery-partners are opted into completing a cash drop by default, as actively opting in later could require a network connection. At this initial point in the trip, shown in Figure 2, we can safely assume that a delivery-partner has connectivity, otherwise, they would not receive the dispatch. We send down all required information to complete the flow so that subsequent steps will not require a network connection and inform the restaurant of the potential cash transaction, shown in Figure 3. A delivery-partner may opt out of making a cash payment and continue through the delivery flow, as Optimistic Mode will write failed network requests to disk. Upon regaining connectivity, the backend will be notified of the decision to temporarily skip the payment.
The service supports delivery-partners setting the amounts they are able to pay, which is useful if a delivery-partner does not have all the requested cash on hand or wants change for future deliveries. However, we have not enabled this feature, as more thought is required around the restaurant experience of accepting cash payments that differ from the order total. In current practice, if a delivery-partner opts to complete the cash payment, they enter the payment exchange state with the amount of cash automatically set to the order amount.
So how do we perform the cash payment exchange offline? Requiring both the restaurant and delivery-partner to acknowledge that a cash payment took place reassures all parties and is the most resistant to potential fraud. As we cannot rely on network requests to provide instant notifications to both parties upon confirmation, we utilize the exchange of a four-digit code.
We provide both the driver app and restaurant app all required information to complete the flow at dispatch. The restaurant is given a randomly generated code, shown in Figure 4, below, and the delivery-partner is instructed to request it at the point of exchange.
Conversely, we send the mobile client the SHA256 salted hash of this code, which is compared against the client hashed code later entered by the delivery-partner when they receive it from the restaurant. Upon successful code entry, the delivery-partner can continue through the flow and begin the next stage of the trip. The equality check of the hashed values occurs entirely offline. To prevent fraud, rate limiting and a maximum number of attempts are enforced. Moreover, the option to pay in cash will expire after a reasonable duration if not completed. If a transaction inconsistency is discovered, Uber will investigate further and potentially ban any bad actors from the platform.
Upon successful code entry, depicted in Figure 5, above, a pre-populated confirmation screen is shown to both the delivery-partner and restaurant. If a network failure occurs again, Optimistic Mode will write the failed request to disk and re-attempt when connectivity is restored. The delivery-partner will then be credited for the payment and the restaurant-partner’s balance adjusted against future digital earnings, thus completing the cash payment.
Moving forward with cash payments
Although originally intended for Carbon’s core trip flow, Optimistic Mode has made possible an entirely new set of features. Uber’s Engineering and Design teams are no longer restricted by the requirement of network connectivity when devising new features. Since handing off cash requires significant trust by multiple parties, relying solely on the restaurant to verify arrears collection transactions would not work. Yet, requiring the delivery-partner to have network connectivity could block the trip from progressing by leaving the partner stuck in a verification flow. Optimistic Mode provides the perfect solution by allowing the hand-off operation to occur entirely offline with the backend later being informed of the transaction when a network connection is re-established.
Recognizing the value of offline support, other teams contributing to Carbon are leveraging Optimistic Mode while Uber’s Mobile Network Platform team expands the functionality of the framework. Such efforts in Carbon are moving Uber’s once network-dependent app to one that is responsive in all markets that Uber operates in regardless of connectivity.
Index of articles in Uber driver app series
- Why We Decided to Rewrite Uber’s Driver App
- Architecting Uber’s New Driver App in RIBs
- How Uber’s New Driver App Overcomes Network Lag
- Scaling Cash Payments in Uber Eats
- How to Ship an App Rewrite Without Risking Your Entire Business
- Building a Scalable and Reliable Map Interface for Drivers
- Engineering Uber Beacon: Matching Riders and Drivers in 24-bit RGB Colors
- Architecting a Safe, Scalable, and Server-Driven Platform for Driver Preferences
- Building a Real-time Earnings Tracker into Uber’s New Driver App
Subscribe to our newsletter to keep up with the latest innovations from Uber Engineering.