glitternetwork/pinme/pinme-uniwebpay
- community
Checking that the SKILL.md file is still in the repository.
Use when generating, modifying, or reviewing PinMe Worker (Cloudflare Worker TypeScript) code that accepts payments through UniwebPay — payment links, products/prices, checkout sessions, payment status reads, refunds, subscriptions, or handling UniwebPay webhooks with @uniwebpay/sdk in a PinMe project.
Install
npx vskill@latest install glitternetwork/pinme/pinme-uniwebpaySKILL.md
PinMe UniwebPay Payment Integration
Guides writing payment services in a PinMe Worker (Cloudflare Worker TypeScript) that call UniwebPay directly through @uniwebpay/sdk.
Core model: PinMe provisions the UniwebPay wallet and keys per PinMe user (not per project) and injects UNIWEB_* environment bindings at Worker deploy time; Worker code calls UniwebPay directly with the SDK — it does not go through PinMe payment proxy routes, and it must not call the legacy VibeCash APIs.
Environment Binding Contract
Injection rules (metadata is rebuilt server-side by PinMe at deploy time; client-supplied bindings are ignored):
- The
UNIWEB_*bindings are injected only after the user's UniwebPay credentials have been provisioned. Newly created projects are provisioned automatically and get them immediately; existing projects must be redeployed after enabling UniwebPay or rotating keys to pick up new bindings. WORKER_URL,PROJECT_NAME,API_KEY,DBand other base bindings are injected on every deploy, independent of UniwebPay.- All projects owned by the same PinMe user share one wallet, one
sk_server_, and onewhsec_. - PinMe never gives the full wallet secret (
sk_live_) to a Worker. Do not ask the user for it, and do not put it in code,wrangler.toml,.dev.vars, responses, logs, D1, or frontend bundles. - If
UNIWEB_SECRETis missing at runtime, the user has not enabled UniwebPay or has not redeployed — tell the user to enable it and redeploy; never fabricate a value.
SDK Client
Always instantiate on the server side (the Worker); the SDK throws when run in a browser:
- The constructor's first positional argument is the key (must have an
sk_server_orsk_live_prefix); the second is optional options:{ baseUrl?, payUrl?, timeout? (default 30s), maxRetries? (default 2) }. - The SDK auto-retries only GET/DELETE on 429/5xx; POST/PATCH are never retried (avoids duplicate charges).
- Install
@uniwebpay/sdkonly when Worker code imports it; pick the package manager from the project's existing lockfile.
Choosing an Integration Path
| Scenario | Approach | Returns | |
|---|---|---|---|
| Fixed-amount one-time collection | uniweb.links.create(...) | Permanent, reusable /p/ link (one-time payments only) | |
| Stable product catalog | products.create + prices.create once, store the priceId | Price carries a permanent paymentUrl (/buy/ link) | |
| Dynamic cart/order | Reuse or create a price, then uniweb.checkout.create(...) | session.url — one-time, expires in 24 hours | |
| Subscriptions | Recurring price + checkout.create({ mode: "subscription" }) or subscriptions.create | Same as above | |
| Server-side payment status checks | payments.get / list | Server routes only |
Amounts are always integer minor units (cents). Default currency convention is SGD unless the app has a stronger existing convention. Do not create a new product/price on every page view — create stable catalog items once and persist the priceId.
Payment Methods and Currency Rules
| Method | Supported currencies | |
|---|---|---|
card | SGD, USD, EUR, GBP, JPY, CNY, HKD, AUD, MYR, THB (minimum 10 minor units) | |
wechat | SGD only | |
alipay | SGD only | |
paynow | SGD only |
- The QR methods (wechat/alipay/paynow) all support SGD only — never generate "CNY via WeChat/Alipay" code.
- Subscriptions (recurring /
mode: "subscription") usecardonly. - When
paymentMethodTypesis omitted, the server picks sensible defaults for the currency; when passed explicitly, validate user input against the table above first.
SDK Surface Quick Reference
The surface below is verified against source. All parameter fields are camelCase (priceId, webhookUrl, startingAfter, …); the SDK handles wire-level conversion itself. list() returns { data: T[], hasMore: boolean }; listAll() is an async generator available on products, prices, payments, customers, subscriptions, and links (not on checkout or refunds).
Products (webhookUrl is the per-product callback override):
Prices (the returned price carries a permanent paymentUrl; deactivate takes it off sale):
Checkout sessions (do not accept `webhookUrl` — events resolve through the price → product → wallet chain; the URL is one-time and expires after 24 hours):
Payments (for server-side status checks; only mark a local order paid when amount, currency, metadata, and order state all match expectations):
Refunds (no list/listAll — use payments.listRefunds):
Customers:
Subscriptions (states include trialing / active / past_due / unpaid / canceled; update access only from verified webhooks or a trusted server-side reconciliation job):
Payment links (permanent reusable /p/ links, one-time collection only; webhookUrl is the per-link callback override):
Wallet and wallet-level webhook configuration (danger zone: affects the wallet shared by ALL of the user's projects):
Ordinary project routes must not call webhooks.set / remove / rollSecret or wallet.update — they mutate the wallet callback fallback and signing secret shared across all of the user's projects. Generate them only when the user explicitly asks for wallet administration and the route has project/admin-level authorization. Same for refunds, subscription mutations, payouts, KYC, and bank account APIs: generate only when the user explicitly requests that business flow and the code has validation, persistence, and authorization.
Webhook Integration
Callback URL: set it on the link/product, pointing at this Worker
Event delivery precedence: per-link `webhookUrl` > per-product `webhookUrl` > wallet-level fallback. The signing secret is always the wallet-level whsec_ (i.e. env.UNIWEB_WEBHOOK_SECRET).
PinMe sets a managed fallback callback URL on the wallet, but it exists only to obtain and preserve the signing secret — PinMe's server discards events it receives there (204); it never forwards them to the Worker. Business events must therefore set this project's webhookUrl explicitly on the resource that creates the payment:
- Payment links: pass
webhookUrlonlinks.create. - Checkout sessions:
checkout.createhas nowebhookUrlfield; events route through the price's product — setwebhookUrlonproducts.create(or on the reused product).
Rules for building the webhookUrl:
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 95 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/pinme-uniwebpay/SKILL.md
Popularity
- 7-day trend score
- 0
Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/glitternetwork/pinme/pinme-uniwebpay)