Updated on 2026-08-14

This commit is contained in:
Tangem 2026-05-25 22:45:58 +04:00
parent 84af4950a1
commit ff2559df3e
27 changed files with 904 additions and 20 deletions

View file

@ -83,6 +83,10 @@ sealed class DeepLinkRoute {
data object Yield : DeepLinkRoute() {
override val host: String = "yield"
}
data object PayAppMain : DeepLinkRoute() {
override val host: String = "pay-app-main"
}
}
enum class DeepLinkScheme(val scheme: String) {

View file

@ -6,6 +6,8 @@ object DeeplinkConst {
const val TANGEM_SCHEME = "tangem"
const val WALLET_ID_KEY = "user_wallet_id"
const val CUSTOMER_WALLET_ID_KEY = "customer_wallet_id"
const val CUSTOMER_ID_KEY = "customer_id"
const val NETWORK_ID_KEY = "network_id"
const val TYPE_KEY = "type"
const val TOKEN_ID_KEY = "token_id"

View file

@ -3,6 +3,7 @@ package com.tangem.common.routing.deeplink
import android.os.Bundle
import com.tangem.common.routing.DeepLinkRoute
import com.tangem.common.routing.DeepLinkScheme
import com.tangem.common.routing.deeplink.DeeplinkConst.CUSTOMER_WALLET_ID_KEY
import com.tangem.common.routing.deeplink.DeeplinkConst.DEEPLINK_KEY
import com.tangem.common.routing.deeplink.DeeplinkConst.DERIVATION_PATH_KEY
import com.tangem.common.routing.deeplink.DeeplinkConst.NAME_KEY
@ -11,6 +12,7 @@ import com.tangem.common.routing.deeplink.DeeplinkConst.TOKEN_ID_KEY
import com.tangem.common.routing.deeplink.DeeplinkConst.TRANSACTION_ID_KEY
import com.tangem.common.routing.deeplink.DeeplinkConst.TYPE_KEY
import com.tangem.common.routing.deeplink.DeeplinkConst.WALLET_ID_KEY
import com.tangem.domain.visa.model.TangemPayPushNotificationType
import com.tangem.utils.converter.Converter
object PayloadToDeeplinkConverter : Converter<Map<String, String>, String?> {
@ -18,6 +20,7 @@ object PayloadToDeeplinkConverter : Converter<Map<String, String>, String?> {
override fun convert(value: Map<String, String>): String? {
return when {
value[DEEPLINK_KEY] != null -> value[DEEPLINK_KEY]
isTangemPayPushNotificationPayload(value) -> buildTangemPayNotificationDeeplink(value)
isTangemPushNotificationPayload(value) -> buildNotificationDeeplink(value)
else -> null
}
@ -70,4 +73,19 @@ object PayloadToDeeplinkConverter : Converter<Map<String, String>, String?> {
payload.containsKey(TOKEN_ID_KEY) &&
payload.containsKey(WALLET_ID_KEY)
}
private fun isTangemPayPushNotificationPayload(payload: Map<String, String>): Boolean {
return payload.containsKey(CUSTOMER_WALLET_ID_KEY) && payload[TYPE_KEY] in TangemPayPushNotificationType.all
}
private fun buildTangemPayNotificationDeeplink(payload: Map<String, String>): String? {
val walletId = payload[CUSTOMER_WALLET_ID_KEY]
val type = payload[TYPE_KEY]
if (walletId.isNullOrEmpty() || type.isNullOrEmpty()) return null
return DeepLinkBuilder().setScheme(DeepLinkScheme.Tangem.scheme).apply {
setAction(DeepLinkRoute.PayAppMain.host)
payload.forEach { (key, value) -> addQueryParam(key, value) }
}.build()
}
}

View file

@ -2,11 +2,14 @@ package com.tangem.common.routing.deeplink
import com.google.common.truth.Truth.assertThat
import com.tangem.common.routing.deeplink.DeeplinkConst.DEEPLINK_KEY
import com.tangem.common.routing.deeplink.DeeplinkConst.CUSTOMER_WALLET_ID_KEY
import com.tangem.common.routing.deeplink.DeeplinkConst.DERIVATION_PATH_KEY
import com.tangem.common.routing.deeplink.DeeplinkConst.NETWORK_ID_KEY
import com.tangem.common.routing.deeplink.DeeplinkConst.TOKEN_ID_KEY
import com.tangem.common.routing.deeplink.DeeplinkConst.TRANSACTION_ID_KEY
import com.tangem.common.routing.deeplink.DeeplinkConst.TYPE_KEY
import com.tangem.common.routing.deeplink.DeeplinkConst.WALLET_ID_KEY
import com.tangem.domain.visa.model.TangemPayPushNotificationType
import org.junit.Test
internal class PayloadToDeeplinkConverterTest {
@ -145,4 +148,88 @@ internal class PayloadToDeeplinkConverterTest {
// THEN
assertThat(result).isNull()
}
@Test
fun `GIVEN tangem pay card_ready push payload WHEN convert THEN should return pay-app-main deeplink`() {
// GIVEN
val payload = mapOf(
TYPE_KEY to TangemPayPushNotificationType.CARD_READY.value,
CUSTOMER_WALLET_ID_KEY to "wallet123",
)
// WHEN
val result = PayloadToDeeplinkConverter.convert(payload)
// THEN
assertThat(result).isEqualTo(
"tangem://pay-app-main?type=card_ready&customer_wallet_id=wallet123",
)
}
@Test
fun `GIVEN tangem pay transaction_spend push payload WHEN convert THEN should return pay-app-main deeplink with transaction_id`() {
// GIVEN
val payload = mapOf(
TYPE_KEY to TangemPayPushNotificationType.TRANSACTION_SPEND.value,
CUSTOMER_WALLET_ID_KEY to "wallet123",
TRANSACTION_ID_KEY to "test456",
)
// WHEN
val result = PayloadToDeeplinkConverter.convert(payload)
// THEN
assertThat(result).isEqualTo(
"tangem://pay-app-main?type=transaction_spend&customer_wallet_id=wallet123&transaction_id=test456",
)
}
@Test
fun `GIVEN tangem pay top_up push payload WHEN convert THEN should return pay-app-main deeplink`() {
// GIVEN
val payload = mapOf(
TYPE_KEY to TangemPayPushNotificationType.TOP_UP.value,
CUSTOMER_WALLET_ID_KEY to "wallet123",
TRANSACTION_ID_KEY to "test456",
)
// WHEN
val result = PayloadToDeeplinkConverter.convert(payload)
// THEN
assertThat(result).isEqualTo(
"tangem://pay-app-main?type=declined_top_up&customer_wallet_id=wallet123&transaction_id=test456",
)
}
@Test
fun `GIVEN tangem pay collateral push payload WHEN convert THEN should return pay-app-main deeplink`() {
// GIVEN
val payload = mapOf(
TYPE_KEY to TangemPayPushNotificationType.COLLATERAL.value,
CUSTOMER_WALLET_ID_KEY to "wallet123",
)
// WHEN
val result = PayloadToDeeplinkConverter.convert(payload)
// THEN
assertThat(result).isEqualTo(
"tangem://pay-app-main?type=collateral&customer_wallet_id=wallet123",
)
}
@Test
fun `GIVEN tangem pay push payload with missing customer_wallet_id WHEN convert THEN should return null`() {
// GIVEN
val payload = mapOf(
TYPE_KEY to TangemPayPushNotificationType.CARD_READY.value,
)
// WHEN
val result = PayloadToDeeplinkConverter.convert(payload)
// THEN
assertThat(result).isNull()
}
}