Observable Flutter: Payments in Flutter (Part 2)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
CRAIG LABENZ: Hello, everybody. Welcome back to the fourth episode of Observable Flutter I am your host, Craig Labenz, and today we're going to have a continuation of our last episode before the new year, where if you tuned in, you saw me flounder around with uninstalled Android emulators and overall have a bit of a yak shaving episode before we could actually get to the good stuff. But Jose, who kind of suffered through that with me, has been kind enough to return today. So Jose is once again my guest and he's waiting backstage right now. Let's see. I'll switch over to-- Jose, are you ready? JOSE UGIA: Probably. Hello, hello. CRAIG LABENZ: Welcome. Welcome. JOSE UGIA: Hey. CRAIG LABENZ: So you were just talking about how you wanted to recap again Google Pay and everything that the package can do in Flutter. So the stage is yours. Why don't you summarize for folks what all we can get done with this? JOSE UGIA: Absolutely. Before that, thank you for having me again. I may get used to this if we keep on doing episodes together. Yeah, so for the Flutter plugin for payment, what we were trying to do last time is collect payments on your Flutter application with the help of the Play plugin for Flutter. Just one, maybe, thing to get started with, one little comment, is that there's two types of payments that you can collect on mobile applications. Well, Flutter does more than mobile, but let's say since we are covering Android and iOS for this plugin, let's concentrate on that. One of them is in-app payments and the other one is physical payments. Without navigating too much into each of those, we're going to concentrate on physical payments. Those are payments for things like clothes, gym memberships, maybe physical movies, things that exist in the real world that you can order that you typically pay with your credit card for. And those are the payments that we are going to enable our Flutter applications to collect in this episode, as well as we tried in the previous one. But this time I have a feeling that it's going to go a bit better. What do you think? CRAIG LABENZ: Yeah, I think it is, too. So I did end up figuring out what was-- well, we got to the end. We got to the finish line in the last episode, but my emulator was going so slowly that we just couldn't suffer through it anymore. But when I looked at it later, it just worked. So we actually did troubleshoot everything correctly. But this time all the same, you're going to be driving. So you're the Google Pay expert. So I'm pretty confident. JOSE UGIA: Cool. And I'm going to surely need some support from the Flatiron. So it's good to have you in the back. So why don't we get going? CRAIG LABENZ: All right. Let's do it. JOSE UGIA: All right so let's start from the very beginning. We have an empty folder where we're going to create our project. We're going to start with a new project altogether so that you get a sense on how to integrate the plugin right from the beginning. So let's create a new Flutter project. We're going to call it Easy Pay Flutter. I think I have to use underscore here. And while this--well, that's very quick. So I can just simply go in there, see what's in here. The typical Flutter project structure. So let's open it in code. There we go. That looks more familiar to me. And so as we were commenting a second ago, we want to enable payments in this application. We're going to sell, let's say, t-shirts, and we're going to give our users a way to capture payments. Now one thing to note is that this plugin allows you to add payment providers to your application. It doesn't process payments. What do I mean with that? I mean that we're going to be using Google Pay on Android applications and Apple Pay on iOS applications. For those services, you still need to have a payment processor in the back like Stripe, Braintree, Worldpay. There's many of them, and I'm sure you're using one of them already if you're here. What we're going to do is add this additional layer of payment services that will make collecting payments easier for your users. It's just one thing to keep in mind. Great. So we have this structure of our project. I don't think we need to launch the app right away. We trust that the projects that Flutter Create creates are actually looking good. So if you go to the main page of the plugin pop-up [INAUDIBLE],, which is the one that we are going to integrate, the pay plugin, you can see a good amount of relevant information. I think the two areas that I'll concentrate on is the ReadMe, where you have a really quick tutorial to learn how to use the package. And then you have the repository in GitHub because this is an open source project. But we can talk more about that in just a second. So first things first. You have a good number of prerequisites that I recommend you taking a look into, especially if you're going to integrate this plugin for production usage, then you will need some of those steps. For testing purposes, we are not going to need those, so we're going to skip them for now. It's just for you to know that they are important if you want to integrate for a production integration of the pay plugin. So let's start by adding the dependency, which is going to be Version 1.0.11 of the pay package. So let's go. And this is a great refresher of my Flutter skills. It's been a year since I've touched Flutter, so we'll see how it goes. All dependents are in need. I already have them. CRAIG LABENZ: We're having a redundant line there. There you go. Nice. JOSE UGIA: A great start already. Good. As I say, Flutter pop executing get. So I have my dependency available. Let's go ahead and see how the app looks like in the meantime. So we have a really basic material app with a little counter. Actually, let me just show it. It's just nicer if I show it. So I'll start Pixel 4 simulator. Now talking about simulators, there's a couple of things that we learned during the last episode. One of them is that you need to make sure that you start a simulator that has Google Play services because Google Pay works on top of Google Play services. So if you start a simulator that only has the Google APIs, then you're not going to be able to see the button. Now we just took away 20 minutes from the previous video. So we're good. CRAIG LABENZ: More than that, I fear. Oh boy. JOSE UGIA: I think we can just run this and see how it looks like. And while this runs, I see that I have a Buddy. So that's a buddy of my app with a column view that can have multiple children. I have a text and another text. And then I have a button at the bottom. So I'll just simply add a button here. Should we start with the Google Pay or the Apple Pay integration, Craig? What do you feel like today? CRAIG LABENZ: Well, so we're on an Android emulator, so I think Apple Pay is probably the wrong tree to bark up. What do you think? JOSE UGIA: That's an obvious answer and a good idea. So why don't we go with Google Pay? We already saw an error, and that is because the Google Pay plugin-- sorry, the pay plugin-- needs the minimum SDK version of Android 19 so we need to fix that. To do that, that's a general user recommendation for doing Android things on your Flutter applications, is opening Android Studio, which is, as you know, the most used widely used ID for Android applications. So if we open Android Studio, we can simply open the Android folder in your Flutter project. And if you do that, you're going to have a nice view that you're familiar with about the Android project in a Flutter application. And what you want to go is the build gradle in your application folder. Let's switch to the project view so that we can access the files before the content loads. And then we can open the app gradle, where we have basic configuration. I'm sure you're familiar with this file already. And we have a section in here that it's called mean SDK version. And we saw in the logs that we need 19 there. And again, this is because the Google Pay library needs a minimum version of 19 on the API. So we safe, we think. And now we should be able to run the application. CRAIG LABENZ: While that cooks, I have a question. Whenever I've needed to edit that file, I always just stay in VS code. Are there niceties around those Android-specific edits that draw you back to Android Studio? JOSE UGIA: Yeah, that's a good question. For me, it's probably because I haven't done a lot of Android development on VS Code, and maybe there's tools for doing the things that I do in Android Studio. But I'm personally familiar with Android Studio. And this things, like the gradle thing that probably you also have in VS code. But it's really easy to access. It's easy to find your SDK directory and configuration under preferences. It's also easy to launch and manage your simulators. You can see your simulators in VS Code and launch them, but it's also the manager for creating new ones or changing the configuration. For me it's definitely much easier to find in Android Studio. CRAIG LABENZ: Yeah, indeed. I've certainly never configured an Android emulator in VS code. All right. We're back. JOSE UGIA: How far should we get to? OK, it looks like this works. CRAIG LABENZ: 12,000. JOSE UGIA: Maybe this breaks up at 59. Oh, yeah, broke. Actually, no. It works. So that works fine. So we can go back. CRAIG LABENZ: Oh, real quick, chat is asking to increase the font size. Be good to go full screen on your IDE window. And then yeah, full screen up until the emulator. Yeah. And then a couple command pluses, probably. At least could maybe do another one. And yeah. And then you can get rid of the left bar if you're comfortable with that, which I think is-- nice. You got it. All right. JOSE UGIA: Sorry for that. Good. All right. CRAIG LABENZ: Good call, Damien. JOSE UGIA: Thank you, Damian. I would have some space here. What do you typically recommend here in Flutter, size box or margins or something else? CRAIG LABENZ: Oh. Size box is always fair because you can const to that as well. Of course, if you have a responsibly sized size box then you can no longer use const. But-- oh yeah, there you go. I think that'll do it. JOSE UGIA: So there's the Google Pay button, and there's a few required prompts that we see right away here. One of them is called payment configuration asset. So if that doesn't make sense to you, there's a little note to that in the tutorial right at the beginning, right after you add the dependency. So this is basically a json file now. It's going to be a configurable string in the future, in the really short term future, where you add information about how you want your payment to be. And to make this a bit easier, there's a couple examples in the GitHub repo in the assets folder. So let's take a look at a basic one for Google Pay, for example. As you can see, you have things like the types of card that you want to accept, the networks, the payment gateway that you use, and maybe some information about the items that you are selling. Some of this information can be dynamic as well. CRAIG LABENZ: Can you increase the font size on GitHub as well? Yeah, nice. JOSE UGIA: Hopefully this works for the others. Yeah, good. So yeah, it's just basic information about how you want Google Pay, in this case, to work. So we're going to take one of those as an example. Let's take the default payment profile for Google Pay so you can see similar information. I'm going to copy that into my assets folder on the Flutter project, switch to screen and assets folder, and then a new file. That's going to be Google Pay config.jason. Paste that information that I'm personally happy with, let's say, maybe, for the address. I don't want to have my phone number required because then you're going to see it on screen. And then everything else looks good, I think. CRAIG LABENZ: You don't want us hitting you up with the late night texts? JOSE UGIA: Yeah, especially given that this is PSD friendly. So in six hours, that's going to mean wake-up calls. CRAIG LABENZ: True. JOSE UGIA: All right. Oh, one thing that I have missed already is that I have an asset now. I have a json file in my assets folder. That means that I need to specify that on my pubspec.yaml, I think, and tell it that we're going to have some files in the assets folder. I think that they should suffice. Now all we need to do is just pass in the name file. That will be enough for the Google Pay button to figure out what it needs to do. This has a callback for whenever the payment throws-- returns a result. So now you're going to print it so we can see it on the screen. And we have a list of payment items. So this is going to be because every time you sell something, it's going to be something different with a different price and different text. That's something that you can pass to the button dynamically. You can build it based on the status or the things that the user is buying. And then you can pass it onto the button. What we're going to do, just for the purpose of this example, is add it as a const in here. That's going to be called payment items. It could be an array of items. You can have multiple items. For example, let's say that you have a final invoice or a final checkout page that has two items, and then maybe some VAT, and then a total price, and you can have all those for different items on this list. CRAIG LABENZ: So this is essentially someone's cart when they're checking out, right? JOSE UGIA: Correct. This is what's going to show on the payment sheet when Google Pay or Apple Pay opens to give the user information about what they are paying for. So you don't need to have, maybe, the same level of detail, but something that you think is enough for that amount of real estate in the screen for the user to recognize the payment. Let's just say that label's going to be total. The amount is $100. And the type is going to be payment item type. CRAIG LABENZ: Did that total? Is that we're looking for? JOSE UGIA: Status. So the status will indicate what's the-- I'm trying to look for a word different from status, but nothing's coming to mind. So basically, it's just telling your customers about the status of the payment. That is whether the payment will change or isn't known, or the price is final. So let's say, for example, you are selling, or your users are buying a ride on a bike sharing service, and you don't know what the total amount is going to be. But you have a fixed amount. You have a fixed rate. So you can set that fixed rate as your payment item amount, and then specify or set the status as a known, or something that is pending that will change after the ride happens to give the user, again, that kind of visual indication that the price is not final. In our case, the price of the share that we're going to sell is going to be a final price. So you can very well say that it's final. CRAIG LABENZ: Is there like an estimated status? I'm just thinking about someone getting on a ride share. Oh, pending. Yeah, things like that would probably be it. JOSE UGIA: Yeah, but that's also the result of trying to make both buttons work. I think, in fact, Google Pay has an estimated flag. I believe so. But not Apple Pay, so I think payment works for both of them. But this could be one of those scenarios in which it makes sense to split them in the future. CRAIG LABENZ: Yeah. Yeah. JOSE UGIA: All right. So let's pass the payment items to our Google Pay button. And with that, we seem to be ready with the basic integration. And already saving, shows the Google Play button on the screen of our application. So let's go ahead and try to pay and see what happens. All right. So my test account is showing there with a test card as well. So there's nothing interesting about it. So you can see I have all the information. I can change the account or change the payment method. When I'm ready to go, I can hit continue. But before that, you can see a red text in there that is basically telling us that we are operating in test mode. That is, no charge to your card is going to take place until you go into production. So if I hit Continue, nothing's going to happen. I'm going to receive a test response. So let me do it. And you can see the payment sheet disappeared. And then as I was printing on the payment result, I'm getting that information here, this kind of map or dictionary-looking data. And as you can see here, we have some information about the payment like the billing address, like the card used to pay. This is all metadata for you to use until the payment happens. The most important bit of information here is the tokenization data. The information behind this parameter is what you need to send to your payment gateway or your PSP to actually process the payment. And since we are operating in test, this just has some dummy information. So on the token, so you can see we have something that looks like example payment method token, whereas in a production environment, you will see something that is not readable. It's basically an encrypted payment payload that your PSP will be able to process and issue the order. CRAIG LABENZ: And that token-- there's no other keys in this nested dictionary, right? It's just the token actually contains the goods outside of the test environment. JOSE UGIA: That's right. Yeah, that's internally a little like another nested dictionary, but it's encrypted so far. It's just like an opaque blurb of charts, really. CRAIG LABENZ: Nice. JOSE UGIA: OK. What are the things we can do with this button? Well, I'll get to that in a second, the different integration paths. But there are some other fields that we can have in here just because this button is managed, quote unquote. With that I mean that the button is doing a lot of things for you. You can configure also a number of parameters. For example, you may want the button to be hidden if the user in question cannot pay with Google Pay, and instead show a different widget. You can do that with the child under a param. You can, for example, add a text. Let's actually try it. Text saying Google Pay is not supported. This will be shown as a replacement of the Google Pay button. So if we do this, and then we mess with the configuration, let's say we break it like that and reload, the baton shouldn't show. I think I've broken it so much that the json is incorrect. So it's breaking before it's saying your json is not valid. So let's say-- just make it a bit easier for it. CRAIG LABENZ: So the json will at least parse, but then it will be-- wow. JOSE UGIA: So you see-- let's say for your app, you're supporting, like, 20 payment methods, and you simply just want the ones that are not supported to hide or show something different. You can use that child [INAUDIBLE] for that purpose. I think it's handy. CRAIG LABENZ: Yeah, that is quite handy. So Jose, we have a few questions in the chat. We've already basically gotten further than we got last episode because your emulator works out of the gate. So I was thinking we could maybe pause and chat about a few things, including maybe this question to start. Oh, it went away. I don't know why it went away. Where is the first part, Junveld asks. And the first part is on YouTube, but you've already seen the entirety of that episode in terms of Google Pay payments collecting everything progress. Only watch that episode at this point if you want to watch me try to install Android emulators on a computer that was overtaxed by streaming. But good question. And this is a similar question that we had from last week, Jose. Can you speak to the relationship with Stripe? You mentioned a little bit about it a second ago, that there does still need to be a payment processor in the background. But can you say a little bit more about how Stripe factors into all this, and the Stripe library? JOSE UGIA: Yeah. So Stripe is a payment gateway. That is a collection of services that will help you collect payments in your services, in your application, your backend, in your mobile application. It's the responsible entity of moving the funds. If you need to collect $20 from your customer, then the actual transfer of funds will be done by a PSP, by Stripe, for example. Google Pay, or a payment facilitator like Google Pay or Apple Pay, they are not actually doing the transfer funds. They're not doing the processing itself. They're simply helping your customers to pay. Why? Because in their Google accounts or in their Apple accounts, they already have their frequently used cards that they use for online payments. They already have them there. So they don't need to type them every single time again. So when you use Google Pay, you are giving that ease of checking out to your customers. So they can just simply click. With a couple of taps, they can simply check out. And then that information of the payment method that they have selected, that information is then being sent to your payment gateway, for example, Stripe. There's multiple payment gateways that connect to or can be used with Google Pay, also with Apple Pay. You have them in the Google Pay documentation site, which I can write somewhere, maybe in the comments. Maybe it's not a good idea in the live stream, but you can find them there. And many of them have APIs, as the case in libraries, that you can use in conjunction with Flutter. Concretely for Stripe, they also have a Flutter plugin that it's very easy to use with this plugin. So basically you will get what we have in the payment result here, the payload that has been returned from Google Pay. In this case. They have a method, they have a little class with the method that takes that and creates the order on the Stripe. And so there's other pieces like that will make that integration very easy. And I hope that addresses the question. Let me know otherwise. CRAIG LABENZ: Yeah. I think that was quite detailed. Thank you. There was another question. This is a little Android-specific, and I kind of gather that you have a bit more Android experience than I do. So I was curious what you thought about this question. Out of curiosity, why didn't you locate the flutter.minSdkVersion property rather than directly inserting 19? I have guesses, but they are just guesses. JOSE UGIA: OK. Yeah. Let's try with the combined knowledge of everyone here and see if we can find a solution because I was looking into this today. I wanted to know where that property was set. And I was just looking around on Android Studio and I couldn't find it. So if there's a way to do this, that would be fantastic. Maybe if you know, Lodeki Brian, or you know Craig as well. I was looking in gradle local properties. You have some of them here. But there's not minSdkVersion. So if we could find where that is being set, that'd be great. Do you know where those are set? CRAIG LABENZ: I don't. That's why I was saying I have only guesses. I mean, so I would start by just grepping for that string, minSdkVersion, see if it shows up anywhere. But it might be a thing that gets string replaced at build time, and it comes from some kind of deep buried place. Yeah, I'm not sure. So OK. Yeah, here we have-- but 19, that's what you set it to. So these are probably built artifacts. JOSE UGIA: Yeah, those are build times. The manifest has been-- yeah, this is build directory. CRAIG LABENZ: So is there anything not in the build directory here? JOSE UGIA: This one, which is what we set it to. CRAIG LABENZ: Yeah, OK. So my second thing that I would do to figure that out is just ask someone on the Flutter team who works specifically on the Android bindings, and then they'll just tell me. But no, I don't know. That was a great question, Brian. JOSE UGIA: Yeah, I was looking for that one. And I think it would be elegant if we could do it that way. Yeah. CRAIG LABENZ: All right. Two more I think that it would be good to get to now, and then we'll carry on. So this question is kind of a mix of information about mechanics of the API itself, and then just, I think, a little bit of maybe general application development. Oh, I clicked the wrong one. I do want to get to this question, but the list jumped on me. Shivam asks, but what if we try to send the token information to our payment gateway but the API call fails? JOSE UGIA: Yeah. So that's logic, that's business logic that you have to handle in your application similar to if something else fails. Like if any part of the process of the payment process fails, then at some point, you would want to show some error to your users, or maybe even retry before you show some error. So that really depends on your strategy towards resilience, how defensive you're planning to do it. But that's something that falls under your responsibility because we--well, we-- let's say Google Pay, or any payment provider, will give you the payment information that the user chose when they opened the payment sheet. But then you will have to send it to your gateway. So if that fails, then you have control over that, and you can react to it if you need to. CRAIG LABENZ: Yeah. So I'm going to try to restate what I'm hearing you say here. The interaction with the pay package, that's kind of all on device. And then once you start to send that information to Stripe or whomever, you've now left the universe of this package. And so an error that you get there, that's just entirely outside the scope of the pay package because you've moved on to the next step in the process. Is that right? JOSE UGIA: Yeah. Correct. Maybe we can illustrate it a bit more. So if instead of doing print, we create a little method that takes the result. We call it on Google Pay result. Void on Google Pay result, and then payment results. So that's what's going to be called when your users select a form of payment. And what you have to do here is something like your PSP library, create order in result.token, something similar to that. So let's reload this. CRAIG LABENZ: Yeah, what's it upset about there? JOSE UGIA: Well, maybe like Ascii code. Just doing command space and creating a unrecognizable character. That happened to me so, so many times, so many times. I don't know. Maybe it's my typing skills. CRAIG LABENZ: That's never happened to me. JOSE UGIA: Yeah, it's definitely my typing style. But I have a really weird typing style, I have to confess. CRAIG LABENZ: We computer differently. JOSE UGIA: When you continue, that payment selection is going to be sent to this method. And then you're going to call your PSP on that line, either through your back end or directly through their library, containing the result of the payment. If this request fails, however you want to do it, something like, maybe, const result, and this fails, a result equals some error. CRAIG LABENZ: Retry logic. JOSE UGIA: Then yeah, retry logic. That's really in your hands and something you have control over. CRAIG LABENZ: OK. Oh, there's another question, and we've kind of lightly touched on this, but I think it might be interesting to talk a little bit more about the mechanics. A GDE from Thailand, Vuong-- I hope I'm saying that even remotely close to correctly-- says, can we run this payment process in the dev environment? Now we are in the dev environment right now, but what are the exact limitations of what we can and cannot do? I mean, obviously, we didn't get a real token there. So Stripe is not going to care about your token here value that we just got. So do we have to turn off the dev environment to integrate with Stripe? Or can we kind of connect to a dev environment in Stripe as well? JOSE UGIA: First of all, thank you for the question. I really enjoy this topic, and I think it's very important, especially in the context of payments. You want to make sure that everything works. You want to make sure that this is part of your testing protocols or processes. So now, as Craig pointed out, what you get is a dummy response or result. That means that you have to test both services separately. You have to test Google Pay in one hand and then your payment processor separately. Wouldn't it be great if you could test everything together, like in a more end-to-end-like test in which you could retrieve the test result from Google Pay, and then send that to your PSP, and your PSP confirming that and say, hey, this is a test transaction, but this worked fine. You can go into production. That's something that is not possible today on Google Pay nor Apple Pay as far as I know. We are, though, working internally to tackle precisely just that and give you a set of test cards. You probably familiar with PSP's test cards. They have a collection. They are different in each group. They have a collection of test cards that you can use. CRAIG LABENZ: 4444 and all those. Yeah JOSE UGIA: Yeah. To test different scenarios. So we are working on providing you with those cards on Google Pay so that you can test the entire transaction end to end with your PSP, which we're personally very excited about, and we think it's going to make a big difference to your testing processes, hopefully. CRAIG LABENZ: Nice. Well, yeah. That would be amazing. OK. Last question for now, I promise, then we return to the features. This is a great question that I had as well and I think we got last week, and it's definitely worth hitting again. Mangirdas asks, can we load the payment items from an API, maybe Firebase Remote Config? Or are these expected to be constant? And he's asking this, of course, because we just showed this hardcoded asset file that wouldn't be very mutable. So Jose. JOSE UGIA: Yep. Well, thank you for the question. We're getting such good questions. This is incredible. It's literally the things that I wanted to talk about, I was writing not to forget. And then everyone was helping us cover those topics. So thanks for the question again. We have a variable here, or a param in the Google Pay button widget, that lets you add payment items in here. You can put literally anything valid in here. That is, with valid I mean a list of payment items. You can construct that in however way you find it more useful. You typically do it, as you suggest, that you load that information from somewhere. In fact, we would recommend you doing that because as you know, client applications are, by default, not safe in terms of security. So you want to make sure that your important things like the price come from a safe place or a safe environment like a protected back end system. And so what you do, you fetch that information from your back end, and then with that information, you will construct your payment items. Instead of hard coding like we are doing here you would build those little fields as a result of what you get from your back end request, if that makes sense. CRAIG LABENZ: Now I have a related question here because the payment items, this is like what the user is buying. So of course, this wouldn't be hardcoded because who knows what they're going to put in their cart? A question that I actually misread, Mangirdas's actual question and what I thought he was asking, was about that Config. And that was the question that I thought we got last week. And I have honestly not even really studied what goes in that json, the Google Pay Config. Is it a realistic need for an app developer to have the contents of that file be dynamic? JOSE UGIA: Yeah. And I think there's a use case for that. Right now it's only possible to either create them-- so let's take a step back quickly. There's two ways of integrating this plugin. One of them is what we call the easy or the manage the quick setup in which you have the widgets, you place them in your UI and you're good to go. There's another, more involved way in which you are doing each request separately. In the advanced use case, you can pass in the configuration as a string as well. That means that you have full control over changing that or making that as dynamic as you need to. Now we are also working on bringing that dynamicity, to if you can say that word, that kind of dynamic nature to the widget as well. So we are--there's in fact, a pull request open that will be merged in the next few days that will give you the ability to add a dynamic configuration to the quick or easy integration path as well, because we agree with you that there's a good reason to have a need to have this information change. You may have, for example, in multiple countries, you may want to support different payment methods, for example. There's a whole gazillion of cases that you may want to support. So yeah. That's a good one. CRAIG LABENZ: All right. So all of the things are flexible at runtime. OK. Well, I've interrupted you for quite a while here with some great questions. And now I ask you to just pick up your train of thought from 15 minutes ago. JOSE UGIA: Should we do Apple? CRAIG LABENZ: Sure. Yeah. We do have some questions, actually, also about whether or not it supports iOS and Apple and all that. So hooking up Apple Pay would certainly answer that question. Do we need to switch emulators, and is your iOS emulator ready to go? JOSE UGIA: I think so. But before we do that, just one quick thing that I forgot to mention is that you can have multiple button types because you may want to have a pay with Google Pay or something different. So the type param in the Google Play button will give you a few options. So you can go with donate, for example, and then the label will obviously change. So you can use that to make the Google Play button adapt to what you're collecting payments for. CRAIG LABENZ: All right. JOSE UGIA: So yeah. In the same application-- that's the whole purpose of Flutter-- we're going to add a Apple Play button because we want to support with this application both platforms. We need to start a iOS simulator. And that's something that I'm used to seeing here below. Oh, we just didn't have space. That's why I couldn't see it. So let's start the iOS simulator. CRAIG LABENZ: In the last episode, I was having trouble getting this going, and we concluded that it would only work on a physical device. Was that wrong? Was I just doing something incorrect? JOSE UGIA: That was not my conclusion. Maybe it was your conclusion. CRAIG LABENZ: Oh, OK. Well, great. I'd love to have my conclusion disproved. JOSE UGIA: It should work. It could be that there's something you need to enable here in this simulator that I already have enabled. I don't recall needing to do that at the beginning, but there's certainly some wallets or Apple Pay configuration in here. Like here you can see authorize Apple Pay. Again, I don't think I needed to do that. For me it was just adding an account to my simulator, and it was working. CRAIG LABENZ: All right. Well. JOSE UGIA: And I don't think that was your issue, to be honest. OK. So similarly, we need a configuration asset so let's go ahead and look for a sample configuration for Apple Pay. So just so that I don't have to write the whole thing myself. That will take a long time. And yeah, it's going to take away some precious time that you don't want me to take away from you. So we'll crop it and we'll create a new asset called Apple Pay Config.json. Instead, you'll see similar information here. Some of this is tailored more towards what the Apple Pay library expects, like the merchant identifier. Or you see that the supported networks have a different format as well as the merchant capabilities. You can find detailed information about what is expected here in the Apple Pay documentation the same as you can do for the Google Pay configuration. You can find it in the reference for the Google Pay online API. So let's say that this all looks correct. So you can see here we have some shipping method information as well that will be added as options to the user. So going back to our Apple Pay button in our UI, we are going to add the configuration file. And for the result, we're going to emulate what we had before on Google Pay and just print it to see what's the outcome. And I think the same payment icon should work for Apple pay as well. So I think we can just go ahead and launch it. One question that I have, maybe you can help me with, is if I'm running my app on a Android simulator, can I run it at the same time on an IoS simulator, or do I need to stop the session? CRAIG LABENZ: You sure should be able to. If you think back to Flutter Interact in New York in 2019, this is a bit of a deep cut, but Chris Sells, who was then still on the Flutter team, demonstrated-- what was it called? The Flutter Octagon or Octopus or something. I think it was actually just seven, but nearly eight versions of the same app running at the same time off one laptop connected to a ton of different devices. JOSE UGIA: I wish I'd been there. CRAIG LABENZ: It was a fun event. Right before COVID hit. We had no idea that it was going to be the last time we all got together for so long. JOSE UGIA: Maybe next time, though. CRAIG LABENZ: But yeah, you should be able to click and fire it up. JOSE UGIA: I should have better chances on being part of the next event after having been here to you twice. Maybe just it's just wishful thinking, but that's what I have in my mind. CRAIG LABENZ: You are now on the list of people that I will reach out to about speaking at events. While this builds, I think there is a question that we can probably cover rather quickly. Luxmi asks, will this help with in-app purchases? JOSE UGIA: It won't. Thank you for the question, Luxmi. This comes back to the distinction that we made at the very beginning between the types of payments that you typically can get on a mobile application. One of them will be in a payment. Those are payments which are generally digital goods which are bound to your application and the App Store, or the Google Play store, things like, for example, features of your app on a premium version of your app, or digital currencies or lifes in a game. Those will be good examples of digital items that you need to collect using in-app purchase and the in-app purchase libraries. This is different. So those will not qualify from using the online APIs for Google Pay or Apple Pay. The payments that we are talking about in this session are payments for, typically, physical items like clothing item, like a new speaker, like a gym membership, those which are outside of the policy of the app stores, and those that you typically collect payments through PSPs or through customers paying with cards directly. It's important to make this distinction because if you qualify, or if your app qualifies, what you're selling is part of the policy of the App Store, collection in-app payments, you have to use that one. But if it doesn't, then you can use physical payments. You can use Google Pay, Apple Pay, and your payment processor. So I hope that clarifies, but if it doesn't, there's a really nice summary, at least on the Google Play side, giving you a few bullet points to help you to help you make the distinction. But rule of thumb generally-- again, not for all cases-- generally, digital goods, in-app payments, physical goods, you can use your PSP with Google Pay or Apple Pay. CRAIG LABENZ: Nice. All right. We're up and running. JOSE UGIA: So we have the button. And we'll see what happens today. I don't like it when everything works on the first attempt. Maybe there's something bigger to happen later on. CRAIG LABENZ: Well, there are some predictions in chat that it isn't going to work. JOSE UGIA: All right. CRAIG LABENZ: We'll see. JOSE UGIA: Make it a bit bigger, and let's change the type as well like we did for the Google Play button. As you can see, we have now the available types are different because those are the ones supported by Apple Pay. So let's say in store. That's a bit confusing if we say in store because it looks like a different in-app in store. That's not the case. That probably means in a physical store. CRAIG LABENZ: Also, the button is not changing. JOSE UGIA: And I think that's because it's a-- well, it just refreshed and it's not changing either. So my hypothesis was that given that this is like a native platform component on iOS, so this is building the Apple Pay button using the Apple SDK, it needs to restart the app. That one's not working either. So let me try this one. Problems. I like it. CRAIG LABENZ: Surprising. JOSE UGIA: And let's see if we have enough space. We do have enough space. CRAIG LABENZ: The 50 looks nice, though. 450. Oh, 45. JOSE UGIA: 45 is the actual one. Good. Type, and that's the right one. Apple button type. That should be fine. Let's see. Let me go for the basic obvious. Oh, we have two instances. I code the wrong one, I think. Yeah. Oh, maybe that was the case. Yeah, that was the problem. I was refreshing on the Android one, I think. Correct. CRAIG LABENZ: Hey, look at that. All right. Well, that's a little foot gun to be aware of when you've got multiple simulators going in parallel. JOSE UGIA: So let's say bye. Why don't we go ahead and try to pay with Apple Pay, Craig? CRAIG LABENZ: Let's do it. JOSE UGIA: All right, let's try this. So I click the button. This is in Spanish. Why? Because I think this is configured-- yeah, this is a Spanish phone. I can simply hit on pay with my code. And then as the payment succeeds, then you see a similar response as the one we saw on Google Pay, this time with Apple Pay information. And concretely, the interesting part is the token, which for Apple Pay, comes empty in test mode. CRAIG LABENZ: OK. So that's what people in the chat were saying, that it wasn't going to give a token. But we can still get this far. And we didn't get a token on Google Pay, either. We just got a dummy string that was like example token or something. Exactly as valuable as the empty string here. JOSE UGIA: True, although it looks more kind of working. Just gives you a weird feeling. CRAIG LABENZ: Right. It does, that's true. All right. Well, this is everything that we're trying to do in twice as long last time. JOSE UGIA: Not bad. There's something else that you can change on the Apple Pay button, and that is the style. You can have a black, white, or outlined button. So if you feel that your application goes better with a white outline, you can change it as well. Without even knowing it, you were answering Hamza's question. Can you change the pay button color? You changed. JOSE UGIA: There's some connection here. CRAIG LABENZ: Now I'm wondering, without maybe opening up a massive can of worms, using the standard branded buttons is definitely a good idea because that's what users are used to. But what if I wanted to just start this process from my own on click Handler? Like if I made my own button for some reason, maybe I had odd responsive constraints or something, and I have my own widgets, but I want to trigger one of these workflows. Is that something that the pay package supports easily? JOSE UGIA: It does. There's two things to your question. The first one is, can I use different assets for the Apple Pay or Google Pay buttons? And the answer to that is no because you would be violating the branding guidelines. So when you submit your application for approval so you can use Apple Pay or Google Pay in production, that will not go through. You will get an email back saying, hey, you have to adjust your button to look the way it is intended. And you can see more details on that in the documentation. Now to the other part of your question, you can have more control over the flow. What we saw here is that you're adding a widget to the UI, and you can see there's some things happening in the back room that you don't have full control over like the press event, or what button to show in which scenario if you're in the right platform, and if the payment providers support it. There is a advanced integration path that is also explained in the documentation for this plugin that you can use to have full control over the whole process. And we can take a look if we have some time at the end as well, or maybe even now. CRAIG LABENZ: Yeah, there's an interesting and related question in the chat. Fabian asks, can the language of the button be changed? JOSE UGIA: Yes. So the plugin supports localization. So if you add localization information to your application right away, the button will recognize that and will show the button in the right language. But remember that you have to include that in your application the Flutter way. I cannot fully remember, but I think it was a property on the app or on the theme. And then change the locale of your phone, and then the button will adapt to that. CRAIG LABENZ: Got it. Nice. Great. OK. So are you ready to move on or is there more to cover here? Because I know you've gestured multiple times about an easy path, which we've currently gotten working, and a more advanced customized path. JOSE UGIA: Should we look for trouble and do the advanced one? CRAIG LABENZ: If you're ready. JOSE UGIA: All right. Let's try it. So let's say that you want to have control over the events on how the button is integrated and how things show. You have a little excerpt here about the advanced usage. But basically, it's not super complex. To be honest, I just like to say that beforehand. But there's two main things that happen when you use the pay plugin. The first one is the library will check if the user that is using your application can pay with that payment provider, with Google Pay or Apple Pay, in this case. And if the user can pay, that is, if you have an iPhone or an iOS device on Apple Pay, and then you have a created account, and you have cards of it, then that means the user can pay with Apple Pay. Then the button will show. This is something that happens automatically on the quick integration path. As you saw, there's nothing else that we need to do to make that work. The other main important call, or API event that happens is when the user clicks the button, then you see the payment sheet is coming from the bottom so that the user can select a form of payment and confirm the payment so that you get that information back as a result. So it's mostly two calls that were being done automatically, or automagically, for us in the quick path. Now if we wanted to take control of that, we could do it. It could be that in your application, you need to do that because you have a really kind of detailed way of controlling your checkout process in which, instead of if the user cannot pay with one provider, instead of not showing the button, you want to do something else, maybe go to a different screen, maybe log to your back end. So for those scenarios, the advanced path could be interesting to you. My recommendation would be that if you are integrating this plugin for the first time and you don't have a concrete specific need, I'll encourage you to try the quick path because I believe that path is going to work for most of you. And as you saw, it's very easy to integrate. And then if you see, or if you come across a situation where you need to go a bit deeper, maybe do things in a more particular way for your application, then that's when I would consider the advanced flow. So without further ado, let's take a look at that. So this is just one thing that we add into the sauce, and that is a pay client. That is the little object that will help us do those requests that we were just talking about. So let's create that pay client inside of our state to make it more concentrated on the parts of our application, keeping things modular to where they need to operate. So that will be an instance of pay. And you will see that there's a few ways to instantiate that. And one of them would be with assets. And no way I'm not getting the auto-complete for that. That's basically replicating what we just did before, which is simply letting us pass a list of configuration json files that the pay client will have to deal with. So that looks very similar to what we were passing the buttons before. So let's just add the same thing. Why are we doing this? Because the client needs to know what's the actual configuration for both Google Pay and Apple Pay, in this case. And I'm getting an error here. Why? Because this is not being used. We are going to fix that in a second. So we said that there's two main calls. The first one we're going to figure out is whether the user in question can pay with-- let's do it on Google Pay just to make this easier. I know where my simulator went. It's here. So let's use Google Pay for now. So this first request that we have, to know whether the user can pay with Google Pay, it's in a sinkhole. So we'll use something called the feature builder that I'm not very familiar with, but I have some help. So I'm sure we're going to be able to figure that out. CRAIG LABENZ: With our powers combined. JOSE UGIA: Let's try that. Let me comment that out so we don't see anything else. And then I use a feature builder that will load widgets as a result of an asynchronous call, in this case, user can pay. So the builder, it has this signature. That's the builder prompt that has information about the actual query. And then that will expect a widget as a return, whatever we want to show. This feature builder widget will also have a feature that is, what do we want to load? What is the async call that we want to make? That's going to be part of the pay client. So quickly the user can pay. And we are going to pass the pay provider of Google Pay because we want to find out about whether the user can use Google Pay or not. So that's all we need. Now we need to respond to the multiple instances of results, but this is [INAUDIBLE] can give us. So we're going to use curly braces. And then I think that's one too much, maybe. So let's just add a placeholder size box for all the cases that we are not going to control from that just so that it doesn't throw an error. But basically, we want to cover two different scenarios. One when the call is being made, when we want to show something like a spinner or a loading indicator to let the user know that, hey, there's something going on. Just wait. Wait for it, it's going to come. And I think, if I remember correctly, that's behind the snapshot property. Concretely, connection state. I think that's connection state. CRAIG LABENZ: Yeah, It depends. The connection state could be multiple things, or there could be a data value that changes. I mean, I'm not sure what the user can pay method returns, how that works. We'd have to interrogate that to be totally sure. JOSE UGIA: It's going to make a network request to the Google Pay servers. CRAIG LABENZ: OK. Then I think you're checking to see--OK, this makes sense. JOSE UGIA: Yeah so let's show a circular indicator while the whole thing loads. And then when the connection is finished, so that is the request, we have a result from the request. Then we're interested in two different use cases as well. We want to know because the answer, or the result of this query is going to be either true or false. True, the user can pay with Google Pay. False, these cannot pay with Google Pay. And you really want to show something different in your app based on that. So now we're going to look at the snapshot data. And if that's true, that means the user can pay with Google Pay. And in this case, we want to return to do, return Google Pay button. And if that's not the case, let's go back to our previous example and show a text saying, hey, the user cannot pay with Google Pay. Google Pay is not enabled in this device, for example. Google pay is not anywhere on this list. And it doesn't apply anymore because we are returning a widget in every single instance of our if else tree. [INAUDIBLE] Now before we use a widget called Google Pay button, which has all that business logic inside that is doing all those queries for you, all those network requests for you, we have a simplified version, or UI-only version of the button that it's called raw Google Pay button when you are interested about the graphics, like it's the case here. And as you can see here, there's only a few things that you can configure. The type of the button, we are going to stick to our donate button. And the on pressed event. You can see that this is-- actually, we can const this one as well because it doesn't have any state inside. Keep me true on those things, Craig, but I believe that's the reason why you can const it. So we have all the logic ready, so we can try to run this and see what happens. I'm not sure I have everything. I do believe I do. But let's try. So what should happen is that the pay client should be instantiated. It should make a call to the user campaign method, and this method should return true because I'm running this on Android simulator with an account that has Google Pay enabled. This is running on the iPhone. So in fact, let's let it run because that should return false. I don't think it's finished yet. This is probably from the previous. It's very convenient, though. We could just say, oh, it works and go back to Android. CRAIG LABENZ: Right. You typed the exact same sentence. JOSE UGIA: Let's see. Yeah, that's running now. So that's good. Now we are going to go back to the Android simulator, for which I need to make this bigger on Pixel. Run. Go back. CRAIG LABENZ: Now while this is building, there's one thing I want to talk about, which is line 119. The FutureBuilder has a really kind of alarming foot gun where if you call a method like this in line, and that method doesn't kind of memo-ize its own network request, and if this method makes a new network request every time you call it, then you can unlock some pretty terrible race conditions in your Flutter app. So the best practice for that method on line 119 would be to put this in a stateful widget, which I think we're in a stateful widget because we're still in the counterpart of the counter app. Yeah, and then just save that future in init state. And then actually use the future in the UI. JOSE UGIA: Something like this, right? And then we have to overwrite in InitState. Where is actually that? Is that something that I can override in this space? CRAIG LABENZ: Yeah. Yeah. I'm not sure why you're-- JOSE UGIA: Oh no, not here. CRAIG LABENZ: Yeah, you just can just make a new method basically, InitState. I'm not sure why your snippets didn't pick it up. JOSE UGIA: Is it like override? CRAIG LABENZ: Yep. And then you can call super.InitState, all that good stuff. CRAIG LABENZ: And then user can pay future. Oh, that would have to be-- why is this complaining? Late. Does it have to be late? JOSE UGIA: Yeah. Late, I think, will work. Or nullable. Actually, nullable is probably better. Is nullable a-- this? How you call it? CRAIG LABENZ: Oh, a question mark at the end of the title. Now that I'm thinking about it, would we want it to be late? JOSE UGIA: Late is actually appropriate because we wanted to alert it once and not change anymore. CRAIG LABENZ: InitState will be run before the first build method. So late is fine. JOSE UGIA: User can pay future that is pay client. User can pay. Pay provider, Google Pay. Doing things right. And then here, you can change this with user can pay future. I like it more this way. CRAIG LABENZ: Perfect. JOSE UGIA: This works fine. So now we're making sure that it's all equal at once. Great. Now I click the button. Nothing should happen. It's not even clickable because the on pressed. I remember we are now in the advanced integration. That is, there's nothing being done for you. You have full control over the whole flow. And that is if you haven't set a press callback, the button will not be clickable. So let's go ahead and do that. On pressed on Google Pay pressed. And that doesn't exist. That's why it's complaining. Let's do it right above, which makes more logical sense. Pressed. And then here, we'll be able to do show payment selector. And we can save that already, and the button should be clickable. Not yet. On Google Pay pressed. On Google pay pressed. CRAIG LABENZ: Guessing it's a signature. Oh, invalid constant. Yeah. A closure. So we just, on line 135, we've got to drop the const. Yeah, 135 down. JOSE UGIA: Oh. yeah. Sure. Yeah. We get red. And that's because-- CRAIG LABENZ: Yeah. Now we'll need to restart. JOSE UGIA: And now it's clickable. All right. We are on track. Now what's the second call that we are interested in? The second one on the pay client as well is show payment selector because now, when the button is clicked, now you want to show the payment sheet so that users can select their payment method that they want to pay with. And here, as you can see, we need the payment items now. Not before, because we only want to show the payment items that the user is going to pay for. When the payment selector goes up, it shows. So already if I do this, the payment sheet is going to show. But what I really want to do is capture the result of this request. And that result is being sent directly as a response to this call. So I can directly capture it as a map. I believe it's a map. It's actually a json object as a result of this. This is in a sinkhole, so I'll have to wait on it, which means I will have to make this call a sink as well. And if I now print that payment result, we should see something very similar to what we saw when we integrated the pay plugin through the quick way, through the quick integration. And then we can do it right away. Yeah. And continue. Now this time what's different is that this has been done through this method on line 80, and not as we did before through the managed button. So now that you have the payment result, the next step for you would be to send that to your PSP. So if you're using a PSP just similar to what we did here, if you're using your PSP calls, PSP, and you can just simply do your PSP lib create order. And remember I'm just making this up. This is going to be different on every app payment processor.token. And that will actually create the order in your payment gateway. So it will be the same outcome, the same results, but now through a completely different integration path in which you have control over the first call to the [INAUDIBLE] the user can pay with, in this case, Google Pay. But the flow will be similar with Apple Pay. Show the button, capture the press callback, and then issue the payment selector, get the result sent to your PSP. And the order is created. As you saw, only a couple of steps more, but then full flexibility to do your integration as you prefer. CRAIG LABENZ: Nice. Yeah, I like that. The more branded an app is, the more likely its designers and product folks are to want to control that experience. So it's nice that you can put the LEGOs back together yourself just kind of however you want. JOSE UGIA: Precisely. Yeah. That's cool. So how are we doing on questions? I have been really bad keeping track on this this time. It's a bit of a challenge when you're typing. CRAIG LABENZ: Yeah, you're doing all the work. I'm watching the questions. You're putting together an incredible live demo here. We do have some good questions. So we can get to them. There's one that's come up a handful of times. But I think this was the first person to ask, can we get a refresher on the state of all of this for Flutter Web? JOSE UGIA: Yeah. That's one that I'm personally also really expectant for and can't wait for it to come out. So right now, developments are not active on the web integration for the Payments plugin. That said, it's definitely on our pipeline, something that we'd like to put out because there's web libraries for the providers that are supported right now, Google Pay and Apple Pay, so it's something that will make total sense. That's said, too, again, this is an open source project. And if you take a look at the ReadMe, it's a project for which we expect the community to get involved. It's something that will be very welcomed. In that same vein, we don't see this as a Google project, necessarily, even though it was started by Google. And so there's been already good contributions from the community. But we would like that to develop even further and just let it sail, and go in the direction that everyone feels that it's more appropriate for their purposes. So feel free to take a look. Take a look at the ReadMe and the contribution guidelines. It's very easy to get set up. And if you don't feel like committing code, that's OK. We have a section for issues and discussions where your participation and feedback would be fantastic. If you're willing to commit code, that's even better. So we're waiting for you there. CRAIG LABENZ: Yeah. And a lot of the questions-- there's a set of questions that we've gotten in the chat that I think could be nicely asked on the-- or by that I mean, it'd be nice to ask them on the repo in terms of different country support, different kind of back ends and whatnot. But here, before we get too far-- I wanted to say that quickly because it was just what you were talking about, Jose. But we've got a question that I think pretty important for anyone who is kind of new to this entire space of app development. What does PSP stand for? JOSE UGIA: I'm not searching for it because I don't know where it is. CRAIG LABENZ: I think it's payment service provider, right? JOSE UGIA: Oh. Yeah. PSP is also a gaming console. CRAIG LABENZ: Nintendo. Or not Nintendo. Of course it's PlayStation. Yeah. oh it's PlayStation Portable. But for it's payment service provider, I think. JOSE UGIA: Correct. Yeah. It's payment service provider, or also known as payment gateway. That is a entity or a company that provides you with services if you are collecting payments. Sometimes this is simply processing the payment, that is, moving the funds from your customer credit card or bank account into your bank account as a merchant. But some other times this also includes other features like fraud analysis, like metrics, like merchant features, like invoicing. Pretty much anything that a business selling online would need or would benefit from, it goes by the name of both PSP as payment service provider or payment gateway. And I'm sure you have heard about a few of those already. CRAIG LABENZ: Yep. Nice. Great question. So let's see. What are some other good ones? Oh, this one is certainly worth covering. I love that Muhamad is thinking about security, and they ask how to handle the security on these payments. JOSE UGIA: Especially with payments, right? CRAIG LABENZ: So can you say a little bit about-- exactly. Right. Couldn't be more important. So you can say a little bit just about are there security things that a Flutter developer going through this process has to keep in mind? And which of those things are already handled by the various SDKs? JOSE UGIA: So I'd say that unless your PCI DSS-- which is a whole payments regulation-- PCI DD is compliant, then do not manage payment information of your customers. Depending on the country, I think that's illegal or forbidden in some way. But also, it's definitely not good for your business in the sense that if you mishandle that information, then you will be exposing your users. So most PSPs, most payment gateways, if you use their libraries, they will have proper security mechanisms. They are definitely PCI DSS compliant and they will help you keep your information safe. So for example, when you're using a website, they will be using iFrame to collect card information on the form. And the same goes for the application data is being treated as securely as possible that is, let's say, on one hand make sure you use elements from your service providers in that sense and payments do not deal with payment information do not manage payment information yourself unless you're doing that as part of your business. But then second, there's a general rule of thumb that I apply that we covered before earlier, and that is assuming that client applications or websites running on client browsers are by default unsecure, or are by default breakable in the sense that if someone gets physical access to that device, that means that the information could be compromised, even actually not only physical access, but if a bad intended actor got access to your device, they would have an opportunity to see what's part of that application in terms of what's in that phone, either through memory inspections or disk inspections and so on. So I generally like to treat client applications as not secure. So and the reason we talk about that is because I think for payments, it's important to have every kind of information that could be sensitive be dealt with in a secure place, like your backends, for example. We were talking about the price before our recommendation is that if you are doing price or item calculation, anything that has to do with payments, that you do that in a safe environment that you can trust. You know that you're back ends are private. They can only be accessed externally or they have keys that you're using to encrypt the information. So you get the information from there. You show it in your app. But then when you're creating a transaction again, then that's something that happens, again, from your backend server to the PSP. There are some PSPs that have secure mechanisms from your app and you can use those very well. But as a general rule of thumb, I am personally wary of client apps. And I take special care of those scenarios, and I certainly recommend you to do the same thing. One additional thought is that using payment facilitators like Google Pay or Apple Pay definitely helps you there. And how does it do it? It does in the sense that when you are asking for a payment mechanism-- for example, let's say we go back to Google Pay, we are opening the payment sheet, I'm selecting this Visa card, and then I'm hitting continue-- that information will go back through your app. But it will be encrypted. That is, only Google Pay or the PSP will be able to decrypt that information and see the context. So that's an extra layer of security that you have. So even if someone was able to get access to your device, they wouldn't be able to do anything with that. So I know I gave a collection of answers. But hopefully that makes sense. We can summarize it as, don't trust client apps by default. Do not handle payment information yourself unless your PCI DSS is compliant. And Google Pay and Apple Pay will help you stay more secure, if that makes sense. CRAIG LABENZ: Yeah. No, that's a great answer. I mean, any holistic approach to security, there's so many different facets to having a secure app. And I am going to put that in air quotes. But it's always great to be thinking about it. And Jose definitely nicely hit on all of the basics, and just the state of collecting payments. When you use those SDKs, you go a very, very long way toward having a secure checkout process. JOSE UGIA: They say that full security is impossible, and getting close to 99.9%. The effort goes into infinite. So finding a sweet spot, I think, is appropriate for your use case and try to keep users safe. CRAIG LABENZ: Yeah, absolutely. All right. So we are kind of winding down on questions about pay specifically. Oh, here we have a little success story Thanks so much, Pay Library. I have successfully integrated Google Pay with Stripe gateway for payment on Shopify. JOSE UGIA: Nice. Cool. That's great to hear. Well, if you have more thoughts or feedback, we'd love to hear them. But it's great to see that already. CRAIG LABENZ: Yeah, absolutely. By the way, I apologize to everyone listening at home. We're streaming on an unusual day today, and I didn't choose this day for the recurring day for the show because it's garbage day outside. So I'm trying to mute myself while the garbage truck is farting around picking up everybody's stuff. But can only do so much. Here's an ambitious question. How can we create a payment processor? JOSE UGIA: Wow. Definitely ambitious. CRAIG LABENZ: Yeah. You're talking about founding another Stripe, essentially. JOSE UGIA: Funny shorts. Yeah. Where to start from? Find a good name for your PSP. CRAIG LABENZ: Yeah. I think the answer to this is to not do it. I mean, if you want to make another payment processor, that's like a life commitment to such a startup. And you wouldn't want to take that lightly. And I'm guessing that you're asking something else. But if you're really asking that, then you'd want to know way more about it than Jose and I put together. JOSE UGIA: Yeah. And probably it falls under the category of business questions of trying to find a need that is not solved by the main PSPs today. There's a very good coverage today. We have, especially with modern PSPs with a lot of APIs and online services, it's gone a long way compared to back in the day. You can now take payments globally. You can do everything with API calls, [INAUDIBLE] get information, capture payments, do stage payments. It's just incredible. But if you have found something that you think is not covered, and then again, we're back into the second episode of business class for engineers and payments, then it's something to look into. But yeah, it would be something certainly complex. And you would be dealing with sensitive information as well. So it's important to get the right people in and get it right from the beginning. Otherwise, I think the internet and reputation is not very forgiving in this field. CRAIG LABENZ: That's true. Yeah, people don't like when companies leak all their users' credit cards. All right. So maybe a few kind of generic questions. What was the one that I wanted to go with? Oh, this one is kind of pure Flutter. And say hello, should we only use the build method for layouts, right? For initializations and instance creation, we should use InitState. And short answer is yes. Yeah, when you're laying out your app, everything goes into the build method, and basically nothing else goes in the build method. You are just printing the next frames worth of widgets. And the most dynamic stuff that would go in there would be the callbacks for click events on those widgets. When you're setting anything up, that's where you dive into InitState. And we did that-- I think it was after this question actually appeared. But in this episode, we had a future that was in line in the build method, and then we pulled that out into InitState. So you were definitely on the right track. JOSE UGIA: Oh, maybe they were just calling that out when they were seeing me typing, and softly, gently suggesting, hey, you may want to do it differently. CRAIG LABENZ: Could be. Yeah, I'm not sure the actual timeline on that. That is possible. OK. Let's see here. This is another ambitious one. JOSE UGIA: A lot of those. CRAIG LABENZ: Can we make an IAP without a back end? An IAP stands for Identity Access Provider. So that would be something like Firebase authentication or others. I don't know how to do that without a backend. JOSE UGIA: I think it's impossible. You need that social truth. CRAIG LABENZ: Yep. [INAUDIBLE] back end. JOSE UGIA: Yeah. Or some other source of remote, trustable truth. CRAIG LABENZ: Like a blockchain or something? JOSE UGIA: We could go wild. Yeah. I was just going to that direction, or a group of people that has remote earplugs that receive every request. Well, any form of external social truth, I think you need. But the back end is a very good one that works very well. CRAIG LABENZ: Yep. Yep. And obviously, Web3 and crypto and all that has kind of lost a little bit of its luster over the last few months as I think more and more developers realize that that doesn't actually unlock an entire new universe of wonderfulness. In theory, a blockchain could be an identity access provider that was completely decentralized. Unfortunately, blockchains are extremely slow to write to. So you'd have a very, very, very low bottleneck of new users that you could add to your Rolodex because that distributed trust is expensive to attain across all of your different nodes. So I think you're going to need a back end. JOSE UGIA: I didn't know that. That's actually pretty cool information that you have, Craig, in your brain. CRAIG LABENZ: Every now and then I hear something interesting and don't forget it immediately. Here's a question back to the pay plugin. Is there any roadmap for the project? JOSE UGIA: Yeah. So I'm going to go, as I said, if you go to the discussions on issues in the Flutter plugin, you will see a glimpse of that. So there's things like web integration, making the configuration be dynamic, as we have been discussing, here as well. Especially go to the bottom. You see a few of them. So there's certainly a roadmap. I'd say it's been managed the same as every other open source project, so it's been built with a contribution, not only in terms of code, but also in terms of decision and roadmap with those guidelines in mind as well. And so you will see action there through discussions and issues. And those, the most relevant ones will turn into a feature requests that will then be implemented as just the regular flow for open source projects. This is a great place to start discussions on issues. CRAIG LABENZ: Yeah, absolutely. Nice. This does seem to be quite structured and it's well-organized. Now Jose, I've been really driving on questions. Have you seen any that you want to get to? I can go to a few more here before we wrap up. But if there's any that you've seen, I don't want you to not feel like you have control of the reins, either. JOSE UGIA: I haven't much. But I'm checking it right now. We have an [INAUDIBLE] from our boss to decentralize payments, something that I think connects very well with what you were saying, or doing payments in that centralized environment. And I think the only place to do that right now is blockchain as far as I know. So I think your answer very well fits into that. We have [INAUDIBLE] asking at 6:46-- well, my time, actually, so it might be a different time in your time zone-- whether this will be published in GitHub. And great news is that it's already published in GitHub, and it's been published for the last year and a half. So please do check it out. CRAIG LABENZ: Yeah. Now to fully answer that question, I think to merge his answer and your question, at least the way my brain is seeing all of this, we didn't actually get we didn't really stray very far away from the ReadMe, right? So that's what I think you mean, Jose, by this has been published for a super long time. In the code that Jose wrote today-- is the raw Google button and everything, is that also in the ReadMe? And where would someone find out about the raw Google payment button? JOSE UGIA: Yeah, it should be there. Let me double check and see if I can find it. But yeah, you're actually understanding the questions the right away. I'm misinterpreting most of them. Yeah, so you have an [INAUDIBLE].. Same integration in the advanced user section. So I don't really think you need that code. It's almost like 95% similar to this one. Well, we do have the putting the feature in a variable. So that's something that we may want to do here because as someone else pointed out before, this could be perceived as a bad practice as well. CRAIG LABENZ: Yeah. And even if that function does hold on to a single future internally, I would still recommend the developers make the change that we made because you're really depending on the client-- you're really depending on the library to always behave in that way. JOSE UGIA: That's a good point. We have one really good question from [INAUDIBLE],, how to handle the decimal double value in total amounts. And I think that's a good question because it's different on different platforms. Concretely on Google Pay, it's being treated as a string. So it's expecting a string with a dot separation for all locales. Different locales have different punctuation, as you probably are aware. And that's the reason why you're asking. Whereas if I remember correctly, the Apple Pay library expects an integer or [INAUDIBLE],, basically a number. And so that was a compromise that had to be done for the main layer of the library, for the dark side of the library. By the way, I love when you say dark side. Just sounds like something else. CRAIG LABENZ: It does. JOSE UGIA: And that's very cool. Be on the dark end, we have chosen to go with string, which works for both areas. But there's additional logic that we are doing on the Apple Pay native side, on the iOS side if you look at the plugin, to make sure that there's no catches in there because as you will point out, different numbers with more precision, for example, or large numbers could have trouble on the rounding up. So we haven't found a, let's say, 100% working solution. But this works for majority of the cases. And in any case, it's important to keep in mind that number is not going to define what you charge your users. That's something that is defined internally in your back end when you make the order. This is only there for UI purposes so that when you open up the payment sheet, if you have a final price, the price will show up in here. So that's not going to modify the final price, if that's a concern. CRAIG LABENZ: That you actually charge. Right, right. Though of course, best to not accidentally mislead your users, especially with a decimal location error. Goodness, they would be quite alarmed. JOSE UGIA: Two places to the right. Big impact. CRAIG LABENZ: Yep. All right. We are near the end here. I do want to wish Jasbir Khalif a happy birthday. Nice. JOSE UGIA: Happy birthday, Jasbir. And thank you for bringing your birthday. We really appreciate it. CRAIG LABENZ: Yeah. Hopefully they've stuck around the whole time. All right. Maybe the final question here, at least from my side. Spectator says, observable? Are using reactiveness? And this show is just called Observable Flutter because you get to watch people write Flutter. You get to observe the Flutter, and observable is a class in Dart. I forget if it's from the Dart SDK or the Flutter SDK. Somewhere there's some popular observable class. And of course, it's the language programming-wide pattern of observable reactiveness and whatnot. So that's the cheeky name for the show. Jose, any closing thoughts about pay or anything else? JOSE UGIA: I'd say the only thing that-- I think we have covered everything. So the only thing is that if you want to keep on engaging with us, there's a couple of links that we will post in Twitter on the Google Pay Devs account, potentially on Flutter as well if we convince them to retweet. We'll see. And look at Craig's face. Maybe it works. And those links are pointing to the plugin in [INAUDIBLE] Dev, and then to the GitHub repo as well. Remember that this is a central place where you can engage with us, engage with the plugin itself, contribute, add your thought, feature requests, discuss because this is what, as we covered earlier, what determines the path forward. So we'd love to see you there. We'll certainly wait for you there. So yeah, that's what I would say. CRAIG LABENZ: Absolutely. I would also point, all of our viewers at 17 Days of Flutter, which, if my math checks out, I believe that starts today because I think we're 17 days away from Flutter Forward coming on January 25 in Nairobi. And the next episode of Observable Flutter will be back at the normal time this week, Thursday, so only like three days away. And I will be taking a stab at the coding challenge that [? Khan ?] mentioned in the video. She said there's going to be a weekend coding challenge. So get your keyboards and IDEs ready, and I am going to come in to that episode with my keyboard and IDE ready. So on Thursday, we'll be several days into the 17 Days of Flutter as we approach Flutter Forward. And I invite everyone to tune back in, and we're going to be doing some video game things because that's a big theme of the Learning to Fly season two episode that's coming in the 17 Days of Flutter. All right. Jose, thank you. You waited-- I want to say it was six months ago that you first reached out. And scheduling things across the Atlantic Ocean is quite a headache. So thank you for your patience. Thank you for joining twice. I think we got through a lot of stuff here. We showed the full end to end of the pay plugin. We integrated it on Apple. We integrated it on Android. And I think folks are going to be set up to collect payments in Flutter. JOSE UGIA: It was well worth the wait. A lot of fun. So thank you for having us. CRAIG LABENZ: Yeah, absolutely. All right, everybody. Have a great week and I will see you all on Thursday. JOSE UGIA: Bye.
Info
Channel: Flutter
Views: 10,535
Rating: undefined out of 5
Keywords: payments in flutter, flutter payments, Observable flutter, what is observable flutter, live coding, code tutorial, coding tutorial, how to code, live code, flutter livestream, flutter stream, flutter latest, flutter updates, what’s new in flutter, flutter tutorial, introduction to flutter, how to use flutter, google stream, google livestream, flutter developer, flutter developers, google developer, google developers, flutter, google, Craig Labenz
Id: h8k_pjo7ams
Channel Id: undefined
Length: 95min 55sec (5755 seconds)
Published: Mon Jan 09 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.