Loyalty Credential’dan Uçuş Teklifine: Kimlik Tabanlı Airline Retailing
DemoAir uygulamasındaki Loyalty Credential, dijital wallet, kişiselleştirilmiş offer seçimi ve Order Credential akışını kod örnekleriyle adım adım takip ediyoruz.
Digital Travel Architecture — Bölüm 3
Digital Travel uygulamasının ilk aşamalarında yolcunun pasaport bilgileri doğrulanmış, Passport Credential oluşturulmuş ve dijital cüzdana eklenmişti. Bu bölümde aynı cüzdanın seyahat alışverişi sırasında nasıl kullanılabileceğine odaklanıyoruz: Yolcunun sadakat programı üyeliği doğrulanıyor, üyelik seviyesine göre uçuş teklifleri hazırlanıyor ve seçilen teklif bir Order Credential olarak yeniden cüzdana kaydediliyor.
Makale boyunca geliştirilen DemoAir uygulamasındaki FastAPI ve React akışı referans alınmaktadır. Amaç kaynak kodu değerlendirmek değil; uygulamanın modellediği airline retailing yolculuğunu teknik bileşenleriyle açıklamaktır.
1. Kimlik katmanından retailing katmanına geçiş
Uygulamada dijital cüzdan yalnızca Passport Credential saklayan bir alan değildir. Yolcunun farklı seyahat aşamalarında kullanabileceği birden fazla doğrulanabilir kayıt aynı wallet altında toplanır:
- Passport Credential: Yolcunun kimlik ve seyahat belgesi bilgileri
- Loyalty Credential: Sadakat programı, üye numarası, seviye ve puan bilgileri
- Order Credential: Seçilen uçuş ve oluşturulan sipariş bilgileri
Bu yapı sayesinde shopping işlemi yalnızca rota ve tarihe göre değil, yolcunun cüzdanındaki geçerli üyelik bilgisine göre de şekillenebilir.
Passport Credential
│
▼
Digital Wallet ── Loyalty Credential
│
▼
Offer Search
│
▼
Kişiselleştirilmiş uçuş teklifleri
│
▼
Seçilen Offer
│
▼
Order Credential
│
▼
Digital Wallet
2. Loyalty Credential oluşturulması
React arayüzündeki üçüncü adım başlatıldığında frontend önce /retail/loyalty/enroll endpointini çağırır. İstek içinde kullanıcı kimliğiyle birlikte sadakat programına ait temel bilgiler bulunur:
{
"user_id": "traveller-123",
"program_name": "DemoAir Miles",
"member_id": "MEMBER-123456",
"tier": "GOLD",
"points": 42000
}
Backend bu alanları Loyalty Credential claim'lerine dönüştürür. Ortak credential servisi issuer, subject, oluşturulma zamanı, geçerlilik süresi, credential tipi ve claim alanlarını içeren bir JWT üretir.
claims = {
"program_name": request.program_name,
"member_id": request.member_id,
"tier": request.tier.upper(),
"points": request.points,
}
loyalty_vc = build_loyalty_vc(
subject_id=request.user_id,
claims=claims,
)
Oluşturulan credential doğrulandıktan sonra loyalty tipiyle kullanıcının dijital cüzdanına eklenir. Böylece offer servisi üyelik bilgisini frontend formundan tekrar almak yerine wallet içindeki credential üzerinden okuyabilir.
3. Offer Search isteği
Loyalty Credential oluşturulduktan sonra frontend aynı kullanıcı için offer search işlemini başlatır. Shopping isteği dört temel alan taşır:
searchOffers(
userId,
origin,
destination,
departureDate
)
Backend tarafındaki istek modeli de bu seyahat bağlamını temsil eder:
class OfferSearchRequest(BaseModel):
user_id: str
origin: str
destination: str
departure_date: str
Bu aşamada retail servisi iki farklı veri kaynağını birleştirir. Rota ve tarih frontend'deki seyahat aramasından, loyalty seviyesi ise dijital cüzdandaki credential'dan gelir.
4. Wallet içinden loyalty seviyesinin alınması
Offer servisi önce kullanıcının wallet kayıtları arasında loyalty tipindeki credential'ı bulur. Credential doğrulandıktan sonra claim alanlarındaki tier değeri okunur:
stored_loyalty = wallet_repo.get_first_by_type(
request.user_id,
"loyalty",
)
if stored_loyalty:
payload = verify_vc(stored_loyalty.vc_jwt)
loyalty_claims = payload.get("claims", {})
tier = loyalty_claims.get("tier")
DemoAir örneğinde üyelik seviyesi teklif fiyatına uygulanacak indirim oranını belirler:
- PLATINUM: %20
- GOLD: %15
- SILVER: %10
- BASIC veya üyelik bulunmaması: standart fiyat
def discount_for_tier(tier: str) -> float:
if tier == "PLATINUM":
return 0.20
if tier == "GOLD":
return 0.15
if tier == "SILVER":
return 0.10
return 0.00
Böylece loyalty bilgisi kullanıcı deneyimini etkileyen doğrulanabilir bir retailing girdisine dönüşür.
5. Uçuş tekliflerinin oluşturulması
Demo offer engine üç farklı uçuş seçeneği üretir. Her teklif için benzersiz bir offer_id, uçuş numarası, rota, tarih, taban fiyat, loyalty indirimi, son fiyat ve para birimi hazırlanır.
offer = OrderOffer(
offer_id=str(uuid.uuid4()),
flight_no=flight_number,
origin=request.origin,
destination=request.destination,
departure_date=request.departure_date,
base_price=base_price,
loyalty_discount=round(base_price * discount_rate, 2),
final_price=round(base_price - loyalty_discount, 2),
currency="EUR",
applied_tier=tier,
)
Offer response yalnızca son fiyatı değil, fiyatın nasıl oluştuğunu da arayüze taşır. Kullanıcı taban fiyatı, uygulanan indirimi, loyalty seviyesini ve ödeyeceği toplam tutarı birlikte görebilir.
6. React arayüzünde teklif seçimi
Backend'den dönen teklifler React state'i içinde saklanır ve kartlar halinde listelenir. Her kart aşağıdaki bilgileri gösterir:
- Uçuş numarası
- Kalkış ve varış noktası
- Uçuş tarihi
- Taban fiyat
- Loyalty indirimi
- Uygulanan üyelik seviyesi
- Son fiyat ve para birimi
Yolcu bir karta tıkladığında seçilen offer uygulama state'ine alınır. Uçuş numarası ve fiyat, yolculuğun sonraki adımındaki Order ekranına aktarılır:
function selectOffer(offer: Offer) {
setSelectedOffer(offer)
setSelectedFlightNo(offer.flight_no)
setFinalPrice(offer.final_price)
}
Bu geçiş, shopping aşaması ile order oluşturma aşaması arasındaki kullanıcı onay noktasını temsil eder.
7. Seçilen tekliften Order oluşturulması
Kullanıcı seçimini onayladığında frontend /retail/orders/create endpointini çağırır. Demo uygulamada Order isteği seçilen uçuşun rota, tarih, fiyat ve para birimi bilgilerini taşır.
{
"user_id": "traveller-123",
"flight_no": "DA101",
"origin": "IST",
"destination": "LHR",
"departure_date": "2026-12-30",
"final_price": 127.50,
"currency": "EUR"
}
Retail servisi işlem için yeni bir order_id üretir ve uçuş bilgilerini Order Credential claim'lerine dönüştürür:
order_claims = {
"order_id": str(uuid.uuid4()),
"flight_no": request.flight_no,
"origin": request.origin,
"destination": request.destination,
"departure_date": request.departure_date,
"price": request.final_price,
"currency": request.currency,
}
order_vc = build_order_vc(
subject_id=request.user_id,
claims=order_claims,
)
Passport ve Loyalty credential'larında olduğu gibi Order Credential da JWT biçiminde imzalanır ve kullanıcının wallet'ına eklenir.
8. Wallet'ın yolculuk boyunca gelişmesi
Order işlemi tamamlandığında kullanıcının dijital cüzdanı artık üç farklı iş alanından veri taşır:
Wallet / traveller-123
├── Passport Credential
│ └── nationality, document data, validity
├── Loyalty Credential
│ └── program, member ID, tier, points
└── Order Credential
└── order ID, flight, route, date, price
Bu birleşim sonraki aşama olan airline check-in için gerekli girdiyi oluşturur. Check-in servisi Passport Credential'dan uyruğu, Order Credential'dan rota ve uçuş numarasını alarak Travel Rules değerlendirmesini başlatır.
9. IATA Offers & Orders bağlamı
IATA'nın Modern Airline Retailing yaklaşımı, havayolu ürünlerinin müşteri ve shopping bağlamına göre Offer olarak oluşturulmasını, kabul edilen tekliflerin ise yaşam döngüsü boyunca Order olarak yönetilmesini hedefler.
NDC; airline offer ve order bilgilerinin farklı satış kanallarıyla standart biçimde paylaşılmasına yönelik veri değişim yaklaşımı sunar. ONE Order ise rezervasyon, e-ticket ve EMD gibi farklı kayıtların yerine tek ve bütünleşik müşteri siparişi fikrini geliştirir.
DemoAir uygulaması bu standartların mesaj yapılarını uygulamak yerine temel iş akışını küçük bir prototip üzerinde görünür kılar:
Shop → Offer oluştur → Offer seç → Order oluştur
↑
Loyalty Credential bağlamı
10. Uçtan uca örnek senaryo
- Yolcu IST–LHR rotası ve seyahat tarihini girer.
- DemoAir Miles üyeliği için Loyalty Credential oluşturulur.
- Credential kullanıcının dijital cüzdanına eklenir.
- Offer servisi wallet içindeki GOLD seviyesini okur.
- Üç uçuş seçeneği loyalty indirimi uygulanarak hazırlanır.
- React arayüzü teklifleri fiyat bileşenleriyle listeler.
- Yolcu DA101 uçuşunu seçer.
- Seçilen uçuş için Order Credential oluşturulur.
- Order Credential wallet'a kaydedilir.
- Uygulama check-in ve ready-to-fly aşamasına geçer.
Sonuç
Bu bölümde dijital cüzdandaki Loyalty Credential'ın airline shopping sürecine nasıl dahil edildiğini gördük. Credential içindeki tier bilgisi teklif hesaplamasında kullanıldı, kişiselleştirilmiş uçuş seçenekleri React arayüzünde sunuldu ve yolcunun seçimi Order Credential olarak yeniden cüzdana taşındı.
Böylece Digital Travel uygulaması yalnızca kimlik doğrulayan bir yapı olmaktan çıkıp kimlik, sadakat programı, teklif ve sipariş aşamalarını aynı yolcu yolculuğunda birleştiren uçtan uca bir demo haline geliyor.
Serinin sonraki bölümünde Passport Credential ve Order Credential'ın Travel Rules servisiyle nasıl birleştirildiğini ve ready_to_fly sonucunun check-in sürecinde nasıl üretildiğini inceleyeceğiz.
Demo ve güvenlik notu
Bu makale, geliştirme ve kavram doğrulama amacıyla hazırlanmış çalışan bir demo kod tabanı referans alınarak oluşturulmuştur. Uygulamadaki kimlik, credential, wallet, offer ve order işlemleri gerçek havayolu sistemlerine göre basitleştirilmiştir.
Örnek kod düşük güvenlik seviyeli bir prototip olarak değerlendirilmelidir; gerçek yolcu verisi, ödeme işlemi veya canlı havayolu operasyonunda doğrudan kullanılmamalıdır. Uygulama IATA NDC, ONE Order veya başka bir endüstri standardına tam uyumluluk iddiası taşımamaktadır.
Resmî kaynaklar
Bu makaleyi nasıl değerlendirirsin?
Geri bildirimin sonraki içerikleri geliştirmeme yardımcı olur.