Solentik.Paystack
1.0.2
See the version list below for details.
dotnet add package Solentik.Paystack --version 1.0.2
NuGet\Install-Package Solentik.Paystack -Version 1.0.2
<PackageReference Include="Solentik.Paystack" Version="1.0.2" />
<PackageVersion Include="Solentik.Paystack" Version="1.0.2" />
<PackageReference Include="Solentik.Paystack" />
paket add Solentik.Paystack --version 1.0.2
#r "nuget: Solentik.Paystack, 1.0.2"
#:package Solentik.Paystack@1.0.2
#addin nuget:?package=Solentik.Paystack&version=1.0.2
#tool nuget:?package=Solentik.Paystack&version=1.0.2
Solentik.Paystack
An idiomatic, strongly typed .NET client for the Paystack API, with optional ASP.NET Core webhook routing and event handlers.
Documentation
Full installation, configuration, resource, and ASP.NET Core webhook documentation is available at:
https://paystack.solentik.com/dotnet/introduction.html
Packages
| Package | Purpose |
|---|---|
Solentik.Paystack |
Framework-neutral Paystack API client |
Solentik.Paystack.AspNetCore |
Verified webhook endpoint and typed event dispatch for ASP.NET Core |
Both packages target:
- .NET 8
- .NET 9
- .NET 10
Installation
Install the core package:
dotnet add package Solentik.Paystack
For ASP.NET Core webhook support, also install:
dotnet add package Solentik.Paystack.AspNetCore
Configuration
Add the secret key to configuration. Do not commit production keys to source control.
{
"Paystack": {
"SecretKey": "sk_test_xxxx",
"BaseAddress": "https://api.paystack.co/",
"Timeout": "00:00:45",
"Webhooks": {
"Path": "/integrations/paystack/webhook",
"MaximumBodySize": 524288
}
}
}
Register the client with dependency injection:
using Solentik.Paystack.DependencyInjection;
builder.Services.AddPaystack(builder.Configuration);
Configuration can also be supplied directly:
builder.Services.AddPaystack(options =>
{
options.SecretKey = builder.Configuration["Paystack:SecretKey"]!;
options.Timeout = TimeSpan.FromSeconds(45);
});
The package uses a single IHttpClientFactory-managed HttpClient internally, shared by every resource client, with standard retry/timeout/circuit-breaker resilience applied to GET requests. Inject IPaystackClient or an individual resource interface; do not construct or retain HttpClient instances yourself.
Transactions
using Solentik.Paystack;
using Solentik.Paystack.Transactions.Models;
public sealed class CheckoutService(IPaystackClient paystack)
{
public async Task<string?> InitializeAsync(
string email,
long amount,
CancellationToken cancellationToken)
{
var response = await paystack.Transactions.InitializeAsync(
new InitializeTransactionRequest
{
Email = email,
Amount = amount,
Currency = "GHS"
},
cancellationToken);
return response.Data?.AuthorizationUrl;
}
}
Transaction amounts are supplied in the currency's smallest unit.
Customers
using Solentik.Paystack.Customers.Models;
var response = await paystack.Customers.CreateAsync(
new CreateCustomerRequest
{
Email = "customer@solentik.com",
FirstName = "Ama",
LastName = "Mensah"
});
var customerCode = response.Data?.CustomerCode;
Customer operations include create, fetch, update, list, identity validation, risk actions, and reusable authorization management.
Plans and subscriptions
using Solentik.Paystack.Plans.Models;
using Solentik.Paystack.Subscriptions.Models;
var plan = await paystack.Plans.CreateAsync(
new CreatePlanRequest
{
Name = "Monthly Pro",
Amount = 5000,
Interval = "monthly",
Currency = "GHS"
});
var subscription = await paystack.Subscriptions.CreateAsync(
new CreateSubscriptionRequest
{
Customer = "CUS_xxxx",
Plan = plan.Data!.PlanCode!
});
Subscriptions can also be listed, fetched, enabled, disabled, and managed through card-update links.
Transaction splits
using Solentik.Paystack.TransactionSplits.Models;
var split = await paystack.TransactionSplits.CreateAsync(
new CreateTransactionSplitRequest
{
Name = "Marketplace Split",
Type = "percentage",
Currency = "GHS",
Subaccounts =
[
new SplitSubaccountRequest
{
Subaccount = "ACCT_xxxx",
Share = 20
}
]
});
Splits support create, list, fetch, update, add/update subaccount, and remove subaccount operations.
Miscellaneous
using Solentik.Paystack.Miscellaneous.Models;
// Bank list, filterable by country
var banks = await paystack.Miscellaneous.ListBanksAsync(
new BankListOptions { Country = "ghana" });
// Mobile money channels use the same endpoint, filtered by type
var mobileMoneyChannels = await paystack.Miscellaneous.ListBanksAsync(
new BankListOptions { Country = "ghana", Type = "mobile_money" });
var countries = await paystack.Miscellaneous.ListCountriesAsync();
var states = await paystack.Miscellaneous.ListStatesAsync("NG");
Verification
using Solentik.Paystack.Verification.Models;
// Resolve an account number (bank or mobile money) to an account name
var resolved = await paystack.Verification.ResolveAccountAsync("0123456789", "058");
var accountName = resolved.Data?.AccountName;
// Fuller KYC validation
var validated = await paystack.Verification.ValidateAccountAsync(
new ValidateAccountRequest
{
AccountName = "Ann Bron",
AccountNumber = "0123456789",
AccountType = "personal",
BankCode = "632005",
CountryCode = "ZA",
DocumentType = "identityNumber",
DocumentNumber = "1234567890123"
});
// Card BIN lookup
var cardInfo = await paystack.Verification.ResolveCardBinAsync("539983");
ASP.NET Core webhooks
Register webhook services and map the endpoint:
using Solentik.Paystack.AspNetCore.DependencyInjection;
using Solentik.Paystack.AspNetCore.Routing;
using Solentik.Paystack.AspNetCore.Webhooks;
builder.Services.AddPaystackWebhooks(builder.Configuration);
builder.Services.AddPaystackWebhookHandler<
PaymentSuccess,
PaymentSuccessHandler>();
var app = builder.Build();
app.MapPaystackWebhook();
app.Run();
The overload above binds Paystack:Webhooks from appsettings.json. The default endpoint is POST /paystack/webhook. You can alternatively configure options in code with AddPaystackWebhooks(options => ...). An explicit route can override either configured value:
app.MapPaystackWebhook("/another/paystack/endpoint");
Application path and Dashboard URL
Path is the route inside the ASP.NET Core application, not a complete public URL. If the configured path is /integrations/paystack/webhook and the production domain is https://api.example.com, enter this complete URL in the Paystack Dashboard:
https://api.example.com/integrations/paystack/webhook
Keeping the hostname out of application routing allows local, staging, and production deployments to use different domains with the same route. Include any externally visible reverse-proxy path base in the Dashboard URL.
Maximum body size
MaximumBodySize is the largest webhook request body the endpoint will accept, measured in bytes. The default 524288 bytes equals 512 KiB. The package must temporarily buffer the exact raw bytes to calculate and verify Paystack's HMAC-SHA512 signature before parsing JSON, so this limit prevents oversized requests from consuming unbounded memory. Requests above the limit return HTTP 413. Normal Paystack webhook payloads should be much smaller than 512 KiB.
Create a handler:
public sealed class PaymentSuccessHandler
: IPaystackWebhookHandler<PaymentSuccess>
{
public Task HandleAsync(
PaymentSuccess webhookEvent,
CancellationToken cancellationToken = default)
{
var reference = webhookEvent.Data
.GetProperty("reference")
.GetString();
// Verify business state and fulfil the order idempotently.
return Task.CompletedTask;
}
}
Supported typed events include payment success, subscription lifecycle, invoice lifecycle, and disputes. Generic WebhookReceived and WebhookHandled handlers are also available.
Webhook requests are verified against the exact raw body using HMAC-SHA512 and a timing-safe comparison. Invalid signatures are rejected before dispatch.
Errors
Unsuccessful Paystack responses throw PaystackException, which exposes:
- HTTP status code
- Paystack error type
- Paystack error code
- Paystack metadata
Development
To run the complete test matrix:
dotnet test Solentik.Paystack.slnx -c Release
License
Licensed under the MIT License.
| Product | Versions 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 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 is compatible. 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. |
-
net10.0
- Microsoft.Extensions.Http (>= 10.0.11)
- Microsoft.Extensions.Http.Resilience (>= 10.9.0)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 10.0.11)
-
net8.0
- Microsoft.Extensions.Http (>= 10.0.11)
- Microsoft.Extensions.Http.Resilience (>= 10.9.0)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 10.0.11)
-
net9.0
- Microsoft.Extensions.Http (>= 10.0.11)
- Microsoft.Extensions.Http.Resilience (>= 10.9.0)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 10.0.11)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Solentik.Paystack:
| Package | Downloads |
|---|---|
|
Solentik.Paystack.AspNetCore
ASP.NET Core webhook routing and typed event handlers for Solentik.Paystack. |
GitHub repositories
This package is not used by any popular GitHub repositories.