Integrate Razorpay Payment Gateway in ASP.NET Core

Integrate Razorpay Payment Gateway in ASP.NET Core

In this article we will learn how to Integrate Razorpay Payment Gateway in ASP.Net Core. We discuss here about Razor Pay with learn how to integrate it in ASP.Net Core MVC.  Please go through our previous article Deploy ASP.NET Core Web App in Azure Virtual Machine. At the end of this article you can see output like this, we integrate the Razorpay in ASP.Net Core MVC.

Source Code

Prerequisites

— Razorpay payment Gateway Account ( You can check with free account)
— Visual Studio 2019

What is Razorpay Payment Gateway?

A payment gateway is an online service that authorizes and processes payments for online businesses. It is the glue between the customer and the merchant. Some popular payment Gateway are below,

  • PayPal
  • Stripe
  • Authorize.net
  • Amazon Payments
  • 2Checkout

The Razorpay Payment Gateway enables to accept payments via debit card, credit card, net banking, UPI and popular supported wallets.

Creating Razorpay Payment Gateway Account Setup

  • Let’s signup Razorpay payment Gateway using this link, You can sign up using your Google account also.
  • After sign up it ask the “business type” along with your name and mobile number.
  • Then move Razorpay account dashboard and go to Settings then API Keys Tab and Generate a key for the selected mode (Test or Live) as shown below:
Razorpay API keys

Integrate Razorpay Payment Gateway in ASP.NET Core

  • Let’s create ASP.NET Core MVC 5.0 project using Visual studio 2019.

Add Razorpay package in Nuget

Create Model/Entity Class

Let’s create the 2 entitles that holds the Payment Request and Merchant Order details.

public class MerchantOrder
    {
        public string OrderId { get; set; }
        public string RazorpayKey { get; set; }
        public int Amount { get; set; }
        public string Currency { get; set; }
        public string Name { get; set; }
        public string Email { get; set; }
        public string PhoneNumber { get; set; }
        public string Address { get; set; }
        public string Description { get; set; }
    }
public class PaymentRequest
    {
        [Required]
        public string Name { get; set; }
        [Required]
        public string Email { get; set; }
        [Required]
        public string PhoneNumber { get; set; }
        [Required]
        public string Address { get; set; }
        [Required]
        public int Amount { get; set; } 
    }

Create the Business Logic to Integrate Razorpay

Create the Service method that holds the business logic. Let’s create a folder name as “Service” inside the Razorpay project.

Create Interface

public interface IPaymentService
    {
         Task<MerchantOrder> ProcessMerchantOrder(PaymentRequest payRequest);
         Task<string> CompleteOrderProcess(IHttpContextAccessor _httpContextAccessor);
    }

Implement Interface inside “PaymentService”

public class PaymentService : IPaymentService
    {
       
        public Task<MerchantOrder> ProcessMerchantOrder(PaymentRequest payRequest)
        {
            try
            {
                // Generate random receipt number for order
                Random randomObj = new Random();
                string transactionId = randomObj.Next(10000000, 100000000).ToString();

                Razorpay.Api.RazorpayClient client = new Razorpay.Api.RazorpayClient("rzp_test_8P7RhnsImxd2OR", "kD8tw7ECYsTTZnx0OyrKI4kh");
                Dictionary<string, object> options = new Dictionary<string, object>();
                options.Add("amount", payRequest.Amount * 100);
                options.Add("receipt", transactionId);
                options.Add("currency", "INR");
                options.Add("payment_capture", "0"); // 1 - automatic  , 0 - manual
                //options.Add("Notes", "Test Payment of Merchant");

                Razorpay.Api.Order orderResponse = client.Order.Create(options);
                string orderId = orderResponse["id"].ToString();

                MerchantOrder order = new MerchantOrder
                {
                    OrderId = orderResponse.Attributes["id"],
                    RazorpayKey = "rzp_test_8P7RhnsImxd2OR",
                    Amount = payRequest.Amount * 100,
                    Currency = "INR",
                    Name = payRequest.Name,
                    Email = payRequest.Email,
                    PhoneNumber = payRequest.PhoneNumber,
                    Address = payRequest.Address,
                    Description = "Order by Merchant"
                };
                return Task.FromResult(order);
            }
            catch (Exception ex)
            {
                throw;
            }
        }

        public async Task<string> CompleteOrderProcess(IHttpContextAccessor _httpContextAccessor)
        {
            try
            {
                string paymentId = _httpContextAccessor.HttpContext.Request.Form["rzp_paymentid"];

                // This is orderId
                string orderId = _httpContextAccessor.HttpContext.Request.Form["rzp_orderid"];

                Razorpay.Api.RazorpayClient client = new Razorpay.Api.RazorpayClient("rzp_test_8P7RhnsImxd2OR", "kD8tw7ECYsTTZnx0OyrKI4kh");

                Razorpay.Api.Payment payment = client.Payment.Fetch(paymentId);

                // This code is for capture the payment 
                Dictionary<string, object> options = new Dictionary<string, object>();
                options.Add("amount", payment.Attributes["amount"]);
                Razorpay.Api.Payment paymentCaptured = payment.Capture(options);
                string amt = paymentCaptured.Attributes["amount"];
                return paymentCaptured.Attributes["status"];
            }
            catch (Exception)
            {
                throw;
            }
        }
    }

