Robokassa.NET-Blazor 1.0.0

dotnet add package Robokassa.NET-Blazor --version 1.0.0
                    
NuGet\Install-Package Robokassa.NET-Blazor -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Robokassa.NET-Blazor" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Robokassa.NET-Blazor" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Robokassa.NET-Blazor" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Robokassa.NET-Blazor --version 1.0.0
                    
#r "nuget: Robokassa.NET-Blazor, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Robokassa.NET-Blazor@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Robokassa.NET-Blazor&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Robokassa.NET-Blazor&version=1.0.0
                    
Install as a Cake Tool

Robokassa.NET

Библиотека для интеграции с платежной системой Robokassa на платформе .NET. Поддерживает создание платежных ссылок, получение списка валют и работу с API Robokassa.

Возможности

  • ✅ Генерация платежных ссылок с подписью
  • ✅ Получение списка поддерживаемых валют
  • ✅ Создание HTML форм для платежей
  • ✅ Поддержка тестового режима
  • ✅ Асинхронные операции
  • ✅ Готовность к использованию в Blazor приложениях
  • ✅ Dependency Injection поддержка
  • ✅ Валидация платежных уведомлений (ResultURL/SuccessURL)
  • ✅ Поддержка дополнительных параметров (Shp)
  • ✅ Полная совместимость с интерфейсами для тестирования

Установка

Клонируйте репозиторий и добавьте ссылку на проект:

<ProjectReference Include="path/to/Robokassa.NET/Robokassa.NET.csproj" />

Быстрый старт

1. Базовая настройка

using Robokassa.NET.Configs;
using Robokassa.NET.Services;
using Robokassa.NET.Structures;

// Создаем конфигурацию
var config = new RobokassaConfig
{
    MerchantLogin = "your-merchant-login",
    MerchantPassword1 = "your-password-1", // Пароль #1 из настроек магазина
    MerchantPassword2 = "your-password-2", // Пароль #2 из настроек магазина
    IsTestMode = true // Тестовый режим
};

// Создаем сервис
var robokassaService = new RobokassaService(config);

2. Генерация платежной ссылки

// Создаем параметры платежа
var payment = new PaymentParameters(
    InvoiceId: 678678,           // Уникальный номер счета
    Description: "Тестовый платеж", // Описание платежа
    OutSum: "100.00",            // Сумма к оплате
    IsTest: 1,                   // 1 - тестовый платеж, 0 - боевой
    Shp: new Dictionary<string, string> // Дополнительные параметры (опционально)
    {
        { "UserId", "12345" },
        { "OrderType", "Premium" }
    }
);

// Генерируем ссылку для перенаправления пользователя
string paymentUrl = robokassaService.GeneratePaymentUrl(payment);
Console.WriteLine($"Ссылка для оплаты: {paymentUrl}");

// Результат: https://auth.robokassa.ru/Merchant/Index.aspx?MerchantLogin=underko&OutSum=100.00&InvoiceID=678678&Description=Тестовый%20платеж&SignatureValue=78c1be77d706c894882a81c92cf95cb8&IsTest=1

3. Генерация HTML формы

// Создаем HTML форму для встраивания на сайт
string htmlForm = robokassaService.GeneratePaymentForm(payment);

// Сохраняем в файл для тестирования
File.WriteAllText("payment-form.html", htmlForm);

4. Работа с валютами

// Создаем сервис для работы с валютами
var currencyService = new CurrencyService("your-merchant-login");

try
{
    // Получаем список поддерживаемых валют
    var currencies = await currencyService.GetParsedCurrenciesAsync();
    
    Console.WriteLine("Доступные валюты:");
    foreach (var currency in currencies)
    {
        Console.WriteLine($"- {currency.Label}: {currency.Name} (макс. сумма: {currency.MaxValue})");
    }
}
catch (Exception ex)
{
    Console.WriteLine($"Ошибка получения валют: {ex.Message}");
}

Использование в Blazor приложениях

Регистрация сервисов в Program.cs

using Robokassa.NET.Configs;
using Robokassa.NET.Services;

var builder = WebApplication.CreateBuilder(args);

// Добавляем HttpClient
builder.Services.AddHttpClient();

// Регистрируем конфигурацию Robokassa
builder.Services.AddSingleton<RobokassaConfig>(new RobokassaConfig
{
    MerchantLogin = "your-merchant-login",
    MerchantPassword1 = "your-password-1",
    MerchantPassword2 = "your-password-2",
    IsTestMode = true
});

// Регистрируем сервисы
builder.Services.AddScoped<RobokassaService>();
builder.Services.AddScoped<ICurrencyService, CurrencyService>(provider =>
{
    var config = provider.GetRequiredService<RobokassaConfig>();
    var httpClient = provider.GetRequiredService<HttpClient>();
    return new CurrencyService(config.MerchantLogin, httpClient);
});

