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

@graphland/pgw-merchant

v1.1.1

Published

Merchant/client SDK for Graphland Payment Gateway — create invoices, check status, and verify webhooks

Downloads

415

Readme

@graphland/pgw-merchant

A lightweight, zero-dependency SDK for merchants integrating with the Graphland Payment Gateway.

Features

  • Create invoices — initiate payment requests with idempotency support
  • Get invoices — retrieve full invoice details
  • Check invoice status — quickly see if an invoice is pending, paid, or failed
  • Verify webhooks — cryptographically verify incoming webhook payloads using HMAC-SHA256

Installation

npm install @graphland/pgw-merchant
# or
yarn add @graphland/pgw-merchant
# or
pnpm add @graphland/pgw-merchant
# or
bun add @graphland/pgw-merchant

Quick Start

import { GraphlandPGWClient, verifyWebhookSignature, parseWebhookEvent } from '@graphland/pgw-merchant';
import type { WebhookEvent } from '@graphland/pgw-merchant';

// ── Initialise the client ──────────────────────────────────────
const pgw = new GraphlandPGWClient({
  apiKey: 'graphland_....',   // from the Graphland Console
  clientId: 'my-store',       // your client slug (lowercased)
});

// ── 1. Create an invoice ───────────────────────────────────────
const invoice = await pgw.createInvoice({
  identifier: 'order-123',    // your unique payment reference (idempotency)
  amount: 1000,               // 1000 = 10.00 in your currency
  currency: 'BDT',
  description: 'Order #123',
  customer: {
    name: 'John Doe',
    email: '[email protected]',
    phone: '+8801700000000',
  },
  successUrl: 'https://myshop.com/order/success',
  cancelUrl:  'https://myshop.com/order/cancel',
  failUrl:    'https://myshop.com/order/fail',
  metadata: {
    orderId: 'order-123',
  },
});

console.log(invoice.paymentUrl); // → hosted checkout URL

// ── 2. Check invoice status ────────────────────────────────────
const status = await pgw.getInvoiceStatus(invoice.invoiceUID);
console.log(status.status); // "pending" | "paid" | "failed"

// ── 3. Get full invoice details ────────────────────────────────
const full = await pgw.getInvoice(invoice.invoiceUID);
console.log(full.invoice.amount, full.client.displayName);

Webhook Verification

Graphland signs every webhook POST with your webhook signing secret (get it from the Console or when you create your client). Always verify the signature before acting on the event.

import { verifyWebhookSignature, parseWebhookEvent } from '@graphland/pgw-merchant';
import type { WebhookEvent } from '@graphland/pgw-merchant';

// Example using Express / Hono / Node http
app.post('/webhooks/graphland', (req, res) => {
  const rawBody = req.rawBody; // must be the exact raw body bytes as a string
  const secret = 'your-webhook-signing-secret';

  // 1. Verify HMAC-SHA256 signature (timestamp + raw body)
  if (!verifyWebhookSignature(rawBody, {
    signature: req.headers['x-graphland-signature'],
    timestamp: req.headers['x-graphland-timestamp'],
  }, secret)) {
    return res.status(401).send('Invalid signature');
  }

  // 2. Parse the event payload
  const event: WebhookEvent = parseWebhookEvent(JSON.parse(rawBody));

  // 3. Handle the event
  switch (event.type) {
    case 'payment.paid':
      console.log('Payment received:', event.data);
      break;
    case 'payment.failed':
      console.log('Payment failed:', event.data);
      break;
    default:
      console.log('Unhandled event type:', event.type);
  }

  res.status(200).send('OK');
});

API Reference

GraphlandPGWClient

| Method | Description | |---|---| | createInvoice(input) | Create or upsert an invoice. If identifier matches an existing PENDING invoice, the invoice is updated (idempotent). | | getInvoice(invoiceUID) | Retrieve full invoice details including merchant display info. | | getInvoiceStatus(invoiceUID) | Get the current status (pending, paid, failed) and redirect URLs. |

verifyWebhookSignature(rawBody, headers, secret)

Returns true if the HMAC-SHA256 signature matches HMAC(secret, "{timestamp}.{rawBody}").

parseWebhookEvent(body)

Validates and parses an incoming webhook JSON body into a typed WebhookEvent object.

Error Handling

The SDK throws typed errors that include the HTTP status code:

import { ApiError, ConflictApiError } from '@graphland/pgw-merchant';

try {
  await pgw.createInvoice({ ... });
} catch (err) {
  if (err instanceof ConflictApiError) {
    console.error('Invoice already paid:', err.message);
  } else if (err instanceof ApiError) {
    console.error(`API error ${err.statusCode}:`, err.body);
  } else {
    console.error('Network error:', err);
  }
}

Configuration

| Option | Default | Description | |---|---|---| | apiKey | — | Your Graphland integration API key (required) | | clientId | — | Your lowercased client slug (required) | | baseUrl | https://pgw.graphland.dev | Override the API base URL for testing | | timeout | 15_000 | Request timeout in milliseconds |

Publishing (maintainers)

From packages/merchant-sdk:

npm run build
npm pack --dry-run   # inspect tarball contents
npm login            # npmjs.com account in @graphland org
npm publish --access public

Scoped packages require --access public on first publish (also set in publishConfig). Bump version in package.json for each release.

License

MIT