Astro example for U.CASH Pay: a checkout component and a server-side API route. Non-custodial crypto payments.
Two checkout paths are included:
- Client-side embed link -
UcashPayButton.astrorenders an anchor to the hosted pay page. No server, no secrets. Uses the store Cloud token, which is publishable and safe in the browser. - Server-side tracked checkout -
src/pages/api/checkout.tscreates a transaction against your store (recorded, idempotent perexternal_reference) and returns the hosted payment URL.
Non-custodial: funds go directly to the wallet addresses configured on your pay.u.cash store. U.CASH never holds your customers' funds.
| Path | Purpose |
|---|---|
src/components/UcashPayButton.astro |
Client-side checkout button (hosted pay link) |
src/pages/api/checkout.ts |
Server-side tracked checkout (POST /api/checkout) |
src/pages/index.astro |
Demo page showing both paths |
astro.config.mjs |
Astro config (output: 'server' so the API route runs) |
.env.example |
Where to put your store Cloud token |
# 1. Install dependencies
npm install
# 2. Put your store Cloud token in the environment (for the server route)
cp .env.example .env
# then edit .env and set UCASH_PAY_CLOUD
# 3. Run the dev server
npm run dev
# open http://localhost:4321Import UcashPayButton into any .astro page. The store Cloud token is publishable.
---
import UcashPayButton from '../components/UcashPayButton.astro';
---
<UcashPayButton
cloud="st_your_store_cloud_token"
amount={25}
currency="USD"
title="Pro plan (1 month)"
externalReference="order-1001"
redirect="https://example.com/thanks"
label="Pay with U.CASH"
/>This renders an <a> to:
https://pay.u.cash/embed.php?cloud=...&amount=25¤cy=USD&title=...&external_reference=order-1001&redirect=...
Props:
| Prop | Type | Default | Notes |
|---|---|---|---|
cloud |
string | (required) | Store Cloud token (publishable) |
amount |
number | string | (required) | Charge amount, in currency |
currency |
string | "USD" |
Fiat code |
title |
string | - | Shown on the pay page |
externalReference |
string | - | Your order/reference id |
redirect |
string | - | URL to return to after paying |
label |
string | "Pay with U.CASH" |
Button text |
Call POST /api/checkout with JSON:
const res = await fetch('/api/checkout', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
amount: 25,
currency: 'USD',
title: 'Pro plan (1 month)',
externalReference: 'order-1001', // recommended: makes create idempotent
redirect: 'https://example.com/thanks',
}),
});
const data = await res.json();
// data = { paymentUrl: 'https://pay.u.cash/...', transactionId: '...' }
window.open(data.paymentUrl, '_blank', 'noopener');Set UCASH_PAY_CLOUD in your environment (see .env.example). The route calls https://pay.u.cash/payment/ajax.php with function=create-transaction, cryptocurrency_code= (empty, so the payer picks from the coins enabled on your store), and idempotent=1.
Response codes: 200 { paymentUrl, transactionId }, 400 { error } (bad input), 502 { error } (upstream failure).
- Sign up at pay.u.cash, then click the verification link in the email.
- Set receive addresses under Settings -> Addresses (raw address, ENS, Unstoppable Domains, or FIO).
- Create a store under Account -> Stores and copy its Store Cloud Token (use the store-level token, not the account-wide one).
- For fiat cards, connect your own Stripe under Settings -> Payment processors.
Both paths create a transaction recorded against your store, referenced by your external_reference. To mark orders paid automatically, configure a webhook in your pay.u.cash store dashboard that points at your backend; U.CASH Pay will POST the payment status (including external_reference) when a transaction completes. See the pay.u.cash dashboard for the webhook payload format.
- Recurring billing is not supported. U.CASH Pay is a one-time, non-custodial crypto checkout. For subscriptions, bill on a schedule from your own backend using the server-side checkout path, with your own retry/dunning logic.
- Coin selection is store-side. The server route sends an empty
cryptocurrency_code, so the coins offered are those enabled on your store. To restrict to a single coin, set it in your store settings rather than per-checkout. - Fiat cards require your own Stripe. Card payments are processed by the Stripe account you connect under Settings. Crypto payments settle directly to your configured wallet addresses.
npm run build # outputs to ./dist (server build)
npm run preview # preview the production build locallyBecause output: 'server' is set (the API route needs to run), deploy the server build to a Node-capable host (Vercel, Netlify Functions, Render, a Node server, etc.). The client-side UcashPayButton works from any host, including a fully static export, if you drop the API route.
MIT. See LICENSE.