Skip to content

Repository files navigation

@vignetim/pos

A comprehensive TypeScript/Node.js library for Turkish Virtual POS (Payment Gateway) integrations. Supports all major Turkish banks and payment institutions with unified API, 3D Secure authentication, and NestJS integration.

npm version License: MIT TypeScript

Table of Contents


Features

  • Unified API: Single interface for all banks and payment institutions
  • Type-Safe: Full TypeScript support with comprehensive type definitions
  • 3D Secure: Complete 3D Secure 1.0/2.0 payment flow support
  • Multi-Currency: Support for TRY, USD, EUR, GBP
  • Installment Support: Up to 36 months installment payments
  • Validation: Built-in request validation with detailed error messages
  • BIN Database: Credit card BIN lookup for card identification
  • NestJS Ready: First-class NestJS module support
  • ESM & CJS: Dual module format support
  • Test Cards: Built-in test card data for development

Installation

# Using npm
npm install @vignetim/pos

# Using yarn
yarn add @vignetim/pos

# Using pnpm
pnpm add @vignetim/pos

Requirements

  • Node.js >= 18.0.0
  • TypeScript >= 5.0 (for TypeScript users)

Quick Start

import { VPOSClient, BankCode, Currency, SaleRequest, VirtualPOSAuth } from '@vignetim/pos';

// 1. Configure authentication
const auth = new VirtualPOSAuth({
  bankCode: BankCode.GarantiBBVA,
  merchantId: '7000679',
  merchantUser: 'PROVAUT',
  merchantPassword: '123qweASD/',
  merchantStoreKey: '12345678',
  terminalId: '30691298',
  testPlatform: true, // Set to false for production
});

// 2. Create sale request
const request = new SaleRequest({
  orderNumber: 'ORDER-2024-001',
  customerIpAddress: '192.168.1.100',
  amount: 150.00,
  currency: Currency.TRY,
  installment: 1, // Single payment
  card: {
    holderName: 'John Doe',
    cardNumber: '4155650100416111',
    expiryMonth: 12,
    expiryYear: 2028,
    cvv: '123',
  },
});

// 3. Process payment
const response = await VPOSClient.sale(request, auth);

if (response.isSuccess()) {
  console.log('Payment successful!');
  console.log('Transaction ID:', response.transactionId);
  console.log('Auth Code:', response.authCode);
} else {
  console.error('Payment failed:', response.message);
  console.error('Error Code:', response.errorCode);
}

Bank Support Matrix

Traditional Banks

Bank Code Sale 3D Secure Cancel Refund Query Protocol
Garanti BBVA 0062 GVP (XML)
Yapi Kredi 0067 Posnet (XML)
Akbank (Direct) 0046 JSON API + HMAC-SHA512
Vakifbank 0015 VPos XML
Denizbank 0134 InterPOS
QNB Finansbank (Direct) 0111 Form POST

NestPay (EST) Banks

These banks use the NestPay/EST payment gateway:

Bank Bank Code Sale 3D Secure Cancel Refund Query
Is Bankasi 0064
Akbank 9046
QNB Finansbank 9111
Halkbank 0012
Ziraat Bankasi 0010
TEB 0032
Sekerbank 0059
Anadolubank 0135
Alternatif Bank 0124
ING Bank 0099
Turkiye Finans 0206
Cardplus 9998

Participation Banks (Katilim Bankalari)

Bank Code Sale 3D Secure Cancel Refund Query Protocol
Kuveyt Turk 0205 XML + SHA256
Albaraka Turk 0203 JSON

Payment Institutions

Institution Code Sale 3D Secure Cancel Refund Query Notes
Iyzico 9997 Marketplace support
Moka 9984 SHA256 CheckKey auth
PayTR 9994 iFrame integration
iPara 9995 JSON API
Hepsipay 9992 JSON API
Tosla (AKOde) 9970 JSON API
Lidio 9971 JSON API
PayU 9996 OAuth 2.0 REST
Paratika 9999 Payten MSU
Payten 9993 MSU API
ZiraatPay 9982 Payten-based
VakifPayS 9981 Payten-based
Sipay 9991 CCPayment
QNBpay 9990 CCPayment
PayBull 9988 CCPayment
Parolapara 9987 CCPayment
IQmoney 9986 CCPayment
Vepara 9983 CCPayment
ParamPos 9989 SOAP API
Tami 9980 JSON API
Ahlpay 9985 JSON API

