Delivering payment requests: one of our killer features

exMewser. Tech Lead of guest-facing products at Mews. Programmer during the daytime, Skier during free time, and a Game Developer at nighttime. I used to be a backend engineer but now I love frontend and React.

In this article, I would like to reveal how software development works at MEWS. The development team is product-oriented, meaning that we focus on a single product and do not build applications on demand. We provide multiple applications for hoteliers and other providers whose services can be booked for certain time periods.

I will use a recent problem we resolved as an example. In this example, I will show you what the development process looks like, from describing the problem to implementing the solution.

The problem we were facing

In some cases, the customer needs to pay for hotel bookings upfront or at least provide a partial deposit of the total cost. The payment happens via payment card over an online payment gateway.

This approach isn’t that complicated if payment is taken at the time of booking. Our configuration allows hoteliers to charge payments a couple of days before arrival. The important thing here is that payment is processed asynchronously after a guest confirms a booking.

The time of settlement trigger related to the reservation lifecycle.

As we can see, the core problem lies at the time of payment. The payment is charged via a background job and the user is not present. We do not require the amount to be paid immediately because the guest can have bookings for a couple of months ahead.

We noticed issues where approximately 10% of our reservations could not be charged at the “time of settlement.” The reasons vary from “insufficient funds” to “missing card details” (for bookings arranged via phone call, for example). Basically, something the application can’t handle and resolve by itself.

In the next chapters, I will tell the story of how we iterated over a few ideas to reach the right solution and handle scenarios where automation fails.

The feature design phase

Once we understood the core issue, we could start to think about how to solve the problem. We had a couple of brainstorming meetings to clear our minds and try to find the best solution possible.

Idea #1 – Let’s introduce a preauthorization

Creating a preauthorization once the booking is created would solve the issue with “insufficient funds” but nothing else. Another point against this solution was that preauthorization is active only for a couple of days/weeks, so it would not work for bookings created months before arrival. For those reasons, we abandoned this solution very quickly.

Preauthorizations in the Settlement workflow.

Idea #2 – User will update payment card details

This was originally proposed as a solution to the problem. The goal here was to let guests update payment card details when settlement fails. The flow was kind of easy:

  1. Payment error occurred in a background job (Settlement)
  2. Guest is notified via email to insert new card details
  3. Once this is done, the settlement will try to charge the payment again
The initial design of the problem solution.

The implementation was not that hard either, except for notifying settlement to run again. The feature was scoped on the blue parts of the activity diagram above. While looking at the diagram we were not satisfied with the solution. As you can see, the guests could end up in an infinite loop. Entering a failing payment card over and over would cause email spam and frustration.

While we were designing the solution for this issue, we were close to allowing guests to pay directly in the guest-facing portal. The whole idea was to allow the guest to pay the settlement amount directly in the system. This would allow the guest to have instant feedback on whether the payment was successful or not.

Idea #3 – Payment Requests

The idea was very simple. Once settlement fails, we create the “payment request” which the guest needs to fulfill.

Fully Automated Payment Request flow.

The guest receives an email containing a link to the application, information about the reason, and the total amount that needs to be paid. Via link, the guest enters the application and pays the payment request. The payment is then immediately processed, allowing instant feedback for the user. In case payment fails, the guest can choose another payment card and try again.

This solution had all the benefits we were looking for. It solves all the cases and can even be automated.

When our solution hits reality

The original idea for full automation of the process proved wrong very quickly. We started to discuss this feature with hoteliers to see whether the solution solved the problem from their perspective.

We realized that the automation part of this feature was not ideal. The hoteliers provided very different scenarios of how they handle failed settlements. It is a kind of individual approach to every single booking. Sometimes they contact the guest and ask them for different payment methods (e.g., a wire transfer). Sometimes they just wait to see if the guest shows up at the front desk or not. And sometimes they just cancel the reservation to free up space for any other potential bookings.