Code Explanation

  • Line #4 : ProcessMerchantOrder is use to collect the order details.
  • Line #9-10 : Random transaction id is generate.
  • Line #12-21 : This is use for to collect and generate the order. Here we need to use Razor Key and Secret Key.
  • Line #23-35 : Is used to return the Order details.
  • Line #43-61 : According to the payment info it complete the payment.

Add the Dependency services inside Startup class

public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
            services.AddTransient<IPaymentService, PaymentService>();
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        }

Create a Controller as PaymentController

public class PaymentController : Controller
    {
        private readonly ILogger<PaymentController> _logger;
        private readonly IPaymentService _service;
        private IHttpContextAccessor _httpContextAccessor;
        public PaymentController(ILogger<PaymentController> logger, IPaymentService service, IHttpContextAccessor httpContextAccessor)
        {
            _logger = logger;
            _service = service;
            _httpContextAccessor = httpContextAccessor;
        }
        public IActionResult Index()
        {
            return View();
        }
        [HttpPost]
        public async Task<IActionResult> ProcessRequestOrder(PaymentRequest _paymentRequest)
        {
            MerchantOrder _marchantOrder = await _service.ProcessMerchantOrder(_paymentRequest);
            return View("Payment", _marchantOrder);
        }
        [HttpPost]
        public async Task<IActionResult> CompleteOrderProcess()
        {
            string PaymentMessage =await _service.CompleteOrderProcess(_httpContextAccessor);
            if (PaymentMessage == "captured")
            {
                return RedirectToAction("Success");
            }
            else
            {
                return RedirectToAction("Failed");
            }
        }
        public IActionResult Success()
        {
            return View();
        }

        public IActionResult Failed()
        {
            return View();
        }
    }

Code Explanation

  • Line #3-11 : The controller implements dependency injection.
  • Line #17-20 : Process the merchant order information.
  • Line #23-38 : This is use for the payment is success or failure.

Create Require Razor Pay cshtml

Index.cshtml that hold the payment page information.

