Accept Payments in Flutter App and Website with Razorpay: 2 Ways to Auto-Capture Payments

 

Integration and auto-capture of payment in Razorpay-flutter


In this tutorial, We’ll be integrating razorpay in flutter app and flutter web. And, to avoid auto refund of payment we will auto-capture payments by making call to razorpay order api.

So, without wasting any time let’s get into integration of razorpay in flutter and the 2 different ways to make call to order api so we can auto capture the payment else the payment done get’s refunded after certain time if not captured through the console.

Table of Contents

  1. Setup
  2. Two different ways to call razorpay order api to auto-capture our payments
  3. Integration of razorpay in flutter app
  4. Integration of razorpay in flutter web

Setup

Before proceeding further you need to initiate the steps mentioned below:-

  1. Create a Flutter project
  2. Get Razorpay Api keys

After that, add the following dependency in your pubspec.yaml file and run flutter pub get.

After running pub get we need to add our progaurd file. So, create a proguard-rules.pro file at location:-android/app/proguard-rules.pro and paste the following code in it.

Once the files is created we need to make changes in build types of android>app>build.gradle

Let’s build the model and 2 different ways to trigger API calls

We need to make call to order api of razorpay else the payments received will be refunded in few days if not captured manually from razorpay console. So, let’s start by creating the model for storing the response of order api through which we can access order id and hence fulfill the motive to auto-capture the payments. So, create a response_model.dart file and copy the following code to it.

Now we have the structure ready to hold the response of our api call we shall now create function to call order api. For this we have 2 different ways shown below:

1) By making an http call

This method is quite easy and faster to add in your app but the problem with this method is that it won’t work for flutter web due to CORS. So, for flutter web you need to use the second method. So, to use this method create a file named order_api.dart and copy the following class code to it.

As shown in the code, we need to pass amount which should be in the smallest currency for example if you want user to pay 1200Rs then you need to multiply your price with 100 and convert it to string i.e. (1200*100).toString() and pass it along with the key secret and id received from razorpay to the post request. Then if you get a status code of 200 then you need to store the response in the model declared above and return it else you need to return null. Now we have successfully created a function to call the order api of razorpay which will provide us the required order id to auto-capture the payments.
Ps:- For security concerns, I would suggest you to have this key id and secret stored in your database and fetch it from database and then pass to this function like we are passing the price.

2) By making an http callable cloud function

This is the method which I would recommend personally as the key id and key secret are stored in the cloud function which is well secured and you don’t need to store your key credentials on database and then fetch them which increases read and writes, and is a bit slow as you are fetching key id and secret then making a call to order api.
So, for this you need to setup few things shown below:-
1) Create and link your firebase project
2) Upgrade to blaze plan
3) Install Firebase CLI
4) Add cloud functions support in javascript to your project

Now copy the following code in your index.js file located in yourproject>functions>index.js

Now in your terminal open the functions folder of this project, type npm i razorpay and press enter to install the razorpay plugin for nodejs. For more details you can check this.
Let’s understand the above code, We are making call to order api by passing the amount as data.message which is nothing but the price we will be passing to this function through our flutter project. If the call is made successfully then we will return the key id, status as success and the response received from the api else we will return the status as failure with the error.
Now we will deploy this function by writing the following command in the terminal:- firebase deploy --only functions:orderApi.

Now create another function named cloudFunctionApi in the Http class as shown below, which will be responsible for triggering the cloud function created:-

The function created will be taking price as input and then making the call to our function. The price is passed to it as the value of message that’s why if you remember we used data.message in our cloud function to access the value of price. After this call we will get our response in json which will be decoded and then we will check the value of status which was returned by our cloud function along with other params. If the status is success then we will store the order api response in our response model which is to be returned by our cloudFunctionApi function along with the key id else on failure we will return null.

I know this might have become a bit complicated so have added flow chart to give more clarity. In this the openRazorPay function is not created yet it will be created in further section of this story as it is called when user taps on pay button.


Flow chart of order api

I will be using first method on mobile app and second one for flutter web though you can use second method as well for mobile app but you can’t use the first method for flutter web due to CORS as mentioned earlier in this story.


Let’s work on Razorpay for mobile (Using first method to call order api)

