FluvPay 1.0.0

dotnet add package FluvPay --version 1.0.0
                    
NuGet\Install-Package FluvPay -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="FluvPay" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FluvPay" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="FluvPay" />
                    
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 FluvPay --version 1.0.0
                    
#r "nuget: FluvPay, 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 FluvPay@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=FluvPay&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=FluvPay&version=1.0.0
                    
Install as a Cake Tool

FluvPay SDK para .NET

SDK oficial da FluvPay para .NET. Cobranças PIX, saques, transferências internas e verificação de webhooks, com tipagem forte e zero dependência de runtime (usa HttpClient e System.Text.Json da própria plataforma).

Instalação

Requisitos: .NET 8.0 ou superior.

O SDK ainda não está publicado no NuGet (a publicação no registry depende de uma conta que será criada em breve). Até lá, instale a partir do código-fonte. As duas formas abaixo funcionam hoje.

A partir do código-fonte (recomendado hoje)

Clone o repositório e adicione uma ProjectReference ao FluvPay.csproj no seu projeto:

git clone https://github.com/fluvpay/fluvpay-dotnet.git
dotnet add SeuProjeto.csproj reference ./fluvpay-dotnet/src/FluvPay/FluvPay.csproj

Isso adiciona a seguinte entrada ao seu .csproj (você pode editar à mão se preferir, ajustando o caminho relativo até onde clonou o repositório):

<ItemGroup>
  <ProjectReference Include="..\fluvpay-dotnet\src\FluvPay\FluvPay.csproj" />
</ItemGroup>

Pacote local com dotnet pack

Como alternativa, empacote o SDK localmente e instale o .nupkg gerado a partir de uma pasta no seu disco:

git clone https://github.com/fluvpay/fluvpay-dotnet.git
dotnet pack ./fluvpay-dotnet/src/FluvPay/FluvPay.csproj -c Release -o ./pacotes-locais
dotnet add SeuProjeto.csproj package FluvPay --source ./pacotes-locais

Via NuGet (em breve, quando publicado no NuGet)

Quando o pacote estiver publicado no registry, a instalação será um único comando. Ainda não funciona, não use até o anúncio oficial:

dotnet add package FluvPay

Configuração

A API Key define o modo de operação pelo prefixo: fluv_live_ para produção e fluv_test_ para o sandbox. Você só precisa passar a chave; o SDK cuida do resto.

using FluvPay;

var client = new FluvPayClient("fluv_live_sua_chave");

// Ou com opções explícitas:
var client = new FluvPayClient(new FluvPayClientOptions
{
    ApiKey = Environment.GetEnvironmentVariable("FLUVPAY_API_KEY")!,
    // BaseUrl = "https://api.fluvpay.com/api/v1", // padrão
    // Timeout = TimeSpan.FromSeconds(30),         // padrão
    // MaxRetries = 2,                             // padrão (0 desliga)
});

Console.WriteLine(client.IsTestKey()); // true se a chave for fluv_test_

O FluvPayClient implementa IDisposable. Reaproveite a mesma instância pela vida útil da aplicação em vez de criar uma por requisição.

Criar uma cobrança PIX

A criação de cobrança aceita apenas os campos do contrato. Não envie currency nem method: a moeda e o método (PIX) são implícitos, e a API rejeita campos extras com erro de validação.

var charge = await client.Charges.CreateAsync(new ChargeCreateParams
{
    AmountCents = 2500, // R$ 25,00 (mínimo 100, máximo 100000)
    Description = "Pedido #1042",
    Customer = new ChargeCustomer { Name = "Cliente Exemplo", Email = "cliente@exemplo.com" },
    PassFeeToPayer = true,
    Metadata = new Dictionary<string, object?> { ["pedido_id"] = "1042" },
});

Console.WriteLine(charge.Id);
Console.WriteLine(charge.Status);        // pending | paid | expired | cancelled | refunded
Console.WriteLine(charge.PixCopyPaste);  // código copia-e-cola
Console.WriteLine(charge.PixQrCode);     // imagem do QR em base64

A Idempotency-Key é gerada automaticamente (UUIDv4) se você não informar uma. Para controlar a chave (por exemplo, reusar entre tentativas do seu lado), passe pelas opções de escrita:

var charge = await client.Charges.CreateAsync(
    new ChargeCreateParams { AmountCents = 2500 },
    new WriteOptions { IdempotencyKey = "pedido-1042-tentativa-1" });

Recuperar e listar

var charge = await client.Charges.RetrieveAsync("chg_...");

