---
# System prepended metadata

title: InApp & PlaceHolder

---


# Uygulama Ici Iletisim

Uygulama ici iletisim mobile, web ve backoffice uygulamalarinda calisacak kullanici  ile etkilesim saglayacak iceriklerin sunulmasi amaciyla gelisitilecek altyapidir.

> :last_quarter_moon: Bu ozellikler MVP sonrasi gelistirilecek ozelliklerdir. MVP icerisinde yapilacak ozelliklere ongoru olsun diye belgeye eklenmistir.

## Iletisim Turleri

### InApp

Uygulama icerisinde modal diyalog olarak tam ekran olarak acilarak kullanicidan aksiyon bekleyen ekranlardir. 

Temel yetkinlikleri;
* Icerik olarak Banner, Html ve Lottie gosterebilir.
* Sag ust kosede **Cancel** butonu olabilir.
* Icerik altinda buttonlar olabilir.
* Icerik tiklanabilir ve deep linke yonlendirebilir iceriktir.
* Sayfa girisinde veya sayfa cikisinda gosteribilir.
* :last_quarter_moon: Sayfa ici bir veriye bagli olarak tetiklenebilir. (Kullanici dolar hesabi secerse goster gibi.)


### :last_quarter_moon: Bottomsheet
Uygulama icerisinde ekran altindan cikip kullanicidan aksiyon bekleyen ekranlardir. 

Temel yetkinlikleri;
* Icerik olarak Banner, Html ve Lottie gosterebilir.
* Sag ust kosede **Cancel** butonu olabilir.
* Icerik tiklanabilir ve deep linke yonlendirebilir iceriktir.
* Timeout suresi tanimlanabilir, timeout sonunda kendi kendine kaybolur.
* Sayfa girisinde veya sayfa ici bir veriye bagli olarak tetiklenebilir.

### Placeholder

Uygulama icerisinde ekranlarda bulunan reklam alanlarinin icerik olarak doldurulamasi ile elde edilir. 

Temel yetkinlikleri;
* Icerik olarak Banner, Html ve Lottie gosterebilir.
* Icerik tiklanabilir ve deep linke yonlendirebilir iceriktir.
* Sayfa icerisinde birden fazla placeholder bulunabilir.

## Icerik Gosterimi

Icerikler kullaniciya ozel olarak belirlenebilir ve dinamik olarak olusturulmasi gerebilir.
Bu nedenle her sayfa gecisinde kukllaniciya gosterilecek icerik varligi sorgulanir.
Sorgu sonucuna gore gosterimler ve placeholderi doldurma eylemleri gerceklestirilir.

## Ortak Terim ve İfadeler

**1. Channel**
Müşteriye içerik sunumunun kaç farklı kanaldan yapılacağını ifade eder.
**Türler;**
* InApp (*MobilApp*)
* PlaceHolder (*MobilApp*)
* SMS (*Pasif Kanal*)
* Mail (*Pasif Kanal*)
* Push (*Pasif Kanal*)
* IVN (*Pasif Kanal*)
* ServiceCall (*Pasif Kanal*)

**2. Topic**
İçerik servisine (NBA API) gelen taleplerin çeşidi belirtir.
**Türler;**
* app-navigation (MobilApp üzerinden gelen talepleri karşılar.)
* state-change (Workflow degisimlerinin CDC olarak aktigi senaryo ornegi.)
* bulk-churn (SAS Scheduled Worker üzerinden gelen talepleri karşılar.)

## Teknik Bilesenler

### Mimari Tasarım

> Tüm servis loglarını alabilmek için, servisler apisix gateway üzerinden tüketilecektir. Diagramlarda apisix gateway bypass edilmiştir.

```plantuml
@startuml
title InApp & PlaceHolder Project - C4 Context Diagram

[SAS ID Module] as SASModule #Gray
note left of SASModule
 Müşteri meta verisine göre uygun 
 öneride bulunan analitik uygulamadır.
end note

[Campaign Management Module] as CampaignModule
note left of CampaignModule
 Aksiyon ve Contentlerin tanımlandığı 
 senaryoların yönetildiği portaldır. 
 NBA servisine aksiyona uygun 
 content tanımını besler.
end note

[NBA API] as NBAModule #Green

[Message Gateway Module] as MessageGatewayModule
note right of MessageGatewayModule
 SMS, Push, Email vb. kanallar 
 üzerinden müşteri bilgilendirme için kullanılır
end note

[Mobil App] as MobilApp
note right of MobilApp
 Her sayfa değişiminde veya ilgili sayfadaki 
 komponent değişimlerini NBA servisini 
 tetikleyerek bir müşterinin inapp bilgisini sorgular. 
 Varsa bunu ilgili sayfada servisten genel 
 kanal bilgisine göre müşteriye gösterimini 
 sağlar ve acknowledge bilgisini geri besler.
end note

NBAModule --> SASModule
NBAModule --> CampaignModule
NBAModule --> MessageGatewayModule
MobilApp --> NBAModule
SASModule --> NBAModule
@enduml
```