The UI code can be found on my github account (link at bottom of this story). So, we’ll be directly working on the razorpay logic and the pay button design.

Integrating Razor Pay in Flutter App and auto-capturing the payments

Lets’ declare the razorpay objects, variables and initialize them on the payment page where we need to trigger razorpay. Remember to add import foundation as razorpay plugin currently supports only android and ios for app development and since our project is for both web and app so the variable kIsWeb is used to check whether the project is currently running on app or website. If on website then we don’t need to initialize these variables as for website we need to use different way which will be discussed in the web part of this story.

Below is the pay button UI code , so you can understand the function calls.

Now let’s build the openRazorPay function

This function is responsible for making call to the orderAPI function which will return response model or null based on whether the razor pay order api gave a success response or not. If the response was success then we will make the call to openCheckOut function and pass the order id to it so that payment can be auto-captured. Below is the code for openCheckOut function:-

This function passes the required option to the razorpay object. You can easily understand the use of params by the above snippet. When this function is executed successfully then the following UI of razorpay gateway is shown to make a payment:-

Razorpay Payment Gateway for mobile

If you remember then in initState we attached some events to this object lets define them now:-

The very first function is called when the user have completed the payment and now you can make changes in your database that payment is recieved.

The second function is called when the payment was failed due to some reason.

The third function is called if the user selects external wallet such as paytm, mobikwik etc. to pay then this function is called. Though if paid by these wallets the first function is still called.


Let’s work on Razorpay for flutter web (Using second method to call order api)

Integrating razorpay in flutter web and auto-capturing payments

Before beginning remember to add your firebase config script in index.html and add the following script as well:-

<script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-functions.js"></script>

Now in your assets folder create a file named payment.html and copy the following code to it:-

This html file is used to show the razorpay gateway. We will load this html file through our flutter code and will pass the required arguments to it. The html file will accept these arguments and then pass them to our razorpay options. The file contains 2 handles, first one is at line 22 which is called on successful payment and in this handler we are returning the state as success and the payment id back to our flutter code where we will store and update the data in backend after getting this payment done, the second handler is on line 36 which is called when the user have canceled the payment. When this function is executed successfully then the following UI of razorpay gateway is shown to make a payment:-

Razorpay payment gateway for web

Now we will create some abstracts and their implementation so that we can access dart:ui package for only our flutter web. So create a file named abstract.dart and copy the following code to it:-

Now since we have created this abstract, We will implement it twice and define its function body empty for android or ios and will define complete body for web platform. So, create the file named view_io.dart and copy the following code to it.

Now, create files named view_web.dart, view.dart and copy the following codes to them:-

The reason to define abstract class and function body empty for android/ios app was that if not done then we will get the error “Error: Getter not found: ‘platformViewRegistry’. ui.platformViewRegistry.registerViewFactory(viewId, cb);” while building for app. The reason is that platformViewRegistry is not defined for android/ios apps.

Now we will create the page where we will load the payments.html file and show the payment gateway UI of Razorpay. So create a file named web_view_payment.dart and copy the following code to it:-

We are now making call to registerViewFactory function of BackgroundView and attaching listener in it. If you remember we were returning state as SUCCESS and MODAL_CLOSED from our html file based on payment status. So we are handling those events and returning the payment id from the page for sucess and null for modal closer. In line 30 we are passing arguments to html file in form of a url.

Let’s now return back to openRazorPay function and now define the code for flutter web. So update it with the following code:-

As we were returning a map on success from cloudFunctionApi so we will now fetch the response model from the map and the razorpay secret key. Now, a call to handlePaymentForWeb is madeand the order id from response model and razorpay secret key is passed to it. In this function we are navigating the user to payment gateway page where we are loading payment.html file. In that page based on the events we are returning null and payment id which is stored in paymentId variable and then if it is not null then we can save data to our backend that payment is done successfully.

Conclusion

Congratulations!! You have successfully learned how to integrate and auto-capture payments of razorpay in app and flutter web. In case you need the whole code then you can check it out at my GitHub repo:-

https://github.com/deepaklohmod6789/razorpay_integration

Comments

Popular posts from this blog

Adding Firebase phone authentication in Flutter and removing reCAPTCHA for authentication

Top 5 tips for flutter performance optimization and following best practices to build your next project.