var page = await client.Charges.ListAsync(new ChargeListParams
{
    Status = "paid",
    Page = 1,
    PerPage = 20,
    Sort = "-created_at",
});

Console.WriteLine(page.Data.Count); // ChargeListItem
Console.WriteLine(page.HasNext);    // paginação por page/per_page

Saques e transferências internas

Estas operações são live-only: chaves fluv_test_ recebem 403.

var withdrawal = await client.Withdrawals.CreateAsync(new WithdrawalCreateParams
{
    AmountCents = 5000,
    PixKey = "chave@exemplo.com",
    PixKeyType = "email", // cpf | cnpj | email | phone | evp
});

var withdrawalsPage = await client.Withdrawals.ListAsync(new WithdrawalListParams { Limit = 20, Offset = 0 });
Console.WriteLine(withdrawalsPage.Total); // paginação por limit/offset

var transfer = await client.InternalTransfers.CreateAsync(new InternalTransferCreateParams
{
    AmountCents = 1000,
    RecipientEmail = "destino@exemplo.com", // ou RecipientMerchantId
});

Extrato (transactions)

var txPage = await client.Transactions.ListAsync(new TransactionListParams { Page = 1, PerPage = 50 });
var tx = await client.Transactions.RetrieveAsync("tx_...");

Sandbox

Disponível apenas com chave fluv_test_.

var scenarios = await client.Sandbox.ScenariosAsync();
var reset = await client.Sandbox.ResetAsync();

Verificação de webhooks

A FluvPay assina cada entrega. Verifique a assinatura usando o corpo CRU da requisição (nunca re-serialize o JSON, pois isso muda os bytes e invalida a assinatura). O cálculo é HMAC_SHA256(secret, timestamp + "." + rawBody) em hex, e o header X-FluvPay-Signature vem no formato v1=<hex>.

Exemplo com ASP.NET Core, lendo o corpo cru:

using FluvPay;

app.MapPost("/webhooks/fluvpay", async (HttpRequest request) =>
{
    using var ms = new MemoryStream();
    await request.Body.CopyToAsync(ms);
    byte[] rawBody = ms.ToArray();

    try
    {
        var evt = Webhooks.VerifySignature(
            payload: rawBody,
            signatureHeader: request.Headers["X-FluvPay-Signature"]!,
            timestamp: request.Headers["X-FluvPay-Timestamp"]!,
            secret: Environment.GetEnvironmentVariable("FLUVPAY_WEBHOOK_SECRET")!, // whsec_...
            toleranceSeconds: 300);

        switch (evt.Type)
        {
            case "charge.paid":
                // processar pagamento confirmado
                break;
            case "payout.completed":
                // processar saque concluído
                break;
        }

        return Results.Ok();
    }
    catch (FluvPaySignatureVerificationException)
    {
        return Results.BadRequest();
    }
});

Eventos disponíveis: charge.created, charge.paid, charge.expired, charge.cancelled, charge.refunded, payout.created, payout.completed e payout.failed.

Tratamento de erros

Cada falha vira uma exceção tipada. Todas herdam de FluvPayException e carregam Code, Message, Details, TraceId e StatusCode.

try
{
    await client.Charges.CreateAsync(new ChargeCreateParams { AmountCents = 1 });
}
catch (FluvPayValidationException ex)
{
    Console.Error.WriteLine($"{ex.Code}: {ex.Details.Count} detalhe(s)");
}
catch (FluvPayRateLimitException ex)
{
    Console.Error.WriteLine($"aguardar {ex.RetryAfter} segundos");
}

Mapeamento: 400/422 para FluvPayValidationException, 401 para FluvPayAuthenticationException, 403 para FluvPayPermissionException, 404 para FluvPayNotFoundException, 409 para FluvPayConflictException (inclui IDEMPOTENCY_CONFLICT), 429 para FluvPayRateLimitException (lê Retry-After), 5xx para FluvPayServerException, e falha de rede ou timeout para FluvPayConnectionException.

Retentativas

O SDK retenta automaticamente (padrão 2 tentativas, backoff exponencial com jitter) apenas em situações seguras: requisições GET e POSTs que carregam Idempotency-Key, nos casos de 429 e 5xx ou falha de conexão. O header Retry-After é respeitado. Para desligar, use MaxRetries = 0.

Desenvolvimento

dotnet build
dotnet test    # unit + webhook (sem rede)

O smoke no sandbox roda somente se a variável FLUVPAY_TEST_KEY (prefixo fluv_test_) estiver presente; caso contrário, é ignorado.

Licença

MIT.

Product Compatible and additional computed target framework versions.
.NET 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.
  • net8.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 145 6/8/2026