Legend

  • ✅ Fully supported
  • ❌ Not supported / Not implemented
  • Bank Codes starting with 9xxx are virtual codes for payment institutions

API Reference

Authentication

All operations require a VirtualPOSAuth object:

import { VirtualPOSAuth, BankCode } from '@vignetim/pos';

const auth = new VirtualPOSAuth({
  // Required fields
  bankCode: BankCode.GarantiBBVA,    // Bank identifier
  merchantId: '7000679',              // Merchant ID from bank
  merchantUser: 'PROVAUT',            // API username
  merchantPassword: '123qweASD/',     // API password

  // Optional fields
  merchantStoreKey: '12345678',       // Required for 3D Secure
  terminalId: '30691298',             // Required by some banks
  testPlatform: true,                 // Use test environment
  options: {},                        // Bank-specific options
});

Sale Transaction

2D (Non-3D Secure) Payment

import { VPOSClient, SaleRequest, Currency } from '@vignetim/pos';

const request = new SaleRequest({
  orderNumber: 'ORDER-001',
  customerIpAddress: '192.168.1.100',
  amount: 100.00,
  currency: Currency.TRY,
  installment: 1,
  card: {
    holderName: 'John Doe',
    cardNumber: '4111111111111111',
    expiryMonth: 12,
    expiryYear: 2028,
    cvv: '123',
  },
  // Optional: Billing information
  billingInfo: {
    firstName: 'John',
    lastName: 'Doe',
    email: 'john@example.com',
    phone: '+905551234567',
    address: '123 Main Street',
    city: 'Istanbul',
    country: 'TR',
    postalCode: '34000',
  },
});

const response = await VPOSClient.sale(request, auth);

Installment Payment

const request = new SaleRequest({
  orderNumber: 'ORDER-002',
  customerIpAddress: '192.168.1.100',
  amount: 1200.00,
  currency: Currency.TRY,
  installment: 12, // 12-month installment
  card: {
    holderName: 'John Doe',
    cardNumber: '4111111111111111',
    expiryMonth: 12,
    expiryYear: 2028,
    cvv: '123',
  },
});

3D Secure Flow

3D Secure payments require a two-step process:

Step 1: Initiate 3D Payment

import { VPOSClient, SaleRequest, Payment3DConfig, SaleResponseStatus } from '@vignetim/pos';

const request = new SaleRequest({
  orderNumber: 'ORDER-3D-001',
  customerIpAddress: '192.168.1.100',
  amount: 250.00,
  currency: Currency.TRY,
  installment: 1,
  card: {
    holderName: 'John Doe',
    cardNumber: '4111111111111111',
    expiryMonth: 12,
    expiryYear: 2028,
    cvv: '123',
  },
  // Enable 3D Secure
  payment3D: new Payment3DConfig({
    enabled: true,
    returnUrl: 'https://yoursite.com/payment/callback',
    callbackUrl: 'https://yoursite.com/payment/notify', // Optional
  }),
});

const response = await VPOSClient.sale(request, auth);

// Handle 3D redirect
if (response.status === SaleResponseStatus.RedirectUrl) {
  // Redirect customer to the URL
  console.log('Redirect URL:', response.message);
  // res.redirect(response.message);
} else if (response.status === SaleResponseStatus.RedirectHtml) {
  // Render the HTML form that auto-submits
  console.log('HTML Form:', response.secure3D?.htmlContent);
  // res.send(response.secure3D.htmlContent);
}

Step 2: Handle 3D Callback

import { VPOSClient, Sale3DResponseRequest } from '@vignetim/pos';

// In your callback handler (Express example)
app.post('/payment/callback', async (req, res) => {
  const callbackRequest = new Sale3DResponseRequest({
    orderNumber: 'ORDER-3D-001',
    rawData: req.body, // POST data from bank
  });

  const response = await VPOSClient.sale3DResponse(callbackRequest, auth);

  if (response.isSuccess()) {
    // Payment completed successfully
    res.redirect('/payment/success');
  } else {
    // Payment failed
    res.redirect('/payment/failed?error=' + response.message);
  }
});

Cancel (Void)

Cancel a same-day transaction (before settlement):

import { VPOSClient, CancelRequest } from '@vignetim/pos';

const cancelRequest = new CancelRequest({
  orderNumber: 'ORDER-001',         // Original order number
  transactionId: 'TXN123456',       // Transaction ID from sale response
});

const response = await VPOSClient.cancel(cancelRequest, auth);

