Skip to content

Repository files navigation

btcpayserver-ucashpay

A BTCPay Server plugin that adds U.CASH Pay as an alternative payment method. Shoppers can pay an invoice with multi-coin crypto or fiat cards through pay.u.cash, alongside BTCPay Server's native BTC/Lightning flow. Non-custodial: funds settle directly to the receive addresses the merchant configured in pay.u.cash.

How it works

  1. A BTCPay invoice is created as usual.
  2. The shopper is sent to /ucashpay/checkout/{invoiceId} (a checkout button, redirect rule, or a manual link).
  3. The plugin calls pay.u.cash server-side to create a tracked, idempotent checkout for the invoice total, then redirects the shopper to the hosted pay.u.cash payment page.
  4. After paying, pay.u.cash returns the shopper to the BTCPay invoice status page (or a custom redirect you set).

Because the checkout is created with idempotent=1 keyed on the invoice id, repeated clicks safely resolve to the same pay.u.cash transaction.

Non-custodial note. pay.u.cash never takes custody of funds. The Cloud Token used here is the publishable store-level token, not an operator secret. It is safe to reference from a server route. Cards are processed by the merchant's own Stripe connection configured in pay.u.cash.

Project layout

src/BTCPayServer.Plugins.UcashPay/
  Plugin.cs                              # Plugin entry point (BaseBTCPayServerPlugin)
  Controllers/
    UcashPayController.cs                # /ucashpay/checkout/{invoiceId} redirect route
    UcashPayStoreController.cs           # /stores/{storeId}/ucashpay settings UI
  Services/
    UcashPayClient.cs                    # pay.u.cash API client (POST /payment/ajax.php)
    UcashPaySettings.cs                  # per-store config
    UcashPaySettingsRepository.cs        # settings store (in-memory; see upgrade path)
  Views/UcashPayStore/Edit.cshtml        # settings page
BTCPayServer.Plugins.UcashPay.csproj     # build/manifest
BTCPayServer.Plugins.UcashPay.slnx       # solution

Requirements

  • BTCPay Server >= 2.4.0 (the plugin targets net10.0, matching the current BTCPay Server host). Older hosts on net8.0 are not supported by this release; downgrade <TargetFramework> and the dependency condition in Plugin.cs if you must target an older host.
  • .NET 10 SDK to build.

Build from source

The plugin references BTCPay Server as a git submodule so it compiles against the real host types.

git clone --recurse-submodules https://github.com/UdotCASH/btcpayserver-ucashpay.git
cd btcpayserver-ucashpay
git submodule update --init --recursive   # if you cloned without submodules

dotnet build src/BTCPayServer.Plugins.UcashPay/BTCPayServer.Plugins.UcashPay.csproj -c Release

The built DLL lands in src/BTCPayServer.Plugins.UcashPay/bin/Release/net10.0/BTCPayServer.Plugins.UcashPay.dll.

If you do not want the submodule, the .csproj falls back to a NuGet PackageReference on BTCPayServer.Abstractions. Pin its Version to the BTCPay Server release you target.

Install the plugin

There are two ways to install a BTCPay Server plugin.

Option A: Copy the DLL (any deployment)

  1. Build the plugin (see above).
  2. Copy BTCPayServer.Plugins.UcashPay.dll into your BTCPay Server datadir plugins folder (typically ~/.btcpayserver/plugins/).
  3. Restart BTCPay Server. The plugin loads on the next boot.

Option B: Load during a debug/dev session

./plugin-register.sh

This writes the debug DLL path into submodules/btcpayserver/BTCPayServer/appsettings.dev.json so the plugin starts when you debug BTCPay Server.

Configure your store

  1. Open your BTCPay Server store and go to: https://<your-btcpay>/stores/{storeId}/ucashpay
  2. Paste your pay.u.cash Store Cloud Token.
  3. Set the checkout currency (default USD), an optional checkout title, and an optional redirect URL.
  4. Save.

Use it

Send a shopper to the redirect route for an invoice:

https://<your-btcpay>/ucashpay/checkout/{invoiceId}

For example, add an Pay with U.CASH button to your checkout that links to that URL. The plugin creates the pay.u.cash checkout for the invoice total and redirects the shopper. On success they land back on the BTCPay invoice status page.

