npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@pok-pay/server-sdk

v0.1.0

Published

POK Pay official Node.js/TypeScript server SDK

Downloads

112

Readme

@pok-pay/server-sdk

Official POK Pay Node.js/TypeScript server SDK — full integration kit with API client, webhook handler, NestJS module, and Prisma/TypeORM schemas.

Installation

npm install @pok-pay/server-sdk

Requires Node.js 18+.

Environment Variables

POKPAY_ENV=staging           # 'staging', 'production', or 'live' (alias for production)
POKPAY_KEY_ID=your_key_id
POKPAY_KEY_SECRET=your_key_secret
POKPAY_MERCHANT_ID=your_merchant_id_uuid

| Env | API URL | App URL | |---|---|---| | staging | https://api-staging.pokpay.io | https://app-staging.pokpay.io | | production | https://api.pokpay.io | https://app.pokpay.io | | live | https://api.pokpay.io | https://app.pokpay.io |

Quick Start — Express

import express from 'express';
import { PokPayClient, handlePokWebhook } from '@pok-pay/server-sdk';

const pokConfig = {
  env: process.env.POKPAY_ENV as 'staging' | 'production',
  keyId: process.env.POKPAY_KEY_ID!,
  keySecret: process.env.POKPAY_KEY_SECRET!,
  merchantId: process.env.POKPAY_MERCHANT_ID!,
};

const client = new PokPayClient(pokConfig);
const app = express();
app.use(express.json());

// 1. Create a payment order (requires your app's auth)
app.post('/payments/create-order', authMiddleware, async (req, res) => {
  const { amount, currencyCode, orderId } = req.body;
  const sdkOrderId = await client.createOrder({
    amount,
    currencyCode,
    webhookUrl: `${process.env.API_URL}/webhooks/pok?orderId=${orderId}`,
    redirectUrl: `${process.env.APP_URL}/payment/success`,
  });
  // Save sdkOrderId to your DB order record here
  res.json({ sdkOrderId });
});

// 2. Setup tokenized 3DS for saved cards (user MUST be authenticated)
app.post('/payments/setup-tokenized-3ds', authMiddleware, async (req, res) => {
  const { cardId, sdkOrderId } = req.body;
  const payerAuthentication = await client.setupTokenized3DS(cardId, sdkOrderId);
  res.json({ payerAuthentication });
});

// 3. Webhook handler (public — no auth)
// POK does not provide webhook signatures. This handler cross-verifies
// with the POK API before marking orders complete.
app.post('/webhooks/pok', async (req, res) => {
  const result = await handlePokWebhook(pokConfig, req.body, {
    async getOrder(orderId) {
      // Return your order from DB (must include pokOrderId and userId)
      return db.orders.findUnique({ where: { id: orderId } });
    },
    async markOrderCompleted(orderId) {
      await db.orders.update({ where: { id: orderId }, data: { status: 'COMPLETED' } });
    },
    async saveCardToken(userId, pokCardId) {
      // Upsert — do not throw, card saving must not break payment confirmation
      await db.savedCard.upsert({
        where: { userId_pokCardId: { userId, pokCardId } },
        create: { userId, pokCardId },
        update: {},
      });
    },
  });
  res.status(200).json(result); // Always return 200 to POK
});

Quick Start — NestJS

// app.module.ts
import { PokPayModule } from '@pok-pay/server-sdk/nestjs';

@Module({
  imports: [
    PokPayModule.forRoot({
      env: process.env.POKPAY_ENV as 'staging' | 'production',
      keyId: process.env.POKPAY_KEY_ID!,
      keySecret: process.env.POKPAY_KEY_SECRET!,
      merchantId: process.env.POKPAY_MERCHANT_ID!,
    }),
  ],
})
export class AppModule {}

// payment.controller.ts
import { PokPayService } from '@pok-pay/server-sdk/nestjs';

@Controller('payments')
export class PaymentController {
  constructor(private readonly pokPay: PokPayService) {}