---

```plantuml
@startuml
title InApp & PlaceHolder Project - C4 Container Diagram

package "SAS Module" {
 [SAS ID API] as SASAPI #Gray
 [Kafka Normalizer / Consumer] as KafkaConsumer #Gray
 database SASDB

 SASAPI --> SASDB: [SQL/TCP]
}

package "Banking Module" {
 [Campaign Management API] as CampaignAPI
 database CampaignDB
 [NBA API] as NBAAPI #Green
 database NBADB
 [Message Gateway API] as MessageGatewayAPI
 [Mobil App] as MobilApp

 CampaignAPI --> CampaignDB: [SQL/TCP]
 NBAAPI --> NBADB: [SQL/TCP]
 NBAAPI --> CampaignAPI: [JSON/HTTPS]
 NBAAPI --> MessageGatewayAPI: [JSON/HTTPS]
 MobilApp ---> NBAAPI: [JSON/HTTPS]
}

NBAAPI --> SASAPI: [JSON/HTTPS]
KafkaConsumer ---> () Kafka: [MQ/TCP]
Kafka --> NBAAPI: [JSON/HTTPS]

@enduml
```
---
```plantuml
@startuml
title InApp & PlaceHolder Project - C4 Component Diagram

package "NBA API" as NBAApi{
 [Mobile Controller] as MobileController
 [CDC Controller] as CDCController
 [Churn Controller] as ChurnController
}

[Mobil App] as MobileApp
[SASID API] as SASApi #Gray
[Message Gateway API] as MessageGatewayApi
[Campaign Management API] as CampaignManagementApi
[Kafka Normalizer / Consumer] as KafkaConsumer #Gray

[Kafka]

MobileApp --> MobileController
KafkaConsumer --> ChurnController
KafkaConsumer --> CDCController

NBAApi --> SASApi
NBAApi --> CampaignManagementApi
ChurnController --> Kafka
CDCController --> Kafka
Kafka --> MessageGatewayApi

@enduml
```
---
```plantuml
@startuml
title InApp & PlaceHolder Project - C4 Code Diagram

actor Actor1
actor Actor2 #Blue
participant MobileApp
participant KafkaConsumer #Gray
participant NBAApi #Green
database NBADb
participant SASApi #Gray
participant CampaignManagementApi
participant Kafka
participant MessageGatewayApi

Actor1 --> MobileApp: Sayfa veya aksiyon değişikliği
MobileApp -> NBAApi: ToPage, FromPage ve \npayload bilgisi iletilir.

NBAApi -> SASApi: Gelen input bilgisi SAS'a \niletilerek geriye bir actionId \nve channel bilgisi beklenir.
SASApi --> NBAApi: Dönüş: actionId ve channel bilgisi.
NBAApi -> CampaignManagementApi: actionId ve channel \nbilgisine tanımlanmış olan \ncontent bilgisini talep eder.
CampaignManagementApi --> NBAApi: Dönüş: content/action bilgisi geri döner.
NBAApi -> MobileApp: actionId ve channel ikilisine \nuygun content'i konselide ederek \nMobilApp'e geri döner.

Actor2 --[#Blue]> KafkaConsumer: Pasif kanal üzerinden \nmüşteriye bildiri için\n veri iletimi.
KafkaConsumer -[#Blue]> NBAApi: SAS Schecule veya KafkaTopicler\n üzerinden gelen talepleri iletir.
NBAApi -[#Blue]> SASApi: Gelen input bilgisi SAS'a \niletilerek geriye bir actionId\n ve channel bilgisi beklenir.
SASApi --[#Blue]> NBAApi: Dönüş: actionId ve channel bilgisi.
NBAApi -[#Blue]> CampaignManagementApi: actionId ve channel \nbilgisine tanımlanmış olan \ncontent bilgisini talep eder.
CampaignManagementApi --[#Blue]> NBAApi: Dönüş: content/action bilgisi geri döner.
NBAApi --[#Blue]> Kafka: Pasif kanal üzerinden içerik \ngönderimi için \ncontent bilgisini iletir.
Kafka -[#Blue]> MessageGatewayApi: Kafka consumer mesajı\n MessageGatewayApi'ye işlemesi\n için iletir. 

Actor1 --[#red]> MobileApp: Kullanıcıya sunulan içeriğin \nkullanıcı tarafından görünlenme,\n tıklanma veya aksiyonlarını yapar.
MobileApp -[#red]> NBAApi: Kullanıcının aldığı \naksiyonları NBAApi'ye iletir.
NBAApi -[#red]> NBADb: Gelen aksiyon hareketlerini\n loglamak için veritabanına yazar.
NBAApi --[#red]> MobileApp: Dönüş: HttpStatus: 201 olarak döner. \n(Exception durumu bypass edilir.)
@enduml
```
#### Use Case 1
1. **Actor1** mobil kullanan kullacılar, uygulama üzerinde ki hareketleri (sayfa geçişleri, komponent üzerindeki değişimleri veya aksiyonları) takip edilir.
2. **MobileApp** Actor1'in değişim hareketlerini NBAApi servisine iletir.
3. **NBAApi** talebi alarak SASApi'sine ileterek actionId ve channel bilgisini bekler.
4. **SASApi** müşteriye ugun analizi yaparak en uygun actionId bilgisi channel ile birlikte geri döner.
5. **CampaignManagementApi**, NBAApi'si actionId ve channel ikilisine uygun daha önceden tanımlanmış content bilgisini talep eder.
6. NBAApi content bilgisini müşteri verileri ile binding işlemlerini yaparak son haline getirir ve MobileApp'e geri döner.
7. MobileApp'e bir aksiyon için birden fazla content dönebilir. MobileApp skor bilgisini baz alarak sıralama yapar ve içerikleri inApp veya place holder olarak gösterimini sağlar.

