[ Полезный рекламный блок ]
Попробуйте свои силы в игре, где ваши навыки программирования на C# станут решающим фактором. Переходите по ссылке 🔰.
В этой статье мы рассмотрим, как добавить платежную систему Liqpay для сайта Asp.Net Core, на примере небольшого магазина товаров.
В современном цифровом мире предприятия всех размеров переходят на онлайновые платежи. Однако внедрение безопасного и надежного платежного сервиса может оказаться непростой задачей, особенно для тех, кто только начинает работать в этом направлении.
Именно здесь на помощь приходит Liqpay – популярная платежная система, позволяющая компаниям и частным лицам, с легкостью принимать онлайн-платежи.
Liqpay — это платежная система, которая предоставляет возможность совершать электронные платежи и денежные переводы через интернет. Эта система была разработана украинской компанией «PrivatBank» и запущена в 2008 году. Она стала популярным инструментом для онлайн-бизнесов и пользователей, которые хотят совершать быстрые и безопасные платежи.
Создание и настройка аккаунта Liqpay
Если у вас есть уже аккаунт в Приват24, вам необходимо пройти авторизацию, если нет, выполняйте регистрацию:
https://www.liqpay.ua/authorization?return_to=%2Fuk%2Fadminbusiness
После регистрации, вам необходимо создать компанию, для этого вверху страницы нажимаем «Мої компанії», (https://www.liqpay.ua/uk/adminbusiness/companies) – «Створити компанію» — вводим название компании и Email-адрес. Чтобы принимать реальные платежи, нам необходимо будет заполнить много информации о нашем бизнесе, этот шаг пропустим.
После этого вы попадете на главную страницу платежной системы:
- Включаем «Тестовый режим», внизу сайдбара (Обычно включен по умолчанию).
- В разделе «Главная», раскройте вкладку «Тестові ключі API», и скопируйте Приватный и Публичный ключи:
Они нам пригодятся для проведения платежей через сайт. «Боевые ключи» пока не доступны, для этого необходимо пройти активацию магазина.
Создание и настройка проекта
Чтобы создать проект LiqpayPaymentApp, запустите Visual Studio и выберите в меню File (Файл) — New Project (Создать Проект). Укажите шаблон проекта ASP.NET Core Web Application (Веб-приложение ASP.NET Core).
Введите LiqpayPaymentApp, в поле Name, на следующей странице укажите Framework .Net 7.0 и нажмите кнопку Create.
Мы будем использовать последнюю версию пакета Stripe.net для реализации платежного шлюза Liqpay в вашем проекте. Для этого необходимо перейти в раздел Manage Nuget Packages и добавить Liqpay в свой проект:
Или через Package Manager Console:
Install-Package LiqPay
Для сохранения ключей Api, будем использовать файл appsettings.json. Данный файл находится в корне проекте, изменим его содержимое следующим образом:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "LiqpayApi": { "PublicKey": "sandbox_i20676380499", "PrivateKey": "sandbox_kSThXPJO94A32dd28Qf1yVMloYTlxWYgAr9iMgE4" }, "AllowedHosts": "*" } |
Модель и Репозиторий
Модель для приложения LiqpayPaymentApp будет основана на списке товаров. Создайте папку Models и добавьте в нее файл класса по имени Product.cs со следующим содержимым:
1 2 3 4 5 6 7 8 |
public class Product { public string Id { get; set; } = Guid.NewGuid().ToString(); public string Name { get; set; } public string Category { get; set; } public int Count { get; set; } public decimal Price { get; set; } } |
Мне нравится обеспечивать согласованный доступ к данным в приложении с использованием паттерна «Хранилище» (Repository), в котором интерфейс определяет свойства и методы, предназначенные для доступа к данным, а для работы с механизмом хранения данных применяется класс реализации. Преимущество использования паттерна «Хранилище» связано с облегчением модульного тестирования части MVC приложения, а также с тем, что детали, касающиеся хранения данных, скрыты от остальных частей приложения.
Чтобы создать интерфейс хранилища, создайте папку Interfaces и добавьте в нее файл интерфейса по имени IProduct.cs со следующим содержимым:
1 2 3 4 5 6 |
public interface IProduct { IEnumerable<Product> GetAllProducts(); Product GetProductById(string id); void AddProduct(Product product); } |
Метод GetAllProducts() будет предоставлять доступ только по чтению ко всем товарам, известным приложению. Метод AddProduct() будет использоваться для добавления новых товаров.
В этом проекте мы будем хранить объекты модели в памяти. Создайте папку Repository и добавьте в нее файл класса по имени ProductRepository.cs со следующим содержимым:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
public class ProductRepository : IProduct { private List<Product> products; public ProductRepository() { products = new List<Product>() { new Product { Name = "Плед Ardesto Flannel Бежевый", Category = "Домашний текстиль", Count = 100, Price = 389 }, new Product { Name = "Стиральный порошок Delamark Universal", Category = "Бытовая химия", Count = 55, Price = 526 }, new Product { Name = "Офисные кресла", Category = "Кресло Rondi Монеро", Count = 70, Price = 3990 } }; } public void AddProduct(Product product) { products.Add(product); } public IEnumerable<Product> GetAllProducts() { return products; } public Product GetProductById(string id) { return products.FirstOrDefault(e => e.Id.ToString().Equals(id)); } } |
Класс ProductRepository реализует интерфейс IProduct и применяет экземпляр List для отслеживания объектов Product, т.е. в случае остановки или перезапуска приложения данные будут утрачиваться.
Добавьте в класс Program оператор следующий оператор, чтобы зарегистрировать класс ProductRepository как реализацию для использования в качестве зависимостей интерфейса IProduct:
1 |
builder.Services.AddSingleton<IProduct, ProductRepository>(); |
Данная строка кода, регистрирует класс ProductRepository с применением метода AddSingleton. В результате при распознавании зависимости интерфейса IProduct в первый раз создается одиночный объект, который будет использоваться для всех последующих зависимостей.
Контроллер и Представления для Товаров
В контроллере HomeController, реализуем вывод всех продуктов с возможностью дальнейшего приобретения:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public class HomeController : Controller { private readonly IProduct _products; public HomeController(IProduct products) { _products = products; } public IActionResult Index() { return View(_products.GetAllProducts()); } } |
В папке Views / Home, изменим содержимое Index.cshtml, следующим образом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
@model IEnumerable<Product> @{ ViewData["Title"] = "Онлайн Магазин"; } <div class="container py-5"> @foreach (Product product in Model) { <div class="row justify-content-center mb-3"> <div class="col-md-12 col-xl-10"> <div class="card shadow-0 border rounded-3"> <div class="card-body"> <div class="row"> <div class="col-md-12 col-lg-3 col-xl-3 mb-4 mb-lg-0"> <div class="bg-image hover-zoom ripple rounded ripple-surface"> <img src="https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Products/img%20(4).webp" class="w-100" /> </div> </div> <div class="col-md-6 col-lg-6 col-xl-6"> <h5>@product.Name</h5> <p><b>Категория</b>: @product.Category</p> <p><b>Всего в наличии</b>: @product.Count</p> </div> <div class="col-md-6 col-lg-3 col-xl-3 border-sm-start-none border-start"> <div class="d-flex flex-row align-items-center mb-1"> <h4 class="mb-1 me-1">₴@product.Price</h4> </div> <h6 class="text-success">Бесплатная доставка</h6> <form asp-controller="Payment" asp-action="Pay" asp-route-Id="@product.Id" method="post"> <div class="d-flex flex-column mt-4"> <input type="number" name="Count" class="form-control" value="1" min="1" max="100" /> <button class="btn btn-primary btn-sm mt-2" type="submit"> Купить </button> </div> </form> </div> </div> </div> </div> </div> </div> } </div> |
Для простоты происходящего, я не стану реализовывать корзину в этом проекте, при нажатии на кнопку «Buy», мы сразу же будем переадресовываться на страницу подтверждения оплаты. О том, как сделать корзину, читайте в статье «Магазин на Asp.Net Core MVC EF. Часть 5».
Запустим приложение и проверим его работу:
Контроллер и Представления для Оплаты
В классе Program, добавим сервис IHttpContextAccessor, он потребуется для получения текущего домена сайта при формировании платежного отчета:
1 |
builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); |
В корне проекта определим папку ViewModels, в которую добавим класс PaymentViewModel, со следующим содержимым:
1 2 3 4 5 6 7 8 |
public class PaymentViewModel { public LiqPayRequest PaymentParams { get; set; } public string FormCode { get; set; } public string ProductName { get; set; } public int ProductCount { get; set; } } |
Создадим контроллер PaymentController, и в нем определим действие для обработки запроса оплаты:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
public class PaymentController : Controller { private readonly IProduct _products; public PaymentController(IProduct products) { _products = products; } [HttpPost] [Route("/payment/pay")] public ActionResult Pay([FromServices] IConfiguration config, [FromServices] IHttpContextAccessor httpContextAccessor, Product product) { var currentProduct = _products.GetProductById(product.Id); if (currentProduct == null || product.Count < 1) { return NotFound(); } //Get public and private keys from the configuration string publicKey = config["LiqpayApi:PublicKey"]; string privateKey = config["LiqpayApi:PrivateKey"]; LiqPayClient liqpay = new LiqPayClient(publicKey, privateKey); string baseUrl = HttpContext.Request.Scheme + "://" + httpContextAccessor.HttpContext.Request.Host.Value; //Payment parameters var paymentParams = new LiqPayRequest { Version = 3, //Версия Api Action = LiqPay.SDK.Dto.Enums.LiqPayRequestAction.Pay, //Transaction type Amount = (double)(product.Count * currentProduct.Price), //Payment amount Currency = "UAH", //Payment currency Description = "Оплата тестового продукта - #" + currentProduct.Id, //Payment Description OrderId = Guid.NewGuid().ToString(), //Unique order number on your website ResultUrl = baseUrl + "/payment/success" //Link to successful payment page }; //We get a generated form with Data, Signature and a button for payment var formCode = liqpay.CNBForm(paymentParams); PaymentViewModel pvm = new PaymentViewModel { PaymentParams = paymentParams, FormCode = formCode, ProductName = currentProduct.Name, ProductCount = product.Count }; return View(pvm); } [HttpGet] [Route("/payment/success")] public IActionResult Success() { return View(); } } |
В данном действии Pay контроллера в ASP.NET MVC происходит обработка запроса на оплату продукта с использованием LiqPay API.
Рассмотрим параметры метода:
- [FromServices] IConfiguration config: Внедрение сервиса конфигурации (IConfiguration) для доступа к настройкам приложения, таким как публичный и приватный ключи LiqPay API.
- [FromServices] IHttpContextAccessor httpContextAccessor: Внедрение сервиса для доступа к текущему HTTP-контексту приложения.
- Product product: Модель продукта, передаваемая в запросе от клиента.
Внутри метода, получаем информацию о продукте на основе его идентификатора. Если продукт не найден (currentProduct == null) или количество продукта меньше 1 (product.Count < 1), то возвращаем ответ с кодом 404 — «Not Found».
Получаем публичный и приватный ключи LiqPay API из конфигурации приложения. Создаем экземпляр LiqPayClient с использованием полученных публичного и приватного ключей и объект LiqPayRequest, который содержит параметры для процессинга платежа.
Метод liqpay.CNBForm() используется для генерации кода HTML-формы для оплаты. Сгенерированный код формы (formCode) содержит данные, подпись и кнопку для оплаты через LiqPay.
В итоге, метод возвращает представление View(pvm), передавая в него модель представления pvm. Это представление отображает страницу с информацией о продукте и форму оплаты.
В папку Views / Payment, добавим представление Pay.cshtml, со следующим содержимым:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
@using LiqpayPaymentApp.ViewModels; @model PaymentViewModel @{ ViewData["Title"] = "Оплата"; } <main> <h1>Оплата</h1> <p class="fs-5 col-md-8">@Model.PaymentParams.Description</p> <div class="mb-5"> <a asp-controller="Home" asp-action="Index" class="btn btn-primary btn-lg px-4">« Вернутся</a> </div> <hr class="mb-4"> <div class="row g-5"> <div class="col-md-6"> <h2>@Model.ProductName</h2> <p>Количество: @Model.ProductCount.</p> <ul class="icon-list ps-0"> <li class="text-muted d-flex align-items-start mb-1">К оплате: @Model.PaymentParams.Amount @Model.PaymentParams.Currency</li> </ul> @Html.Raw(Model.FormCode) </div> </div> </main> |
В папку Views / Payment, добавим представление Success.cshtml, со следующим содержимым:
1 2 3 4 5 6 7 8 9 |
<div class="cover-container d-flex h-100 p-3 mx-auto flex-column"> <main role="main" class="inner cover"> <h1 class="cover-heading">Успешная оплата ✅</h1> <p class="lead">Спасибо, ваша заявка принята! Мы свяжемся с вами в ближайшее время.</p> <p class="lead"> <a asp-controller="Home" asp-action="Index" class="btn btn-lg btn-primary">Главная</a> </p> </main> </div> |
Выполнение оплаты
Запустим приложение и проверим его работу. Купим определенное количество товара:
Проверим данные и нажмем на кнопку «Купить»:
Введем данные от карты, емейл адрес для получения квитанции и нажмем кнопку «Оплатить»:
После оплаты, получим результат транзакции:
Если нажмем по ссылке «Повернутися до сайту», попадем на страницу подтверждения оплаты со из контроллера PaymentController, действия Success:
Так же, на указанный Email-адрес, вы получите письмо с подтверждением об оплате:
В данном примере, мы работали в тестовом режиме, чтобы иметь возможность принимать реальные платежи, необходимо получить «Боевые ключи» и указать их в файле appsettings.json.
Я надеюсь, что вам понравилось читать эту статью, и она оказалась легкой для понимания. Пожалуйста, дайте мне знать, если у вас есть какие-либо комментарии или исправления.
Так же вам может быть интересна предыдущая статья — Загрузка файлов перетаскиванием в Asp.Net Core.
Вы хотите научится писать код на языке программирования C#?
Создавать различные информационные системы, состоящие из сайтов, мобильных клиентов, десктопных приложений, телеграмм-ботов и т.д.
Переходите к нам на страницу Dijix и ознакомьтесь с условиями обучения, мы специализируемся только на индивидуальных занятиях, как для начинающих, так и для более продвинутых программистов. Вы можете взять как одно занятие для проработки интересующего Вас вопроса, так и несколько, для более плотной работы. Благодаря личному кабинету, каждый студент повысит качество своего обучения, в вашем распоряжении:
- Доступ к пройденному материалу
- Тематические статьи
- Библиотека книг
- Онлайн тестирование
- Общение в закрытых группах
Живи в своем мире, программируй в нашем.
Спасибо, все работает!