You can also generate the client-side embed link directly (publishable token only, no server round-trip):

https://pay.u.cash/embed.php?cloud=<STORE_CLOUD_TOKEN>&amount=<AMOUNT>&currency=USD&external_reference=<INVOICE_ID>

The server-side redirect route above is preferred because it creates a tracked, idempotent checkout record at pay.u.cash.

Set up your pay.u.cash account

  1. Sign up at pay.u.cash, then click the verification link in the email.
  2. Set receive addresses under Settings -> Addresses (raw address, ENS, Unstoppable Domains, or FIO).
  3. Create a store under Account -> Stores and copy its Store Cloud Token (use the store-level token, not the account-wide one).
  4. For fiat cards, connect your own Stripe under Settings -> Payment processors.

Pay.u.cash API contract

The plugin implements this contract exactly.

Server-side tracked checkout (idempotent per external_reference):

POST https://pay.u.cash/payment/ajax.php
Content-Type: application/x-www-form-urlencoded

function=create-transaction
&amount=<decimal>
&currency_code=<USD>
&cryptocurrency_code=
&external_reference=<INVOICE_ID>
&title=<label>
&redirect=<return URL>
&cloud=<STORE_CLOUD_TOKEN>
&idempotent=1

Response JSON { success: true, response: [paymentUrl, transactionId, ...] }. The payment URL is the response array element that starts with http(s)://.

Client-side hosted embed (publishable cloud token, browser-safe):

GET https://pay.u.cash/embed.php?cloud=&amount=&currency=&title=&external_reference=&redirect=

Limitations (honest)

  • Payment status reconciliation is out of scope for v0.1. The redirect route starts a pay.u.cash checkout and sends the shopper there, but this scaffold does not yet mark the BTCPay invoice paid from a pay.u.cash webhook. Today, BTCPay keeps its own on-chain BTC/Lightning state; the U.CASH checkout is an alternative off-ramp you reconcile manually or via a future webhook handler (see Roadmap).
  • Settings are in-memory. UcashPaySettingsRepository keeps per-store config in process memory for a zero-dependency starter. Restarting BTCPay Server loses the token. For production, replace it with a persistent store (BTCPay StoreBlob additional data, or a plugin EF Core DB context) before relying on it.
  • No native BTCPay "payment method" registration. This version adds a redirect route and a settings UI rather than a full IPaymentMethodHandler so the invoice checkout shows it as a redirect link, not as an integrated tab. A follow-up can register it as a first-class payment method.
  • Automatic crypto recurring billing is not supported by pay.u.cash and is therefore not implemented.

Roadmap

  • Webhook handler that marks the BTCPay invoice Settled/Processing when pay.u.cash reports the external_reference paid.
  • Persist settings in the BTCPay StoreBlob instead of in-memory.
  • Register U.CASH Pay as a first-class BTCPay payment method (IPaymentMethodHandler) so it appears as a tab in the checkout.
  • Per-store currency and coin allow-list UI.

Publish (maintainers only)

This is a BTCPay plugin, not a standalone app, so there is no npm/PyPI/crates publish. To ship a release, build the Release DLL and attach it to a GitHub Release (BTCPay Server loads plugins from a DLL dropped in the plugins folder):

dotnet build src/BTCPayServer.Plugins.UcashPay/BTCPayServer.Plugins.UcashPay.csproj -c Release
# then attach bin/Release/net10.0/BTCPayServer.Plugins.UcashPay.dll to a GitHub Release

If you later publish the abstractions-only library to NuGet, the package id is BTCPayServer.Plugins.UcashPay and the publish command is:

dotnet pack src/BTCPayServer.Plugins.UcashPay/BTCPayServer.Plugins.UcashPay.csproj -c Release
dotnet nuget push bin/Release/BTCPayServer.Plugins.UcashPay.0.1.0.nupkg --api-key <KEY> --source https://api.nuget.org/v3/index.json

License

MIT. See LICENSE.

About

BTCPay Server plugin adding U.CASH Pay as an alternative payment method (multi-coin + cards). Non-custodial.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages