0.0.8 • Published 10 months ago

@kioskengine/sdk v0.0.8

Weekly downloads
-
License
Copyright © 2025 ...
Repository
-
Last release
10 months ago

KioskEngine SDK

A TypeScript SDK for interacting with KioskEngine Platform hardware devices. This SDK provides a simple and type-safe way to communicate with various hardware devices such as payment terminals, card dispensers and fiscal printers.

Features

  • 🔒 Type-safe API with full TypeScript support
  • 🎮 Easy device management and communication
  • 🔄 Automatic reconnection handling
  • 🏖 Sandbox mode for testing
  • 📝 Comprehensive logging system
  • 🎯 Event-driven architecture
  • ⚡ Promise-based async API

Currently supported hardware

  • Payment terminal
  • Fiscal printer
  • Thermal printer

Installation

npm install @kioskengine/sdk
# or
yarn add @kioskengine/sdk
# or
pnpm add @kioskengine/sdk

Quick Start

import {
  KioskEngineBuilder,
  DeviceType,
  SDKEventType,
  LogLevel,
  ProductItem,
} from "@kioskengine/sdk";

// Create SDK instance
const sdk = new KioskEngineBuilder()
  .withSandboxMode(process.env.NODE_ENV === "development")
  .withDevice(DeviceType.PAYMENT_TERMINAL)
  .build();

// Subscribe to events
sdk.on(SDKEventType.CONNECTED, (event) => {
  console.log("SDK Connected!", event);
});

// Initialize SDK
await sdk.initialize();

// Get payment terminal
const terminal = sdk.getPaymentTerminal();

// Get terminal status
const status = await terminal.getStatus();
console.log("Terminal status:", status);

// Define products for the transaction
const products: ProductItem[] = [
  {
    id: "SKU123",
    name: "Premium Coffee",
    quantity: 2,
    unit_price: 599, // $5.99 per unit
  },
  {
    id: "SKU456",
    name: "Croissant",
    quantity: 1,
    unit_price: 299, // $2.99 per unit
  },
];

// Initialize a transaction
// Total amount will be calculated automatically: (2 * $5.99) + (1 * $2.99) = $14.97
const result = await terminal.initializeTransaction(products);
console.log("Transaction result:", result);

Configuration

The SDK can be configured using the builder pattern:

const sdk = new KioskEngineBuilder()
  .withSandboxMode(true) // Enable sandbox mode for testing
  .withWebSocketUrl("ws://your-server:5000") // Custom WebSocket URL
  .withDevice(DeviceType.PAYMENT_TERMINAL) // Add payment terminal device
  .withTimeout(10000) // Set custom timeout (10 seconds)
  .build();

Processing Transactions

Product Structure

Each product in a transaction must include:

interface ProductItem {
  id: string; // Unique identifier of the product
  name: string; // Name of the product
  quantity: number; // Quantity being purchased
  unit_price: number; // Price per unit in cents (e.g., 599 for $5.99)
}

Transaction Example

// Get payment terminal instance
const terminal = sdk.getPaymentTerminal();

// Define products
const products: ProductItem[] = [
  {
    id: "COFFEE-001",
    name: "Espresso",
    quantity: 2,
    unit_price: 399, // $3.99 each
  },
  {
    id: "PASTRY-001",
    name: "Chocolate Muffin",
    quantity: 1,
    unit_price: 299, // $2.99 each
  },
];

try {
  // Initialize transaction
  // Total amount: (2 * $3.99) + (1 * $2.99) = $10.97
  const result = await terminal.initializeTransaction(products);

  if (result.auth_res === "approval") {
    console.log("Transaction approved!");
    console.log("Amount:", result.amount);
    console.log("Card type:", result.card_type);
    console.log("Authorization code:", result.card_payment_data.auth_code);
  } else {
    console.log("Transaction declined:", result.auth_res);
  }
} catch (error) {
  if (error instanceof TimeoutError) {
    console.error("Transaction timed out");
  } else {
    console.error("Transaction failed:", error);
  }
}

Testing Declined Transactions

In sandbox mode, you can test declined transactions by including [decline] in any product name. For example:

const products: ProductItem[] = [
  {
    id: "TEST-001",
    name: "Test Product [decline]", // This will trigger a declined transaction
    quantity: 1,
    unit_price: 1000,
  },
];