if (response.status === ResponseStatus.Success) {
  console.log('Transaction cancelled successfully');
}

Refund

Refund a transaction (full or partial):

import { VPOSClient, RefundRequest, Currency } from '@vignetim/pos';

// Full refund
const fullRefund = new RefundRequest({
  orderNumber: 'ORDER-001',
  transactionId: 'TXN123456',
  amount: 100.00,
  currency: Currency.TRY,
});

// Partial refund
const partialRefund = new RefundRequest({
  orderNumber: 'ORDER-001',
  transactionId: 'TXN123456',
  amount: 50.00, // Refund only 50 TRY
  currency: Currency.TRY,
});

const response = await VPOSClient.refund(fullRefund, auth);

if (response.status === ResponseStatus.Success) {
  console.log('Refunded amount:', response.refundedAmount);
}

Transaction Query

Query the status of a transaction:

import { VPOSClient, SaleQueryRequest } from '@vignetim/pos';

const queryRequest = new SaleQueryRequest({
  orderNumber: 'ORDER-001',
  // OR
  transactionId: 'TXN123456',
});

const response = await VPOSClient.saleQuery(queryRequest, auth);

console.log('Transaction Status:', response.transactionStatus);
console.log('Amount:', response.amount);
console.log('Date:', response.transactionDate);

Installment Query

Query available installment options:

import { VPOSClient, BINInstallmentQueryRequest } from '@vignetim/pos';

// Query by card BIN
const request = new BINInstallmentQueryRequest({
  bin: '411111',        // First 6 digits of card
  amount: 1000.00,
  currency: Currency.TRY,
});

const response = await VPOSClient.binInstallmentQuery(request, auth);

for (const option of response.installments) {
  console.log(`${option.count} months: ${option.monthlyAmount} TRY/month`);
}

Bank-Specific Configuration

Garanti BBVA

const auth = new VirtualPOSAuth({
  bankCode: BankCode.GarantiBBVA,
  merchantId: '7000679',           // Merchant ID (Uye Is Yeri No)
  merchantUser: 'PROVAUT',         // Provision Username
  merchantPassword: '123qweASD/',  // Provision Password
  merchantStoreKey: '12345678',    // 3D Secure Store Key
  terminalId: '30691298',          // Terminal ID
  testPlatform: true,
});

Yapi Kredi (Posnet)

const auth = new VirtualPOSAuth({
  bankCode: BankCode.YapiKrediBankasi,
  merchantId: '6706598320',        // Merchant ID
  merchantUser: '67005551',        // Terminal ID (used as user)
  merchantPassword: '',            // Not used for Posnet
  merchantStoreKey: '10,10,10,10,10,10,10,10', // Encryption Key
  terminalId: '67005551',
  testPlatform: true,
});

NestPay Banks (Akbank, Is Bankasi, etc.)

const auth = new VirtualPOSAuth({
  bankCode: BankCode.IsBankasi,    // Or any NestPay bank
  merchantId: '100100000',         // Client ID
  merchantUser: 'ISBANK',          // Username
  merchantPassword: 'ISBANK123',   // Password
  merchantStoreKey: 'TRPS1234',    // 3D Secure Store Key
  testPlatform: true,
});

Kuveyt Turk

const auth = new VirtualPOSAuth({
  bankCode: BankCode.KuveytTurk,
  merchantId: '496',               // Customer ID (Musteri No)
  merchantUser: '496',             // Merchant ID (Magaza Kodu)
  merchantPassword: 'apiuser',     // API Username
  merchantStoreKey: 'Api123',      // API Password
  testPlatform: true,
});

Albaraka Turk

const auth = new VirtualPOSAuth({
  bankCode: BankCode.AlbarakaTurk,
  merchantId: 'merchant123',       // Uye Isyeri No
  terminalId: 'terminal123',       // Terminal No
  merchantUser: 'username',        // API Username
  merchantPassword: 'password',    // API Password
  testPlatform: true,
});

Iyzico

const auth = new VirtualPOSAuth({
  bankCode: BankCode.Iyzico,
  merchantId: 'sandbox-xxxxx',     // API Key
  merchantUser: '',                // Not used
  merchantPassword: 'sandbox-secret-xxxxx', // Secret Key
  testPlatform: true,
});

PayTR