#### Use Case 2
1. **Actor2** SAS Zamanlanmış Task'ları veya Kafka'da belirlenmiş Topicler üzerinden veri iletimi sağlanır.
3. **NBAApi** talebi alarak SASApi'sine ileterek actionId ve channel bilgisini bekler.
4. **SASApi** müşteriye ugun analizi yaparak en uygun actionId bilgisi channel ile birlikte geri döner.
5. **CampaignManagementApi**, NBAApi'si actionId ve channel ikilisine uygun daha önceden tanımlanmış content bilgisini talep eder.
6. NBAApi content bilgisini müşteri verileri ile binding işlemlerini yaparak son haline getirir ve channel bilgisini baz alarak Kafka'ya iletir.
7. **Kafka** gelen mesajı **MessageGatewayApi**'ye ileterek pasif kanallar üzerinden gönderimini işler.

### Use Case 3 (Trace Logging)
1. **Actor1**, kullanıcıya sunulan içerik ile ilgili aksiyonlarını (görüntüleme, tıklanma vs...) durumlarını işler.
2. **MobileApp**, kullanıcının aldığı tüm aksiyonları takip eder ve bunları NBAApi'ye iletir.
3. **NBAApi**, gelen her talebi NBADb veritabanına yazar.
4. NBAApi sonucu MobileApp'e **202 (Accepted) Http Status** kodu ile döner. *MobileApp, trace istekleri için exception durumlarını bypass eder.*


### Ortak Konular
#### Servislerde standart Http Header icerikleri

* User : Kullanici tckn bilgisi.
* X-Customer : Musteri tckn veya vkn bilgisi.
* Scope: Kullanicinin musteriyle ilgili islem yaparken kullandigi kapsam.
* Client: Kullanicinin eristigi uygulama(mobile, web, cagri merkezi gibi)
* Accept-Language: Donulecek contentin icerik dili bildirilir.



### Content Servisleri
Kullanici arabiriminin her bir ekran gecisinde kullaniciya uygun gosterilecek bir icerigin olup olmadigini sorguladigi servistir. Temel olarak kullaniciya ozel icerikleri o sayfaya ozel olarak derler ve doner.

#### API Operations

* Content Sorgulama
    * Customer Present
    * Non-Customer Present
* Content Trace Logging

#### Content Sorgulama
Mobile, CDC ve churn isteklerini karşılamak için 2 endpoint olarak oluşturulmuştur.

#### Customer Present
İstemciye içeriğe paylaşır.

**POST** /in-app/message/present
#### REQUEST
**REQUEST BODY:** application/json

```json
{
  "topic": "string",
  "customer": 0,
  "fromRoute": "string",
  "toRoute": "string",
  "fromRoutePayload": {
    "sourceAmount": "string",
    "targetAccount": "string",
    "amount": "string"
  }
}
```

###### SCHEMA

| Field | Type | Description |
| -------- | -------- | -------- |
| topic *     | string     | Hangi kanaldan geldiğini ifade eder. Mobil için "app-navigation"
| customer * | integer | Müşteri kimlik bilgisi |
| fromRoute * | string | Mevcut sayfa adı |
| toRoute * | string | Geçiş yapılan sayfa adı |
| fromRoutePayload | dictionary / object | Mevcut sayfada ki payload bilgisi. Bu alan dinamiktir |