const result = await terminal.initializeTransaction(products);
// result.auth_res will be "refusal"
// result.card_payment_data.auth_response will be "ODMOWA"
// result.card_payment_data.auth_response_code will be "0005"

Transaction Events

Monitor transaction progress using events:

// Subscribe to transaction events
sdk.on(SDKEventType.TRANSACTION_STARTED, (event) => {
  console.log("Transaction started:", event.data);
  // event.data contains: { amount: number, products: ProductItem[] }
});

sdk.on(SDKEventType.TRANSACTION_COMPLETED, (event) => {
  console.log("Transaction completed:", event.data);
  // event.data contains the TransactionResponse
});

sdk.on(SDKEventType.TRANSACTION_ERROR, (event) => {
  console.error("Transaction failed:", event.data.error);
});

Transaction Response

The transaction response includes:

interface TransactionResponse {
  auth_res: "approval" | "refusal" | "unable_to_complete_transaction";
  amount: number;
  card_type: string;
  card_payment_data: {
    transaction_time: string;
    transaction_date: string;
    card_name: string;
    masked_card_number: string;
    auth_code: string;
    // ... additional payment details
  };
}

Working with Fiscal Printer

The SDK provides comprehensive support for fiscal printer operations. Here's how to use the fiscal printer:

Initializing the Fiscal Printer

import { KioskEngineBuilder, DeviceType } from "@kioskengine/sdk";

const sdk = new KioskEngineBuilder()
  .withSandboxMode(process.env.NODE_ENV === "development")
  .withDevice(DeviceType.FISCAL_PRINTER)
  .build();

await sdk.initialize();

// Get fiscal printer instance
const printer = sdk.getFiscalPrinter();

Checking Printer Status

const status = await printer.getStatus();
console.log("Printer status:", status);
// status contains:
// - command_queue: "empty" | "not_empty" | "unknown"
// - connection: "ok" | "error"
// - device: "ok" | "error_in_menu" | "error_waitin_for_key" | "error_waiting_for_user_reaction" | "unknown"
// - mechanism: "ok" | "error_lever_raised" | ... (various error states)
// - paper_sensor: "ok" | "no_paper" | "low_paper" | "not_ok"
// - connection_details: error details (when connection is "error")

Printing Fiscal Receipt

const products = [
  {
    name: "Coffee",
    number: 2,
    price: 5.99, // $5.99
    tax_code: 1, // Tax rate code
  },
  {
    name: "Croissant",
    number: 1,
    price: 2.99, // $2.99
    tax_code: 1,
  },
];

try {
  // Optional parameters
  const customerNip = "1234567890"; // Customer tax number
  const discount = "10"; // 10% discount
  const paymentMethod = "card"; // Payment method (cash, card, etc.)

  const result = await printer.printFiscalReceipt(
    products,
    customerNip,
    discount,
    paymentMethod
  );

  if (result.print_result === "ok") {
    console.log("Receipt printed successfully");
  } else {
    console.log("Print error:", result.print_result_details);
  }
} catch (error) {
  console.error("Failed to print receipt:", error);
}

Printing Card Payment Receipt

const cardPaymentData = {
  auth_res: "approval",
  transaction_nr: "1023",
  terminal_id: "82328135",
  merchandiser_id: "76328988",
  acceptor_id: "A0000000041010",
  auth_code: "471948",
  total_transaction_price: "535",
  card_name: "VISA",
  masked_card_number: "************1234",
  method_of_reading_card: "C", // C for chip, M for magnetic, E for contactless, etc.
  masked_card_expire_date: "**/**",
  transaction_date: "20240315", // Format: YYYYMMDD
  transaction_time: "143000", // Format: HHMMSS

  // Required fields
  auth_code_source: "1", // "1" for online authorization
  cardholder_authorization_method: "A", // Authorization method

  // EMV fields
  emv_transaction_cryptogram: "55E13384CCA22CFD",
  emv_application_identifier: "A0000000041010",
  terminal_printing_indicator: "0",

  // DCC (Dynamic Currency Conversion) fields
  transaction_currency_code: "EUR", // Set to EUR or USD for DCC mode
  terminal_currency: "PLN",
  transaction_amount_in_terminal_currency: "1000",
  currency_exchange_rate: "0.2400570",
  dcc_text1: "THIS CURRENCY CONVERSION SERVICE IS PROVIDED BY VISA",
  dcc_text2:
    "I HAVE BEEN OFFERED A CHOICE OF CURRENCIES AND HAVE CHOSEN TO PAY IN EUR",
};

