Node 예제 — 자체 호스팅 라이선스 서버 (BYOS)
핵심 요약
Node 22 예제는 자체 서버(BYOS)에서 라이선스를 검증하는 방법을 보여줍니다. 전체 결제 서비스를 구성하는 예제가 아닙니다.
개발용 저장소로 시작하고 잘못된 사용권·만료·재사용 요청이 거부되는지 확인하세요.
@yetdapay/license-server로 만드는 최소 강제 호스트 — Worker가 사용하는 것과 동일한 wire 계약을 자체 서비스 안에서 실행합니다. Node 22 필요.
js
import { createLicenseServer, createSqliteStore } from '@yetdapay/license-server';
import { createWorkerConfig } from '@yetdapay/license-server';
const server = createLicenseServer({
store: createSqliteStore({ file: './.data/license.db' }),
keys: { load: async () => JSON.parse(process.env.DEVPAY_LICENSE_KEYS) },
issuer: 'devpay', // 또는 iss='devpay-lic'를 위해 createWorkerConfig({store, keys})
entitlementTtlSec: 120,
});1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
두 종류의 라우트를 직접 노출하세요(패키지는 HTTP 서버가 아닌 라이브러리입니다):
js
// POST /api/license/activate — body {key, product_id, public_jwk}
const { entitlement, expires_in, features } = await server.activate(body);
// POST /api/premium/convert — 게이트된 유료 연산
const ctx = await server.authorize(headers, requestTarget, rawBody);
// ctx는 license + feature 컨텍스트를 가짐; 거부는 LicenseError를 throw1
2
3
4
5
6
2
3
4
5
6
프레임워크 헬퍼:
- h3/Nuxt →
@yetdapay/license-nuxt(defineLicenseEventHandler). - Express/Fastify/Workers/
node:http→@yetdapay/license-nuxt/core의createLicenseGuard— 4필드{headers, method, requestTarget, rawBody}디스크립터를 공급.
클라이언트 측은 @yetdapay/license-web과 페어링하세요(activatePath 기본값 /api/license/activate가 이미 이 자체 호스팅 형태를 타겟합니다 — 호스트가 Worker가 아니면 createWorkerConfig 불필요).
저장소 어댑터
테스트용 createMemoryStore(seed?) · 레퍼런스 영속 어댑터이자 D1/Postgres 포트의 템플릿인 createSqliteStore({file}) (node:sqlite은 Node 22에서 실험적 — 프로덕션 전에 포트하세요).