Automating this would require a configuration that started to be an even bigger project than introducing payment requests. But the discussions revealed a few things that we were missing.

Up to that moment, we hadn’t considered displaying a list of created payment requests to allow hotel staff to see what has been fulfilled and what was still pending. The payment request did not have any expiration date which would eventually make it invalid. We did not have any option to cancel the request in case it was created by mistake.

With all this information gathered, we went back to the whiteboard and started re-designing the flow.

Final design of payment request flow.

The only change from the original automated solution was that we notify a hotel employee once settlement fails. The notification contains a suggestion to create a payment request.

Automation still covered email communication. Once an employee creates a payment request, we would automatically send an email to the recipient. We would also need to collect the expired payment requests via a background job to notify hoteliers about expired payment requests and allow them to act on those.

The design of the feature had been finalized. We went through the second round of discussion with hoteliers to confirm the solution was correct and started building the feature.

Email of payment request on the left. Web UI for payment request on the right.

Development cycle

When we have clear expectations of a feature it is way easier to develop it in a shape where it will be shipped to our customers. I don’t think our development process differs a lot from other software development companies. It starts with grooming and splitting a big feature into smaller pieces that can be developed in a single day or two. The split of big features is a necessity for us to keep the quality standard up and prevent bugs. We are building code the same way a house is built from LEGO bricks, layer by layer until finished. There are several reasons to do it this way but mainly:

It is safer

Every line of code can potentially lead to a bug which will cause a malfunction of the feature or whole system. The smaller the code contribution, the less likely it will have bugs. It also gives us time to test the feature in a real environment and potentially fix any bug that was missed during the review and testing phase.

It is more predictable

The estimated release date is more accurate. Smaller things usually go into production faster because the review process and testing time are lower as well. Also, it is easier to keep track of the progress on a project because we can see what has been done and what parts are missing.

The impact

We built the payment request feature to resolve the failing settlement in a couple design and brainstorming iterations. Now we can see that over 50% of payment requests are created for “other” reasons (not what it was originally built for). This just proves the feasibility of the feature.

Payment request reason distribution.

Also, adoption by our clients is still growing—we are onboarding more properties every month. Of course, there was a huge spike at rollout time. It is also important that usage is increasing without a costly campaign. This means that more and more clients find the feature beneficial.

Number of hotels using the payment request feature.

When we built payment requests, we realized that it can solve even more problems than we imagined.

Security of payment cards

For phone bookings there was no way to securely share data between the guest and hotelier. Now, the hotelier can just create a payment request for the deposit and guest is able to securely share their card details via secured web application.

Pay on behalf of a different person

In some cases, the person paying and the person staying are not the same. Imagine a situation where parents pay for the college dorm of their children. Now they can do it since the person paying does not need to be a direct consumer of a property’s services.

Alternative payment methods

iDeal, Apple Pay, Mastercard Masterpass, and others, are called alternative payment methods. All of them need the explicit authorization of the payer. We can very easily offer these methods by by allowing the payment request to be satisfied with them. Hoteliers do not even need to have a physical terminal at the front desk to support Apple Pay. They don’t even need to be in a country where terminals or banks support this payment method.

Option to become a payment gateway

We can offer a payment gateway implementation to any of our clients. Since the purpose of a payment request is to exchange money from a recipient to the initiator, it can even be used for payments in e-shops or any other business. They can benefit from any alternative payment methods we implement very easily without moving a finger or going through the verification processes of APM providers.

Final words

I promised to provide some insight into how software development works at MEWS. At MEWS the dev team is not just a factory for code. We participate in solving the problems our clients have. Members of our team are in touch with our customers, creating a strong foundation for getting things right. The development phase does not stop when the feature is delivered to production: we also monitor and measure the impact of our work and health of the development cycles.

exMewser. Tech Lead of guest-facing products at Mews. Programmer during the daytime, Skier during free time, and a Game Developer at nighttime. I used to be a backend engineer but now I love frontend and React.

More About &