diff --git a/android/navi-base/build.gradle b/android/navi-base/build.gradle index 446a388088..37b7288ad5 100644 --- a/android/navi-base/build.gradle +++ b/android/navi-base/build.gradle @@ -75,6 +75,7 @@ dependencies { api libs.android.play.reviewKtx api libs.androidx.hilt.navigation.compose api libs.firebase.analytics + api libs.firebase.crashlytics api libs.firebase.firestore api libs.gson api libs.guava diff --git a/android/navi-base/src/main/java/com/navi/base/utils/FirestoreDataProvider.kt b/android/navi-base/src/main/java/com/navi/base/utils/FirestoreDataProvider.kt index df524b86b4..1962d9bb9e 100644 --- a/android/navi-base/src/main/java/com/navi/base/utils/FirestoreDataProvider.kt +++ b/android/navi-base/src/main/java/com/navi/base/utils/FirestoreDataProvider.kt @@ -1,20 +1,23 @@ /* * - * * Copyright © 2024 by Navi Technologies Limited + * * Copyright © 2024-2025 by Navi Technologies Limited * * All rights reserved. Strictly confidential * */ package com.navi.base.utils +import com.google.firebase.crashlytics.FirebaseCrashlytics import com.google.firebase.firestore.DocumentSnapshot import com.google.firebase.firestore.QuerySnapshot import com.google.firebase.firestore.ktx.firestore import com.google.firebase.ktx.Firebase import javax.inject.Inject +import kotlin.coroutines.resumeWithException import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.callbackFlow +import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.tasks.await /** @@ -38,6 +41,9 @@ interface FirestoreDataProvider { /** @throws Exception in case Task is cancelled */ suspend fun getDocumentSnapShotForDocumentPath(documentPath: String): DocumentSnapshot + + /** Used this if last node is collection Returns document id if write is successful */ + suspend fun writeDocument(collectionPath: String, data: Any): String } class FirestoreDataProviderImpl @Inject constructor() : FirestoreDataProvider { @@ -89,4 +95,16 @@ class FirestoreDataProviderImpl @Inject constructor() : FirestoreDataProvider { ): DocumentSnapshot { return db.document(documentPath).get().await() } + + override suspend fun writeDocument(collectionPath: String, data: Any): String { + return suspendCancellableCoroutine { continuation -> + db.collection(collectionPath) + .add(data) + .addOnSuccessListener { continuation.resumeWith(Result.success(it.id)) } + .addOnFailureListener { + FirebaseCrashlytics.getInstance().recordException(it) + continuation.resumeWithException(it) + } + } + } } diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/dao/MessagesDao.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/dao/MessagesDao.kt index ba347496d4..64a989a0a3 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/dao/MessagesDao.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/dao/MessagesDao.kt @@ -13,6 +13,7 @@ import androidx.room.RawQuery import androidx.room.Upsert import androidx.sqlite.db.SupportSQLiteQuery import com.navi.pay.management.chat.model.view.MessageEntity +import com.navi.pay.management.chat.model.view.MessageStatus import com.navi.pay.utils.NAVI_PAY_DATABASE_MESSAGES_TABLE_NAME @Dao @@ -26,4 +27,9 @@ interface MessagesDao { @Query("DELETE FROM $NAVI_PAY_DATABASE_MESSAGES_TABLE_NAME") suspend fun deleteAll() @RawQuery suspend fun deleteRows(query: SupportSQLiteQuery): Int + + @Query( + "UPDATE $NAVI_PAY_DATABASE_MESSAGES_TABLE_NAME SET status = :status WHERE messageId = :messageId" + ) + suspend fun updateMessageStatus(messageId: String, status: MessageStatus) } diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/model/network/CreateConversationRequest.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/model/network/CreateConversationRequest.kt new file mode 100644 index 0000000000..20a19f3189 --- /dev/null +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/model/network/CreateConversationRequest.kt @@ -0,0 +1,23 @@ +/* + * + * * Copyright © 2025 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.pay.management.chat.model.network + +import com.google.gson.annotations.SerializedName + +data class CreateConversationRequest( + @SerializedName("conversation_id") val conversationId: String, + @SerializedName("users") val users: List, + @SerializedName("type") val type: String = "P2P", + @SerializedName("tenant") val tenant: String = "UPI", +) + +data class Participant( + @SerializedName("user_id") val userId: String, + @SerializedName("role") val role: String = "CUSTOMER", + @SerializedName("user_id_type") val userIdType: String = "EXTERNAL", +) diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/model/network/CreateConversationResponse.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/model/network/CreateConversationResponse.kt new file mode 100644 index 0000000000..282e88c257 --- /dev/null +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/model/network/CreateConversationResponse.kt @@ -0,0 +1,12 @@ +/* + * + * * Copyright © 2025 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.pay.management.chat.model.network + +import com.google.gson.annotations.SerializedName + +data class CreateConversationResponse(@SerializedName("conversationId") val conversationId: String) diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/model/network/MessageSyncResponse.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/model/network/MessageSyncResponse.kt index bd47e4eb14..536fcc6e18 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/model/network/MessageSyncResponse.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/model/network/MessageSyncResponse.kt @@ -7,7 +7,10 @@ package com.navi.pay.management.chat.model.network +import com.google.firebase.firestore.FieldValue import com.google.gson.annotations.SerializedName +import com.navi.pay.management.chat.model.view.MessageContent.TextContent +import com.navi.pay.management.chat.model.view.MessageEntity data class MessageSyncResponse( @SerializedName("messagesPageSize") val messagesPageSize: Int, @@ -19,7 +22,6 @@ data class MessageItem( @SerializedName("content") val content: MessageContent, @SerializedName("realtimeCreatedAt") val realtimeCreatedAt: String, @SerializedName("messageCreatedAt") val messageCreatedAt: String, - @SerializedName("realtimeMessageId") val realtimeMessageId: String, @SerializedName("conversationId") val conversationId: String, ) @@ -28,3 +30,33 @@ data class MessageContent( @SerializedName("senderMobileNumber") val senderMobileNumber: String, @SerializedName("text") val text: String, ) + +fun MessageEntity.toMessageItem(): MessageItem { + return MessageItem( + messageId = messageId, + content = + MessageContent( + senderExternalId = (content as TextContent).senderExternalId, + senderMobileNumber = content.senderMobileNumber, + text = content.text, + ), + realtimeCreatedAt = createdAt.toString(), + messageCreatedAt = updatedAt.toString(), + conversationId = conversationId, + ) +} + +fun MessageItem.toFirestorePayload(): Map { + return hashMapOf( + "messageId" to messageId, + "content" to + mapOf( + "senderExternalId" to content.senderExternalId, + "senderMobileNumber" to content.senderMobileNumber, + "text" to content.text, + ), + "realtimeCreatedAt" to FieldValue.serverTimestamp(), + "messageCreatedAt" to messageCreatedAt, + "conversationId" to conversationId, + ) +} diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/model/view/ConversationEntity.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/model/view/ConversationEntity.kt index f1d53b72d1..0e71b42756 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/model/view/ConversationEntity.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/model/view/ConversationEntity.kt @@ -11,10 +11,13 @@ import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.PrimaryKey import com.navi.pay.utils.NAVI_PAY_DATABASE_CONVERSATIONS_TABLE_NAME +import org.joda.time.DateTime +import org.joda.time.DateTimeZone @Entity(tableName = NAVI_PAY_DATABASE_CONVERSATIONS_TABLE_NAME) data class ConversationEntity( @PrimaryKey @ColumnInfo(name = "conversationId") val conversationId: String, - @ColumnInfo(name = "lastSyncedTimestamp") val lastSyncedTimestamp: String, + @ColumnInfo(name = "lastSyncedTimestamp") + val lastSyncedTimestamp: String = DateTime(0, DateTimeZone.UTC).toString(), @ColumnInfo(name = "isFullSyncCompleted") val isFullSyncCompleted: Boolean, ) diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/repository/ChatRepository.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/repository/ChatRepository.kt new file mode 100644 index 0000000000..9451e7cd69 --- /dev/null +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/repository/ChatRepository.kt @@ -0,0 +1,204 @@ +/* + * + * * Copyright © 2025 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.pay.management.chat.repository + +import com.navi.base.sharedpref.CommonPrefConstants +import com.navi.base.sharedpref.PreferenceManager +import com.navi.base.utils.FirestoreDataProvider +import com.navi.common.checkmate.model.MetricInfo +import com.navi.common.network.models.RepoResult +import com.navi.common.network.models.isSuccessWithData +import com.navi.common.network.retrofit.ResponseCallback +import com.navi.common.utils.log +import com.navi.pay.common.usecase.UpiRequestIdUseCase +import com.navi.pay.common.utils.fetchUserPhoneNumber +import com.navi.pay.management.chat.dao.ConversationsDao +import com.navi.pay.management.chat.dao.MessagesDao +import com.navi.pay.management.chat.model.network.ConversationsResponse +import com.navi.pay.management.chat.model.network.CreateConversationRequest +import com.navi.pay.management.chat.model.network.CreateConversationResponse +import com.navi.pay.management.chat.model.network.MessageSyncRequest +import com.navi.pay.management.chat.model.network.MessageSyncResponse +import com.navi.pay.management.chat.model.network.Participant +import com.navi.pay.management.chat.model.network.toFirestorePayload +import com.navi.pay.management.chat.model.network.toMessageItem +import com.navi.pay.management.chat.model.view.ConversationEntity +import com.navi.pay.management.chat.model.view.MessageContent +import com.navi.pay.management.chat.model.view.MessageEntity +import com.navi.pay.management.chat.model.view.MessageStatus +import com.navi.pay.management.chat.model.view.MessageType +import com.navi.pay.management.common.transaction.model.network.TransactionRole +import com.navi.pay.network.retrofit.NaviPayRetrofitService +import com.navi.pay.utils.NAVI_PAY_CHAT_CONVERSATION_FIREBASE_PATH +import com.navi.pay.utils.NAVI_PAY_CHAT_CONVERSATION_IDENTIFIER +import javax.inject.Inject +import org.joda.time.DateTime + +class ChatRepository +@Inject +constructor( + private val conversationsDao: ConversationsDao, + private val naviPayRetrofitService: NaviPayRetrofitService, + private val messagesDao: MessagesDao, + private val requestIdUseCase: UpiRequestIdUseCase, + private val firestoreDataProvider: FirestoreDataProvider, +) : ResponseCallback() { + + suspend fun getConversations( + metricInfo: MetricInfo> + ): RepoResult { + return apiResponseCallback( + response = naviPayRetrofitService.getConversations(), + metricInfo = metricInfo, + ) + } + + suspend fun insertAllConversations(conversationEntityList: List) = + conversationsDao.insertAll(conversationEntityList = conversationEntityList) + + suspend fun getConversationsBySyncStatus(isFullSyncCompleted: Boolean) = + conversationsDao.getConversationsBySyncStatus(isFullSyncCompleted = isFullSyncCompleted) + + suspend fun getAllConversationsByIds(conversationIds: List) = + conversationsDao.getAllConversationsByIds(conversationIds = conversationIds) + + suspend fun insertAllMessages(messageEntityList: List) = + messagesDao.insertAll(messageEntityList = messageEntityList) + + suspend fun getMessagesForConversationIdsFromNetwork( + messageSyncRequest: MessageSyncRequest, + metricInfo: MetricInfo>, + ): RepoResult { + return apiResponseCallback( + response = naviPayRetrofitService.getMessages(messageSyncRequest = messageSyncRequest), + metricInfo = metricInfo, + ) + } + + suspend fun sendMessage( + text: String, + conversationId: String, + receiverExternalId: String, + metricInfo: MetricInfo>, + ) { + + val ownUserExternalId = + PreferenceManager.getStringPreference(CommonPrefConstants.USER_EXTERNAL_ID) + val ownUserPhoneNumber = fetchUserPhoneNumber() + + val messageId = requestIdUseCase.execute() + + val messageEntity = + MessageEntity( + messageId = messageId, + conversationId = conversationId, + type = MessageType.TEXT, + createdAt = DateTime.now(), + updatedAt = DateTime.now(), + content = + MessageContent.TextContent( + text = text, + senderExternalId = ownUserExternalId!!, + senderMobileNumber = ownUserPhoneNumber, + ), + role = TransactionRole.PAYER, + status = MessageStatus.PENDING, + ) + + messagesDao.insertAll(messageEntityList = listOf(messageEntity)) + + val createConversationResult = + createConversation( + conversationId = conversationId, + senderExternalId = ownUserExternalId, + receiverExternalId = receiverExternalId, + metricInfo = metricInfo, + ) + + if (!createConversationResult) { + messagesDao.updateMessageStatus(messageId = messageId, status = MessageStatus.FAILURE) + return + } + + writeMessageInFirestore(messageEntity = messageEntity) + } + + private suspend fun createConversation( + conversationId: String, + senderExternalId: String, + receiverExternalId: String, + metricInfo: MetricInfo>, + ): Boolean { + val isConversationAclExist = conversationsDao.get(conversationId = conversationId) != null + + if (isConversationAclExist) { + return true + } + + val createConversationApiResponse = + apiResponseCallback( + response = + naviPayRetrofitService.createConversation( + createConversationRequest = + CreateConversationRequest( + conversationId = conversationId, + users = + listOf( + Participant(userId = senderExternalId), + Participant(userId = receiverExternalId), + ), + ) + ), + metricInfo = metricInfo, + ) + + if (createConversationApiResponse.isSuccessWithData()) { + conversationsDao.insertAll( + conversationEntityList = + listOf( + ConversationEntity( + conversationId = conversationId, + isFullSyncCompleted = false, + ) + ) + ) + } + + return createConversationApiResponse.isSuccessWithData() + } + + private suspend fun writeMessageInFirestore(messageEntity: MessageEntity) { + val conversationPath = + getFirebaseConversationPath(conversationId = messageEntity.conversationId) + + try { + firestoreDataProvider.writeDocument( + collectionPath = conversationPath, + data = messageEntity.toMessageItem().toFirestorePayload(), + ) + + messagesDao.updateMessageStatus( + messageId = messageEntity.messageId, + status = MessageStatus.SUCCESS, + ) + } catch (e: Exception) { + e.log() + messagesDao.updateMessageStatus( + messageId = messageEntity.messageId, + status = MessageStatus.FAILURE, + ) + } + } + + private fun getFirebaseConversationPath(conversationId: String): String { + return NAVI_PAY_CHAT_CONVERSATION_FIREBASE_PATH.replace( + oldValue = NAVI_PAY_CHAT_CONVERSATION_IDENTIFIER, + newValue = conversationId, + ) + } +} diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/util/MessageContentConverter.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/util/MessageContentConverter.kt index e5adf39fff..e626a8716e 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/util/MessageContentConverter.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/util/MessageContentConverter.kt @@ -66,15 +66,15 @@ class MessageContentTypeAdapterFactory : TypeAdapterFactory { out.beginObject() when (value) { is MessageContent.TextContent -> { - out.name("type") + out.name("fieldValueType") out.value(MessageType.TEXT.name) - out.name("content") + out.name("fieldValueContent") textContentAdapter.write(out, value) } is MessageContent.OrderContent -> { - out.name("type") + out.name("fieldValueType") out.value(MessageType.ORDER.name) - out.name("content") + out.name("fieldValueContent") orderContentAdapter.write(out, value) } else -> @@ -98,8 +98,8 @@ class MessageContentTypeAdapterFactory : TypeAdapterFactory { while (reader.hasNext()) { when (reader.nextName()) { - "type" -> type = reader.nextString() - "content" -> content = JsonParser.parseReader(reader) + "fieldValueType" -> type = reader.nextString() + "fieldValueContent" -> content = JsonParser.parseReader(reader) else -> reader.skipValue() } } diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/util/SyncConversationsUseCase.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/util/SyncConversationsUseCase.kt index c68ad3676b..09cce59518 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/util/SyncConversationsUseCase.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/util/SyncConversationsUseCase.kt @@ -12,7 +12,7 @@ import com.navi.pay.common.sync.model.view.SyncEntity import com.navi.pay.common.sync.repository.SyncRepository import com.navi.pay.common.utils.getMetricInfo import com.navi.pay.management.chat.model.view.ConversationEntity -import com.navi.pay.management.chat.repository.ConversationsRepository +import com.navi.pay.management.chat.repository.ChatRepository import com.navi.pay.utils.NAVI_PAY_SYNC_TABLE_CONVERSATIONS_LIST_KEY import javax.inject.Inject @@ -20,7 +20,7 @@ import javax.inject.Inject class SyncConversationsUseCase @Inject constructor( - private val conversationsRepository: ConversationsRepository, + private val chatRepository: ChatRepository, private val syncRepository: SyncRepository, ) { @@ -36,7 +36,7 @@ constructor( } val conversationsApiResponse = - conversationsRepository.getConversations( + chatRepository.getConversations( metricInfo = getMetricInfo(screenName = screenName, isNae = { false }) ) @@ -44,12 +44,11 @@ constructor( return } - conversationsRepository.insertAll( + chatRepository.insertAllConversations( conversationEntityList = conversationsApiResponse.data!!.conversations.map { ConversationEntity( conversationId = it.conversationId, - lastSyncedTimestamp = "0", isFullSyncCompleted = false, ) } diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/util/SyncMessagesUseCase.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/util/SyncMessagesUseCase.kt index 7ad3b739d3..4911f8d9c5 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/util/SyncMessagesUseCase.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/management/chat/util/SyncMessagesUseCase.kt @@ -18,27 +18,19 @@ import com.navi.pay.management.chat.model.view.MessageContent import com.navi.pay.management.chat.model.view.MessageEntity import com.navi.pay.management.chat.model.view.MessageStatus import com.navi.pay.management.chat.model.view.MessageType -import com.navi.pay.management.chat.repository.ConversationsRepository -import com.navi.pay.management.chat.repository.MessagesRepository +import com.navi.pay.management.chat.repository.ChatRepository import javax.inject.Inject import org.joda.time.DateTime import org.joda.time.DateTimeZone -class SyncMessagesUseCase -@Inject -constructor( - private val conversationsRepository: ConversationsRepository, - private val messagesRepository: MessagesRepository, -) { +class SyncMessagesUseCase @Inject constructor(private val chatRepository: ChatRepository) { private val CONVERSATION_SYNC_BATCH_SIZE = 10 suspend fun execute(preferredConversationIds: List = emptyList(), screenName: String) { val existingConversationEntitiesFromPreferredConversationIds = - conversationsRepository.getAllConversationsByIds( - conversationIds = preferredConversationIds - ) + chatRepository.getAllConversationsByIds(conversationIds = preferredConversationIds) val existingIdsInDatabase = existingConversationEntitiesFromPreferredConversationIds.map { it.conversationId } @@ -56,7 +48,7 @@ constructor( } val partiallySyncedExistingConversations = - conversationsRepository.getConversationsBySyncStatus(isFullSyncCompleted = false) + chatRepository.getConversationsBySyncStatus(isFullSyncCompleted = false) val conversationsMap = (partiallySyncedExistingConversations + @@ -100,7 +92,7 @@ constructor( ) val messageSyncApiResponse = - messagesRepository.getMessagesForConversationIdsFromNetwork( + chatRepository.getMessagesForConversationIdsFromNetwork( messageSyncRequest = messageSyncRequest, metricInfo = getMetricInfo(screenName = screenName, isNae = { false }), ) @@ -155,13 +147,13 @@ constructor( ) } - messagesRepository.insertAll(messageEntityList = messageEntityListForConversation) + chatRepository.insertAllMessages(messageEntityList = messageEntityListForConversation) val latestUpdatedAtTimestamp = messageItemList.maxOf { it.messageCreatedAt } val isFullSyncCompleted = messageItemList.size < messageSyncResponse.messagesPageSize - conversationsRepository.insertAll( + chatRepository.insertAllConversations( conversationEntityList = listOf( ConversationEntity( diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/network/retrofit/NaviPayRetrofitService.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/network/retrofit/NaviPayRetrofitService.kt index 718ec6b704..b582c4905d 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/network/retrofit/NaviPayRetrofitService.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/network/retrofit/NaviPayRetrofitService.kt @@ -17,6 +17,8 @@ import com.navi.pay.management.blockedusers.model.network.BlockedUsersListRespon import com.navi.pay.management.blockedusers.model.network.UnblockActionRequest import com.navi.pay.management.blockedusers.model.network.UnblockActionResponse import com.navi.pay.management.chat.model.network.ConversationsResponse +import com.navi.pay.management.chat.model.network.CreateConversationRequest +import com.navi.pay.management.chat.model.network.CreateConversationResponse import com.navi.pay.management.chat.model.network.MessageSyncRequest import com.navi.pay.management.chat.model.network.MessageSyncResponse import com.navi.pay.management.collectrequest.model.network.CollectRequestsRequest @@ -367,11 +369,16 @@ interface NaviPayRetrofitService { @Path("orderId") orderId: String ): Response> - @GET("/chat/api/v1/conversations") + @GET("/v1/conversations") suspend fun getConversations(): Response> - @POST("/v1/conversations/messages/get") + @POST("/v2/conversations/fetch-messages") suspend fun getMessages( @Body messageSyncRequest: MessageSyncRequest ): Response> + + @POST("/chat/conversations") + suspend fun createConversation( + @Body createConversationRequest: CreateConversationRequest + ): Response> } diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/utils/NaviPayConstants.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/utils/NaviPayConstants.kt index 8913c2562e..7cc3aa1d62 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/utils/NaviPayConstants.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/utils/NaviPayConstants.kt @@ -377,6 +377,9 @@ const val SCRATCH_CARD_BANNER_BG = "https://public-assets.prod.navi-sa.in/navi-pay/png/scratch_card_banner_bg.png" const val NAVI_PAY_TNC_URL = "https://navi.com/terms-and-conditions" const val NAVI_PAY_BANK_LOGOS_V2_URL_BANK_IDENTIFIER_KEY = "bankIdentifier" +const val NAVI_PAY_CHAT_CONVERSATION_FIREBASE_PATH = + "conversations_ntl/{conversationId}/messages_ntl" +const val NAVI_PAY_CHAT_CONVERSATION_IDENTIFIER = "conversationId" // Navi pay bbps constants const val NAVI_PAY_BBPS_CATEGORY_ID = "category_id"