Cross-runtime Webpay package scaffold for Node, Bun, and Deno.
npm install @bunhov_leom/webpayThis node/ directory is the npm package for WebPay client integration.
It ships a lightweight base client plus a server-side client for OAuth and
signed gateway requests.
- Package name: webpay
- Runtime target: Node.js (primary), with smoke coverage for Bun and Deno
- Output: ESM + CJS + type declarations
- Exports:
- webpay -> base client (src/index.ts)
- webpay/server -> server client (src/server.ts)
- Node.js >=18
- npm
``bash`
npm install
`bash`
npm run build
npm run typecheck
npm test
Extra runtime checks:
`bash`
npm run test:bun
npm run test:deno
Sandbox sign check (uses ../credenail.txt and ../sandbox-public.key by default):
`bash`
npm run test:sandbox-sign
Browser E2E:
`bash`
npx playwright install chromium
npm run test:e2e
- src/index.ts: Base WebPayClient (ping() smoke API)src/server.ts
- : WebPayServerClient for OAuth, signing, gateway callstest/
- : Vitest tests for signatures and server client behaviorbun/
- , deno/: Cross-runtime smoke testse2e/
- : Playwright browser smoke test and fixture pagescripts/e2e-server.mjs
- : Static server used by Playwright
- Required:
- WEBPAY_API_SECRET_KEYWEBPAY_CLIENT_ID
- Required for OAuth authentication:
- WEBPAY_CLIENT_SECRET
- WEBPAY_USERNAME
- WEBPAY_PASSWORD
- WEBPAY_BASE_URL
- Optional:
- (default: https://devwebpayment.kesspay.io)WEBPAY_SELLER_CODE
- WEBPAY_SIGN_TYPE
- (MD5 or HMAC-SHA256)WEBPAY_PUBLIC_KEY_FILE
- (path to sandbox-public.key or another RSA public key PEM file)WEBPAY_PUBLIC_KEY_PEM
- (raw RSA public key PEM text; takes priority over WEBPAY_PUBLIC_KEY_FILE)
Note: request signing (MD5 and HMAC-SHA256) uses api_secret_key.encryptToHex
The sandbox public key is for RSA encryption helpers (, encryptObjectToHex).POST /oauth/token
The server client authenticates via using grant_type: "password" and uses the returned access_token for gateway routes.401
On , it re-authenticates once and retries the gateway request.
`ts
import { createWebPayClient } from "webpay";
const client = createWebPayClient();
console.log(client.ping()); // webpay:ok
`
`ts
import { createWebPayServerClient } from "webpay/server";
const client = createWebPayServerClient();
const result = await client.queryOrder({ out_trade_no: "ORDER-1001" });
console.log(result);
`
`ts
import { createWebPayServerClient } from "webpay/server";
const client = createWebPayServerClient({
baseUrl: "https://devwebpayment.kesspay.io",
apiSecretKey: process.env.WEBPAY_API_SECRET_KEY!,
signType: "MD5",
publicKeyFile: process.env.WEBPAY_PUBLIC_KEY_FILE,
credentials: {
clientId: process.env.WEBPAY_CLIENT_ID!,
clientSecret: process.env.WEBPAY_CLIENT_SECRET!,
username: process.env.WEBPAY_USERNAME!,
password: process.env.WEBPAY_PASSWORD!
},
sellerCode: process.env.WEBPAY_SELLER_CODE
});
`
`ts
import { makeSignature, verifySignature } from "webpay/server";
const payload = {
service: "webpay.acquire.queryOrder",
sign_type: "MD5",
out_trade_no: "ORDER-1001"
};
const sign = makeSignature(payload, process.env.WEBPAY_API_SECRET_KEY!);
const valid = verifySignature({ ...payload, sign }, process.env.WEBPAY_API_SECRET_KEY!);
console.log(valid);
`
Use the documented card shape (number, securityCode, expiry.month, expiry.year) and encrypt it to hex.publicKeyFile
If your client is configured with /publicKeyPem (or WEBPAY_PUBLIC_KEY_FILE/WEBPAY_PUBLIC_KEY_PEM), use client.encryptDirectPayCard(...):
`ts
const card = client.encryptDirectPayCard(
{
number: "5473500160001018",
securityCode: "123",
expiry: {
month: "12",
year: "35"
}
}
);
await client.directPay({
out_trade_no: "TEST-1234567891",
body: "iPhone 13 pro Case",
total_amount: 10,
currency: "USD",
service_code: "VISA_MASTER",
card,
ip_address: "203.0.113.10"
});
`
You can also keep using encryptDirectPayCardToHex(cardPayload, publicKeyPem) directly when needed.
For nativePay, boolean flags (only_deeplink, is_ios_device) are normalized to 1/0 before signing and sending, matching WebPay signing behavior.
- WebPayHttpError: non-2xx HTTP responses (inspect error.status, error.response, error.details)WebPayApiError
- : gateway response with success: false (inspect error.response, error.details, error.code)
Example:
`ts
import { WebPayApiError, WebPayHttpError } from "webpay/server";
try {
await client.queryOrder({ out_trade_no: "ORDER-1001" });
} catch (error) {
if (error instanceof WebPayHttpError || error instanceof WebPayApiError) {
console.error(error.message);
console.error("response:", error.response);
}
}
`
Agent workflow for this package is documented in AGENT.md`.