Updated on 2026-08-14

This commit is contained in:
Tangem 2022-10-17 19:46:06 +05:00
parent 84e5496689
commit 123f8b2e34
25 changed files with 411 additions and 296 deletions

View file

@ -1,6 +1,7 @@
package com.tangem.network.api.paymentology
import retrofit2.http.Body
import retrofit2.http.Headers
import retrofit2.http.POST
/**
@ -8,21 +9,30 @@ import retrofit2.http.POST
*/
interface PaymentologyApi {
@Headers("Content-Type: application/json")
@POST("card/verify")
fun checkRegistration(
suspend fun checkRegistration(
@Body request: CheckRegistrationRequests,
): RegistrationResponse.Item
): RegistrationResponse
@Headers("Content-Type: application/json")
@POST("card/get_challenge")
fun requestAttestationChallenge(
suspend fun requestAttestationChallenge(
@Body request: CheckRegistrationRequests.Item,
): AttestationResponse
@Headers("Content-Type: application/json")
@POST("card/set_pin")
fun registerWallet(
suspend fun registerWallet(
@Body request: RegisterWalletRequest,
): RegisterWalletResponse
@Headers("Content-Type: application/json")
@POST("card/kyc")
suspend fun registerKYC(
@Body request: RegisterKYCRequest,
): RegisterWalletResponse
companion object {
val baseUrl: String = "https://paymentologygate.oa.r.appspot.com/"
}

View file

@ -3,6 +3,7 @@ package com.tangem.network.api.paymentology
import com.tangem.common.extensions.toHexString
import com.tangem.common.services.Result
import com.tangem.common.services.performRequest
import com.tangem.network.common.MoshiConverter
import com.tangem.network.common.createRetrofitInstance
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@ -15,17 +16,19 @@ class PaymentologyApiService(
) {
private val api = createRetrofitInstance(
baseUrl = PaymentologyApi.baseUrl,
converterFactory = MoshiConverter.createFactory(MoshiConverter.sdkMoshi()),
logEnabled = logEnabled,
).create(PaymentologyApi::class.java)
suspend fun checkRegistration(
cardId: String,
publicKey: ByteArray,
): Result<RegistrationResponse.Item> = withContext(Dispatchers.IO) {
// later convert response to SaltPayRegistrator.State
): Result<RegistrationResponse> = withContext(Dispatchers.IO) {
val requestItem = CheckRegistrationRequests.Item(cardId, publicKey.toHexString())
val requests = listOf(requestItem)
performRequest { api.checkRegistration(CheckRegistrationRequests(requests)) }
val request = CheckRegistrationRequests(listOf(requestItem))
performRequest {
api.checkRegistration(request)
}
}
suspend fun requestAttestationChallenge(
@ -33,12 +36,28 @@ class PaymentologyApiService(
publicKey: ByteArray,
): Result<AttestationResponse> = withContext(Dispatchers.IO) {
val requestItem = CheckRegistrationRequests.Item(cardId, publicKey.toHexString())
performRequest { api.requestAttestationChallenge(requestItem) }
performRequest {
api.requestAttestationChallenge(requestItem)
}
}
suspend fun registerWallet(
request: RegisterWalletRequest,
): Result<RegisterWalletResponse> = withContext(Dispatchers.IO) {
performRequest { api.registerWallet(request) }
performRequest {
api.registerWallet(request)
}
}
suspend fun registerKYC(
request: RegisterKYCRequest,
): Result<RegisterWalletResponse> = withContext(Dispatchers.IO) {
performRequest {
api.registerKYC(request)
}
}
companion object {
fun stub(): PaymentologyApiService = PaymentologyApiService(false)
}
}

View file

@ -1,6 +1,7 @@
package com.tangem.network.api.paymentology
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import com.tangem.common.extensions.calculateHashCode
/**
@ -9,10 +10,11 @@ import com.tangem.common.extensions.calculateHashCode
data class CheckRegistrationRequests(
val requests: List<Item>,
) {
@JsonClass(generateAdapter = true)
data class Item(
@Json(name = "CID")
var cardId: String = "",
var publicKey: String = "",
val cardId: String = "",
val publicKey: String = "",
)
}
@ -35,12 +37,12 @@ data class RegisterWalletRequest(
other as RegisterWalletRequest
if (cardId != other.cardId) return false
if (publicKey.contentEquals(other.publicKey)) return false
if (walletPublicKey.contentEquals(other.walletPublicKey)) return false
if (walletSalt.contentEquals(other.walletSalt)) return false
if (walletSignature.contentEquals(other.walletSignature)) return false
if (cardSalt.contentEquals(other.cardSalt)) return false
if (cardSignature.contentEquals(other.cardSignature)) return false
if (!publicKey.contentEquals(other.publicKey)) return false
if (!walletPublicKey.contentEquals(other.walletPublicKey)) return false
if (!walletSalt.contentEquals(other.walletSalt)) return false
if (!walletSignature.contentEquals(other.walletSignature)) return false
if (!cardSalt.contentEquals(other.cardSalt)) return false
if (!cardSignature.contentEquals(other.cardSignature)) return false
if (pin != other.pin) return false
return true
@ -56,4 +58,34 @@ data class RegisterWalletRequest(
cardSignature.contentHashCode(),
pin.hashCode(),
)
}
data class RegisterKYCRequest(
@Json(name = "CID")
val cardId: String,
val publicKey: ByteArray,
val kycProvider: String,
val kycRefId: String,
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as RegisterKYCRequest
if (cardId != other.cardId) return false
if (!publicKey.contentEquals(other.publicKey)) return false
if (kycProvider != other.kycProvider) return false
if (kycRefId != other.kycRefId) return false
return true
}
override fun hashCode(): Int = calculateHashCode(
cardId.hashCode(),
publicKey.contentHashCode(),
kycProvider.hashCode(),
kycRefId.hashCode(),
)
}

View file

@ -6,16 +6,12 @@ import com.tangem.common.extensions.calculateHashCode
/**
[REDACTED_AUTHOR]
*/
interface ErrorContainer {
val error: String?
}
data class RegistrationResponse(
val results: List<Item>,
val results: List<Item> = listOf(),
val success: Boolean,
override val error: String?,
val errorCode: String?,
) : ErrorContainer {
val error: String?,
val errorCode: Int?,
) {
data class Item(
@Json(name = "CID")
@ -28,20 +24,22 @@ data class RegistrationResponse(
val blockchainInit: Boolean?,
@Json(name = "kyc_passed")
val kycPassed: Boolean?,
@Json(name = "kyc_waiting")
val kycWaiting: Boolean?,
@Json(name = "kyc_provider")
val kycProvider: String?,
@Json(name = "kyc_date")
val kycDate: String?,
@Json(name = "disabled_by_admin")
val disabledByAdmin: Boolean?,
override val error: String?,
) : ErrorContainer
val error: String?,
)
}
data class AttestationResponse(
val challenge: ByteArray,
val challenge: ByteArray?,
val success: Boolean,
override val error: String?,
val errorCode: String?,
) : ErrorContainer {
val error: String?,
val errorCode: Int?,
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
@ -49,7 +47,7 @@ data class AttestationResponse(
other as AttestationResponse
if (challenge.contentEquals(other.challenge)) return false
if (!challenge.contentEquals(other.challenge)) return false
if (success != other.success) return false
if (error != other.error) return false
if (errorCode != other.errorCode) return false
@ -67,6 +65,6 @@ data class AttestationResponse(
data class RegisterWalletResponse(
val success: Boolean,
override val error: String?,
val errorCode: String?,
) : ErrorContainer
val error: String?,
val errorCode: Int?,
)

View file

@ -1,6 +1,7 @@
package com.tangem.network.common
import com.tangem.common.module.ModuleError
import com.tangem.common.module.ModuleErrorCode
import com.tangem.common.module.ModuleMessage
/**
@ -12,12 +13,11 @@ sealed class NetworkError(
subCode: Int,
override val message: String,
override val data: Any?,
) : NetworkModuleMessage, ModuleError {
override val code: Int = ERROR_CODE_NETWORK + subCode
) : NetworkModuleMessage, ModuleError() {
override val code: Int = ModuleErrorCode.NETWORK + subCode
companion object {
// base code used for all error in the module
const val ERROR_CODE_NETWORK = 20000
// const val CODE_ANY_OTHER = 100..199
// const val CODE_ANY_OTHER = 100..199, 200..299
}
}

View file

@ -1,9 +0,0 @@
package com.tangem.network.common
/**
[REDACTED_AUTHOR]
*/
interface NetworkInternalException
sealed class NetworkException(message: String?) : Throwable(message), NetworkInternalException {
}