var app = builder.Build();

Blazor компонент для отображения валют

@page "/currencies"
@using Robokassa.NET.Services
@using Robokassa.NET.Structures
@inject ICurrencyService CurrencyService

<h3>Поддерживаемые валюты</h3>

@if (isLoading)
{
    <p>Загрузка валют...</p>
}
else if (!string.IsNullOrEmpty(errorMessage))
{
    <div class="alert alert-danger">
        <strong>Ошибка:</strong> @errorMessage
    </div>
    <button class="btn btn-primary" @onclick="LoadCurrencies">Повторить</button>
}
else
{
    <table class="table table-striped">
        <thead>
            <tr>
                <th>Код</th>
                <th>Название</th>
                <th>Псевдоним</th>
                <th>Макс. сумма</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var currency in currencies)
            {
                <tr>
                    <td>@currency.Label</td>
                    <td>@currency.Name</td>
                    <td>@currency.Alias</td>
                    <td>@(currency.MaxValue?.ToString() ?? "Без ограничений")</td>
                </tr>
            }
        </tbody>
    </table>
}

@code {
    private List<Currency> currencies = new();
    private bool isLoading = true;
    private string? errorMessage;

    protected override async Task OnInitializedAsync()
    {
        await LoadCurrencies();
    }

    private async Task LoadCurrencies()
    {
        isLoading = true;
        errorMessage = null;
        
        try
        {
            currencies = await CurrencyService.GetParsedCurrenciesAsync();
        }
        catch (Exception ex)
        {
            errorMessage = ex.Message;
        }
        finally
        {
            isLoading = false;
        }
    }
}

Blazor компонент для создания платежей

@page "/payment"
@using Robokassa.NET.Services
@using Robokassa.NET.Structures
@inject RobokassaService RobokassaService
@inject IJSRuntime JSRuntime

<h3>Создание платежа</h3>

<EditForm Model="@paymentModel" OnValidSubmit="@CreatePayment">
    <DataAnnotationsValidator />
    <ValidationSummary />

    <div class="mb-3">
        <label for="amount" class="form-label">Сумма:</label>
        <InputText id="amount" class="form-control" @bind-Value="paymentModel.Amount" />
    </div>

    <div class="mb-3">
        <label for="description" class="form-label">Описание:</label>
        <InputText id="description" class="form-control" @bind-Value="paymentModel.Description" />
    </div>

    <div class="mb-3">
        <label for="invoiceId" class="form-label">Номер счета:</label>
        <InputNumber id="invoiceId" class="form-control" @bind-Value="paymentModel.InvoiceId" />
    </div>

    <button type="submit" class="btn btn-primary" disabled="@isProcessing">
        @if (isProcessing)
        {
            <span class="spinner-border spinner-border-sm" role="status"></span>
            <text>Создание...</text>
        }
        else
        {
            <text>Создать платеж</text>
        }
    </button>
</EditForm>

@if (!string.IsNullOrEmpty(paymentUrl))
{
    <div class="alert alert-success mt-3">
        <h5>Платеж создан успешно!</h5>
        <p>Ссылка для оплаты:</p>
        <code>@paymentUrl</code>
        <br />
        <button class="btn btn-success mt-2" @onclick="RedirectToPayment">
            Перейти к оплате
        </button>
    </div>
}

@code {
    private PaymentModel paymentModel = new();
    private bool isProcessing = false;
    private string? paymentUrl;

    private async Task CreatePayment()
    {
        isProcessing = true;
        
        try
        {
            var payment = new PaymentParameters(
                paymentModel.InvoiceId,
                paymentModel.Description,
                paymentModel.Amount,
                1, // Тестовый режим
                null // Без дополнительных параметров
            );

            paymentUrl = RobokassaService.GeneratePaymentUrl(payment);
        }
        catch (Exception ex)
        {
            // Здесь можно добавить обработку ошибок
            Console.WriteLine($"Ошибка создания платежа: {ex.Message}");
        }
        finally
        {
            isProcessing = false;
        }
    }

    private async Task RedirectToPayment()
    {
        if (!string.IsNullOrEmpty(paymentUrl))
        {
            await JSRuntime.InvokeVoidAsync("open", paymentUrl, "_blank");
        }
    }

    public class PaymentModel
    {
        [Required]
        public string Amount { get; set; } = "100.00";
        
        [Required]
        public string Description { get; set; } = "Тестовый платеж";
        
        [Required]
        public int InvoiceId { get; set; } = Random.Shared.Next(100000, 999999);
    }
}

