paygenix-sdk
v0.0.2
Published
Thin JavaScript SDK for collecting card payments via Paygenix. Wraps VGS Collect.js — merchants mount secure card fields and receive a tokn_xxx token without raw card data ever touching their server.
Maintainers
Readme
paygenix-sdk
CDN: https://cdn.jsdelivr.net/npm/[email protected]/dist/paygenix-sdk.umd.js
Collect card payments without raw card data ever touching your server.
The SDK mounts secure hosted fields (powered by VGS) into your page and returns a tokn_xxx token you send to your backend.
Who should read what
| I want to… | Go to | |------------|-------| | Add Paygenix payments to my app | Merchant Integration | | Run the HTML demo locally | Running the Demo | | Contribute to this package | Development |
Merchant Integration
You only need: a publishable key and your checkout page.
No.envfile, no demo server, no local setup beyondnpm install.
Step 0 — Get your publishable key
Log in to the Paygenix dashboard and copy your key:
| Environment | Key format | Use for |
|-------------|------------|---------|
| Sandbox | pk_test_… | Development, QA, CI |
| Production | pk_live_… | Real payments |
Never commit keys to source control. Use environment variables (
process.env,import.meta.env, etc.)
Step 1 — Install
CDN (recommended — no bundler required):
<!-- Pin the version. Replace 0.0.2 with the latest version from npm. -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/paygenix-sdk.umd.js"></script>npm (optional, for bundler users):
npm install paygenix-sdkStep 2 — Add a mount point to your HTML
<!-- Any empty element works — the SDK injects hosted iframes here -->
<div id="card-form"></div>
<button id="pay">Pay now</button>Step 3 — Initialise and mount
// CDN: Paygenix is on window.Paygenix after the <script> tag loads.
// npm: import { Paygenix } from 'paygenix-sdk';
const pg = await Paygenix.init({ publishableKey: 'pk_test_xxx' });
pg.mountCardForm('#card-form');
// Three hosted fields (card number, expiry, CVV) now render inside #card-form.
// Raw card data is captured only inside VGS iframes — never in your JS.Step 4 — Tokenise on submit
const { token, error } = await pg.createToken({
cardholderName: 'Somchai Prasert', // from a name input in your UI
country: 'TH', // ISO 3166-1 alpha-2
});
if (error) {
// Always resolves — never throws
alert(error.message); // e.g. "Card number is invalid"
} else {
// Send token.id to YOUR backend — the only card identifier you ever handle
await fetch('/api/charge', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token: token.id }),
});
}The token contains:
token.id // 'tokn_xxx' — send this to your server
token.card.brand // 'visa'
token.card.last4 // '4242'
token.card.exp_month // 3
token.card.exp_year // 2029React example
import { Paygenix } from 'paygenix-sdk';
import type { PaygenixInstance } from 'paygenix-sdk';
const PUBLISHABLE_KEY = import.meta.env.VITE_PAYGENIX_PUBLISHABLE_KEY;
useEffect(() => {
Paygenix.init({ publishableKey: PUBLISHABLE_KEY }).then((pg) => {
pgRef.current = pg;
pg.mountCardForm('#card-form');
});
}, []);
// On form submit:
const { token, error } = await pgRef.current.createToken({
cardholderName: `${firstName} ${lastName}`.trim(),
country,
});See examples/react/CheckoutForm.tsx for the full component with loading state, error handling, and styling.
Plain HTML example (no bundler)
<div id="card-form"></div>
<button id="pay">Pay now</button>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/paygenix-sdk.umd.js"></script>
<script>
Paygenix.init({ publishableKey: 'pk_test_xxx' }).then(function (pg) {
pg.mountCardForm('#card-form');
document.getElementById('pay').addEventListener('click', async function () {
var result = await pg.createToken({
cardholderName: document.getElementById('name').value,
country: 'TH',
});
if (result.error) {
alert(result.error.message);
} else {
console.log('Token:', result.token.id); // send to your server
}
});
});
</script>Styling
The SDK injects this structure inside your mount node:
<div class="pg-card-fields">
<div class="pg-field-group"> <!-- card number row -->
<label>Card number</label>
<div class="vgs-input-wrap"> <!-- style border/background here -->
<div id="pg-card-number" class="vgs-mount"></div>
</div>
</div>
<div class="pg-row2"> <!-- expiry + CVV side by side -->
...
</div>
</div>Key CSS targets: .vgs-input-wrap (border, background), .pg-row2 (two-column grid), .pg-field-group label (field labels).
CORS — what you need to do
The SDK makes two requests from the customer's browser to the Paygenix API:
GET /v2/external/checkout-config (on init)
POST /v2/tokens (on createToken)Because these are cross-origin requests from the customer's browser, your checkout domain must be registered in Paygenix.
| Your page is on… | What to do |
|-----------------|-----------|
| https://checkout.yourstore.com | Register this origin in the Paygenix dashboard (or contact support) |
| http://localhost:* (local dev) | Register your localhost origin in the sandbox dashboard, or point apiBase at a same-origin proxy you control |
The demo server (
npm run demo) uses a built-in proxy so it does not need CORS registration — see Running the Demo.
API reference
Paygenix.version
Semver string baked into the build (e.g. 0.0.2). On Paygenix.init(), the SDK fetches the latest version from npm via jsDelivr and logs a one-time console.warn with an updated script URL if yours is behind — init is never blocked.
Paygenix.init(options)
| Option | Type | Required | Description |
|--------|------|:--------:|-------------|
| publishableKey | string | ✅ | pk_test_… or pk_live_… from the dashboard |
| apiBase | string | — | Override the API origin. Omit this in production — the correct URL is already in the package. |
Returns Promise<PaygenixInstance>. Throws PaygenixError on failure.
pg.mountCardForm(selector)
Injects three hosted fields (card number, expiry, CVV) into the element matched by selector. Idempotent — safe to call again on re-mount.
pg.createToken(options?)
| Option | Type | Description |
|--------|------|-------------|
| cardholderName | string | Full name on the card. Stored in the token record. |
| country | string | ISO 3166-1 alpha-2 (e.g. TH). Stored in the token record. |
Returns Promise<CreateTokenResult> — never throws:
{ token: { id: 'tokn_xxx', card: { brand, last4, exp_month, exp_year } } }
// or
{ error: { code, message } }Error codes
| Code | Meaning |
|------|---------|
| invalid_card | Card number / expiry / CVV failed VGS validation |
| submit_failed | Network error or Paygenix API rejected the request |
| config_fetch_failed | Could not reach Paygenix API (wrong key, CORS not set up, network) |
| vgs_load_failed | VGS Collect.js <script> failed to load |
| mount_failed | selector matched no element in the DOM |
| init_failed | publishableKey was empty or missing |
Security notes
- Raw PAN and CVV never enter your JavaScript — VGS hosted iframes own that data.
token.id(tokn_xxx) is the only card-related value your code handles.- Never log or persist
error.causein production — it may contain upstream API payloads. - Use
pk_test_…everywhere outside production. Never commit keys to source control.
Running the Demo
This section is for Paygenix team members and contributors who want to run
examples/html/index.htmlagainst a local gupay-api.
Merchants do not need any of this.
How the demo avoids CORS
The demo server proxies API calls server-side so the browser never talks cross-origin:
Browser → http://localhost:3002/v2/tokens (same origin — no CORS check)
↓ Node.js proxy
demo-server → http://localhost:3000/v2/tokens (server-to-server — CORS not applied)
↓
gupay-api respondsNo CORS registration is needed anywhere for the demo.
Prerequisites
| Requirement | Details |
|-------------|---------|
| Paygenix API | Dev default: https://dev-api.paygenix.co (or local gupay-api on :3000) |
| Publishable key | A pk_test_… key valid for the API environment you target |
| Built SDK | dist/paygenix-sdk.umd.js must exist (npm run build) |
Start the demo
# 1. Copy and edit env
cp .env.example .env
# Set GUPAY_API_BASE to the API you want the demo proxy to target:
# https://dev-api.paygenix.co ← dev (default in .env.example)
# https://uat-api.paygenix.co ← UAT
# http://localhost:3000 ← local gupay-api
# https://api.paygenix.co ← production (use real pk_live_ key, be careful)
# 2. Build the SDK
npm install && npm run build
# 3. Start gupay-api (if pointing at local), then:
npm run demoOpen http://localhost:3002/examples/html/index.html
| Port | Role |
|------|------|
| 3002 | Demo page + /v2/* reverse proxy |
| GUPAY_API_BASE | Actual API target (proxied server-side) |
Point the demo at production or sandbox
Just change .env and restart — no rebuild required for the proxy target:
# .env
GUPAY_API_BASE=https://dev-api.paygenix.co # dev
# GUPAY_API_BASE=https://uat-api.paygenix.co # UAT
# GUPAY_API_BASE=https://api.paygenix.co # production (real charges possible!)Update the PUBLISHABLE_KEY constant in examples/html/index.html to match the environment.
⚠️ Pointing at production with
pk_live_…uses your live VGS vault. Real card aliases will be created. Only do this for deliberate live-vault testing.
Releasing (maintainers)
Use this checklist when shipping a new version (CDN-first; npm is optional).
Prerequisites
| Tool | Version |
|------|---------|
| Node.js | ≥ 18 |
| npm | ≥ 9 |
| git | configured with access to github.com/paygenix/paygenix-sdk |
| npm account | only if you publish to the public registry |
1 — One-time git setup
cd paygenix-sdk # or your local clone path
# Initialise (skip if already a repo)
git init
git remote add origin https://github.com/paygenix/paygenix-sdk.git
# Never commit secrets
# .env is already in .gitignoreRename the GitHub repository to paygenix-sdk if it is still paygenix-cards-js (Settings → Repository name).
2 — Build and verify locally
npm install
cp .env.example .env # set GUPAY_API_BASE for the target API
npm run lint
npm test
npm run buildConfirm the UMD bundle exists and contains the right version:
ls -la dist/paygenix-sdk.umd.js
# Should embed version 0.0.1 in the built fileOptional smoke test:
npm run demo
# Open http://localhost:3002/examples/html/index.html3 — Commit the CDN artifact
Only dist/paygenix-sdk.umd.js (+ .map) are tracked for jsDelivr; other dist/ files are gitignored.
git add package.json package-lock.json src/ tests/ README.md
git add dist/paygenix-sdk.umd.js dist/paygenix-sdk.umd.js.map
git commit -m "build: release v0.0.2"4 — Tag v0.0.2 and push (optional GitHub mirror)
git tag v0.0.2
git push origin main
git push origin v0.0.2Primary CDN is npm via jsDelivr (no GitHub tag required):
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/paygenix-sdk.umd.js"></script>Optional: commit dist/paygenix-sdk.umd.js and use GitHub jsDelivr only if you maintain that mirror. After git push + tag, the GitHub CDN URL is live (may take a few minutes):
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/paygenix-sdk.umd.js"></script>Latest (always points at the newest tag):
<script src="https://cdn.jsdelivr.net/npm/paygenix-sdk@latest/dist/paygenix-sdk.umd.js"></script>Pin @0.0.2 in production; use @latest only for experiments.
5 — npm publish (optional)
CDN is the primary distribution. Publish to npm only if bundler users need npm install paygenix-sdk:
npm login
npm publish --access publicprepublishOnly runs lint, test, and build automatically.
6 — Version check (built into the SDK)
Merchants do not configure this. On every Paygenix.init():
- The bundled version is read from
Paygenix.version(e.g."0.0.1"). - The SDK fetches
https://cdn.jsdelivr.net/npm/paygenix-sdk/package.json(latest on npm). - If the published version is newer, a one-time
console.warnprints the upgrade script URL. Init is never blocked.
Verify after release:
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/paygenix-sdk.umd.js"></script>
<script>
Paygenix.init({ publishableKey: 'pk_test_xxx' }).then(() => {
console.log('Loaded SDK version:', Paygenix.version); // e.g. "0.0.2"
});
</script>Open DevTools → Console. If a newer tag exists on GitHub, you will see the upgrade warning.
7 — Ship a patch release (example 0.0.2)
# Bump version in package.json → "0.0.2"
npm run build
git add package.json package-lock.json dist/paygenix-sdk.umd.js dist/paygenix-sdk.umd.js.map
git commit -m "build: release v0.0.2"
git tag v0.0.2
git push origin main --tags
# optional: npm publishUpdate CDN examples in this README from @0.0.2 to the new tag.
Development (this package)
npm install
cp .env.example .env # GUPAY_API_BASE bakes into the bundle at build time
npm run build # ESM + CJS + UMD → dist/
npm test # vitest
npm run lint # tsc --noEmitGUPAY_API_BASE in .env is substituted at build time — change it and rebuild for the bundle default to update. See .env.example for all variables.
License
MIT
