Updated on 2026-08-14

This commit is contained in:
Tangem 2025-12-16 16:22:06 +04:00
parent 495545fb58
commit 2cbaf822cf
37 changed files with 310 additions and 242 deletions

View file

@ -31,7 +31,7 @@ internal class TangemPay(
private fun createDevEnvironment(): ApiEnvironmentConfig = ApiEnvironmentConfig(
environment = ApiEnvironment.DEV,
baseUrl = "https://api.dev.us.paera.com/bff/",
baseUrl = "https://api.dev.us.paera.com/bff-v2/",
headers = createHeaders(),
)
@ -43,7 +43,7 @@ internal class TangemPay(
private fun createProdEnvironment(): ApiEnvironmentConfig = ApiEnvironmentConfig(
environment = ApiEnvironment.PROD,
baseUrl = "https://api.us.paera.com/bff/",
baseUrl = "https://api.us.paera.com/bff-v2/",
headers = createHeaders(),
)

View file

@ -3,109 +3,13 @@ package com.tangem.datasource.api.pay
import com.tangem.datasource.api.common.response.ApiResponse
import com.tangem.datasource.api.pay.models.request.*
import com.tangem.datasource.api.pay.models.response.*
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.POST
import retrofit2.http.PUT
import retrofit2.http.Path
import retrofit2.http.Query
import retrofit2.http.*
private const val TX_HISTORY_PAGING_DEFAULT_LIMIT = 20
@Suppress("TooManyFunctions")
interface TangemPayApi {
// region: auth
@POST("v1/auth/challenge")
suspend fun generateNonceByCardId(@Body request: GenerateNoneByCardIdRequest): ApiResponse<GenerateNonceResponse>
@POST("v1/auth/challenge")
suspend fun generateNonceByCardWallet(
@Body request: GenerateNoneByCardWalletRequest,
): ApiResponse<GenerateNonceResponse>
@POST("v1/auth/token")
suspend fun getAccessTokenByCardId(@Body request: GetAccessTokenByCardIdRequest): ApiResponse<JWTResponse>
@POST("v1/auth/token")
suspend fun getTokenByCustomerWallet(@Body request: GetTokenByCustomerWalletRequest): ApiResponse<JWTResponse>
@POST("v1/auth/token/refresh")
suspend fun refreshCustomerWalletAccessToken(
@Body request: RefreshCustomerWalletAccessTokenRequest,
): ApiResponse<JWTResponse>
@POST("v1/auth/token")
suspend fun getAccessTokenByCardWallet(@Body request: GetAccessTokenByCardWalletRequest): ApiResponse<JWTResponse>
@POST("v1/auth/token/refresh")
suspend fun refreshCardIdAccessToken(@Body request: RefreshTokenByCardIdRequest): ApiResponse<JWTResponse>
@POST("v1/auth/token/refresh")
suspend fun refreshCardWalletAccessToken(@Body request: RefreshTokenByCardWalletRequest): ApiResponse<JWTResponse>
@POST("v1/auth/token/exchange")
suspend fun exchangeAccessToken(@Body request: ExchangeAccessTokenRequest): ApiResponse<JWTResponse>
// endregion
// region: activation
@POST("v1/activation/status")
suspend fun getRemoteActivationStatus(
@Header("Authorization") authHeader: String,
@Body request: ActivationStatusRequest,
): ApiResponse<CardActivationRemoteStateResponse>
@POST("v1/activation/acceptance/message")
suspend fun getCardWalletAcceptance(
@Header("Authorization") authHeader: String,
@Body request: GetCardWalletAcceptanceRequest,
): ApiResponse<VisaDataToSignResponse>
@POST("v1/activation/acceptance/message")
suspend fun getCustomerWalletAcceptance(
@Header("Authorization") authHeader: String,
@Body request: GetCustomerWalletAcceptanceRequest,
): ApiResponse<VisaDataToSignResponse>
@POST("v1/activation/data")
suspend fun activateByCardWallet(
@Header("Authorization") authHeader: String,
@Body body: ActivationByCardWalletRequest,
): ApiResponse<Unit>
@POST("v1/activation/data")
suspend fun activateByCustomerWallet(
@Header("Authorization") authHeader: String,
@Body body: ActivationByCustomerWalletRequest,
): ApiResponse<Unit>
@POST("v1/activation/pin")
suspend fun setPinCode(
@Header("Authorization") authHeader: String,
@Body body: SetPinCodeRequest,
): ApiResponse<Unit>
// endregion
@GET("customer/info")
suspend fun getCustomerInfo(
@Header("Authorization") authHeader: String,
@Query("card_id") cardId: String,
): ApiResponse<VisaCustomerInfo>
@GET("product_instance/transactions")
suspend fun getTxHistory(
@Header("Authorization") authHeader: String,
@Query("customer_id") customerId: String,
@Query("product_instance_id") productInstanceId: String,
@Query("limit") limit: Int,
@Query("offset") offset: Int,
): ApiResponse<VisaTxHistoryResponse>
@GET("v1/customer/transactions")
suspend fun getTangemPayTxHistory(
@Header("Authorization") authHeader: String,

View file

@ -12,11 +12,11 @@ data class CustomerMeResponse(
data class Result(
@Json(name = "id") val id: String,
@Json(name = "state") val state: String,
@Json(name = "createdAt") val createdAt: String,
@Json(name = "created_at") val createdAt: String,
@Json(name = "product_instance") val productInstance: ProductInstance?,
@Json(name = "payment_account") val paymentAccount: PaymentAccount?,
@Json(name = "kyc") val kyc: Kyc?,
@Json(name = "depositAddress") val depositAddress: String?,
@Json(name = "deposit_address") val depositAddress: String?,
@Json(name = "card") val card: Card?,
@Json(name = "balance") val balance: BalanceResponse?,
)
@ -24,49 +24,49 @@ data class CustomerMeResponse(
@JsonClass(generateAdapter = true)
data class ProductInstance(
@Json(name = "id") val id: String,
@Json(name = "cid") val cid: String,
@Json(name = "cid") val cid: String?,
@Json(name = "card_id") val cardId: String,
@Json(name = "card_wallet_address") val cardWalletAddress: String,
@Json(name = "card_wallet_address") val cardWalletAddress: String?,
@Json(name = "status") val status: Status,
@Json(name = "updated_at") val updatedAt: String,
@Json(name = "payment_account_id") val paymentAccountId: String,
) {
@JsonClass(generateAdapter = false)
enum class Status {
@Json(name = "new")
@Json(name = "NEW")
NEW,
@Json(name = "ready_for_manufacturing")
@Json(name = "READY_FOR_MANUFACTURING")
READY_FOR_MANUFACTURING,
@Json(name = "manufacturing")
@Json(name = "MANUFACTURING")
MANUFACTURING,
@Json(name = "sent_to_delivery")
@Json(name = "SENT_TO_DELIVERY")
SENT_TO_DELIVERY,
@Json(name = "delivered")
@Json(name = "DELIVERED")
DELIVERED,
@Json(name = "activating")
@Json(name = "ACTIVATING")
ACTIVATING,
@Json(name = "active")
@Json(name = "ACTIVE")
ACTIVE,
@Json(name = "blocked")
@Json(name = "BLOCKED")
BLOCKED,
@Json(name = "deactivating")
@Json(name = "DEACTIVATING")
DEACTIVATING,
@Json(name = "deactivated")
@Json(name = "DEACTIVATED")
DEACTIVATED,
@Json(name = "canceled")
@Json(name = "CANCELED")
CANCELED,
@Json(name = "unknown")
@Json(name = "UNKNOWN")
UNKNOWN,
}
}
@ -91,8 +91,8 @@ data class CustomerMeResponse(
@JsonClass(generateAdapter = true)
data class Card(
@Json(name = "token") val token: String,
@Json(name = "expiration_month") val expirationMonth: Int,
@Json(name = "expiration_year") val expirationYear: Int,
@Json(name = "expiration_month") val expirationMonth: String,
@Json(name = "expiration_year") val expirationYear: String,
@Json(name = "emboss_name") val embossName: String,
@Json(name = "card_type") val cardType: String,
@Json(name = "card_status") val cardStatus: String,

View file

@ -4,7 +4,7 @@ import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class VisaErrorResponse(
data class TangemPayErrorResponse(
@Json(name = "error") val error: Error,
) {
@JsonClass(generateAdapter = true)

View file

@ -0,0 +1,104 @@
package com.tangem.datasource.api.visa
import com.tangem.datasource.api.common.response.ApiResponse
import com.tangem.datasource.api.pay.models.request.RefreshTokenByCardIdRequest
import com.tangem.datasource.api.pay.models.request.RefreshTokenByCardWalletRequest
import com.tangem.datasource.api.pay.models.request.SetPinCodeRequest
import com.tangem.datasource.api.visa.models.request.ActivationByCardWalletRequest
import com.tangem.datasource.api.visa.models.request.ActivationByCustomerWalletRequest
import com.tangem.datasource.api.visa.models.request.ActivationStatusRequest
import com.tangem.datasource.api.visa.models.request.ExchangeAccessTokenRequest
import com.tangem.datasource.api.visa.models.request.GenerateNoneByCardIdRequest
import com.tangem.datasource.api.visa.models.request.GenerateNoneByCardWalletRequest
import com.tangem.datasource.api.visa.models.request.GetAccessTokenByCardIdRequest
import com.tangem.datasource.api.visa.models.request.GetAccessTokenByCardWalletRequest
import com.tangem.datasource.api.visa.models.request.GetCardWalletAcceptanceRequest
import com.tangem.datasource.api.visa.models.request.GetCustomerWalletAcceptanceRequest
import com.tangem.datasource.api.visa.models.response.CardActivationRemoteStateResponse
import com.tangem.datasource.api.visa.models.response.GenerateNonceResponse
import com.tangem.datasource.api.visa.models.response.JWTResponse
import com.tangem.datasource.api.visa.models.response.VisaCustomerInfo
import com.tangem.datasource.api.visa.models.response.VisaDataToSignResponse
import com.tangem.datasource.api.visa.models.response.VisaTxHistoryResponse
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.POST
import retrofit2.http.Query
interface VisaApi {
@POST("v1/auth/token/refresh")
suspend fun refreshCardWalletAccessToken(@Body request: RefreshTokenByCardWalletRequest): ApiResponse<JWTResponse>
@POST("v1/auth/challenge")
suspend fun generateNonceByCardId(@Body request: GenerateNoneByCardIdRequest): ApiResponse<GenerateNonceResponse>
@POST("v1/auth/challenge")
suspend fun generateNonceByCardWallet(
@Body request: GenerateNoneByCardWalletRequest,
): ApiResponse<GenerateNonceResponse>
@POST("v1/auth/token")
suspend fun getAccessTokenByCardId(@Body request: GetAccessTokenByCardIdRequest): ApiResponse<JWTResponse>
@POST("v1/auth/token")
suspend fun getAccessTokenByCardWallet(@Body request: GetAccessTokenByCardWalletRequest): ApiResponse<JWTResponse>
@POST("v1/auth/token/refresh")
suspend fun refreshCardIdAccessToken(@Body request: RefreshTokenByCardIdRequest): ApiResponse<JWTResponse>
@POST("v1/auth/token/exchange")
suspend fun exchangeAccessToken(@Body request: ExchangeAccessTokenRequest): ApiResponse<JWTResponse>
@POST("v1/activation/status")
suspend fun getRemoteActivationStatus(
@Header("Authorization") authHeader: String,
@Body request: ActivationStatusRequest,
): ApiResponse<CardActivationRemoteStateResponse>
@POST("v1/activation/acceptance/message")
suspend fun getCardWalletAcceptance(
@Header("Authorization") authHeader: String,
@Body request: GetCardWalletAcceptanceRequest,
): ApiResponse<VisaDataToSignResponse>
@POST("v1/activation/acceptance/message")
suspend fun getCustomerWalletAcceptance(
@Header("Authorization") authHeader: String,
@Body request: GetCustomerWalletAcceptanceRequest,
): ApiResponse<VisaDataToSignResponse>
@POST("v1/activation/data")
suspend fun activateByCardWallet(
@Header("Authorization") authHeader: String,
@Body body: ActivationByCardWalletRequest,
): ApiResponse<Unit>
@POST("v1/activation/data")
suspend fun activateByCustomerWallet(
@Header("Authorization") authHeader: String,
@Body body: ActivationByCustomerWalletRequest,
): ApiResponse<Unit>
@POST("v1/activation/pin")
suspend fun setPinCode(
@Header("Authorization") authHeader: String,
@Body body: SetPinCodeRequest,
): ApiResponse<Unit>
@GET("customer/info")
suspend fun getCustomerInfo(
@Header("Authorization") authHeader: String,
@Query("card_id") cardId: String,
): ApiResponse<VisaCustomerInfo>
@GET("product_instance/transactions")
suspend fun getTxHistory(
@Header("Authorization") authHeader: String,
@Query("customer_id") customerId: String,
@Query("product_instance_id") productInstanceId: String,
@Query("limit") limit: Int,
@Query("offset") offset: Int,
): ApiResponse<VisaTxHistoryResponse>
}

View file

@ -1,4 +1,4 @@
package com.tangem.datasource.api.pay.models.request
package com.tangem.datasource.api.visa.models.request
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

View file

@ -1,4 +1,4 @@
package com.tangem.datasource.api.pay.models.request
package com.tangem.datasource.api.visa.models.request
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

View file

@ -1,4 +1,4 @@
package com.tangem.datasource.api.pay.models.request
package com.tangem.datasource.api.visa.models.request
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

View file

@ -1,4 +1,4 @@
package com.tangem.datasource.api.pay.models.request
package com.tangem.datasource.api.visa.models.request
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

View file

@ -1,4 +1,4 @@
package com.tangem.datasource.api.pay.models.request
package com.tangem.datasource.api.visa.models.request
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

View file

@ -1,4 +1,4 @@
package com.tangem.datasource.api.pay.models.request
package com.tangem.datasource.api.visa.models.request
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

View file

@ -1,4 +1,4 @@
package com.tangem.datasource.api.pay.models.request
package com.tangem.datasource.api.visa.models.request
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

View file

@ -1,4 +1,4 @@
package com.tangem.datasource.api.pay.models.request
package com.tangem.datasource.api.visa.models.request
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

View file

@ -1,4 +1,4 @@
package com.tangem.datasource.api.pay.models.request
package com.tangem.datasource.api.visa.models.request
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

View file

@ -1,4 +1,4 @@
package com.tangem.datasource.api.pay.models.request
package com.tangem.datasource.api.visa.models.request
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

View file

@ -1,4 +1,4 @@
package com.tangem.datasource.api.pay.models.response
package com.tangem.datasource.api.visa.models.response
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

View file

@ -1,4 +1,4 @@
package com.tangem.datasource.api.pay.models.response
package com.tangem.datasource.api.visa.models.response
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

View file

@ -1,4 +1,4 @@
package com.tangem.datasource.api.pay.models.response
package com.tangem.datasource.api.visa.models.response
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

View file

@ -1,4 +1,4 @@
package com.tangem.datasource.api.pay.models.response
package com.tangem.datasource.api.visa.models.response
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

View file

@ -1,4 +1,4 @@
package com.tangem.datasource.api.pay.models.response
package com.tangem.datasource.api.visa.models.response
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

View file

@ -1,4 +1,4 @@
package com.tangem.datasource.api.pay.models.response
package com.tangem.datasource.api.visa.models.response
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

View file

@ -5,7 +5,6 @@ import com.tangem.datasource.api.common.blockaid.BlockAidApi
import com.tangem.datasource.api.common.config.ApiConfig
import com.tangem.datasource.api.common.config.ApiConfig.Companion.MOCKED_BUILD_TYPE
import com.tangem.datasource.api.common.config.ApiConfigs
import com.tangem.datasource.api.common.config.MoonPay
import com.tangem.datasource.api.common.config.managers.ApiConfigsManager
import com.tangem.datasource.api.common.config.managers.DevApiConfigsManager
import com.tangem.datasource.api.common.config.managers.MockApiConfigsManager
@ -21,6 +20,7 @@ import com.tangem.datasource.api.pay.TangemPayAuthApi
import com.tangem.datasource.api.stakekit.StakeKitApi
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.api.tangemTech.YieldSupplyApi
import com.tangem.datasource.api.visa.VisaApi
import com.tangem.datasource.di.utils.RetrofitApiBuilder
import com.tangem.datasource.di.utils.RetrofitApiBuilder.Timeouts
import com.tangem.datasource.local.preferences.AppPreferencesStore
@ -129,7 +129,16 @@ internal object NetworkModule {
@Provides
@Singleton
fun provideTangemVisaApi(retrofitApiBuilder: RetrofitApiBuilder): TangemPayApi {
fun provideTangemPayApi(retrofitApiBuilder: RetrofitApiBuilder): TangemPayApi {
return retrofitApiBuilder.build(
apiConfigId = ApiConfig.ID.TangemPay,
applyTimeoutAnnotations = false,
)
}
@Provides
@Singleton
fun provideVisaApi(retrofitApiBuilder: RetrofitApiBuilder): VisaApi {
return retrofitApiBuilder.build(
apiConfigId = ApiConfig.ID.TangemPay,
applyTimeoutAnnotations = false,

View file

@ -251,7 +251,7 @@ internal class ProdApiConfigsManagerTest {
id = ApiConfig.ID.TangemPay,
expected = ApiEnvironmentConfig(
environment = ApiEnvironment.DEV,
baseUrl = "https://api.dev.us.paera.com/bff/",
baseUrl = "https://api.dev.us.paera.com/bff-v2/",
headers = mapOf(
"version" to ProviderSuspend { VERSION_NAME },
"platform" to ProviderSuspend { "Android" },