Структуры данных

RobokassaConfig

Класс конфигурации с настройками подключения к Robokassa:

public class RobokassaConfig
{
    public string MerchantLogin { get; set; } = string.Empty;          // Логин магазина
    public string MerchantPassword1 { get; set; } = string.Empty;      // Пароль #1
    public string MerchantPassword2 { get; set; } = string.Empty;      // Пароль #2
    public string BaseUrl { get; set; } = "https://auth.robokassa.ru"; // Базовый URL API
    public string DefaultLanguage { get; set; } = "ru";               // Язык по умолчанию
    public bool IsTestMode { get; set; } = false;                     // Тестовый режим
    public int TimeoutMs { get; set; } = 30000;                       // Таймаут запросов
}

PaymentParameters

Структура с параметрами платежа:

public readonly record struct PaymentParameters(
    int InvoiceId,                        // Уникальный номер счета
    string Description,                   // Описание платежа
    string OutSum,                        // Сумма к оплате
    int IsTest,                          // 1 - тестовый, 0 - боевой
    Dictionary<string, string> Shp       // Дополнительные параметры (опционально)
);

PaymentNotification

Структура для получения уведомлений о платежах от Robokassa:

public record PaymentNotification
{
    public string OutSum { get; init; } = string.Empty;                    // Сумма платежа
    public int InvId { get; init; }                                        // Номер счета
    public string SignatureValue { get; init; } = string.Empty;            // Подпись от Robokassa
    public Dictionary<string, string> ShpParameters { get; init; } = new(); // Дополнительные параметры
    public string MerchantLogin { get; init; } = string.Empty;             // Логин магазина
}

Currency

Структура с информацией о валюте:

public record Currency(
    string Label,    // Код валюты (RUB, USD, EUR)
    string Alias,    // Внутренний псевдоним Robokassa
    string Name,     // Человекочитаемое название
    int? MaxValue    // Максимальная сумма платежа (null = без ограничений)
);

API Reference

RobokassaService

GeneratePaymentUrl(PaymentParameters payment)

Создает URL для перенаправления пользователя на страницу оплаты Robokassa.

Параметры:

  • payment - параметры платежа

Возвращает: Полная ссылка для оплаты

Пример:

var url = service.GeneratePaymentUrl(new PaymentParameters(12345, "Покупка", "1000.00", 1, null));
// https://auth.robokassa.ru/Merchant/Index.aspx?MerchantLogin=...&SignatureValue=...
GeneratePaymentForm(PaymentParameters payment)

Создает HTML форму для встраивания на сайт.

Параметры:

  • payment - параметры платежа

Возвращает: HTML код с формой оплаты

CurrencyService / ICurrencyService

GetCurrenciesUrl()

Возвращает URL для запроса списка валют.

GetCurrenciesAsync(CancellationToken cancellationToken = default)

Асинхронно получает XML ответ со списком валют.

ParseCurrenciesFromXml(string xml)

Парсит XML ответ и возвращает список объектов Currency.

GetParsedCurrenciesAsync(CancellationToken cancellationToken = default)

Объединяет получение и парсинг валют в одном методе.

ValidateResultPayment(string queryString)

Валидирует платежное уведомление от Robokassa через ResultURL.

Параметры:

  • queryString - строка параметров из запроса ResultURL

Возвращает: Кортеж с результатом валидации, ответом и номером счета

Пример:

var (isValid, response, invoiceId) = service.ValidateResultPayment("OutSum=100&InvId=123&SignatureValue=...");
if (isValid)
{
    // Обработать успешный платеж
    await ProcessPayment(invoiceId);
    return Content(response); // "OK123"
}
return Content("bad sign");
ValidateSuccessPayment(string queryString)

Валидирует параметры платежа в SuccessURL (проверка кассира).

Параметры:

  • queryString - строка параметров из запроса SuccessURL

Возвращает: Кортеж с результатом валидации и сообщением

ParsePaymentNotification(string queryString)

Парсит строку параметров в объект PaymentNotification.

Параметры:

  • queryString - строка параметров от Robokassa

Возвращает: Объект PaymentNotification с извлеченными данными

Обработка ошибок

Библиотека генерирует следующие типы исключений:

  • HttpRequestException - ошибки сети или API
  • InvalidOperationException - некорректный ответ API
  • OperationCanceledException - отмена операции
  • ArgumentException - некорректные параметры
  • XmlException - ошибки парсинга XML

Пример обработки ошибок