@model Razorpay.Integration.Models.PaymentRequest
@{
    ViewData["Title"] = "Payment Page";
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
    <form class="well form-horizontal" asp-action="ProcessRequestOrder" method="post" id="contact_form">
        <center><h2><b>Razorpay Payment Gateway Integration</b></h2></center>
        <div class="form-group">
            <label class="col-md-4 control-label">Customer Name</label>
            <div class="col-md-4 inputGroupContainer">
                <div class="input-group">
                    <span class="input-group-addon"><i class="fa fa-user"></i></span>
                    <input placeholder="Name" class="form-control" type="text" asp-for="Name" autocomplete="off" required>
                </div>
            </div>
        </div>
        <div class="form-group">
            <label class="col-md-4 control-label">E-Mail</label>
            <div class="col-md-4 inputGroupContainer">
                <div class="input-group">
                    <span class="input-group-addon"><i class="fa fa-envelope" style="font-size:11px"></i></span>
                    <input placeholder="E-Mail Address" class="form-control" type="text" asp-for="Email" autocomplete="off" required>
                </div>
            </div>
        </div>
        <div class="form-group">
            <label class="col-md-4 control-label">Phone Number</label>
            <div class="col-md-4 inputGroupContainer">
                <div class="input-group">
                    <span class="input-group-addon"><i class="fa fa-phone"></i></span>
                    <input placeholder="Phone" class="form-control" type="text" asp-for="PhoneNumber" autocomplete="off" required>
                </div>
            </div>
        </div>
        <div class="form-group">
            <label class="col-md-4 control-label">Address</label>
            <div class="col-md-4 inputGroupContainer">
                <div class="input-group">
                    <span class="input-group-addon"><i class="fa fa-address-book-o" style="font-size:11px"></i></span>
                    <input placeholder="Address" class="form-control" type="text" asp-for="Address" autocomplete="off" required>
                </div>
            </div>
        </div>
        <div class="form-group">
            <label class="col-md-4 control-label">Amount (INR)</label>
            <div class="col-md-4 inputGroupContainer">
                <div class="input-group">
                    <span class="input-group-addon"><i class="fa fa-inr" style="font-size:19px"></i></span>
                    <input placeholder="Amount (INR)" class="form-control" type="text" asp-for="Amount" autocomplete="off" required>
                </div>
            </div>
        </div>
        <div class="form-group">
            <label class="col-md-4 control-label"></label>
            <div class="col-md-4" style="text-align:center;">
                <button type="submit" class="btn btn-warning">SUBMIT <span class="glyphicon glyphicon-send"></span></button>
            </div>
        </div>
    </form>

After input all the information then click on Submit button it redirect to payment.cshtml page like below;

@model Razorpay.Integration.Models.MerchantOrder
<button id="RzP_btn" hidden>Pay</button>
<script src="https://checkout.razorpay.com/v1/checkout.js"></script>
<script>
var options = {
    "key": "@Html.DisplayFor(model => model.RazorpayKey)", // Enter the Key ID generated from the Dashboard
    "amount": "@Html.DisplayFor(model => model.Amount)", // Amount is in currency subunits. Default currency is INR. Hence, 50000 refers to 50000 paise
    "currency": "@Html.DisplayFor(model => model.Currency)",
    "name": "@Html.DisplayFor(model => model.Name)",
    "description": "@Html.DisplayFor(model => model.Description)",
    "image": "https://avatars.githubusercontent.com/u/65504583?v=4", // You can give your logo url
    "order_id": "@Html.DisplayFor(model => model.OrderId)",
    "handler": function (response){
        // After payment successfully made response will come here
        // Set the data in hidden form
        document.getElementById('rzp_paymentid').value = response.razorpay_payment_id;
        document.getElementById('rzp_orderid').value = response.razorpay_order_id;
        // // Let's submit the form automatically
        document.getElementById('rzp-paymentresponse').click();
    },
    "prefill": {
        "name": "@Html.DisplayFor(model => model.Name)",
        "email": "@Html.DisplayFor(model => model.Email)",
        "contact": "@Html.DisplayFor(model => model.PhoneNumber)"
    },
    "notes": {
        "address": "@Html.DisplayFor(model => model.Address)"
    },
    "theme": {
        "color": "#F37254"
    }
};
    var rzp1 = new Razorpay(options);
    //<!-- onload function -->
    window.onload = function(){
        document.getElementById('RzP_btn').click();
    };
    document.getElementById('RzP_btn').onclick = function(e){
    rzp1.open();
    e.preventDefault();
}
</script>
<form action="CompleteOrderProcess" method="post" asp-antiforgery="true">
    <input type="hidden" id="rzp_paymentid" name="rzp_paymentid" />
    <input type="hidden" id="rzp_orderid"  name="rzp_orderid"/>
    <button type="submit" id="rzp-paymentresponse" class="btn btn-primary" hidden>Submit</button>
</form>

That’s it. Let run the application and see the result.

Source Code

Source Code

Summary

This article explained about Integrate Razorpay Payment Gateway in ASP.Net Core. We discussed here about Razorpay and learned how to Integrate Razorpay Payment Gateway in ASP.Net Core.

Before implement the Razprpay into Production, please review about the product, features and security.

That’s a wrap for this article. I hope that it cleared about Integrate Razorpay Payment Gateway in ASP.NET Core. Please write to us if have any.

Have you enjoyed this post and found it useful? If so, please consider supporting me:

Buy me a coffeeBuy me a coffee

Deploy ASP.NET Core Web App in Azure Virtual Machine
Deploy ASP.NET Core Web App in Azure Virtual Machine

This article explain about Deploy ASP.NET Core Web App in Azure Virtual Machine. We discuss here how to create VM Read more

ASP.NET Core Web API with MongoDB CRUD- Beginner’s Guide
ASP.NET CORE WEB API 5.0 MONGODB CRUD

This article explain CRUD operation using MongoDB in ASP.NET Core Web API. We discuss here basics of MongoDB and how Read more

How to send Email in ASP.NET Core-Beginner’s Guide
How to send Email in ASP.NET Core

This article explain how to send Email in ASP.NET Core using Mailkit. It is open-source cross-platform library that can be Read more

Toast Notifications in ASP.NET Core Razor Pages
Toast Notifications in ASP.NET Core Razor Pages

This article we will learn how simply we can use Toast Notifications in ASP.NET Core Razor Pages 5.0. Mainly on Read more

Migrate from ASP.NET Core 3.1 to 5.0- Beginners guide

Migrate from ASP.NET Core 3.1 to 5.0- Beginners guide


Notice: rest_validate_value_from_schema was called incorrectly. The "type" schema keyword for list can only be one of the built-in types: array, object, string, number, integer, boolean, and null. Please see Debugging in WordPress for more information. (This message was added in version 5.5.0.) in /var/www/wp-includes/functions.php on line 5535

Notice: rest_validate_value_from_schema was called incorrectly. The "type" schema keyword for list can only be one of the built-in types: array, object, string, number, integer, boolean, and null. Please see Debugging in WordPress for more information. (This message was added in version 5.5.0.) in /var/www/wp-includes/functions.php on line 5535

Notice: rest_validate_value_from_schema was called incorrectly. The "type" schema keyword for list can only be one of the built-in types: array, object, string, number, integer, boolean, and null. Please see Debugging in WordPress for more information. (This message was added in version 5.5.0.) in /var/www/wp-includes/functions.php on line 5535

Notice: rest_validate_value_from_schema was called incorrectly. The "type" schema keyword for list can only be one of the built-in types: array, object, string, number, integer, boolean, and null. Please see Debugging in WordPress for more information. (This message was added in version 5.5.0.) in /var/www/wp-includes/functions.php on line 5535

Notice: rest_validate_value_from_schema was called incorrectly. The "type" schema keyword for list can only be one of the built-in types: array, object, string, number, integer, boolean, and null. Please see Debugging in WordPress for more information. (This message was added in version 5.5.0.) in /var/www/wp-includes/functions.php on line 5535

Notice: rest_validate_value_from_schema was called incorrectly. The "type" schema keyword for list can only be one of the built-in types: array, object, string, number, integer, boolean, and null. Please see Debugging in WordPress for more information. (This message was added in version 5.5.0.) in /var/www/wp-includes/functions.php on line 5535

Notice: rest_validate_value_from_schema was called incorrectly. The "type" schema keyword for list can only be one of the built-in types: array, object, string, number, integer, boolean, and null. Please see Debugging in WordPress for more information. (This message was added in version 5.5.0.) in /var/www/wp-includes/functions.php on line 5535

This article explains how to update an existing ASP.NET Core 3.1 project to ASP.NET Core 5.0. We already aware of that .NET 5.0 is released on November 2020. Let’s discuss in brief what’s new in .NET 5.0 and how to migrate it from 3.1 to 5.0. Please have a look our previous article Angular 10 with ASP.NET Web API-CRUD Operations.

Prerequisites

You can see my current Visual studio version is 2019 16.7. I updated it into new version, the right-hand side is the updated version of Visual studio 2019 16.8, after then we can use .NET 5.0. You can find this option using Help-About Visual studio, for update you select Help-Check for updates.

Download .NET 5.0 SDK

You can find the .NET 5.0 SDK here or you can find the SDK in this link https://dotnet.microsoft.com/download/. As per the below image you can see that you can downloads the SDK according to Operating system and according to the version also. Earlier Version used in .NET Framework 4.8 , then we currently use .NET Core SDK 3.1 which extended (LTS) Long term support by Microsoft. Now the left one is .NET 5.0 which is newly introduced.

Note – The image is picked from Microsoft site

What’s new in .NET 5.0 ?

Before migrating to the higher version .NET 5.0, let’s first understand what’s the new features introduced in .NET 5.0 over 3.1.

.NET 5.0 include providing a unified .NET SDK experience, with a single base class library(BCL) across all .NET 5 applications, and with support for both native and web applications across multiple operating systems. A single .NET 5 native application project would support targets such as Windows, Microsoft Duo (Android), and Apple iOS using native controls on those platforms.

The main goal of .NET 5 is to empower unified .NET Client Application projects to create deliverables for various platforms including Windows, UNIX, Linux, Legacy Windows, iOS, Droid, HTML5, and Mac. Also .NET 5 additional features as

  • Allow developers to automatically find bugs in code.
  • Assembly trimming which means it trim the unused assemblies to reduce the size of applications. .NET 5 is paired with C# 9, which brings many new features to the language
  • Source generators allow code that runs during compilation to inspect the program and produce additional files that are compiled together with the rest of the code.
  • System.Text.Json provides the ability to ignore default values for value-type properties when serializing. This is a breaking change. Also added for System.text.json is the ability to deal with circular references when serializing.

.NET 5 offer everything that you expect from the .NET core while making it suitable for Mobile and IoT platform development. .NET 5 ensures to incorporate the best of .NET core functionalities.

The above details about .NET 5.0 are referenced from the below link.

Create an ASP.NET Core 3.1 Project

To create an ASP .NET Core MVC 3.1 project follow below steps.

  • Open Visual Studio and click on Create New Project then choose project template as ASP.NET Core MVC application.
  • Then set the Project location and Project Path.
  • Choose the Project template- In our case we choose ASP .NET Core MVC template.
  • Finally run the application and you can see the output like below image.

If you check the .csproj file then you can find the below source code and you can see there is a package found Microsoft.EntityFrameworkCore and the version is 3.1.10 as currently we the project is targeting to .NET Core 3.1

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <RootNamespace>Migrate_3._1_5._0</RootNamespace>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.10" />
  </ItemGroup>
</Project>

Migrate ASP.NET Core 3.1 to 5.0

Let’s discuss how easily we migrate to the .NET Core framework 3.1 to 5.0

  • To migrate from 3.1 to 5.0, Open the solution and right click on the project and choose properties.
  • Then from properties window, select the target .NET Framework and choose .NET 5.0.
  • Select the target framework as .NET 5.0 and save the changes.
  • Build the project and see if there are any errors raised.

Updating Project Dependencies

Now as the project is change to .NET 5.0, so we need to update the project dependencies so that the project stays up-to-date with the latest framework version.

  • Right Click on the Project then choose Manage Nuget packages. As you can see on below image the earlier version of Microsoft.EntityFrameworkCore is 3.1.10 but as we migrate it into .NET 5.0 so we need to update the packages to V5.0
  • As you see on above image, we need to update it into v5.0.0.
  • Also if you have multiple packages then you select all packages checkbox and update all simultaneously.
  • After update all packages, rebuild the project again.

After updating it, when you Edit the project file you can find on .csproj the target framework is changed to net5.0 and the PackageReference version 5.0.0 also like below code.

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
    <RootNamespace>Migrate_3._1_5._0</RootNamespace>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.0" />
  </ItemGroup>

</Project>

Run the ASP .NET 5.0 Core Project

Now, all the migration work is complete so lets run the application and see the output.

Boom, Now the output is displayed perfectly and we migrated to .NET 5.0.

Publish & Deploy ASP .NET Core 5.0 in IIS

In this section we discuss how the ASP .NET Core 5.0 application is publish and deploy it into IIS.

Publish the ASP.NET Core 5.0

Following below steps, we can publish our .NET Core 5.0 project

  • Right click on Project then select publish as like below image.
  • After click on the properties window a modal dialog come up with following way of publish with following below steps as like the screenshot.
Publish method

There is multiple ways we can publish the file according to our requirement.

  • We can publish the file directly to cloud Azure portal.
  • We can also publish directly to the Docker Container if any.
  • We can publish the file local folder like we did in earlier .NET version publish.
  • We can publish it directly in FTP server.
  • We can publish directly on Web Server(IIS) using web deploy or web deploy package.
  • Also we can publish using Import Profile.

In this example we consider the publish method using traditional way, using folder. On future we may have another article where we discuss step by step to publish file of different ways.

Now the file publishing is done, then the next step is install .NET 5.0 hosting bundle then deploy it into IIS.

Install ASP.NET Core Runtime 5.0 Hosting Bundle

Let’s see our final step of this article how to deploy the ASP .NET Core 5.0 project in IIS.

  • First we need to install ASP .NET Core Runtime 5.0.0 hosting bundle to deploy the .NET 5.0 application in IIS.
  • If your application is already deployed to an IIS on Windows Server, you just need to install the hosting bundle and deploy.

Deploy ASP .NET Core 5.0 in IIS

Now the file is published and .NET 5.0 hosting bundle is installed, then the final step is deploy it into IIS. if you are doing fresh deploy of your migrated ASP.NET Core 5.0 project then you need to setup the application pool and do it.

Creating Application pool

  • To create the application pool, open your IIS manager, then navigate to Application Pools, then click “Add Application Pool”, a dialog will appear, Give it a name such as “DOTNET5” .
  • In the .NET Framework version, choose “No managed code” then press Ok.

Configure the ASP.NET 5.0 application into IIS

  • The application pool ready now then we need to create a new website under IIS Sites. So from the left-side menu of IIS manager, right-click on sites, then choose “Add Website” .
  • Then it open a dialog box, from the dialog box give it a name like “ASPNETCore5Demo”, assign it to the newly created application pool “DOTNET5”, and select the physical path of our application folder.
  • You can see we select the application pool that we created earlier and set the physical path and port we set as 8081.
  • You can see now our .NET 5 website is hosted in IIS, let’s run the application and see the output like below. As we set the port no. is 8081 then when we run the application and the application run in browser with URL http://localhost:8081.

Summary

So far in this article we discuss how to Migrate ASP .NET Core MVC 3.1 app to .NET 5.0. Also we discuss how to install .NET 5 hosting bundle and how to publish & deploy the ASP.NET Core 5.0 in IIS.

Still I am newbie on .NET 5.0, I try to upload more content on future time to time. Be with us.

That’s a wrap for this article. I hope that it cleared about Migrate from ASP.NET Core 3.1 to 5.0- Beginners guide. Please write to us if have any.

Have you enjoyed this post and found it useful? If so, please consider supporting me:

Buy me a coffeeBuy me a coffee

Related Post

Running WordPress on ASP.NET Core with Peachpie
Running WordPress on ASP.NET Core with Peachpie

This article explain about Running WordPress on ASP.NET Core with Peachpie, We discussed here how without using PHP, or any Read more

Integrate Razorpay Payment Gateway in ASP.NET Core
Integrate Razorpay Payment Gateway in ASP.NET Core

This article explain about Integrate Razorpay Payment Gateway in ASP.NET Core. We discuss here how to implement Razorpay gateway in Read more

Deploy ASP.NET Core Web App in Azure Virtual Machine
Deploy ASP.NET Core Web App in Azure Virtual Machine

This article explain about Deploy ASP.NET Core Web App in Azure Virtual Machine. We discuss here how to create VM Read more

CQRS pattern with MediatR in ASP.NET Core 5.0
CQRS pattern with MediatR in ASP.NET Core 5.0

This article explain CQRS design pattern with MediatR in ASP.Net Core 5.0. CQRS is a design pattern that separated the Read more

Pin It on Pinterest