00:00:15.500
Joining a little late, I have a lot of slides, so I'll try to go really fast through them. I promise I'll do my best. So, hello!
00:00:26.960
That's going to be a tough act to follow, but I'm going to try.
00:00:34.880
I ordered a MacBook selfie stick today. It didn't get here on time for the talk, but I'm sure this will be one more experiment.
00:00:42.780
My God, my selfie stick had to use his finger!
00:00:48.329
I hope this is going to be interesting as we dive into it.
00:01:01.379
Now, let's get into the talk. The name of this talk is "When Making Money Becomes a Headache: Dealing with Payments." My name is Sebastian Sogamoso, and you can find me on Twitter as @saratoga. I work at Ride, which is a company that built the best app for carpooling. You should check it out at ride.com.
00:01:19.610
I also organize a Ruby conference in Colombia called Rails Live, and you should join us there. It's going to be in Medellín, which is a pretty cool city. We are currently receiving proposals, so check out the CFP to submit.
00:01:34.799
Okay, now let's dive into the talk. This talk is going to be about trust. I'm going to tell you why it's crucial to have trust from your colleagues, from your company, and, more importantly, from your users. You must gain your users' trust. How do you do that? You can achieve this in two ways: first, by keeping information safe, and second, by keeping your ad-free gift box ready to show.
00:02:21.569
In this talk, we're going to focus on the latter. This is how your users' trust looks like, and if you have a bug appear, trust diminishes. The loss of trust is significant. For example, at Ride, if we experience a bug in our chat service or location service, trust is heavily impacted.
00:02:49.260
However, if we have a bug in a non-critical feature, like traffic updates or reminders, trust will suffer, but it won't be as bad. On the other hand, if we have bugs in the payment process, user trust can drop to almost zero. This is dangerous because users can easily stop using your app and lose their trust.
00:03:35.220
To prevent this from happening, I want to discuss some common pitfalls I've found when working with payments. I've personally dealt with these issues or seen others struggle with them.
00:03:41.069
The first pitfall is relying too much on payment gateways. Many people think that when you make a request to a payment gateway, the status code of the response tells you whether the transaction was successful. This is not true in many cases.
00:04:11.849
I will show code during this talk, but I'll be using over-simplified examples to make my point, so bear with me. Let's say we have a transfer class that creates a transfer in a payment gateway. This class also checks the status code of the response to determine if the transfer was successful.
00:04:32.650
When using this class to create a transfer, we might accidentally introduce bugs. This happens because if we trust that the status code indicates success, we might be surprised later. Some operations, like transfers, take time to settle, which can be up to several days.
00:05:39.279
When you make a request to the payment gateway to create a transfer and receive a 200 OK status code, you might think that the transaction was successful. However, many payment gateways only notify you later if the transaction was actually successful.
00:06:00.460
They typically do this via callbacks, known as webhooks. They will inform you of the transaction result and keep sending them until you acknowledge receipt of the message or they hit their retry limit. This is a common struggle I've noticed: not checking for the actual transaction status via webhooks.
00:06:23.649
Another important aspect when exposing an endpoint to a third-party service, like a payment gateway, is security. When exposing such an endpoint, it’s best to add authentication. However, some payment gateways do not require that.
00:06:58.280
One alternative is to retrieve the event ID from the payment gateway's payload and then fetch the relevant data based on that event ID, rather than processing it immediately.
00:07:03.710
Now I want to talk about another common issue, which is ensuring operations are idempotent. Failing to address this can be a significant problem when dealing with payment transactions.
00:07:45.380
Let’s take a look at some code to understand this better. At the top, there's a method that charges for an item every time it's called. At the bottom, there’s a method that charges the invoice only if it hasn't been charged before.
00:08:31.490
This might seem small, but there are companies that have dealt with bugs caused by overcharging users. Overcharging is terrible. It can easily happen, and it’s something we need to be vigilant about.
00:09:01.640
Another common pitfall is tracking payment history. This is crucial for accountability and for handling support requests. It’s essential to be able to determine how a record reached its current state.
00:09:16.700
It can be challenging to determine which actions led to a particular state change, especially if the code responsible for that change is no longer available. A good way to handle this is to record events every time there’s a change in state.
00:10:23.600
Once you start recording events for state changes, be strict about never modifying those events. Doing so undermines the purpose of logging them. You can achieve this with tools like the gem PaperTrail that helps manage recording events.
00:10:51.230
If the tool does not meet your specific needs, you could create a custom solution, potentially using an event sourcing approach. For instance, you could have a Charge class with many events that detail their type and relevant data.
00:11:06.590
When you initiate a charge, you send it to the payment gateway and update the charge record based on the response. This way, if a user complains about payment issues, you can investigate the relevant events related to that charge.
00:11:30.950
We just covered three critical pitfalls when dealing with payments: trusting payment gateways, understanding payment history, and ensuring operations are idempotent. While this might seem dull, effective handling of these tasks is crucial.
00:12:05.840
I know that Godfrey, a Rails core team member, will break the news about a new module called Action Payments, which sounds boring. It should be called Horrible Payments.
00:12:29.890
Now that we have a possible solution to some of our issues, let's get serious again. We want to maintain our users' trust. Payments play a huge role in user experience. If you’re focused on backend development, you might think your work doesn’t impact user experience. However, that’s not true, especially concerning payments.
00:13:04.320
Here are five ways I think you can provide a good user experience regarding payments: using asynchronous transactions, giving users visibility into payment statuses, allowing users to delete their payment information at any time, deploying large changes seamlessly, and efficiently addressing bugs, which we’ll discuss last.
00:13:56.960
To illustrate my first point on asynchronous transactions, let’s simplify a scenario. Imagine a charge controller that interacts with a payment gateway to create charges. This seems simple; the user initiates a request, which is processed, and a response is returned.
00:14:29.840
In reality, what happens is much more complex. Requests are sent to a payment processor that handles the heavy lifting and checks for the validity of the card and availability of funds. The payment processor communicates with multiple entities, including banks.
00:15:35.940
This process can leave the user waiting too long, leading to a poor experience. To fix this, consider implementing asynchronous processes. For example, your controller should schedule background jobs that handle payment processing. This allows you to provide a better user experience and enables easier retry mechanisms for failed transactions.
00:16:57.979
For the second point regarding payment status visibility, it's crucial to allow users to see their payment history. Users frequently inquire about charges on their statements, so providing a dedicated section can help address their concerns.
00:17:43.840
The more transparent you are regarding payment history, the more trust you will earn from users. The third point is allowing users control over their payment information. It’s important not to trap users into payment systems that don’t allow them to withdraw their consent.
00:18:54.220
Empowering users to delete their payment information is crucial. However, do consider that if users can delete their payment data, ensure they settle any outstanding transactions first.
00:19:35.940
When suggesting users delete their payment methods, check for any pending transactions first. For instance, if a user has pending trips, charge them before deleting their payment method.
00:21:02.220
Moving on to the fourth point: how to prepare for significant changes without negatively impacting users. Discussing these changes with your team is crucial.
00:21:46.230
Document these changes comprehensively by explaining the intention behind the modification and consider how it will impact other systems. One effective method we use is RFCs (Request for Comments), an open document where team members can provide feedback.
00:22:51.700
Additionally, you should work to decouple your code; ensure the billing logic isn't intertwined with payment gateway functions. This allows for more flexible adaptations in the future.
00:23:20.440
You can also simulate billing in non-production settings to test how changes might impact users. This can catch potential issues before they reach real transactions. Having a simulation payment gateway can allow for testing of payment flows without real transactions.
00:24:52.690
Last but not least, let’s discuss how to deal with bugs. Accept that bugs are an inevitable part of software development. To maintain user trust, proactively monitor for bugs before users encounter them.
00:27:11.940
Monitoring and alerting systems are key to quickly catching these bugs. For example, if you notice a charge of an unusual amount, alert the relevant teams. Additionally, maintain a damage control plan to ensure swift communication with affected users.
00:28:27.650
Communication is critical during these times. Make sure all team members understand how to respond, what information to provide, and how to approach users effectively.
00:29:50.270
Finally, conduct post-mortems to analyze what went wrong, why it happened, and how to prevent similar issues in the future. Learn from these experiences as they enhance your team's knowledge and preparedness.
00:30:30.350
To recap, we explored asynchronous transactions, payment status visibility, user control of payment information, preparing for significant changes, and dealing effectively with bugs.
00:30:52.660
All the points lead back to one critical aspect: maintaining user trust. I hope you found this talk useful and interesting; it compiles a lot of lessons learned from my experiences and the struggles of others.
00:32:17.530
If this resonated with you, please come talk to me after the talk. I'll be here for both days. Don’t be shy! I love discussing payments, as it's an area I've been working in for years.
00:32:41.060
Thank you for listening.