try
{
    var currencies = await currencyService.GetParsedCurrenciesAsync();
    // Обработка успешного результата
}
catch (HttpRequestException ex)
{
    // Проблемы с сетью или недоступность API
    logger.LogError("Ошибка сети: {Message}", ex.Message);
}
catch (OperationCanceledException ex)
{
    // Операция была отменена (таймаут или пользователь)
    logger.LogWarning("Операция отменена: {Message}", ex.Message);
}
catch (Exception ex)
{
    // Общие ошибки
    logger.LogError("Неожиданная ошибка: {Message}", ex.Message);
}

Безопасность

  • Никогда не храните пароли в коде
  • Используйте переменные окружения или конфигурационные файлы
  • В production отключайте тестовый режим (IsTestMode = false)

Пример конфигурации через appsettings.json

{
  "Robokassa": {
    "MerchantLogin": "your-login",
    "MerchantPassword1": "your-password-1",
    "MerchantPassword2": "your-password-2",
    "IsTestMode": false
  }
}
// В Program.cs
builder.Services.Configure<RobokassaConfig>(
    builder.Configuration.GetSection("Robokassa"));

Обработка платежных уведомлений

ResultURL (серверные уведомления)

Robokassa отправляет уведомления о статусе платежей на ваш сервер. Вот пример обработки в Blazor Server или API контроллере:

[ApiController]
[Route("api/[controller]")]
public class PaymentController : ControllerBase
{
    private readonly IRobokassaService _robokassaService;
    private readonly ILogger<PaymentController> _logger;

    public PaymentController(IRobokassaService robokassaService, ILogger<PaymentController> logger)
    {
        _robokassaService = robokassaService;
        _logger = logger;
    }

    [HttpPost("robokassa/result")]
    public async Task<IActionResult> HandleResult()
    {
        try
        {
            // Получаем строку параметров из запроса
            var queryString = Request.QueryString.ToString().TrimStart('?');
            
            // Валидируем уведомление
            var (isValid, response, invoiceId) = _robokassaService.ValidateResultPayment(queryString);
            
            if (isValid)
            {
                _logger.LogInformation("Received valid payment notification for invoice {InvoiceId}", invoiceId);
                
                // Здесь обрабатываем успешный платеж
                await ProcessSuccessfulPayment(invoiceId);
                
                // Возвращаем подтверждение для Robokassa
                return Content(response); // "OK{InvoiceId}"
            }
            else
            {
                _logger.LogWarning("Invalid payment notification signature for invoice {InvoiceId}", invoiceId);
                return Content("bad sign");
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error processing payment notification");
            return Content("bad sign");
        }
    }

    [HttpGet("robokassa/success")]
    public IActionResult HandleSuccess()
    {
        try
        {
            // Получаем строку параметров из запроса
            var queryString = Request.QueryString.ToString().TrimStart('?');
            
            // Валидируем успешное возвращение пользователя
            var (isValid, message) = _robokassaService.ValidateSuccessPayment(queryString);
            
            if (isValid)
            {
                // Перенаправляем на страницу успеха
                return Redirect("/payment/success");
            }
            else
            {
                // Перенаправляем на страницу ошибки
                return Redirect("/payment/error");
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error processing success return");
            return Redirect("/payment/error");
        }
    }

    private async Task ProcessSuccessfulPayment(int invoiceId)
    {
        // Здесь ваша логика обработки платежа:
        // - обновление статуса заказа
        // - отправка уведомлений пользователю
        // - активация услуг и т.д.
        
        _logger.LogInformation("Processing payment for invoice {InvoiceId}", invoiceId);
        // await _orderService.MarkAsPaid(invoiceId);
        // await _notificationService.SendPaymentConfirmation(invoiceId);
    }
}

Работа с Shp параметрами

Дополнительные параметры Shp позволяют передавать пользовательские данные через платежную систему:

// Создание платежа с дополнительными параметрами
var payment = new PaymentParameters(
    InvoiceId: 12345,
    Description: "Покупка премиум аккаунта",
    OutSum: "999.00",
    IsTest: 0,
    Shp: new Dictionary<string, string>
    {
        { "UserId", "user_123" },
        { "PlanType", "premium" },
        { "Duration", "12" } // месяцев
    }
);

// При получении уведомления от Robokassa
var notification = robokassaService.ParsePaymentNotification(queryString);

// Извлекаем дополнительные параметры
if (notification.ShpParameters.TryGetValue("UserId", out var userId))
{
    var user = await userService.GetUserById(userId);
    if (notification.ShpParameters.TryGetValue("PlanType", out var planType) &&
        notification.ShpParameters.TryGetValue("Duration", out var duration))
    {
        await subscriptionService.ActivatePlan(user, planType, int.Parse(duration));
    }
}

Лицензия

MIT License

Поддержка

Для вопросов и предложений создавайте issues в репозитории.

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net9.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 141 8/20/2025