#### RESPONSE
**Http Status:** 200
```json
[
    {
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "type": "place-holder",
        "score": 1,
        "content": {
            "title": "string",
            "body": "string",
            "type": "html",
            "image": "http://example.com",
            "sound": "http://example.com"
        },
        "action": {
            "code": "string",
            "actionType": "deepLink"
            "actipnLink": "amorphie://fx-buy-input"
        }
    },
    {
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "type": "in-app",
        "when": "page-load",
        "content": {
            "title": "string",
            "body": "string",
            "type": "html",
            "image": "http://example.com",
            "sound": "http://example.com"
        },
        "button": [
            [
                {
                    "code": "string",
                    "type": "default-submit",
                    "label": "string",
                    "actionLink": "amorphie://fx-buy-input",
                    "actionType": "deepLink"
                    "sound": "http://example.com",
                    "icon": "http://example.com"
                },
                {
                    "code": "string",
                    "type": "cancel",
                    "label": "string",
                    "action": "http://example.com",
                    "actionType": "externalLink"
                    "sound": "http://example.com",
                    "icon": "http://example.com"
                }
            ]
        ]
    }
]
```
###### SCHEMA

| Field | Type | Description |
| -------- | -------- | -------- |
| id     | guid     | Her bir content için benzersiz kimlik bilgisi     |
| type | string | Gösterim yapılacak tür bilgisi. |
| score | float | Sıralama/Skor bilgisi |
| content | object | İçerik bilgisi |
| - title | string | İçerik başlığı |
| - body | string | İçerik metni | 
| - type | string | İçerik tipi |
| - image | string | İçerik görsel |
| - sound | string | İçerik ses |
| action | object | Aksiyon bilgisi |
| - code | string | Aksiyon kodu |
| - actionLink | string | Aksiyon linki |
| - actionType | string | Aksiyon tipi (DeepLink, ExternalLink) |
| when | string | İçeriğin sayfada hangi aksiyon/event durumunda gösterileceği |
| button | object | Aksiyon alınabilecek komponent objesi |
| - code | string | Kod |
| - type | string | Tip |
| - label | string | Komponent görünür adı |
| - actionType | string | Aksiyon tipi (DeepLink, ExternalLink) |
| - actionLink | string | Aksiyon linki |
| - sound | string | Ses |
| - icon | string | İkon |


#### Non-Customer Present
**POST** /in-app/message/non-present
#### REQUEST
**REQUEST BODY:** application/json

```json
{
  "topic": "string",
  "customer": 0,
  "action": {
    "id": "string",
    "channel": "string"
  },
  "fromRoute": "string",
  "toRoute": "string",
  "fromRoutePayload": {
    "sourceAmount": "string",
    "targetAccount": "string",
    "amount": "string"
  }
}
```

###### SCHEMA

| Field | Type | Description |
| -------- | -------- | -------- |
| topic *     | string     | Hangi kanaldan geldiğini ifade eder. Mobil için "app-navigation"
| customer * | integer | Müşteri kimlik bilgisi |
| action | object | SAS üzerinden tüketilecek aksiyon bilgisi | 
| - id | string | Aksiyon Id |
| - channel | string | Kanal tipi |
| fromRoute | string | Mevcut sayfa adı |
| toRoute | string | Geçiş yapılan sayfa adı |
| fromRoutePayload | dictionary / object | Mevcut sayfada ki payload bilgisi. Bu alan dinamiktir |

**Topic bazlı request örnekleri**

- Ornek Istek(CDC State Change)
```json
{
  "topic":"state-change"
  "customer": 38552069008,
  "from-route": "profile-input",
  "to-route": "evaluation",
  "from-route-payload": {
    "application-id": "68af7f88-b11e-4277-a9e6-3296e2873633"
  }
}
```
- Ornek Istek(Bulk Process - Churn)
```json
{
  "topic":"bulk-churn"
  "customer": 38552069008,
}
```

#### RESPONSE
**HTTP STATUS:** 202


#### Content Trace Logging
**POST** /in-app/message/{id}/trace
#### REQUEST

**Path Params**
| Field | Type | Description |
| -------- | -------- | -------- |
| id     | guid     | Her bir content için benzersiz kimlik bilgisi     |

**REQUEST BODY:** application/json
```json
{
  "route": "money-transfer-fast-input",
  "event": "clicked",
  "action": "http://example.com"
}
```

###### SCHEMA

| Field | Type | Description |
| -------- | -------- | -------- |
| route *     | string     | Route adı
| event * | integer | Gerçekleştirilen eylem Ör: viewed, clicked |
| action | string | Link veya aksiyon bilgisi |

#### RESPONSE
**Http Status:** 202

### Beklenen Konular
* Pasif kanal kullanımında schedule durumu olacak mı? Nasıl handle edilecek?
* InApp gösteriminde bekleme süresi (timeout) bilgis olacak mı?
* SAS Worker'ları NBA Api'sini tükettiğinde actionId ve channel bilgisini hazır olarak iletebilir mi? (SAS'tan teyit alınacak!)