[ Полезный рекламный блок ]
Попробуйте свои силы в игре, где ваши навыки программирования на 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 і ознайомтеся з умовами навчання, ми спеціалізуємося тільки на індивідуальних заняттях, як для початківців, так і для просунутих програмістів. Ви можете взяти як одне заняття для опрацювання питання, що вас цікавить, так і кілька, для більш щільної роботи. Завдяки особистому кабінету, кожен студент підвищить якість свого навчання, у вашому розпорядженні:
- Доступ до пройденого матеріалу
- Тематичні статті
- Бібліотека книг
- Онлайн тестування
- Спілкування в закритих групах