  @Post('create-order')
  @UseGuards(JwtAuthGuard)
  async createOrder(@Body() body: CreateOrderDto) {
    const sdkOrderId = await this.pokPay.createOrder({
      amount: body.amount,
      currencyCode: body.currencyCode,
      webhookUrl: `${process.env.API_URL}/webhooks/pok?orderId=${body.orderId}`,
      redirectUrl: `${process.env.APP_URL}/payment/success`,
    });
    return { sdkOrderId };
  }

  @Post('setup-tokenized-3ds')
  @UseGuards(JwtAuthGuard)  // Must be authenticated
  async setup3DS(@Body() body: Setup3DSDto) {
    const payerAuthentication = await this.pokPay.setupTokenized3DS(
      body.cardId,
      body.sdkOrderId,
    );
    return { payerAuthentication };
  }
}

Database Schema

Prisma

Copy node_modules/@pok-pay/server-sdk/src/schema/saved-card.prisma into your schema.prisma.

TypeORM

Copy node_modules/@pok-pay/server-sdk/src/schema/saved-card.typeorm.ts into your entities directory and adjust the User relation import.

Payment Flow

1. Backend: createOrder() → sdkOrderId
2a. Card:   Frontend renders POK card form with sdkOrderId
2b. Wallet: Frontend displays QR code at {APP_URL}/sdk-orders/{sdkOrderId}
            (user scans with POK app)
2c. Saved card: Frontend calls POST /payments/setup-tokenized-3ds
                → payerAuthentication → frontend completes 3DS
3. User pays
4. POK → POST /webhooks/pok?orderId={your-internal-id}
5. handlePokWebhook() cross-verifies with POK API, marks order COMPLETED,
   saves card token (if applicable and user is logged in)

API Reference

new PokPayClient(config)

| Param | Type | Description | |---|---|---| | env | 'staging' \| 'production' \| 'live' | Resolves API URLs automatically ('live' is an alias for 'production') | | keyId | string | POK API key ID | | keySecret | string | POK API key secret | | merchantId | string | POK merchant UUID |

client.createOrder(params)Promise<string>

Returns sdkOrderId. Obtains a fresh access token on each call (tokens are short-lived).

client.getOrderStatus(sdkOrderId)Promise<{ isCompleted: boolean, status: string, canBeCaptured: boolean }>

Cross-verify order completion with POK's API. canBeCaptured is true only for orders created with autoCapture: false where payment has been frozen but not yet captured.

client.getCardDetails(cardId)Promise<PokCardDetails>

Always call once per card. POK does not guarantee response ordering for multi-card requests.

client.setupTokenized3DS(cardId, sdkOrderId)Promise<unknown>

Returns payerAuthentication blob. Pass it unmodified to the frontend setUpCardTokenPayment() call.

handlePokWebhook(config, body, deps)Promise<{ ok: boolean }>

Idempotent webhook handler. Cross-verifies with POK API before confirming. Card saving is best-effort (errors are swallowed).

client.captureOrder(sdkOrderId)Promise<Record<string, unknown>>

Capture a frozen payment. Only valid when canBeCaptured is true (orders created with autoCapture: false). Endpoint: POST /merchants/{merchantId}/sdk-orders/{sdkOrderId}/capture.

client.cancelOrder(sdkOrderId)Promise<Record<string, unknown>>

Release frozen funds without capturing. Use to cancel an autoCapture: false order. Endpoint: POST /merchants/{merchantId}/sdk-orders/{sdkOrderId}/cancel.

client.refundOrder(sdkOrderId, amount?)Promise<Record<string, unknown>>

Refund a captured order. Omit amount for a full refund; supply it for a partial refund. Only valid when isRefundable is true on the order. Endpoint: POST /merchants/{merchantId}/sdk-orders/{sdkOrderId}/refund.

handleCaptureOrder(config, input) / handleCancelOrder / handleRefundOrder

Framework-agnostic route handlers — same pattern as handleCreateOrder. Wire into Express/NestJS/etc. with your own auth middleware.

Security Notes

  • Never expose keyId, keySecret, or merchantId to the browser or mobile app
  • Access tokens are obtained server-side only and never returned to the client
  • POK does not provide webhook HMAC signatures; this SDK uses API cross-verification instead
  • The setup-tokenized-3ds endpoint must be protected by your authentication middleware
  • Card token saving (saveCardToken) must never throw — wrap your DB call in try/catch