UNPKG

@gpmpay/sdk

Version:

Official Node.js SDK for GPM Pay — VietQR codes, transaction webhooks, and payment reconciliation.

109 lines (106 loc) • 4.05 kB
import { B as BankAccount, a as Bank } from './bank-SVz37Xt1.cjs'; interface VietQrInput { /** NAPAS BIN of the beneficiary bank (`bank.bin`). */ bankBin: string; accountNumber: string; /** Omit for a static QR the payer fills in themselves. */ amount?: number | string; /** Truncated to 25 chars, matching the server. */ description?: string; serviceCode?: 'QRIBFTTA' | 'QRIBFTTC'; } interface VietQrImageInput extends VietQrInput { template?: 'compact' | 'compact2' | 'qr_only' | 'print'; accountName?: string; } /** * Build an EMVCo/VietQR payload string. * * @remarks * This is the main entry point when you handle reconciliation yourself — the * common case. Put your own order code in `description`; it becomes the * transfer content, and you match it against `event.payload.content` when the * webhook arrives. * * ```ts * const payload = buildVietQrPayload({ * bankBin: '970422', // account.bank.bin * accountNumber: '1234567890', * amount: 50_000, * description: 'DH123', // your own code — keep it <= 25 chars * }); * ``` * * Also fine for a static account QR: omit `amount` and the payer fills it in. * * `description` is what the payer ends up transferring, so it carries your * reconciliation code. VietQR truncates it to 25 characters and banks may * prepend their own prefix — keep the code short and at the front. For the * common case, {@link buildPaymentInstructions} wraps this up from a bank * account object. * * Byte-for-byte port of `apps/backend/src/modules/vietqr/vietqr.util.ts`. */ declare function buildVietQrPayload(input: VietQrInput): string; /** * Build an `img.vietqr.io` image URL. * * The server always emits the `compact` template; pass `template` to pick a * different one for your own checkout page. */ declare function buildVietQrImageUrl(input: VietQrImageInput): string; interface PaymentRequest { /** * The destination account, as returned by * `client.bankAccounts.retrieve(id)`. Must carry its `bank` relation — the * NAPAS BIN lives there. */ bankAccount: BankAccount & { bank?: Bank; }; /** VND. A number, or the string form the API returns for `Decimal`. */ amount: number | string; /** * The transfer content you will look for later. Put **your own** order * reference in here — GPM Pay mints nothing and matches nothing. Truncated * to 25 chars inside the QR, so keep the code short and near the front. */ transferContent: string; serviceCode?: 'QRIBFTTA' | 'QRIBFTTC'; template?: VietQrImageInput['template']; } interface PaymentInstructions { /** EMVCo payload. Render this as the QR. */ qrPayload: string; qrImageUrl: string; amount: number; /** What the payer MUST put in the transfer content. */ transferContent: string; bankName: string | undefined; bankBin: string | undefined; accountNumber: string; accountName: string; } /** * Everything a checkout page needs, built entirely client-side. * * @remarks * There is no server-side order to read this from — GPM Pay has no * order/QR-minting endpoint. You choose the reference code, you render the QR, * and you reconcile it yourself when the transaction webhook arrives by looking * for that code in `payload.content`. * * @throws {GpmPayConfigError} when `bankAccount.bank.bin` is missing — without * the BIN there is no valid VietQR payload to build. * * @example * const account = await client.bankAccounts.retrieve(bankAccountId); * const ref = `SHOP${orderId}`; * const instructions = buildPaymentInstructions({ * bankAccount: account, * amount: 250_000, * transferContent: ref, * }); */ declare function buildPaymentInstructions(request: PaymentRequest): PaymentInstructions; export { type PaymentInstructions as P, type VietQrImageInput as V, type PaymentRequest as a, type VietQrInput as b, buildPaymentInstructions as c, buildVietQrImageUrl as d, buildVietQrPayload as e };