@rekl0w/sanal-pos
v0.2.0
Published
Node.js, Bun ve TypeScript ile kullanılabilen Türkiye odaklı sanal POS orkestrasyon kütüphanesi
Maintainers
Readme
@rekl0w/sanal-pos
evrenonur/sanalpos yaklaşımını Node.js, Bun ve TypeScript dünyasına taşıyan, testli ve npm paketlemeye hazır bir sanal POS orkestrasyon katmanı.
Bu repo iki şekilde kullanılabilir:
- Kütüphane olarak:
SanalPosClientüzerinden satış, 3D dönüş, iptal, iade ve sorgu akışları - HTTP API olarak: Hono üstünden JSON endpoint'leri ile servisleşmiş kullanım
Not: Bu sürüm, referans projedeki gerçek banka / provider akışlarını TypeScript tarafına async olarak taşır. Node.js ve Bun ile kullanılabilir; dokümante edilmemiş katalog kayıtları için fallback davranış korunur, dokümante edilen gateway aileleri gerçek HTTP/XML/JSON transport ile çalışır.
Özellikler
- Hono + Node.js/Bun + TypeScript mimarisi
- Referans listedeki 48 banka / ödeme kuruluşu kataloğu
- Tek istemci sınıfı: async
SanalPosClient - 3D'siz satış ve 3D satış başlangıç akışları
- 3D callback / dönüş işleme akışı
- İptal ve iade işlemleri
- BIN ve taksit sorguları
- Banka listesi filtreleme
- Gerçek gateway contract testleri + opsiyonel canlı smoke testleri
- Zod tabanlı request doğrulama
- Vitest ile kapsamlı test seti
- Güvenlik taraması yapılmış bağımlılıklar
Gereksinimler
- Node.js >= 18.18.0 veya Bun >= 1.3.0
- TypeScript >= 6
- XML/JSON tabanlı banka gateway'leri için ağ erişimi
- Canlı smoke test için
.env.exampledosyasından türetilmiş bir.envve gerçek merchant bilgileri
Kurulum
Kütüphane olarak kurmak için:
npm install @rekl0w/sanal-posAlternatifleri:
pnpm add @rekl0w/sanal-pos
yarn add @rekl0w/sanal-pos
bun add @rekl0w/sanal-posRepo geliştirme kurulumu için:
npm installKullanılabilir sanal POS'lar
| Sanal POS | Satış | Satış 3D | İptal | İade | Durum | | --------------------- | :---: | :------: | :---: | :--: | ------------------ | | Akbank | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | Akbank Nestpay | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | Albaraka Türk | ✔️ | ✔️ | ✔️ | ✔️ | Fallback / katalog | | Alternatif Bank | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | Anadolubank | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | Denizbank | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | Fibabanka | ✔️ | ✔️ | ✔️ | ✔️ | Fallback / katalog | | QNB Finansbank | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | Finansbank Nestpay | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | Garanti BBVA | ✔️ | ✔️ | ❌ | ❌ | Gerçek gateway | | Halkbank | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | HSBC | ✔️ | ✔️ | ✔️ | ✔️ | Fallback / katalog | | ING Bank | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | İş Bankası | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | Odeabank | ✔️ | ✔️ | ✔️ | ✔️ | Fallback / katalog | | Türk Ekonomi Bankası | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | Türkiye Finans | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | Vakıfbank | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | Yapı Kredi Bankası | ✔️ | ✔️ | ❌ | ❌ | Gerçek gateway | | Şekerbank | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | Ziraat Bankası | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | Aktif Yatırım Bankası | ✔️ | ✔️ | ✔️ | ✔️ | Fallback / katalog | | Kuveyt Türk | ✔️ | ✔️ | ❌ | ❌ | Gerçek gateway | | Vakıf Katılım | ✔️ | ✔️ | ❌ | ❌ | Gerçek gateway | | Ziraat Katılım | ✔️ | ✔️ | ✔️ | ✔️ | Fallback / katalog | | Paynet | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | PayNKolay | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | HalkÖde | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | Tami | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | VakıfPayS | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | ZiraatPay | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | Vepara | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | Moka | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | Ahlpay | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | IQmoney | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | Parolapara | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | PayBull | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | ParamPos | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | QNBpay | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | Sipay | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | Hepsipay | ✔️ | ✔️ | ✔️ | ✔️ | Fallback / katalog | | Payten (MSU) | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | PayTR | ✔️ | ✔️ | ✔️ | ✔️ | Fallback / katalog | | IPara | ✔️ | ✔️ | ✔️ | ✔️ | Fallback / katalog | | PayU | ✔️ | ✔️ | ✔️ | ✔️ | Fallback / katalog | | Iyzico | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | Cardplus | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway | | Paratika | ✔️ | ✔️ | ✔️ | ✔️ | Gerçek gateway |
Fallback / katalogetiketi, bu repodaki katalog kaydınındocumented: falseolmasına veBankService.createGateway()çağrısında gerçek gateway yerineSandboxGatewayçözülmesine dayanır. Yani bu kayıtlar katalogda vardır; ancak bu pakette şu an gerçek binding yerine kontrollü fallback davranışı ile çalışır.
Çalıştırma
Geliştirme:
npm run devNormal çalıştırma:
npm run startVarsayılan port: 3000
Aynı scriptler hem
npm run ...hembun run ...ile çalışır. Örneğinnpm run startyerine doğrudanbun run startda kullanabilirsiniz.
Test ve doğrulama
Testler:
npm testTip kontrolü:
npm run typecheckToplu kontrol:
npm run checkPaket build:
npm run buildOpsiyonel canlı smoke test:
# .env.example dosyasını .env olarak kopyalayıp merchant bilgilerini doldurduktan sonra
npm run test:liveBağımlılık güvenlik taraması:
npm auditAPI bilgileri - MerchantAuth
bank_code(string): Banka / ödeme kuruluşu kodu.BankCodesveyaBankServicesabitleri kullanılabilir.merchant_id(string): Firma kodu / üye işyeri numarası / client code.merchant_user(string): API kullanıcı adı / terminal no / app id.merchant_password(string): API şifresi / terminal safe id / secret.merchant_storekey(string): 3D store key / merchant key / guid / secret key.test_platform(boolean):truetest ortamı,falsecanlı ortam.installment_commission_policy(InstallmentCommissionPolicy): CCPayment tabanlı kuruluşlarda taksit komisyon davranışını belirler.
CCPayment taksit komisyon politikası
InstallmentCommissionPolicy sabiti ile CCPayment ailesinde taksit komisyon davranışı kontrol edilebilir:
InstallmentCommissionPolicy.Default: gateway varsayılan davranışını kullanırInstallmentCommissionPolicy.ChargeToCustomer: komisyon müşteriye yansıtılırInstallmentCommissionPolicy.AbsorbByMerchant: komisyon satıcı üzerinde bırakılır
import {
BankCodes,
InstallmentCommissionPolicy,
SanalPosClient,
} from "@rekl0w/sanal-pos";
await SanalPosClient.sale(request, {
bank_code: BankCodes.QNBPAY,
merchant_id: "merchant-id",
merchant_user: "merchant-user",
merchant_password: "merchant-password",
merchant_storekey: "merchant-storekey",
test_platform: true,
installment_commission_policy: InstallmentCommissionPolicy.ChargeToCustomer,
});Banka bazlı credential alan eşlemesi
| Sanal POS | bank_code | merchant_id | merchant_user | merchant_password | merchant_storekey |
| ---------------- | ------------------------ | ------------------------ | -------------------- | ------------------------------------ | ------------------------ |
| Akbank | BankCodes.AKBANK | İş Yeri No | merchantSafeId | terminalSafeId | Secret Key |
| Nestpay ailesi | İlgili Nestpay kodu | Mağaza Kodu | API Kullanıcısı | API Şifresi | 3D Storekey |
| Garanti BBVA | BankCodes.GARANTI_BBVA | Firma Kodu | Terminal No | PROVAUT Şifresi | 3D Anahtarı |
| Vakıfbank | BankCodes.VAKIFBANK | Üye İşyeri No | POS No | API Şifresi | — |
| Yapı Kredi | BankCodes.YAPI_KREDI | Firma Kodu | Terminal No | PosNet ID | ENCKEY |
| CCPayment ailesi | İlgili CCPayment kodu | Üye İşyeri ID | Uygulama Anahtarı | Uygulama Parolası | Merchant Key |
| Paynet | BankCodes.PAYNET | Paynet Merchant ID | Basic Auth kullanıcı | Basic Auth şifresi | — |
| ParamPos | BankCodes.PARAMPOS | Client Code | Kullanıcı Adı | Şifre | Guid Anahtar |
| Moka | BankCodes.MOKA | Bayi Kodu | API Kullanıcısı | API Şifresi | — |
| Ahlpay | BankCodes.AHLPAY | Member ID | API Kullanıcısı | API Şifresi | API Key |
| Payten ailesi | İlgili Payten kodu | Firma Kodu | API Kullanıcısı | API Şifresi | Dealer Type / ek anahtar |
| Tami | BankCodes.TAMI | Üye İşyeri No | Terminal No | KidValue / KValue (pipe-separated) | Secret Key |
| PayNKolay | BankCodes.PAYNKOLAY | sx token / merchant id | sx list | sx iptal | Secret Key |
| Iyzico | BankCodes.IYZICO | Üye İşyeri No | API Anahtarı | Güvenlik Anahtarı | — |
HTTP API
Sağlık kontrolü
GET /health
Banka listesi
GET /api/banks
İsteğe bağlı filtreler:
collective_vpos=true|falseinstallment_api=true|falsesupports_refund=true|false
Tek banka detayı
GET /api/banks/:bankCode
Satış
POST /api/sale
Örnek payload:
{
"auth": {
"bank_code": "9990",
"merchant_id": "20158",
"merchant_user": "07fb70f9d8de575f32baa6518e38c5d6",
"merchant_password": "61d97b2cac247069495be4b16f8604db",
"merchant_storekey": "$2y$10$N9IJkgazXMUwCzpn7NJrZePy3v.dIFOQUyW4yGfT3eWry6m.KxanK",
"test_platform": true
},
"request": {
"order_number": "ORDER-001",
"customer_ip_address": "1.1.1.1",
"sale_info": {
"card_name_surname": "test kart",
"card_number": "4022780520669303",
"card_expiry_month": 1,
"card_expiry_year": 2050,
"card_cvv": "988",
"amount": 10,
"currency": 949,
"installment": 1
},
"payment_3d": {
"confirm": false
},
"invoice_info": {
"name": "cem",
"surname": "pehlivan"
},
"shipping_info": {
"name": "cem",
"surname": "pehlivan"
}
}
}3D dönüş işleme
POST /api/sale/3d-response
İptal
POST /api/cancel
İade
POST /api/refund
BIN sorgusu
POST /api/query/bin
Satış sorgusu
POST /api/query/sale
Taksit sorguları
POST /api/query/installments/allPOST /api/query/installments/additional
Kütüphane kullanımı
import { BankCodes, CurrencyMap, SanalPosClient } from "@rekl0w/sanal-pos";
const response = await SanalPosClient.sale(
{
order_number: "ORDER-001",
customer_ip_address: "1.1.1.1",
sale_info: {
card_name_surname: "test kart",
card_number: "4022780520669303",
card_expiry_month: 1,
card_expiry_year: 2050,
card_cvv: "988",
amount: 10,
currency: CurrencyMap.TRY,
installment: 1,
},
payment_3d: { confirm: false },
invoice_info: { name: "cem", surname: "pehlivan" },
shipping_info: { name: "cem", surname: "pehlivan" },
},
{
bank_code: BankCodes.QNBPAY,
merchant_id: "20158",
merchant_user: "07fb70f9d8de575f32baa6518e38c5d6",
merchant_password: "61d97b2cac247069495be4b16f8604db",
merchant_storekey:
"$2y$10$N9IJkgazXMUwCzpn7NJrZePy3v.dIFOQUyW4yGfT3eWry6m.KxanK",
test_platform: true,
},
);
console.log(response.status, response.transaction_id);Desteklenen işlem yüzeyi
salesale3DResponsecancelrefundbinInstallmentQueryallInstallmentQueryadditionalInstallmentQuerysaleQueryallBankList
Mimari
src/
├── app.ts # Hono uygulaması
├── client/
│ └── sanalpos-client.ts # Tek giriş istemcisi
├── domain/
│ ├── banks.ts # Banka / provider kataloğu
│ ├── enums.ts # Enum sabitleri
│ ├── schemas.ts # Zod şemaları
│ └── types.ts # Domain tipleri
├── gateways/
│ ├── abstract-gateway.ts # Ortak gateway soyutlaması
│ ├── bank-gateways.ts # Gerçek banka gateway implementasyonları
│ ├── provider-gateways.ts # Gerçek provider gateway implementasyonları
│ ├── sandbox-gateway.ts # Deterministic sandbox davranışı
│ └── types.ts # Gateway interface'i
├── infra/
│ ├── http-client.ts # HTTP taşıma katmanı
│ ├── payment-utils.ts # Hash/format yardımcıları
│ ├── xml.ts # XML parse/build yardımcıları
│ └── iyzico-pki.ts # Iyzico PKI/JWT yardımcıları
├── config/
│ └── gateway-config.ts # Endpoint ve familya konfigurasyonları
└── services/
├── bank-service.ts # Banka servis katmanı
├── bin-service.ts # BIN / taksit mantığı
├── sanitizer-service.ts # Veri sanitizasyonu
└── validation-service.ts # İş kuralı validasyonlarıGüvenlik notu
axioskullanılmadınpm auditvebun auditile temiz doğrulama alınabilir- Kart ve müşteri alanları sanitize edilir
- Doğrulama hataları kontrollü JSON response olarak döner
Hata yönetimi
Gerçek HTTP isteklerinde bağlantı, timeout veya upstream hata durumları HttpRequestError olarak yükseltilir. İş kuralı / input problemleri ise ValidationError üzerinden döner.
import {
HttpRequestError,
SanalPosClient,
ValidationError,
} from "@rekl0w/sanal-pos";
try {
const response = await SanalPosClient.sale(request, auth);
console.log(response.status);
} catch (error) {
if (error instanceof HttpRequestError) {
console.error(error.url, error.statusCode, error.responseBody);
}
if (error instanceof ValidationError) {
console.error(error.issues);
}
}Canlı entegrasyon notu
SanalPosClientmetotları async çalışır- Dokümante edilen bankalar/providerlar
BankService.createGatewayiçinde gerçek gateway sınıflarına bağlanır - Dokümante edilmemiş katalog kayıtları kontrollü fallback ile çalışmaya devam eder
- Paketle birlikte
.env.examplegelir; bunu.envolarak kopyalayıp gerçek smoke testleri buradan yönetebilirsiniz
Referans
- Bu proje,
evrenonur/sanalposrepo akışlarını TypeScript/Bun tarafına taşır. - Referans PHP paketinin kendisi de
cempehlivan/CP.VPOSmimarisi üzerine kuruludur.
