Accept U.CASH Pay for paid Cal.com bookings (crypto + cards). Non-custodial.
This is a Cal.com payment app stub that implements the
IAbstractPaymentService contract (the interface Cal.com payment apps use) on
top of U.CASH Pay. When an event type requires payment,
the app records an idempotent tracked checkout on the server and returns the
hosted embed.php pay link so the booker can pay with crypto or cards.
- Crypto: BTC, ETH, USDC, and many more, straight to the merchant's receive addresses (raw address, ENS, Unstoppable Domains, or FIO).
- Cards: fiat cards through the merchant's own Stripe.
- Non-custodial: funds never touch this app. The Store Cloud Token is publishable (safe in the browser/app) and only generates payment links.
- A booker submits a paid event type.
- Cal.com calls
BuildPaymentService(credentials).create(...). - The service posts an idempotent
create-transactiontohttps://pay.u.cash/payment/ajax.phpkeyed onexternal_reference, then returns aPaymentwhosedata.urlis theembed.phppay link. - Cal.com redirects the booker to
data.url. The booker pays on the hosted U.CASH Pay page. - The booker is returned to Cal.com; settlement lands directly in the merchant's wallets.
This package is framework-agnostic TypeScript. Install it into your Cal.com deployment (or any Node/Next.js project) from source:
npm install cal-ucashpayWhile it is not yet published to a registry, install from the git URL:
npm install github:UdotCASH/cal-ucashpayThen wire the factory into your Cal.com payment app. In a Cal.com workspace
app (e.g. packages/app-store/ucashpay), re-export the factory and metadata:
// packages/app-store/ucashpay/lib/index.ts
export { BuildPaymentService } from "cal-ucashpay";
// packages/app-store/ucashpay/_metadata.ts
export { default } from "cal-ucashpay/metadata";Cal.com discovers the payment service through the lib.PaymentService /
BuildPaymentService convention and instantiates it with the credentials
stored when the app is installed.
import { createPayLink } from "cal-ucashpay";
const link = createPayLink({
cloud: process.env.NEXT_PUBLIC_UCASH_CLOUD_TOKEN, // publishable
amount: 25,
currency: "USD",
title: "30 min consultation",
external_reference: "cal-booking-123",
});
// link -> https://pay.u.cash/embed.php?cloud=...&amount=25¤cy=USD&...
window.location.href = link;import { createTrackedCheckout } from "cal-ucashpay";
const result = await createTrackedCheckout({
cloud: STORE_CLOUD_TOKEN,
amount: 25,
currency: "USD",
external_reference: "cal-booking-123", // stable per booking; idempotent
title: "30 min consultation",
});
console.log(result.paymentUrl); // the embed.php pay link
console.log(result.transactionId); // pay.u.cash transaction id (if any)See examples/server-route.ts for a Next.js route handler and
examples/pay-link.html for a browser-only demo.
The app stores one credential: the U.CASH Pay Store Cloud Token (publishable). Optional fields:
| Field | Required | Description |
|---|---|---|
cloud |
yes | Store Cloud Token. Publishable; safe in the browser/app. |
payOrigin |
no | Override the pay.u.cash origin (testing/mirrors). |
defaultCurrency |
no | Default currency code if the event type omits one (e.g. USD). |
The zod schema is exported from src/zod.ts for use in the Cal.com settings
form.
- 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.
Builds the hosted embed.php pay link. Browser-safe; no server secret.
cloud(required): Store Cloud Token.amount(required): decimal amount, e.g.25or"25.00".currency(default"USD"): ISO 4217 or crypto code.title,external_reference,redirect(optional).
Returns the absolute https://pay.u.cash/embed.php?... URL.
Posts function=create-transaction to https://pay.u.cash/payment/ajax.php
with idempotent=1. Idempotent per external_reference. Returns
{ paymentUrl, transactionId, raw }.
Cal.com IAbstractPaymentService factory. create() returns a Payment
whose data.url is the pay link and data.embedUrl is the browser-safe
equivalent.
| Cal.com method | Support | Notes |
|---|---|---|
create |
yes | Records a tracked checkout; returns data.url pay link. |
collectCard / HOLD |
partial | Falls back to a live checkout (no card-on-file hold). |
chargeCard |
no | U.CASH Pay captures payment live; charge a new checkout. |
refund |
no | Issue refunds manually from the pay.u.cash dashboard. |
getPaymentPaidStatus |
no | Reconcile via the redirect URL or a pay.u.cash webhook. |
afterPayment |
yes | No-op (no post-payment side effect required). |
deletePayment |
yes | No-op (non-custodial; nothing to void server-side). |
isSetupAlready |
yes | True once the Cloud Token is set. |
Honest limitations:
- Recurring billing: U.CASH Pay does not support automatic crypto recurring billing. Recurring Cal.com event types are not supported by this app; use one-time paid event types.
- Synchronous payment status: the publishable API has no synchronous
status query. Reconcile payment status from the return redirect or a
pay.u.cash webhook keyed on
external_reference. - Refunds: funds are non-custodial and land in the merchant's wallets, so refunds are issued manually from the pay.u.cash dashboard.
This repo only contains packaging files. To publish later:
npm run build
npm version 0.1.0
npm publish --access publicMIT. See LICENSE.