@gpmpay/sdk
Version:
Official Node.js SDK for GPM Pay — VietQR codes, transaction webhooks, and payment reconciliation.
61 lines (47 loc) • 2.04 kB
Markdown
# Next.js App Router
Server action to mint the payment code and build the QR, route handler to
receive the webhook, client component to display it.
## Files
```
app/
├── actions/payment.ts server action — mints the code, builds the QR
├── api/webhooks/gpmpay/route.ts webhook receiver
└── checkout/page.tsx the checkout page
```
Copy them into a Next.js 14+ project (App Router).
## Setup
```bash
npm install @gpmpay/sdk
```
```bash
# .env.local
GPMPAY_API_TOKEN=gpm_xxxxxxxx_yyyyyyyyyyyyyyyyyyyyyyyy
GPMPAY_BANK_ACCOUNT_ID=<uuid>
GPMPAY_WEBHOOK_SECRET=<from createHmacEndpoint>
```
> None of these carry a `NEXT_PUBLIC_` prefix — on purpose. Adding one would
> ship your API token to every visitor's browser.
Register the endpoint once (e.g. from a script or `node --eval`):
```ts
const { secret } = await client.webhookSettings.createHmacEndpoint({
url: 'https://your-app.vercel.app/api/webhooks/gpmpay',
});
// store `secret` as GPMPAY_WEBHOOK_SECRET
```
For local development, point it at an ngrok tunnel.
## What to copy
- **The webhook route needs no body-parser configuration.** In the App Router,
`await request.text()` already gives the exact raw bytes — that's what
`createNextWebhookHandler` uses.
- **The server action returns only display-safe fields.** The `GpmPay` client
never crosses into a client component.
- **A payment code derived from the cart id**, so a double-submitted form
produces the *same* code instead of a second pending payment. GPM Pay has no
order entity to deduplicate for you.
- **Matching with a regex over `payload.content`** — banks normalize the transfer
content, so an exact-string comparison will eventually miss.
- **The amount comparison in the webhook handler.** Nothing checks it for you.
- **Idempotency on `payload.id`** in the webhook handler.
- On Vercel, keep the webhook handler on the Node.js runtime
(`export const runtime = 'nodejs'`) — the SDK's signature verification uses
`node:crypto`.