const result = await printer.printCardPaymentReceipt(cardPaymentData);
console.log("Card payment receipt result:", result);

DCC (Dynamic Currency Conversion) Mode

The receipt will automatically be formatted as a DCC receipt when:

  • transaction_currency_code is EUR or USD (not PLN)
  • terminal_currency is set to PLN (local currency)

In DCC mode, the receipt will include:

  • Both original amount in PLN and converted amount in the foreign currency
  • Currency exchange rate information
  • Additional legal texts (provided in dcc_text1 and dcc_text2)
  • Special formatting based on the card brand (VISA vs MasterCard)

Standard Domestic Transaction (Non-DCC)

For standard domestic transactions:

  • Set transaction_currency_code to "PLN" or leave it empty
  • The receipt will be printed in standard Polish format with a single amount in PLN

Printing QR Code

// Print a QR code (simplified API)
const qrCode = "https://example.com/order/123";
const result = await printer.printQRCode(qrCode);
console.log("QR code print result:", result);

Printing Order Number

// Print an order number (must be exactly 3 digits)
const result = await printer.printOrderNumber("042"); // Valid: 3 digits

// Invalid examples (will throw an error):
// await printer.printOrderNumber("42");  // Error: less than 3 digits
// await printer.printOrderNumber("1234"); // Error: more than 3 digits
// await printer.printOrderNumber("abc"); // Error: non-numeric characters

console.log("Order number print result:", result);

The order number must:

  • Be exactly 3 numeric digits (000-999)
  • Be provided as a string
  • Contain only numeric characters

Daily Report

// Initialize and print daily report with optional ID
const reportId = 3; // Optional identifier for the report
const report = await printer.initDailyReport(reportId);

console.log("Daily report date:", report.report_date);
console.log("Print result:", report.print_result);
console.log("Completed:", report.completed); // Indicates if report generation completed successfully

Handling Print Events

// Subscribe to print events
sdk.on(SDKEventType.PRINT_STARTED, (event) => {
  console.log("Print operation started:", event.data);
});

sdk.on(SDKEventType.PRINT_COMPLETED, (event) => {
  console.log("Print operation completed:", event.data);
});

sdk.on(SDKEventType.PRINT_ERROR, (event) => {
  console.error("Print operation failed:", event.data.error);
});

Working with Thermal Printer

The SDK provides comprehensive support for thermal printer operations, allowing you to create receipts, labels, and other printed content.

Initializing the Thermal Printer

import { KioskEngineBuilder, DeviceType } from "@kioskengine/sdk";

const sdk = new KioskEngineBuilder()
  .withSandboxMode(process.env.NODE_ENV === "development")
  .withDevice(DeviceType.THERMAL_PRINTER)
  .build();

await sdk.initialize();

// Get thermal printer instance
const printer = sdk.getThermalPrinter();

Checking Printer Status

const status = await printer.getStatus();
console.log("Printer status:", status);
// status contains:
// - connection: "ok" | "error"
// - paper_level: "ok" | "low" | "empty"
// - error_status: "ok" | string
// - online: boolean
// - printer_type: string
// - last_check: string (timestamp)
// - connection_details: string (optional error details)

Basic Printing with Commands

The thermal printer uses a command-based API where you create an array of commands to execute:

// Create an array of print commands
const commands = [
  {
    command: "print_text",
    value: "Hello, World!",
    align: "center",
    bold: true,
    width_size: 2,
    height_size: 2,
  },
  {
    command: "feed_lines",
    value: 2,
  },
  {
    command: "print_qr",
    value: "https://example.com",
    size: 8,
  },
  {
    command: "feed_lines",
    value: 3,
  },
  {
    command: "cut_paper",
  },
];

// Send commands to the printer
const result = await printer.print(commands);
console.log("Print result:", result);

Using Command Generation Utilities

For convenience, the SDK provides utility methods to create properly formatted commands:

// Create commands using utility methods
const commands = [
  printer.createTextCommand("Hello, World!", {
    align: "center",
    bold: true,
    width_size: 2,
    height_size: 2,
  }),
  printer.createFeedLinesCommand(2),
  printer.createQRCommand("https://example.com", 8),
  printer.createFeedLinesCommand(3),
  printer.createCutPaperCommand(),
];

// Send commands to the printer
const result = await printer.print(commands);

Printing a Complete Receipt

