SilverLabs.SilverDotPay.Sdk 1.8.0

SilverDotPay SDK

Typed .NET client for the SilverDotPay payment gateway.

Install

dotnet add package SilverLabs.SilverDotPay.Sdk

The SilverLABS NuGet feed must be configured. In nuget.config:

<add key="silverlabs" value="https://nuget.silverlabs.uk/v3/index.json" />

Quick start

services.AddSilverDotPaySdk(opts =>
{
    opts.BaseAddress = "https://silverdotpay.silverlabs.uk";
    opts.Mode = SilverDotPayClientMode.ApiKey;
    opts.ApiKey = configuration["SilverDotPay:ApiKey"];
    opts.Timeout = TimeSpan.FromSeconds(30);
})
.AddPublicClient()      // ICurrenciesClient + exchange rates, no auth
.AddMerchantClient()    // orders, balances, withdrawals, webhooks
.AddAdminClient()       // applications, keys, secrets, escrow, settings
.AddCardClient();       // card rail: charge-saved, setup, saved cards (1.3.0)

Then inject any of:

  • ISilverDotPayClient — narrow legacy surface (order create, get, escrow release/refund) — used by Crowding-style integrations.
  • ISilverDotPayPublicClient — currencies, exchange rates. No auth.
  • ISilverDotPayMerchantClient — orders, my balance, withdrawals, webhook config.
  • ISilverDotPayAdminClient — applications, API keys, webhook secret rotation, balances, escrow, settings.
  • ISilverDotPayCardClient — card rail: rail status, charge saved card, setup-mode capture, list/remove saved cards.

Auth modes

Pick one per HttpClient:

  • SilverDotPayClientMode.ApiKey — sets X-API-Key header from opts.ApiKey. Used by service accounts and admin keys.
  • SilverDotPayClientMode.PassportBearer — forwards a Passport SSO token from a pluggable ITokenSource. Used in ASP.NET Core hosts where the inbound user's token is propagated downstream.

Inbound webhook validation

services.AddSingleton<ISilverDotPayWebhookValidator>(sp =>
    new SilverDotPayWebhookValidator(secret: cfg["SilverDotPay:WebhookSecret"], logger));

Validator parses X-SilverDotPay-Signature: t=<unix>,v1=<hex>, recomputes HMAC-SHA256("<unix>.<raw body>", secret), and rejects if the timestamp falls outside a 5-minute replay window. Fails closed when no secret is configured.

See docs/WEBHOOKS.md in the silverdotpay repo for the wire format.

Card rail (1.3.0)

  • Card checkout: CreateOrderAsync with Rail = SilverDotPayRail.Card, GBP Amount, BuyerIdentifier (tenant id), SuccessUrl, CancelUrl; redirect the buyer to CreateOrderResponse.PaymentUrl. The card is saved for renewals.
  • payment_confirmed carries payment_method.ref — store it and pass it as PaymentMethodRef to ISilverDotPayCardClient.ChargeSavedAsync for renewals (optionally with BuyerIdentifier as an ownership check). Use a new ExternalOrderId per attempt; reuse it only to retry the same attempt (never double-charges).
  • ChargeSavedResponse.Status is one of SilverDotPayChargeStatus. processing means the outcome is unknown: do not treat it as failed and do not start another attempt; reconcile via POST /api/orders/{id}/reconcile.
  • payment_failed carries failure.reason (SilverDotPayFailureReason) and, for authentication_required, failure.action_url — send the customer there to authenticate.
  • payment_method_saved (setup mode) has no order; key it on payment_method.buyer_identifier.
  • A 503 (SilverDotPayException.StatusCode == 503) or GetCardRailStatusAsync().IsConfigured == false means cards are not configured for this application: hide the card option.

1.5.0 (additive)

  • livemode on CreateOrderResponse, OrderStatusResponse and the webhook order: the Stripe livemode of the completing payment (false = test mode). Null until paid, for crypto orders, or from a SilverDotPay older than this SDK. Consumers must not provision from a false payment outside a designated test tenant. A null on a paid card order means unknown: hold it for a person rather than provisioning, and never read null as test mode.
  • ISilverDotPayCardClient.ReconcileOrderAsync(orderId): asks SilverDotPay to reconcile a card order with Stripe (missed-webhook recovery) and returns the order; 404/503 surface as SilverDotPayException.

1.6.0 (additive)

  • Stripe Connect calls: ISilverDotPayMerchantClient and ISilverDotPayAdminClient (leading applicationId) gain StartStripeConnectAsync, CompleteStripeConnectAsync(StripeConnectCompleteRequest), GetStripeConnectStatusAsync and DisconnectStripeAsync, returning StripeConnectStartDto / StripeConnectStatusDto.
  • ApplicationDto += StripeConnectedAccountId, StripeConnectLivemode, StripeConnectedAtUtc, StripeChargesOnPlatform.
  • UpdateApplicationRequest += WalletMode, ExtendedPublicKeys.
  • Fix: RotateWebhookSecretAsync now POSTs to .../webhook-secret/rotate (the previous path did not match the API action).
  • Obsolete (still functional, removal scheduled for SDK 2.0): GetMyBalancesAsync, RequestWithdrawalAsync, ListWithdrawalsAsync, GetGlobalBalancesAsync, GetApplicationBalancesAsync. Custodial surfaces are parked.

1.8.0 (additive)

  • ApplicationDto += ExtendedPublicKeys (the stored JSON map) and WatchOnlyFirstAddresses (Silver Pay Stage 7: the 0/0 address per stored key for a WatchOnly application, so a console can show the merchant what to compare with their wallet). Both null when absent; older servers simply leave them null.

1.7.0 (additive)

  • CreateApplicationRequest.WalletMode is now int?. Omitted means WatchOnly, the Silver Pay Stage 6 default: a non-custodial, card-only application needs no extended public keys. Set 1 (WatchOnly) explicitly if you prefer; 0 (PlatformCustody) is first-party only.
  • Behaviour change on the server (not the SDK): the custodial surfaces (balances, escrow) answer 404 while Platform:CustodialFeaturesEnabled is off, and custody-mode crypto orders are refused with 503 for non-first-party applications. The [Obsolete] custodial members remain for source compatibility.
  • Server-side since Silver Pay Stage 7 (no SDK change): a WatchOnly application takes BTC/LTC/ETH with its own account-level extended public keys, set through UpdateApplicationRequest.ExtendedPublicKeys (JSON {"BTC":"zpub…","LTC":"zpub…","ETH":"xpub…"}; Litecoin native segwit shares the zpub prefix, Mtub is wrapped segwit; {} clears). Invalid keys → 400 Invalid extended public keys: …; a crypto order without a usable key for the coin → 503 naming the problem. The application response now carries watchOnlyFirstAddresses (not yet on ApplicationDto; planned for the next SDK minor together with ExtendedPublicKeys). The BTCPay webhook route is gone.

Versioning

SemVer. Major versions track breaking API contract changes on the silverdotpay backend.

No packages depend on SilverLabs.SilverDotPay.Sdk.

Version Downloads Last updated
1.9.0 0 11/10/2026
1.8.0 28 11/09/2026
1.7.0 1 11/09/2026
1.6.0 19 11/06/2026
1.5.0 94 11/06/2026
1.4.0 691 10/06/2026
1.3.0 6 10/06/2026
1.2.0 2,537 04/28/2026
1.1.0 47 04/28/2026
1.0.0 21 04/28/2026