GatekeeperX.Events.Sdk
1.0.5
dotnet add package GatekeeperX.Events.Sdk --version 1.0.5
NuGet\Install-Package GatekeeperX.Events.Sdk -Version 1.0.5
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="GatekeeperX.Events.Sdk" Version="1.0.5" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="GatekeeperX.Events.Sdk" Version="1.0.5" />
<PackageReference Include="GatekeeperX.Events.Sdk" />
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 GatekeeperX.Events.Sdk --version 1.0.5
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: GatekeeperX.Events.Sdk, 1.0.5"
#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 GatekeeperX.Events.Sdk@1.0.5
#: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=GatekeeperX.Events.Sdk&version=1.0.5
#tool nuget:?package=GatekeeperX.Events.Sdk&version=1.0.5
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
GatekeeperX.Events.Sdk
SDK oficial de .NET para integración con GatekeeperX Events API - Plataforma de detección de fraude y evaluación de riesgo en tiempo real.
Características
- 🔒 Detección de Fraude - Evaluación de riesgo en tiempo real
- 🏗️ Patrón Builder - API fluida para construir requests
- 🔄 Reintentos Automáticos - Políticas de reintento con backoff exponencial
- 📊 Scoring de Riesgo - Scores detallados y reglas coincidentes
- 🌐 Multi-Ambiente - Soporte para Sandbox y Producción
Instalación
dotnet add package GatekeeperX.Events.Sdk
O via Package Manager Console:
Install-Package GatekeeperX.Events.Sdk
Inicio Rápido
using GatekeeperX.Events.Sdk;
using GatekeeperX.Events.Sdk.Models.Request;
// Crear cliente
using var client = EventsApiClient.Builder()
.Sandbox()
.WithOrganizationId("tu-organization-id")
.WithApiKey("tu-api-key")
.Build();
// Crear request
var request = EventRequest.Builder()
.WithEventType("create_cashout")
.WithTimestamp(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds())
.WithCustomer(Customer.Builder()
.WithCustomerId("cust_001")
.WithEmail("usuario@ejemplo.com")
.Build())
.WithMovement(Movement.Builder()
.WithMovementId("mov_001")
.WithAmount(Money.Builder()
.WithAmount(50000m)
.WithAmountInMinorUnits(5000000)
.WithCurrencyCode("COP")
.Build())
.Build())
.Build();
// Enviar evento
var response = await client.ProcessEventAsync(request);
if (response.Decision == "allow")
{
// Transacción permitida
}
else if (response.Decision == "block")
{
// Transacción bloqueada
}
Configuración del Cliente
Básica
using var client = EventsApiClient.Builder()
.Sandbox() // o .Production()
.WithOrganizationId("tu-organization-id")
.WithApiKey("tu-api-key")
.Build();
Avanzada
using var client = EventsApiClient.Builder()
.Production()
.WithOrganizationId("tu-organization-id")
.WithApiKey("tu-api-key")
.WithTimeout(TimeSpan.FromSeconds(30))
.WithMaxRetries(3)
.WithRetryBackoff(TimeSpan.FromMilliseconds(500))
.WithRetryMultiplier(2.0)
.WithMaxBackoff(TimeSpan.FromSeconds(10))
.WithLogger(logger)
.Build();
Opciones de Configuración
| Método | Descripción | Default |
|---|---|---|
.Sandbox() |
Usar ambiente sandbox | - |
.Production() |
Usar ambiente producción | - |
.WithOrganizationId(string) |
ID de organización | Requerido |
.WithApiKey(string) |
API Key | Requerido |
.WithTimeout(TimeSpan) |
Timeout del request | 30 segundos |
.WithMaxRetries(int) |
Máximo de reintentos | 3 |
.WithRetryBackoff(TimeSpan) |
Delay inicial de reintento | 500ms |
.WithRetryMultiplier(double) |
Multiplicador de backoff | 2.0 |
.WithMaxBackoff(TimeSpan) |
Máximo delay de backoff | 10 segundos |
.WithHttpClient(HttpClient) |
HttpClient personalizado | Auto-creado |
.WithLogger(ILogger) |
Logger personalizado | Ninguno |
Métodos Disponibles
ProcessEventAsync (Asíncrono - Recomendado)
var response = await client.ProcessEventAsync(
request,
returnScore: true,
cancellationToken: default
);
ProcessEvent (Síncrono)
var response = client.ProcessEvent(request, returnScore: true);
| Parámetro | Descripción |
|---|---|
request |
Objeto EventRequest con los datos del evento |
returnScore |
true para esperar evaluación completa, false para respuesta inmediata |
Ejemplo Completo: create_cashout
var request = EventRequest.Builder()
.WithEventType("create_cashout")
.WithTimestamp(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds())
// ═══════════════════════════════════════════════════════════════
// MOVEMENT
// ═══════════════════════════════════════════════════════════════
.WithMovement(Movement.Builder()
.WithMovementId("7e43e0ce-69ab-406d-baa4-8ce0c31df36d")
.WithCustomerId("cust_001")
.WithExternalId("1955346017")
.WithType("4")
.WithStatus("pending")
.WithCreatedAt(DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ"))
.WithProcessedBy("system")
.WithChannel("mobile")
.WithAmount(Money.Builder()
.WithCurrencyCode("COP")
.WithAmount(25000m)
.WithAmountInMinorUnits(2500000)
.Build())
// Origin
.WithOrigin(MovementOrigin.Builder()
.WithPaymentMethod(MovementPaymentMethod.Builder()
.WithType("bankAccount")
.WithPaymentMethodId("pm_origin_001")
.WithAccountNumber("100000056298")
.WithStatus("active")
.WithAlias("Mi cuenta principal")
.WithCustomFields(new Dictionary<string, object>
{
{ "thirdPartyId", 11 }
})
.Build())
.WithCustomFields(new Dictionary<string, object>
{
{ "accountBalanceHistoricId", "uuid-balance" },
{ "finalValue", 4000 }
})
.Build())
// Destination
.WithDestination(MovementDestination.Builder()
.WithPaymentMethod(MovementPaymentMethod.Builder()
.WithType("bankAccount")
.WithPaymentMethodId("pm_dest_001")
.WithAccountNumber("200000012345")
.WithBankId("001")
.WithBankCode("BANCOLOMBIA")
.WithCustomFields(new Dictionary<string, object>
{
{ "externalAccountId", "ext-acc-uuid" },
{ "achAccountId", "ach-uuid" }
})
.Build())
.Build())
.Build())
// ═══════════════════════════════════════════════════════════════
// CUSTOMER
// ═══════════════════════════════════════════════════════════════
.WithCustomer(Customer.Builder()
.WithCustomerId("cust_001")
.WithPhoneNumber("+573001234567")
.WithEmail("usuario@ejemplo.com")
.WithEmailVerifiedAt(true)
.WithFirstName("Juan")
.WithLastName("Pérez")
.WithBirthDate("1990-05-18")
.WithGender("1")
.WithIsPep(false)
.WithThirdPartyId("0")
.WithTags(new List<string> { "verified", "premium" })
.WithCreatedAt("2024-01-01T00:00:00Z")
.WithUpdatedAt("2024-06-01T00:00:00Z")
// Address
.WithAddress(Location.Builder()
.WithCountry("CO")
.WithCity("Bogotá")
.WithRegion("DC")
.WithStreet1("Calle 100 #15-20")
.Build())
// Identification Document
.WithIdentificationDocument(IdentificationDocument.Builder()
.WithType("CC")
.WithNumber("12345678")
.WithExpeditionDate("2020-01-01")
.WithExpirationDate("2030-01-01")
.Build())
// External Risk
.WithExternalRisk(new List<ExternalRisk>
{
ExternalRisk.Builder()
.WithSegment(1)
.WithScore(85)
.WithScoreProvider("COINK_INTERNAL")
.Build()
})
// Custom Fields
.WithCustomFields(new Dictionary<string, object>
{
{ "fullName", "Juan Pérez García" },
{ "fixPhoneNumber", "+5714567890" }
})
.Build())
// ═══════════════════════════════════════════════════════════════
// PAYMENT METHOD (root level)
// ═══════════════════════════════════════════════════════════════
.WithPaymentMethod(PaymentMethod.Builder()
.WithType("bankAccount")
.WithPaymentMethodId("pm_origin_001")
.WithAccountNumber("100000056298")
.WithBankCode("BANCOLOMBIA")
.Build())
.Build();
// Enviar y procesar respuesta
var response = await client.ProcessEventAsync(request, returnScore: true);
Respuesta
Estructura de EventResponse
public class EventResponse
{
public string? RequestId { get; set; } // ID único de la petición
public string? Decision { get; set; } // "allow", "block", "review"
public string? Source { get; set; } // Tipo de evento evaluado
public List<string>? Rules { get; set; } // Reglas que coincidieron
public Evaluation? Evaluation { get; set; } // Detalles de la evaluación
}
public class Evaluation
{
public double? Score { get; set; } // Score de riesgo (0-100)
public List<MatchedRule>? MatchedRules { get; set; } // Reglas que coincidieron
public List<string>? Rules { get; set; } // Lista de reglas
}
public class MatchedRule
{
public string? Rule { get; set; } // Nombre de la regla
public string? Description { get; set; } // Descripción
}
Uso de la Respuesta
var response = await client.ProcessEventAsync(request, returnScore: true);
// Información básica
Console.WriteLine($"RequestId: {response.RequestId}");
Console.WriteLine($"Decision: {response.Decision}");
Console.WriteLine($"Score: {response.Evaluation?.Score}");
// Evaluar decisión
switch (response.Decision?.ToLower())
{
case "allow":
// ✅ Aprobar transacción
break;
case "block":
// ❌ Rechazar transacción
break;
case "review":
// ⚠️ Enviar a revisión manual
break;
}
// Obtener reglas que coincidieron
if (response.Evaluation?.MatchedRules?.Any() == true)
{
foreach (var rule in response.Evaluation.MatchedRules)
{
Console.WriteLine($"Regla: {rule.Rule} - {rule.Description}");
}
}
Manejo de Errores
using GatekeeperX.Events.Sdk.Exceptions;
try
{
var response = await client.ProcessEventAsync(request);
}
catch (ValidationException ex)
{
// HTTP 400/422 - Datos inválidos
Console.WriteLine($"Error de validación: {ex.Message}");
Console.WriteLine($"Código: {ex.ErrorCode}");
}
catch (AuthenticationException ex)
{
// HTTP 401 - API Key inválida
Console.WriteLine($"Error de autenticación: {ex.Message}");
}
catch (AuthorizationException ex)
{
// HTTP 403 - Sin permisos
Console.WriteLine($"Sin autorización: {ex.Message}");
}
catch (NotFoundException ex)
{
// HTTP 404 - Recurso no encontrado
Console.WriteLine($"No encontrado: {ex.Message}");
}
catch (RateLimitException ex)
{
// HTTP 429 - Rate limit excedido
Console.WriteLine($"Rate limit excedido. Reintentar en: {ex.RetryAfter}s");
}
catch (ServerException ex)
{
// HTTP 5xx - Error del servidor
Console.WriteLine($"Error del servidor [{ex.StatusCode}]: {ex.Message}");
Console.WriteLine($"RequestId: {ex.RequestId}");
}
catch (GatekeeperXTimeoutException ex)
{
// Timeout de la petición
Console.WriteLine($"Timeout: {ex.Message}");
}
catch (NetworkException ex)
{
// Error de conectividad
Console.WriteLine($"Error de red: {ex.Message}");
}
catch (GatekeeperXException ex)
{
// Excepción base para cualquier error del SDK
Console.WriteLine($"Error: {ex.Message}");
Console.WriteLine($"Código: {ex.ErrorCode}");
Console.WriteLine($"RequestId: {ex.RequestId}");
}
Inyección de Dependencias
Registro del Cliente
// En Program.cs o Startup.cs
services.AddSingleton<EventsApiClient>(sp =>
{
var config = sp.GetRequiredService<IConfiguration>();
var logger = sp.GetService<ILogger<EventsApiClient>>();
var environment = config["GatekeeperX:Environment"] ?? "sandbox";
var builder = environment.ToLower() == "production"
? EventsApiClient.Builder().Production()
: EventsApiClient.Builder().Sandbox();
return builder
.WithOrganizationId(config["GatekeeperX:OrganizationId"]!)
.WithApiKey(config["GatekeeperX:ApiKey"]!)
.WithTimeout(TimeSpan.FromSeconds(
config.GetValue<int>("GatekeeperX:TimeoutSeconds", 10)))
.WithMaxRetries(config.GetValue<int>("GatekeeperX:MaxRetries", 2))
.WithLogger(logger!)
.Build();
});
Configuración en appsettings.json
{
"GatekeeperX": {
"Environment": "sandbox",
"OrganizationId": "tu-organization-id",
"ApiKey": "tu-api-key",
"TimeoutSeconds": 10,
"MaxRetries": 2
}
}
Ejemplo de Servicio de Fraude
public interface IFraudService
{
Task<FraudResult> EvaluateAsync(Guid transferId);
}
public class FraudResult
{
public bool IsApproved { get; set; }
public string? RequestId { get; set; }
public decimal? RiskScore { get; set; }
public string? Decision { get; set; }
public string? Reason { get; set; }
public static FraudResult Approved(string? requestId = null) => new()
{
IsApproved = true,
RequestId = requestId,
Decision = "allow"
};
public static FraudResult Rejected(string reason, string? requestId = null, decimal? score = null) => new()
{
IsApproved = false,
RequestId = requestId,
RiskScore = score,
Decision = "block",
Reason = reason
};
}
public class FraudService : IFraudService
{
private readonly EventsApiClient _client;
private readonly IFraudTransactionRepository _repository;
private readonly ILogger<FraudService> _logger;
public FraudService(
EventsApiClient client,
IFraudTransactionRepository repository,
ILogger<FraudService> logger)
{
_client = client;
_repository = repository;
_logger = logger;
}
public async Task<FraudResult> EvaluateAsync(Guid transferId)
{
try
{
// 1. Obtener datos de la transacción
var data = await _repository.GetTransactionDataAsync(transferId);
if (data == null)
{
_logger.LogWarning("No se encontraron datos para transferId: {TransferId}", transferId);
return FraudResult.Approved(); // Fail-open
}
// 2. Construir request
var request = BuildEventRequest(data);
// 3. Enviar a GatekeeperX
var response = await _client.ProcessEventAsync(request, returnScore: true);
_logger.LogInformation(
"Fraude evaluado - TransferId: {TransferId}, Decision: {Decision}, Score: {Score}, RequestId: {RequestId}",
transferId, response.Decision, response.Evaluation?.Score, response.RequestId);
// 4. Interpretar respuesta
return InterpretResponse(response);
}
catch (GatekeeperXException ex)
{
_logger.LogError(ex,
"Error evaluando fraude para TransferId: {TransferId}", transferId);
// Fail-open: permitir si hay error
return FraudResult.Approved();
}
}
private EventRequest BuildEventRequest(FraudTransactionDataDto data)
{
return EventRequest.Builder()
.WithEventType("create_cashout")
.WithTimestamp(data.CreationDate.ToUnixTimeMilliseconds())
.WithMovement(BuildMovement(data))
.WithCustomer(BuildCustomer(data))
.WithPaymentMethod(BuildRootPaymentMethod(data))
.Build();
}
private Movement BuildMovement(FraudTransactionDataDto data)
{
return Movement.Builder()
.WithMovementId(data.TransferId.ToString())
.WithCustomerId(data.UserId.ToString())
.WithExternalId(data.CustomId ?? "")
.WithType(data.OperationId?.ToString() ?? "")
.WithStatus(data.StatusId?.ToString() ?? "")
.WithCreatedAt(data.CreationDate.ToString("yyyy-MM-ddTHH:mm:ssZ"))
.WithChannel(data.Channel ?? "mobile")
.WithAmount(Money.Builder()
.WithCurrencyCode("COP")
.WithAmount(data.Amount ?? 0m)
.WithAmountInMinorUnits((long)((data.Amount ?? 0m) * 100))
.Build())
.WithOrigin(BuildOrigin(data))
.WithDestination(BuildDestination(data))
.Build();
}
private MovementOrigin BuildOrigin(FraudTransactionDataDto data)
{
return MovementOrigin.Builder()
.WithPaymentMethod(MovementPaymentMethod.Builder()
.WithType(data.OriginAccountType ?? "bankAccount")
.WithPaymentMethodId(data.OriginUserId?.ToString() ?? "")
.WithAccountNumber(data.OriginAccountNumber ?? "")
.WithStatus(data.OriginAccountStatus?.ToString() ?? "")
.WithAlias(data.OriginAlias ?? "")
.WithCustomFields(new Dictionary<string, object>
{
{ "thirdPartyId", data.OriginThirdPartyId ?? 0 }
})
.Build())
.WithCustomFields(new Dictionary<string, object>
{
{ "accountBalanceHistoricId", data.OriginAccountBalanceHistoricId?.ToString() ?? "" },
{ "finalValue", data.OriginFinalValue ?? 0 }
})
.Build();
}
private MovementDestination BuildDestination(FraudTransactionDataDto data)
{
var pmBuilder = MovementPaymentMethod.Builder()
.WithType(data.DestinationAccountType ?? "bankAccount")
.WithPaymentMethodId(data.DestinationUserId?.ToString() ?? "")
.WithAccountNumber(data.DestinationAccountNumber ?? "");
if (data.IsExternal == true)
{
pmBuilder
.WithBankId(data.DestinationBankId?.ToString() ?? "")
.WithBankCode(data.DestinationBankName ?? "")
.WithCustomFields(new Dictionary<string, object>
{
{ "externalAccountId", data.DestinationExternalAccountId?.ToString() ?? "" },
{ "achAccountId", data.AssociatedDataAchAccountId?.ToString() ?? "" },
{ "canceledAt", data.DestinationCancelDate?.ToString("o") ?? "" }
});
}
else
{
pmBuilder
.WithBankCode("COINK")
.WithCustomFields(new Dictionary<string, object>
{
{ "isInternal", true }
});
}
return MovementDestination.Builder()
.WithPaymentMethod(pmBuilder.Build())
.Build();
}
private Customer BuildCustomer(FraudTransactionDataDto data)
{
var builder = Customer.Builder()
.WithCustomerId(data.UserId.ToString())
.WithPhoneNumber(data.UserPhoneNumber ?? "")
.WithEmail(data.UserEmail ?? "")
.WithFirstName(data.UserNames ?? "")
.WithLastName(data.UserLastNames ?? "")
.WithThirdPartyId(data.UserThirdPartyId?.ToString() ?? "0")
.WithCreatedAt(data.UserCreatedDate?.ToString("yyyy-MM-ddTHH:mm:ssZ") ?? "")
.WithUpdatedAt(data.UserUpdatedDate?.ToString("yyyy-MM-ddTHH:mm:ssZ") ?? "");
if (data.UserBirthDate.HasValue)
builder.WithBirthDate(data.UserBirthDate.Value.ToString("yyyy-MM-dd"));
if (data.UserGenderId.HasValue)
builder.WithGender(data.UserGenderId.Value.ToString());
if (data.UserIsPep.HasValue)
builder.WithIsPep(data.UserIsPep.Value);
// Address
if (data.UserCityId.HasValue || data.UserStateId.HasValue)
{
builder.WithAddress(Location.Builder()
.WithCountry("CO")
.WithCity(data.UserCityId?.ToString() ?? "")
.WithRegion(data.UserStateId?.ToString() ?? "")
.WithStreet1(data.UserAddress ?? "")
.Build());
}
// Identification Document
if (!string.IsNullOrEmpty(data.UserDocumentNumber))
{
builder.WithIdentificationDocument(IdentificationDocument.Builder()
.WithType(data.UserDocumentTypeId?.ToString() ?? "")
.WithNumber(data.UserDocumentNumber)
.WithExpeditionDate(data.UserDocumentExpeditionDate?.ToString("yyyy-MM-dd") ?? "")
.Build());
}
// External Risk
if (data.Segment.HasValue)
{
builder.WithExternalRisk(new List<ExternalRisk>
{
ExternalRisk.Builder()
.WithSegment(data.Segment.Value)
.WithScoreProvider("COINK_INTERNAL")
.Build()
});
}
// Custom Fields
builder.WithCustomFields(new Dictionary<string, object>
{
{ "fullName", data.UserRegisterName ?? "" },
{ "fixPhoneNumber", data.UserFixPhoneNumber ?? "" }
});
return builder.Build();
}
private PaymentMethod BuildRootPaymentMethod(FraudTransactionDataDto data)
{
return PaymentMethod.Builder()
.WithType(data.OriginAccountType ?? "bankAccount")
.WithPaymentMethodId(data.OriginUserId?.ToString() ?? "")
.WithAccountNumber(data.OriginAccountNumber ?? "")
.WithBankCode(data.IsExternal == true ? data.DestinationBankName ?? "" : "COINK")
.Build();
}
private FraudResult InterpretResponse(EventResponse response)
{
var decision = response.Decision?.ToUpperInvariant() ?? "";
var isApproved = decision is "ALLOW" or "APPROVE" or "ACCEPT";
if (isApproved)
{
return new FraudResult
{
IsApproved = true,
RequestId = response.RequestId,
RiskScore = (decimal?)(response.Evaluation?.Score),
Decision = response.Decision
};
}
var reason = response.Evaluation?.MatchedRules?.FirstOrDefault()?.Rule
?? response.Decision
?? "FRAUD_REJECTED";
return new FraudResult
{
IsApproved = false,
RequestId = response.RequestId,
RiskScore = (decimal?)(response.Evaluation?.Score),
Decision = response.Decision,
Reason = reason
};
}
}
Registro del Servicio de Fraude
// En Program.cs o Startup.cs
services.AddSingleton<EventsApiClient>(/* ... */);
services.AddScoped<IFraudTransactionRepository, FraudTransactionRepository>();
services.AddScoped<IFraudService, FraudService>();
Modelos Disponibles
Request Models
| Modelo | Descripción |
|---|---|
EventRequest |
Request principal del evento |
Movement |
Movimiento (cashout, cashin, transfers) |
MovementOrigin |
Origen del movimiento |
MovementDestination |
Destino del movimiento |
MovementPaymentMethod |
Método de pago en movimiento |
Customer |
Información del cliente |
IdentificationDocument |
Documento de identidad |
ExternalRisk |
Evaluación de riesgo externo |
PaymentMethod |
Método de pago (nivel raíz) |
Money |
Montos monetarios |
Location |
Direcciones |
Device |
Información del dispositivo |
Transaction |
Transacciones de compra/venta |
Merchant |
Información del comercio |
Order |
Información de la orden |
PointOfSale |
Terminal POS |
Response Models
| Modelo | Descripción |
|---|---|
EventResponse |
Respuesta del evento |
Evaluation |
Detalles de la evaluación |
MatchedRule |
Regla que coincidió |
Exceptions
| Excepción | HTTP Code | Descripción |
|---|---|---|
ValidationException |
400/422 | Datos inválidos |
AuthenticationException |
401 | API Key inválida |
AuthorizationException |
403 | Sin permisos |
NotFoundException |
404 | Recurso no encontrado |
RateLimitException |
429 | Rate limit excedido |
ServerException |
5xx | Error del servidor |
GatekeeperXTimeoutException |
- | Timeout |
NetworkException |
- | Error de red |
GatekeeperXException |
- | Base exception |
Buenas Prácticas
- Reutilizar el Cliente - Crea una única instancia y reutilízala (es thread-safe)
- Usar Métodos Async - Prefiere
ProcessEventAsyncsobreProcessEvent - Configurar Timeouts - Ajusta según tus SLAs (recomendado: 5-10 segundos)
- Manejar Todas las Excepciones - Implementa manejo para todos los tipos
- Loguear RequestIds - Guarda los RequestIds para troubleshooting
- Fail-Open vs Fail-Close - Decide qué hacer cuando el servicio no responde:
- Fail-Open: Permitir transacción si hay error (mejor UX, más riesgo)
- Fail-Close: Rechazar transacción si hay error (más seguro, peor UX)
Requisitos
- .NET 6.0, 7.0 o 8.0
Microsoft.Extensions.Logging.Abstractions(incluido)
Soporte
Para soporte técnico:
- 📧 Email: support@gatekeeperx.com
- 📖 Documentación: https://docs.gatekeeperx.com
Licencia
MIT License - Ver LICENSE para más detalles.
Desarrollado por GatekeeperX
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. 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.
-
net6.0
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.0)
-
net7.0
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.0)
-
net8.0
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.