 really fast for them. I promise I'll do my best. So, hello. That's going to be a tough act to follow, but I'm going to app that for this game. So, I ordered a MacBook selfie stick. Too bad it didn't get on time for the talk, but I'm sure this one works, not that like God's selfie stick. He had to use his fingers to follow the point, right? Yeah. I hope this is going to be interesting. I'll let you know how it goes. Too bad it didn't get on time. So, now let's get into the talk. So, the name of this talk is When Making Money Becomes A Headache, dealing with payments. My name is Sevastian Sogamoso. You can find me in Twitter as Sevastoga. I work at Ride, which is a company where we build the best app for carpooling. You should check it out, ride.com. I also co-organize a Ruby conference in Colombia, where I live. You should join us there. It's going to be imagine, which is a pretty cool city. We are currently receiving proposals, so you should check out CFP and same proposals, but after this talk, not right now. So, now let's get into the talk. This talk is going to be about trust. And I'm going to tell you what I mean by trust. So, it's about having trust from your colleagues, having trust from your company, and more importantly, having trust from your users. Having your users trust you. And how do you do that? Well, you do that in two ways. First, is keeping your information safe. And second, keeping your app free of bugs, basically. So, in this talk, we're going to focus on the latter. And this is how your users trust look like. And then, if you have a bug up here, the trust diminishes. If the bug is really big, it diminishes a lot. So, for example, a ride, if we have a bug in our chat service or your location service, trust is really affected and it diminishes considerably. But if we have a bug in traffic updates, weather updates, or with reminders, trust won't be that affected. It will certainly suffer, but it won't be that bad. On the other hand, if we have bugs related to payment, the trust of our users in our app goes really down. It goes, I mean, yeah, it's really affected. It goes down to almost zero. And this is really bad because users can also disappear. You can just stop using your app, start trusting you at all, which we don't really want. So, in order to prevent this from happening, I want to talk about some common pitfalls I've found when working with payments that I found myself dealing with or that I've seen others struggle with, too. So, let's talk about them. The first one I want to talk is related to payment gateway. So, a lot of people think that when you make a request to a payment gateway, the status code of the response, the response is basically telling you if the transaction was successful or not. A lot of people think that the status code of the response correlates to the result of the transaction. And that's not true in a lot of cases. So, I'm going to show code during this talk, but it's only over simplified examples. I know they may seem a bit dumb, but I'm trying to make a point, so bear with me. You'll see why. So, let's say we have a transfer class that creates a transfer in a payment gateway. So, that class also checks the status code of the response to decide if the transfer was successful or not. When using that class to create a transfer, we might end up introducing bugs. And that's because by trusting it, but trusting it will tell us if the transaction was successful, some operations such as minute transfers take some time to be settled. And with time, I don't mean like a few minutes, a few hours. They take up to like a few days. So, if you make a request to your payment gateway to create a transfer and then you get a response saying like, yeah, you have a 200 code and you think that means that the transaction was successful, you might get a surprise. Because like, well, how a lot of payment gateways work is that only until later, they will let you know if the transaction, if the transfer was actually successful, no, at their own time, they will let you know. And normally, they do that via web callbacks, which are very known as web hooks. And they will let you know that way, the result of the transaction. And they will keep sending them until you acknowledge you got the message. Or until they just like reach their retry limit. But this is normally, this is something that I've seen people struggle with, not being aware of checking for the actual result of the transaction via web hook, web hook, sorry, which are asynchronous. So, there's some important thing that I've seen a lot of people also like, not considered when exposing an endpoint to a third party service such as a payment gateway. You have to think about security. So, when you're exposing an endpoint to a third party, the best way to make it secure is to add authentication to it. But sometimes, some payment gateways don't support that. So, another, like one thing you can do in those cases, if possible, it's just like, get the event ID from the payment, from the payload that the payment gateway sends you. And instead of processing the data you get there, just like going back to the payment gateway, fetching for the data based on the event that you got. Okay, so now I want to talk about another thing, which is operations. And it's a really common problem that it comes when dealing with payment, with money transactions, sorry. So, we fail a lot at making sure that they are idempotent. So, let's look in code what that really means. So, basically in code, that's the difference between the method at the top, which basically charges the invoice every time it is called. And the method at the bottom that only charges the invoice if it hasn't been charged before. In other words, the code at the top right there will charge the invoice 10 times. But the code at the bottom, sorry, the code at the bottom will only charge it once. So, this might seem like a really small thing, but there are a bunch of companies that have dealt with bugs when they have overcharged users, charge them a lot of times, even taking their users accounts to overdraft, which is terrible. With something that can be dealt with really simply, it's like a really basic concept that we forget about a lot of times. So, just keep it in mind. Another common pitfall I found that people deal with that I want to touch here is tracking payment history. So, this is key for stuff like accountability, like being able to deal with support requests from users, even debugging. So, you start to get questions when looking at the code or the records in your database, like how does this record get into its current state or what was this record set at some point in time. And the problem is that it's usually hard to know which code led to a specific state change or if the data, I mean, if the current state was overwritten or if the code that led to a state change is not there anymore, it was removed or it changed. So, a pretty good way to deal with this is recording events every time there's a state change. So, after you start recording events every time you change the event of a record, you need to be really strict about never going back and updating those events because that would basically undermine the whole purpose of doing this. So, getting more practical, there are two ways of doing this. So, one is pretty simple, one alternative is using something like a gem called paper trail, I don't know if you know it, but it's basically magical. You just hook it up and it will take care of a lot of this for you, but it might not work for specific needs. So, you can run your own custom solution for this and maybe doing something like event sourcing. So, let's say you have a charge class that has many events and those events record, record, sorry, records such as stuff such as like the type of event, the relevant data for that event and then you have an order class and that order when being charged creates a charge record and it's corresponding event. So, then after you create the charge, you send it to a payment gateway. Once you send it to a payment gateway, based on the response for the payment gateway, you will also update the charge and create an event based on if it was successful or not. This way, if later in time, I used to complain about why didn't they get their money or why a charge failed, then you can go to your database and check which events are related to the charge the user is complaining about and find out what went wrong or what was going on at the time. So, we just saw three really common pitfalls when dealing with payments. One was related to the payment gateways, the other one was about how to track history, like state changes for your payments and also how to make operations item voting. So, this may seem like boring work, like something that you don't really want to deal with. So, I have great news and speaking after Godfrey, who is a Rails core team member, I was worried that he would break the news before me and is that Rails 5 will introduce a new module called Action Payments. Well, that sounds boring. It should be called School of Payments. So, now that we know there's a magical solution to all of our problems, let's get serious again. We want to keep our users stressed like this, right? And to do that, and I mean basically that's really important because we have to realize that payments play a huge role in the user experience. If you are mostly focused on back-end, as I am most of the time, you think that what you're doing with the course you're writing, it's not really related to user experience. We don't really think of user experience as something that people working front-end is dealing with or responsible for, but that's not really true, especially when talking about payments. So, I want to present five ways I consider that you can provide a good user experience in regards to payments. So, they are doing asynchronous transactions, giving users payment status visibility, allowing them to delete their payment information at any time they want, being able to seamlessly deliver big changes, and being effective at dealing with bugs, which is the hardest one. So, we'll leave it for the last. So, let's review the first one. Again, before we go into this, I'm going to show over-simplified versions of code. Bear with me, I'm trying to make a point. So, let's say we have a charge controller, charges controller, and every time it gets a request, it creates a charge. What this method is doing in particular is going to the payment gateway to create a charge, right there in the controller. So, then it returns true or false, a Boolean basically, based on the status of the result of the transaction in the payment gateway. So, on the surface, this seems to be pretty simple, pretty straightforward, and it looks like this is what's going on. Basically, a user makes a request to your system, and then your system goes to the payment gateway, and then they all go back with a response. Cool, simple, right? But this is what really happens. It's not as simple as that. So, once the request gets to application and goes to the payment gateway, the payment gateway goes to something called the payment processor, which is like where all the heavy lifting related to payment is done. And the payment processor then goes to the card franchise and checks for, like, I don't know, that the number is valid, but the security code is valid, and stuff like that. So, it goes to talk to Visa, to Ramex, or to MasterCard, companies like that. Then after, if your card is validated there, it will check that you have funds. So, it will talk to the issuing bank, the card, the bank that gave you the credit card, debit card even. If you have funds, then it will go and connect to your merchant's bank, which is basically the bank where you get your money deposited to. And in case everything is good with your merchant's bank, then it will go back all the way back to the payment gateway, to your system, and eventually to your user. So, what happens here is that you let your user hang in for a while, and something might go wrong at that point. So, there's a big chance that you're giving your user a bad user experience. So, how can you deal with that? You can change that implementation to an asynchronous one. So, this is something that you should do whenever possible. It's not possible all the time, but it's possible mostly times in my experience. So, in code, being more concrete about it, how would that look? So, basically, your controller will now look like this. You would, when you get the request, you will schedule a job to be executed by another process in the background. This is, it has a lot of benefits, other than just not, like, leaving your user hanging there. So, one is, it makes really easy to retry, charge it fails. So, for example, if your worker looks like this, by adding a background job processor such as Sidekick, you will get free retries. And Sidekick even allows you to specify how many retries you want to have. And the good thing about it is that even if after retrying, for example, three times here, like, the job won't get lost. It will just, like, go to that job queue where you can recuperate later and deal with it. So, now let's move on to the second point I want to talk about. So, it's payment status visibility. So, when dealing with payments, you'll get a lot of questions or requests from users asking like, why don't I see the refund in my card statement? Or, when am I getting paid out? Or, why was I charged $10 for? I just started charging my bank statement on my card statement. So, having a place where users can go and see the payment history will help you deal with that and keep your users happy. So, you can have something like this, or you can go and see the trip you took and how much you were charged for it. The more transparent you are, the more trust you will have from your users. Okay, so moving on to the third point, which is the leading payment information. This might seem trivial, but it's not. You need to give users full control of their payment information. Otherwise, they feel like you're leading them to a trap, or you're just trying to get payment information and then not allowing them to leave, which is terrible. So, giving users full control of their payment information, such as, like, the leading payment matters whenever they want, it's a good thing to do. And you can just, like, have us release in point of implementation whenever a user makes a request to destroy a credit card, you're just going to wipe it from the database. That's good, I guess, but you should also consider that if you allow users to do that, you might be allowing them to, like, get out of your application with pending charges or even leave you with no way to pay them for money you owe them. So, instead of just, like, going ahead and deleting payment information right away, you can do stuff such as checking if they have payment, yeah, sorry, checking the pending transactions and settling them first. So, you could just, like, do something like checking if the Korean user, for example, right, right, has pending trips to be charged and if it does, like, charging them and then deleting the card in case you can delete the card, like, letting the user know, like, hey, I really want to delete your card, but I can't because you have stuff pending, okay. So, going to the fourth point is, let's talk about how to prepare to ship big changes seamlessly without affecting your user experience. So, there are a few ways you can make that easier. The first way is discussing big changes. So, this is too general, too broad. So, there are a lot of ways to do this and I want to talk about how we do it right. We create RSCs. So, RSC stands for Request for Comments and what we do at Riot is to basically create like an open document where everyone gets an amount of time to comment on so basically they can give you feedback about the changes you're proposing. So, what we generally do is explain what we want to do, the overall intention of it, and then focus mostly on how the change will affect other parts of our system. RSCs are not like an invention of us, they've been, they've existed for a long time, they have worked really well for open source and they work for us, too. Another way you can deal with ship big changes seamlessly for your users is to be prepared to by making changing stuff easy. So, let's say this big circle is your billing code. So, there you have business logic and like payment gateway code mixed up and as you can see I mean, maybe you can't but that's why it's represent there is that this code is tightly coupled. So, there's a lot of coupling between the payment gateway code and the business logic. So, the first thing you might want to do is to prepare to like make big changes as to separate them basically. So, breaking the coupling so that you can end up actually kind of extracting your payment gateway from the business logic that will allow you to, for example in the future, like stop using a payment gateway and just plug another one or switch based on the location of your users or I don't know in whatever weird business rule the market you're operating in has and this is how all of these circles could look in code against an oversimplified version of it. So, let's say you have a charge class that receives a payment gateway every time it's instantiated that will allow you to use dot typing to introduce as many payment gates as you want as long as they follow the same contract. So, basically you could use the charge class with one payment gateway or the other and they should work the same. They should be able to seamlessly replace one with the other. So, another thing you can do is to simulate billing. This has been really useful for us at Ride because like we have tests, we test our code, we have unit tests, we have bigger tests that test, for example, all of our billing flow, but still sometimes we want to make sure that changes that we did, how changes that we did will actually run in production, how they will affect our users in the real world somehow. So, having a way to simulate that, it's really useful before running, before doing real transactions in production. So, we use like our simulator in production, not in like in development in QA where we just have like simulated environments to basically see how billing will behave. This is useful for debugging problems that we already have or to see if a new feature we introduced is going to break something. So, building on the steps we just followed like by extracting payment gateway to make changes here, we just basically introduced another payment gateway which we call simulation payment gateway. So, again, using that simulation payment gateway instead of like a real one, you can just basically log everything that will happen that will be sent to a payment gateway and see if what it's actually doing is what you expect it to do. So, that allows you to basically just replay the payment gateway for the simulation one, run your code and check that everything behave how you want it to. So, last but not least, let's talk about dealing with bugs. There's no change in accepting that we create bugs. It's part of building software. Building software is a human process. We're humans, we're not perfect. So, this will eventually happen and we have to be prepared for it. The sooner we accept that we're going to eventually hit billing bugs, the better we'll be prepared to deal with them. So, what's really important is that you catch them quick even before your users notice it, notice that they happened. So, this is really important to keep your users trust in good sending because if you are, yeah, sorry, because if you are proactive about it, they, I mean, your trust won't be affected as bad. But we will talk about a little bit about that later. So, how can you catch your bugs quickly? So, one good way to do that that has worked well for us is basically monitoring and alerting. So, for example, I'm going to show just some serial code. So, if you charge, if you create a charge whose amount is bigger than a thousand dollars, you want to alert everyone because that's something that shouldn't normally happen. It might not be a bug, but it very likely is. Another thing you can do is like, for example, if, right, if we charge a user for a specific trip more than once, send an alert, that shouldn't happen. We shouldn't charge someone more than once for the same thing. So, that's, that's very likely to be a bug. We want to know about that as soon as it happens. And you need to have, like, what I like to call a damage control plan. So, when bugs happen, you need to have three things on that damage control plan or three things to be prepared. So, the first one is communication, which I really talked a little bit about. And you need to have, like, clear communication guidelines. How, who is in charge of approaching users? How are you going to approach them? What's the best way? Like, how long are you going to wait for them to respond if they don't respond and what do you do and stuff like that? So, as I mentioned before, be proactive, reach to the users that were affected by a bug before they reach out to you. That's really important. And then, like, internally, write-off is more than. So, this is something that you can do after, like, the bug was contained and even fixed. But this is really important. Otherwise, like, bugs will happen and you will learn about them. You want to learn why they happened, what went wrong. You will learn how you fixed them. And more importantly, you know what, like, or at least your team will know what plans you have in place to prevent them from happening again. Writing postmortem is a really important thing. We have benefited a lot from this. Because that way, when something goes wrong, everyone knows exactly what happened and they know how to prevent, like, how to, yeah, prevent those types of errors from happening to them, too. So, another part of, I mean, the rest of the part of having, like, a contention, a damage-contention plan is are really, like, focused on something that I call, like, don't be, not being a bottleneck. So, when dealing with payments and a few companies I've worked for, I've found that, like, because it's really number for us, I think, here is to focus on what we know the most about or what we lack the most, yeah, the most. We end up, like, focusing or knowing more about specific parts of our system. So, I found out that, I have found out that there's, it's pretty common for someone in a company to be, like, the payment expert. And that's, that, as we know, it's normally pretty bad. So, let's see what you can do to, like, make this less of a problem when the billing box or, sorry, a payment bug arrives. So, the first thing is, like, have kind of a handbook to deal with problems so that anyone can deal with bugs when that is expert in payments to start around. So, you can include stuff such as, like, how do I refund the user? How do I reverse the transfer? How can I recalculate a balance that's clearly off? Also, write a documentation. The documentation is specifically focusing on the structure of your billing code, how it works, and how it implements the business rules specific to your domain problem, to the domain of your problem. So, doing a quick recap about the five things we talked about. We talked about doing asynchronous transactions, about payment status flexibility, about allowing users to have full control of their payment information and delete their payment information whenever they want. Also, how to be better prepared to ship big changes and how to deal with bugs. So, all of this we saw, that how to prevent the three most common pitfalls and how to improve your user experience in regards to payments, it's all pointing out one thing. One thing we started talking about and is having your users trust. Okay. I hope this was useful and interesting for you. This is kind of a compilation of a lot of things, as I said at the beginning of the talk, that I've dealt with and I've seen other people struggle with. So, I hope this is useful. If it was, come and talk to me after the talk. I'll be here both days, don't be shy, or just treat me and let's start a conversation over there. I love talking about payments because it's what I've been doing for the last couple of years. So, thanks a lot for listening.