@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, orfailed - 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-merchantQuick 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 publicScoped packages require --access public on first publish (also set in publishConfig). Bump version in package.json for each release.
License
MIT
