UNPKG

smart-upiqr

Version:

Easily generate branded UPI QR codes and payment links with customizable options for JavaScript and Node.js.

194 lines (193 loc) 8.01 kB
"use strict"; // index.ts var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.UPILink = UPILink; exports.UPIQR = UPIQR; // --- Imports --- // qrcode is always required const QRCode = __importStar(require("qrcode")); // Lazy import for canvas (only used in Node.js) let nodeCanvas; function getNodeCanvas() { if (!nodeCanvas) { nodeCanvas = require("canvas"); } return nodeCanvas; } // --- Utilities --- const formatDateIsoWithOffset = (date) => { const pad = (n) => n.toString().padStart(2, "0"); const tzOffset = -date.getTimezoneOffset(); const sign = tzOffset >= 0 ? "+" : "-"; const tzHours = pad(Math.floor(Math.abs(tzOffset) / 60)); const tzMinutes = pad(Math.abs(tzOffset) % 60); return (date.getFullYear() + "-" + pad(date.getMonth() + 1) + "-" + pad(date.getDate()) + "T" + pad(date.getHours()) + ":" + pad(date.getMinutes()) + ":" + pad(date.getSeconds()) + sign + tzHours + ":" + tzMinutes); }; // --- UPI Link Generator --- function UPILink(options) { const { PayeeUPI, PayeeName, Amount, TransactionNote, MerchantCode, TransactionRef, TransactionId, invoiceNo, invoiceDate, QrExpireDays, QrTimestamp, GSTno, } = options; if (!PayeeUPI || !PayeeName || !Amount) { throw new Error(`"PayeeUPI", "PayeeName", "Amount > 0" is required. Received --> PayeeUPI: ${PayeeUPI} | PayeeName: ${PayeeName} | Amount: ${Amount}`); } if (isNaN(Amount) || Amount <= 0) { throw new Error(`"Amount" must be number > 0. Received: ${Amount}`); } if (QrExpireDays && (isNaN(QrExpireDays) || QrExpireDays <= 0)) { throw new Error(`"QrExpireDays" must be number > 0 for Future expiry. Received: ${QrExpireDays}`); } const now = new Date(); let upi = `upi://pay?pa=${PayeeUPI}&pn=${PayeeName}&am=${Amount}&cu=INR`; if (TransactionNote) upi += `&tn=${TransactionNote}`; if (MerchantCode) upi += `&mc=${MerchantCode}`; if (TransactionRef) upi += `&tr=${TransactionRef}`; if (TransactionId) upi += `&tid=${TransactionId}`; if (invoiceNo) upi += `&invoiceNo=${invoiceNo}`; if (invoiceDate) upi += `&invoiceDate=${formatDateIsoWithOffset(now)}`; if (QrTimestamp) upi += `&QRts=${formatDateIsoWithOffset(now)}`; if (QrExpireDays) { const expireDate = new Date(now.getTime() + QrExpireDays * 86400000); upi += `&QRexpire=${formatDateIsoWithOffset(expireDate)}`; } if (GSTno) upi += `&gstIn=${GSTno}`; return upi; } // --- Browser/Node detection --- function isBrowser() { return typeof window !== "undefined" && typeof document !== "undefined"; } // --- UPI QR Generator --- function UPIQR(options) { return __awaiter(this, void 0, void 0, function* () { var _a, _b, _c, _d; const link = UPILink(options); if (!link) return null; // Browser path if (isBrowser()) { const qrDataUrl = yield QRCode.toDataURL(link, { type: "image/png", color: { dark: ((_a = options.color) === null || _a === void 0 ? void 0 : _a.dark) || "#000000", light: ((_b = options.color) === null || _b === void 0 ? void 0 : _b.light) || "#ffffff", }, margin: 2, scale: 8, }); if (options.logo) { return new Promise((resolve, reject) => { const qrImg = new Image(); qrImg.crossOrigin = "anonymous"; qrImg.src = qrDataUrl; qrImg.onload = () => { const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d"); canvas.width = qrImg.width; canvas.height = qrImg.height; ctx.drawImage(qrImg, 0, 0); const logo = new Image(); logo.crossOrigin = "anonymous"; logo.src = options.logo; logo.onload = () => { const logoSize = options.logoSize || qrImg.width / 6; const x = (canvas.width - logoSize) / 2; const y = (canvas.height - logoSize) / 2; ctx.drawImage(logo, x, y, logoSize, logoSize); resolve(canvas.toDataURL("image/png")); }; logo.onerror = reject; }; qrImg.onerror = reject; }); } return qrDataUrl; } // Node.js path const { createCanvas, loadImage } = getNodeCanvas(); const qrBuffer = yield QRCode.toBuffer(link, { type: "png", color: { dark: ((_c = options.color) === null || _c === void 0 ? void 0 : _c.dark) || "#000000", light: ((_d = options.color) === null || _d === void 0 ? void 0 : _d.light) || "#ffffff", }, margin: 2, scale: 8, }); if (options.logo) { const qrImg = yield loadImage(qrBuffer); const canvas = createCanvas(qrImg.width, qrImg.height); const ctx = canvas.getContext("2d"); ctx.drawImage(qrImg, 0, 0); const logo = yield loadImage(options.logo); const logoSize = options.logoSize || qrImg.width / 6; const x = (canvas.width - logoSize) / 2; const y = (canvas.height - logoSize) / 2; ctx.drawImage(logo, x, y, logoSize, logoSize); return canvas.toDataURL("image/png"); } return `data:image/png;base64,${qrBuffer.toString("base64")}`; }); }