const auth = new VirtualPOSAuth({
  bankCode: BankCode.PayTR,
  merchantId: 'merchant_id',       // Merchant ID
  merchantUser: 'merchant_key',    // Merchant Key
  merchantPassword: 'merchant_salt', // Merchant Salt
  testPlatform: true,
});

iPara

const auth = new VirtualPOSAuth({
  bankCode: BankCode.IPara,
  merchantId: 'public_key',        // Public Key
  merchantUser: '',                // Not used
  merchantPassword: 'private_key', // Private Key
  testPlatform: true,
});

PayU

const auth = new VirtualPOSAuth({
  bankCode: BankCode.PayU,
  merchantId: 'pos_id',            // POS ID (merchant_pos_id)
  merchantUser: 'client_id',       // OAuth Client ID
  merchantPassword: 'client_secret', // OAuth Client Secret
  testPlatform: true,
});

CCPayment Banks (Sipay, QNBpay, PayBull, etc.)

const auth = new VirtualPOSAuth({
  bankCode: BankCode.Sipay,        // Or QNBpay, PayBull, Parolapara, IQmoney, Vepara
  merchantId: 'merchant_id',       // Uye Isyeri ID
  merchantUser: 'app_key',         // Uygulama Anahtari
  merchantPassword: 'app_secret',  // Uygulama Parolasi
  merchantStoreKey: 'merchant_key', // Uye Isyeri Anahtari
  testPlatform: true,
});

NestJS Integration

Module Setup

// app.module.ts
import { Module } from '@nestjs/common';
import { PosModule } from '@vignetim/pos/nestjs';

@Module({
  imports: [
    PosModule.forRoot({
      timeout: 30000,
      debug: process.env.NODE_ENV === 'development',
    }),
  ],
})
export class AppModule {}

Service Usage

// payment.service.ts
import { Injectable } from '@nestjs/common';
import { PosService } from '@vignetim/pos/nestjs';
import { SaleRequest, VirtualPOSAuth, Currency, BankCode } from '@vignetim/pos';

@Injectable()
export class PaymentService {
  constructor(private readonly posService: PosService) {}

  async processPayment(orderData: any) {
    const auth = new VirtualPOSAuth({
      bankCode: BankCode.GarantiBBVA,
      merchantId: process.env.POS_MERCHANT_ID,
      merchantUser: process.env.POS_USER,
      merchantPassword: process.env.POS_PASSWORD,
      merchantStoreKey: process.env.POS_STORE_KEY,
      terminalId: process.env.POS_TERMINAL_ID,
      testPlatform: process.env.NODE_ENV !== 'production',
    });

    const request = new SaleRequest({
      orderNumber: orderData.orderId,
      customerIpAddress: orderData.clientIp,
      amount: orderData.amount,
      currency: Currency.TRY,
      installment: orderData.installment || 1,
      card: orderData.card,
    });

    return this.posService.sale(request, auth);
  }
}

BIN (Card Number) Lookup

Identify card type and issuing bank from card number:

import { VPOSClient } from '@vignetim/pos';

// Query by card number
const result = VPOSClient.queryBIN('411111');

console.log('Bank:', result.bankName);
console.log('Card Brand:', result.cardBrand);    // Visa, Mastercard, etc.
console.log('Card Type:', result.cardType);      // Credit, Debit
console.log('Is Commercial:', result.isCommercial);

// Check card type
const isDebit = VPOSClient.isDebitCard('411111');
const isCommercial = VPOSClient.isCommercialCard('411111');

// Get issuing bank
const bankName = VPOSClient.getCardBank('411111');

Error Handling

Response Status Codes

import { SaleResponseStatus, ResponseStatus, SaleQueryResponseStatus } from '@vignetim/pos';

// Sale Response Statuses
SaleResponseStatus.Success       // Payment completed
SaleResponseStatus.Error         // Payment failed
SaleResponseStatus.RedirectUrl   // Redirect to 3D URL
SaleResponseStatus.RedirectHtml  // Render 3D HTML form

// General Response Statuses (Cancel, Refund)
ResponseStatus.Success           // Operation successful
ResponseStatus.Error             // Operation failed

// Query Response Statuses
SaleQueryResponseStatus.Success  // Transaction found
SaleQueryResponseStatus.Error    // Query failed
SaleQueryResponseStatus.NotFound // Transaction not found

Error Response

const response = await VPOSClient.sale(request, auth);

if (response.isError()) {
  console.error('Error Message:', response.message);
  console.error('Error Code:', response.errorCode);
  console.error('Raw Response:', response.rawResponse);
}