The SDK includes a utility to generate a complete receipt with a single method call:

const receiptCommands = printer.generateReceiptCommands({
  title: "ACME Store",
  subtitle: "123 Main Street, Anytown",
  items: [
    { name: "Coffee", quantity: 2, price: 599 }, // $5.99 each
    { name: "Croissant", quantity: 1, price: 299 }, // $2.99 each
    { name: "Orange Juice", quantity: 1, price: 349 }, // $3.49 each
  ],
  total: 1846, // $18.46
  orderNumber: "A42",
  footer: "Thank you for shopping with us",
  qrCode: "https://example.com/receipt/42",
});

const result = await printer.print(receiptCommands);

Supported Commands

The thermal printer supports the following commands:

  1. Print Text

    printer.createTextCommand("Text to print", {
      align: "left" | "center" | "right", // default: "left"
      font: "a" | "b", // default: "a"
      bold: true | false, // default: false
      width_size: 1 - 8, // default: 1
      height_size: 1 - 8, // default: 1
    });
  2. Feed Lines

    printer.createFeedLinesCommand(numberOfLines); // default: 1
  3. Cut Paper

    printer.createCutPaperCommand(partial); // default: true
  4. Print QR Code

    printer.createQRCommand("data", size); // size default: 6
  5. Print Barcode

    printer.createBarcodeCommand("5901234123457", {
      height: 64, // default: 64
      width: 2 - 6, // default: 3
      position: "below" | "above" | "both" | "none", // default: "below"
      font: "a" | "b", // default: "a"
    });
  6. Print Image

    printer.createImageCommand("/path/to/image.png", highDensity); // highDensity default: true
  7. Print Logo

    printer.createLogoCommand(logoNumber); // default: 1
  8. Initialize Printer

    printer.createInitializeCommand();
  9. Set Print Mode

    printer.createPrintModeCommand({
      font_b: true | false, // default: false
      emphasized: true | false, // default: false
      width_size: 1 - 8, // default: 1
      height_size: 1 - 8, // default: 1
      underline: true | false, // default: false
    });
  10. Set Paper Width

    printer.createPaperWidthCommand(58 | 80); // 58mm or 80mm

Handling Print Events

// Subscribe to print events
sdk.on(SDKEventType.PRINT_STARTED, (event) => {
  console.log("Print operation started:", event.data);
});

sdk.on(SDKEventType.PRINT_COMPLETED, (event) => {
  console.log("Print operation completed:", event.data);
});

sdk.on(SDKEventType.PRINT_ERROR, (event) => {
  console.error("Print operation failed:", event.data.error);
});

Testing with Sandbox Mode

In sandbox mode, all print operations will be simulated. To simulate printing failures, include the string [fail] in any text command:

const failingCommand = printer.createTextCommand("Test failure [fail]");
const result = await printer.print([failingCommand]);
// result.success will be false
// result.errors will contain details about the simulated failure

Logging

The SDK provides different log levels that can be configured:

import { KioskEngine, LogLevel } from "@kioskengine/sdk";

KioskEngine.setLogLevel(LogLevel.DEBUG); // Set to DEBUG for development

Available log levels:

  • DEBUG: Detailed information for debugging
  • INFO: General information about operations
  • WARN: Warning messages for potential issues
  • ERROR: Error messages for operation failures

Event System

The SDK uses an event-driven system to notify about various states and operations:

sdk.on(SDKEventType.DEVICE_READY, (event) => {
  console.log("Device is ready:", event.deviceType);
});

sdk.on(SDKEventType.TRANSACTION_COMPLETED, (event) => {
  console.log("Transaction completed:", event.data);
});

Available events:

  • CONNECTED: SDK successfully connected
  • DISCONNECTED: SDK disconnected
  • DEVICE_READY: Device is initialized and ready
  • DEVICE_ERROR: Device encountered an error
  • TRANSACTION_STARTED: Payment transaction started
  • TRANSACTION_COMPLETED: Payment transaction completed
  • TRANSACTION_ERROR: Payment transaction failed

API Documentation

The SDK is written in TypeScript and provides full type definitions. No additional @types packages are required.

License

Copyright © 2024 KioskEngine. All rights reserved.

0.0.8

10 months ago

0.0.7

10 months ago

0.0.6

10 months ago

0.0.5

11 months ago

0.0.4

11 months ago

0.0.3

11 months ago

0.0.2

11 months ago

0.0.1

11 months ago