API · webhook · mobil
Geliştirici ve API
Zarfora; web, mobil ve sunucunun aynı iş kurallarını paylaştığı bir monorepo olarak geliştirildi. Aşağıdaki sözleşme kurulumda kurumunuzun altyapısında uygulanır; bu demoda sunucu yoktur, işlemler tarayıcıdaki demo adaptörüyle çalışır.
Mimari
Adaptör değişimi tek satırdır: demo MockAdapter yerine new HttpAdapter({ taban, jeton, kanal: new WebSocketKanal(…) }). Canlı oturum motoru saf ve belirlenimcidir; aynı girdiyle her istemcide ve sunucuda aynı sıralamayı, uzatmayı ve en iyi teklifi üretir. Ayrıntı için mobil uygulama sayfasına bakın.
OpenAPI 3.1 sözleşmesi
Para alanları kuruş cinsinden tam sayıdır; zamanlar ISO 8601. Teklif uçları yalnız şifreli zarf kabul eder.
Canlı oturum kanalı
Kurulumda canlı e-eksiltme ve açık artırma olayları WebSocket üzerinden iletilir; sunucu her teklifi çekirdekteki teklifDogrula fonksiyonuyla doğrular. Demoda aynı olaylar sekmeler arasında BroadcastChannel ile taşınır.
// Gerçek zamanlı kanal (kurulum): wss://api.ornek-kurum.com/v1/canli?oturum=o-i-akis
← { "tur": "durum", "kalanMs": 312000, "siraniz": 2, "enIyi": 431250000, "uzatma": 0 }
→ { "tur": "teklif", "tutar": 429100000 }
← { "tur": "teklif", "katilimci": "İstekli C", "tutar": 429100000, "zaman": "2026-10-28T11:31:05+03:00" }
← { "tur": "uzatma", "yeniBitis": "2026-10-28T11:34:00+03:00" }
← { "tur": "bitis", "siralama": [{ "sira": 1, "katilimci": "Siz" }, { "sira": 2, "katilimci": "İstekli C" }] }Webhook örnekleri
ihale.yayimlandiYeni ilan yayımlandığında (ERP'de talep kaydını güncellemek, kategori abonelerine kendi kanalınızdan duyuru göndermek için).
{
"olay": "ihale.yayimlandi",
"zaman": "2026-10-14T09:00:12+03:00",
"ihaleId": "i-akis",
"ikn": "2026/ZR-004199",
"kategori": "ZK-32",
"yon": "alim",
"usul": "e-eksiltme",
"teklifSon": "2026-10-27T14:00:00+03:00"
}teklif.alindiBir zarf mühürlendiğinde. Gövde tutar İÇERMEZ; yalnız makbuz özeti ve sürüm.
{
"olay": "teklif.alindi",
"zaman": "2026-10-26T10:05:41+03:00",
"ihaleId": "i-akis",
"firmaId": "f-000",
"surum": 2,
"makbuz": "3b7e90c2a1f4d6e8b2c0a97f13e5d4c3b2a1908f7e6d5c4b3a291807f6e5d4c3"
}oturum.sonuclandiCanlı e-eksiltme ya da açık artırma bittiğinde (tutanak üretimi ve karar akışını başlatmak için).
{
"olay": "oturum.sonuclandi",
"zaman": "2026-10-28T11:42:05+03:00",
"oturumId": "o-i-akis",
"ihaleId": "i-akis",
"tur": "eksiltme",
"enIyi": 412850000,
"teklifSayisi": 37,
"uzatma": 3
}// Webhook doğrulama (Node.js) — X-Zarfora-Imza başlığı = HMAC-SHA256(gizli, ham gövde), hex
import { createHmac, timingSafeEqual } from 'node:crypto'
export function imzaGecerli(hamGovde: Buffer, baslik: string, gizli: string) {
const beklenen = createHmac('sha256', gizli).update(hamGovde).digest('hex')
return beklenen.length === baslik.length && timingSafeEqual(Buffer.from(beklenen), Buffer.from(baslik))
}e-İmza, KEP, ERP ve banka adaptörleri
Demo — gerçek bağlantı yok; kurulumda kurumun yetkisi ve sağlayıcının arayüzü üzerinden bağlanır.
// Entegrasyon noktaları — kurulumda kurumun sağlayıcısına göre uygulanır
export interface EImzaAdaptoru {
/** İmzalanacak özet (teklif mektubu PDF'inin SHA-256'sı) → imza isteği; kullanıcı kart/mobil imza ile onaylar */
imzaIste(ozet: string, imzalayan: { tckn?: string; ad: string }): Promise<{ istekId: string }>
sonuc(istekId: string): Promise<{ durum: 'bekliyor' | 'imzali' | 'red'; imza?: string; sertifika?: string; zaman?: string }>
dogrula(imza: string, ozet: string): Promise<{ gecerli: boolean; sahibi?: string }>
}
export interface KepAdaptoru {
/** Sonuç bildirimi, itiraz kararı gibi resmî yazışmalar için kayıtlı elektronik posta */
gonder(alici: string, konu: string, ekler: { ad: string; icerik: Uint8Array }[]): Promise<{ delilId: string }>
delil(delilId: string): Promise<{ teslim: boolean; zaman?: string }>
}
export interface ErpAdaptoru {
/** Satın alma talebi → ihale taslağı; ihale sonucu → sipariş/sözleşme kaydı */
talepleriGetir(kurumId: string): Promise<{ talepNo: string; kalemler: { malzemeKodu: string; ad: string; birim: string; miktar: number }[]; butceKodu: string }[]>
siparisOlustur(s: { ihaleId: string; tedarikciVkn: string; kalemler: { malzemeKodu: string; miktar: number; birimFiyat: number }[] }): Promise<{ siparisNo: string }>
butceKontrol(butceKodu: string, tutar: number): Promise<{ yeterli: boolean; kalan: number }>
}
export interface TeminatAdaptoru {
/** Banka e-teminat doğrulaması */
dogrula(referans: string, vkn: string): Promise<{ gecerli: boolean; tutar: number; bitis?: string }>
}Kalite
- Çekirdek birim testleri (vitest): teklif cetveli kuruş yuvarlaması ve KDV kırılımı, iş günü ve resmî tatil, hash zinciri doğrulama ve kurcalama tespiti, canlı oturumda son dakika uzatması, geçersiz adım reddi, vekil pey, belirlenimcilik.
- Mobil uygulama TypeScript tip denetiminden geçer; web ile aynı çekirdeği kullanır.
- Uçtan uca akış testi: arama → ilan → soru-cevap → firma kaydı → kapalı zarf → zeyilname → zarf açılışı → karşılaştırma → iki sekmede canlı e-eksiltme → sonuç; açık artırmada vekil pey; denetim zinciri doğrulaması.