Common Error Codes

Bank Code Description
All 05 Transaction not approved
All 12 Invalid transaction
All 13 Invalid amount
All 14 Invalid card number
All 51 Insufficient funds
All 54 Expired card
All 57 Transaction not permitted
All 91 Issuer unavailable
Garanti 0054 Card expired
NestPay 99 General error
Vakifbank 0057 Card restricted

Test Cards

The library includes comprehensive test card data for development and testing.

Using Built-in Test Cards

import {
  NestPayTestCards,
  GarantiTestCards,
  IyzicoTestCards,
  TestCredentials,
  getTestCardsByBank,
  getRandomTestCard,
} from '@vignetim/pos';

// Get a specific bank's test cards
const garantiCards = GarantiTestCards;
const isbankCards = getTestCardsByBank('Is Bankasi');

// Get a random test card
const randomCard = getRandomTestCard();

// Use test credentials
const auth = new VirtualPOSAuth({
  bankCode: BankCode.GarantiBBVA,
  ...TestCredentials.GarantiBBVA,
  testPlatform: true,
});

Test Cards Reference

NestPay Banks (Is Bankasi, Akbank, Halkbank, Ziraat, etc.)

Bank Card Number Expiry CVV 3D Password
Is Bankasi 4508034508034509 12/26 000 a
Is Bankasi 5406675406675403 12/26 000 a
Akbank 4355084355084358 12/30 000 a
Akbank 5571135571135575 12/30 000 a
Ziraat 4546711234567894 12/26 000 a
Ziraat 5401341234567891 12/26 000 a
Halkbank 5818775818772285 12/26 001 a
Halkbank 4531444531442283 12/26 001 a

Garanti BBVA

Card Number Expiry CVV Type
5289394722895016 01/25 030 Mastercard
5406697543211173 04/27 423 Mastercard
5170410000000004 12/30 123 Debit
5400360000000003 12/30 123 Credit

Yapi Kredi

Card Number Expiry CVV 3D Password
4506347027911094 03/25 000 34020
5400619360964581 03/25 000 34020

QNB Finansbank

Card Number Expiry CVV Type
4022774022774026 12/26 000 Credit
4155650100416111 01/25 123 Credit
5311570000000005 12/30 123 Credit

Kuveyt Turk

Card Number Expiry CVV 3D Password
5188961939192544 06/25 929 123456

Iyzico (Sandbox)

For Iyzico sandbox, expiry and CVV can be any valid future date and 3-digit number.

Card Number Bank Type Notes
5890040000000016 Akbank Debit Success
5526080000000006 Akbank Credit Success
4766620000000001 Denizbank Debit Success
4603450000000000 Denizbank Credit Success
9792072000017956 Akbank Troy Success
374427000000003 Garanti Amex CVV: 1234

Iyzico Error Cards:

Card Number Error Type
4111111111111129 Insufficient funds
4129111111111111 Do not honor
4125111111111115 Expired card
4124111111111116 Invalid CVC

CCPayment (Sipay, QNBpay, PayBull, etc.)

Card Number Expiry CVV Notes
4022780520669303 01/50 988 Works with all CCPayment providers

Foreign/International Cards

Card Number Type Notes
5400010000000004 Credit Non-Turkish
4054180000000007 Debit Non-Turkish

Test Credentials

// Garanti BBVA
{
  merchantId: '7000679',
  merchantUser: '30691297',
  merchantPassword: '123qweASD/',
  merchantStoreKey: '12345678',
  terminalId: '30691298',
}

// Is Bankasi
{
  merchantId: '700655000200',
  merchantUser: 'ISBANKAPI',
  merchantPassword: 'ISBANK07',
  merchantStoreKey: 'TRPS0200',
}

// QNBpay
{
  merchantId: '20158',
  merchantUser: '07fb70f9d8de575f32baa6518e38c5d6',
  merchantPassword: '61d97b2cac247069495be4b16f8604db',
  merchantStoreKey: '$2y$10$N9IJkgazXMUwCzpn7NJrZePy3v.dIFOQUyW4yGfT3eWry6m.KxanK',
}

Migration from Other Libraries

From CP.VPOS (C#)

This library is a TypeScript port of CP.VPOS with an identical API structure:

CP.VPOS (C#) @vignetim/pos (TypeScript)
VirtualPOSFactory.CreateVirtualPOSService() VPOSClient.sale()
SaleRequest SaleRequest
SaleResponse SaleResponse
VirtualPOSAuth VirtualPOSAuth
BankCode.GarantiBBVA BankCode.GarantiBBVA

From nestpay-js

// Before (nestpay-js)
const nestpay = new NestPay({ clientId: '...', storeKey: '...' });
await nestpay.pay({ amount: 100, ... });

// After (@vignetim/pos)
const auth = new VirtualPOSAuth({ bankCode: BankCode.IsBankasi, merchantId: '...', ... });
const request = new SaleRequest({ amount: 100, ... });
await VPOSClient.sale(request, auth);

Project Structure

src/
├── enums/                    # Enumerations (BankCode, Currency, etc.)
├── models/                   # Data models (Request/Response classes)
├── interfaces/               # TypeScript interfaces
├── helpers/                  # Utility functions (HTTP, XML, Crypto)
├── services/                 # Core services (Bank, BIN)
├── data/                     # Test cards and credentials
├── integrations/
│   ├── banks/
│   │   ├── garanti/         # Garanti BBVA (GVP Protocol)
│   │   ├── yapikredi/       # Yapi Kredi (Posnet Protocol)
│   │   ├── akbank/          # Akbank Direct (JSON API)
│   │   ├── vakifbank/       # Vakifbank (XML VPos)
│   │   ├── denizbank/       # Denizbank (InterPOS)
│   │   ├── qnb-finansbank/  # QNB Finansbank Direct
│   │   ├── kuveytturk/      # Kuveyt Turk (XML + SHA256)
│   │   ├── albaraka/        # Albaraka Turk (JSON)
│   │   └── nestpay/         # NestPay banks (EST Protocol)
│   └── payment-institutions/
│       ├── iyzico/          # Iyzico
│       ├── moka/            # Moka
│       ├── paytr/           # PayTR
│       ├── ipara/           # iPara
│       ├── hepsipay/        # Hepsipay
│       ├── tosla/           # Tosla (AKOde)
│       ├── lidio/           # Lidio
│       ├── payu/            # PayU
│       ├── payten/          # Payten, Paratika, ZiraatPay, VakifPayS
│       ├── ccpayment/       # Sipay, QNBpay, PayBull, Parolapara, IQmoney, Vepara
│       ├── parampos/        # ParamPos
│       ├── tami/            # Tami
│       └── ahlpay/          # Ahlpay
├── nestjs/                   # NestJS module integration
├── vpos-client.ts           # Main client facade
└── index.ts                 # Public exports

Adding Custom Bank Integration

import { BaseVirtualPOSService, IVirtualPOSService, VPOSClient, VirtualPOSAuth, SaleRequest, SaleResponse } from '@vignetim/pos';

class CustomBankService extends BaseVirtualPOSService implements IVirtualPOSService {
  readonly bankCode = 'CUSTOM';
  readonly bankName = 'Custom Bank';

  protected getApiUrl(auth: VirtualPOSAuth): string {
    return auth.testPlatform ? 'https://test-api.bank.com' : 'https://api.bank.com';
  }

  protected get3DUrl(auth: VirtualPOSAuth): string {
    return this.getApiUrl(auth) + '/3d';
  }

  async sale(request: SaleRequest, auth: VirtualPOSAuth): Promise<SaleResponse> {
    // Implement bank-specific logic
    request.validateOrThrow();

    // Make API call...
    // Parse response...
    // Return SaleResponse
  }

  async sale3DResponse(request: Sale3DResponseRequest, auth: VirtualPOSAuth): Promise<SaleResponse> {
    // Handle 3D callback
  }

  async cancel(request: CancelRequest, auth: VirtualPOSAuth): Promise<CancelResponse> {
    // Implement cancel logic
  }

  async refund(request: RefundRequest, auth: VirtualPOSAuth): Promise<RefundResponse> {
    // Implement refund logic
  }

  async saleQuery(request: SaleQueryRequest, auth: VirtualPOSAuth): Promise<SaleQueryResponse> {
    // Implement query logic
  }
}

// Register the custom service
VPOSClient.registerService('CUSTOM', CustomBankService);

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Development Setup

# Clone the repository
git clone https://github.com/vignetim/pos.git
cd pos

# Install dependencies
npm install

# Run in development mode
npm run dev

# Run tests
npm test

# Build
npm run build

# Lint
npm run lint

# Format
npm run format

License

This project is licensed under the MIT License - see the LICENSE file for details.


Support


Made with by Vignetim

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages