Skip to content

Commit

Permalink
Merge pull request #174 from Tinkoff/v2.11
Browse files Browse the repository at this point in the history
V2.11
  • Loading branch information
jQwout authored Dec 29, 2022
2 parents 8769b11 + 79dc876 commit fb835d9
Show file tree
Hide file tree
Showing 94 changed files with 2,767 additions and 61 deletions.
2 changes: 0 additions & 2 deletions cardio/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,4 @@ dependencies {
implementation project(':ui')

testImplementation 'junit:junit:4.13'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
1 change: 1 addition & 0 deletions core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ dependencies {
implementation "com.squareup.okhttp3:okhttp:${okHttpVersion}"
implementation "com.google.code.gson:gson:$gsonVersion"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion"
testImplementation 'junit:junit:4.13'
}

Expand Down
4 changes: 4 additions & 0 deletions core/src/main/java/ru/tinkoff/acquiring/sdk/AcquiringSdk.kt
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,10 @@ class AcquiringSdk(
}
}

fun getTerminalPayMethods() : GetTerminalPayMethodsRequest {
return GetTerminalPayMethodsRequest(terminalKey)
}

fun submit3DSAuthorization(threeDSServerTransID: String, transStatus: String, request: (Submit3DSAuthorizationRequest.() -> Unit)? = null): Submit3DSAuthorizationRequest {
return Submit3DSAuthorizationRequest().apply {
terminalKey = this@AcquiringSdk.terminalKey
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package ru.tinkoff.acquiring.sdk.models.paysources

import ru.tinkoff.acquiring.sdk.models.PaymentSource

/**
* Тип оплаты с помощью Yandex Pay
*
* @param yandexPayToken токен для оплаты, полученный через Yandex Pay
*
* Created by i.golovachev
*/
class YandexPay(var yandexPayToken: String) : PaymentSource
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ object AcquiringApi {
const val SUBMIT_3DS_AUTHORIZATION = "Submit3DSAuthorization"
const val SUBMIT_3DS_AUTHORIZATION_V2 = "Submit3DSAuthorizationV2"
const val COMPLETE_3DS_METHOD_V2 = "Complete3DSMethodv2"
const val GET_TERMINAL_PAY_METHODS = "GetTerminalPayMethods"

const val API_ERROR_CODE_3DSV2_NOT_SUPPORTED = "106"
const val API_ERROR_CODE_CUSTOMER_NOT_FOUND = "7"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ internal class NetworkClient {

fun createGson(): Gson {
return GsonBuilder()
.disableHtmlEscaping()
.excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.STATIC)
.setExclusionStrategies(SerializableExclusionStrategy())
.registerTypeAdapter(CardStatus::class.java, CardStatusSerializer())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package ru.tinkoff.acquiring.sdk.requests

import com.google.gson.Gson
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.Deferred
import okhttp3.Response
import ru.tinkoff.acquiring.sdk.AcquiringSdk
import ru.tinkoff.acquiring.sdk.exceptions.NetworkException
Expand All @@ -34,7 +36,8 @@ import java.security.PublicKey
*
* @author Mariya Chernyadieva, Taras Nagorny
*/
abstract class AcquiringRequest<R : AcquiringResponse>(internal val apiMethod: String) : Request<R> {
abstract class AcquiringRequest<R : AcquiringResponse>(internal val apiMethod: String) :
Request<R> {

protected val gson: Gson = NetworkClient.createGson()

Expand All @@ -43,6 +46,7 @@ abstract class AcquiringRequest<R : AcquiringResponse>(internal val apiMethod: S

internal lateinit var terminalKey: String
internal lateinit var publicKey: PublicKey

@Volatile
private var disposed = false
private val ignoredFieldsSet: HashSet<String> = hashSetOf(DATA, RECEIPT, RECEIPTS, SHOPS)
Expand All @@ -51,7 +55,6 @@ abstract class AcquiringRequest<R : AcquiringResponse>(internal val apiMethod: S
internal open val tokenIgnoreFields: HashSet<String>
get() = ignoredFieldsSet


protected abstract fun validate()

override fun isDisposed(): Boolean {
Expand Down Expand Up @@ -81,6 +84,28 @@ abstract class AcquiringRequest<R : AcquiringResponse>(internal val apiMethod: S
client.call(request, responseClass, onSuccess, onFailure)
}

open fun performRequestAsync(responseClass: Class<R>): Deferred<Result<R>> {
this.validate()
val client = NetworkClient()
val deferred: CompletableDeferred<Result<R>> = CompletableDeferred()

client.call(this, responseClass,
onSuccess = {
deferred.complete(Result.success(it))
},
onFailure = {
deferred.complete(Result.failure(it))
})
return deferred
}

suspend fun performSuspendRequest(responseClass: Class<R>): Result<R> {
return performRequestAsync(responseClass).run {
start()
await()
}
}

@kotlin.jvm.Throws(NetworkException::class)
protected fun <R : AcquiringResponse> performRequestRaw(request: AcquiringRequest<R>): Response {
request.validate()
Expand Down Expand Up @@ -188,7 +213,7 @@ abstract class AcquiringRequest<R : AcquiringResponse>(internal val apiMethod: S
const val REQUEST_KEY = "RequestKey"
const val SOURCE = "Source"
const val PAYMENT_SOURCE = "PaymentSource"
const val ANDROID_PAY_TOKEN = "EncryptedPaymentData"
const val ENCRYPTED_PAYMENT_DATA = "EncryptedPaymentData"
const val DATA_TYPE = "DataType"
const val REDIRECT_DUE_DATE = "RedirectDueDate"
const val NOTIFICATION_URL = "NotificationURL"
Expand All @@ -202,5 +227,10 @@ abstract class AcquiringRequest<R : AcquiringResponse>(internal val apiMethod: S
const val THREE_DS_SERVER_TRANS_ID = "threeDSServerTransID"
const val TRANS_STATUS = "transStatus"
const val CRES = "cres"
const val PAYSOURCE = "Paysource"
}
}

suspend inline fun <reified R : AcquiringResponse> AcquiringRequest<R>.performSuspendRequest(): Result<R> {
return performSuspendRequest(R::class.java)
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,10 @@

package ru.tinkoff.acquiring.sdk.requests

import kotlinx.coroutines.Deferred
import ru.tinkoff.acquiring.sdk.exceptions.AcquiringSdkException
import ru.tinkoff.acquiring.sdk.models.PaymentSource
import ru.tinkoff.acquiring.sdk.models.paysources.AttachedCard
import ru.tinkoff.acquiring.sdk.models.paysources.CardData
import ru.tinkoff.acquiring.sdk.models.paysources.CardSource
import ru.tinkoff.acquiring.sdk.models.paysources.GooglePay
import ru.tinkoff.acquiring.sdk.models.paysources.*
import ru.tinkoff.acquiring.sdk.network.AcquiringApi.FINISH_AUTHORIZE_METHOD
import ru.tinkoff.acquiring.sdk.responses.FinishAuthorizeResponse

Expand Down Expand Up @@ -71,7 +69,7 @@ class FinishAuthorizeRequest : AcquiringRequest<FinishAuthorizeResponse>(FINISH_
private var cardId: String? = null
private var cvv: String? = null
private var source: String? = null
private var googlePayToken: String? = null
private var encryptedToken: String? = null
private var encodedCardData: String? = null

override val tokenIgnoreFields: HashSet<String>
Expand All @@ -93,7 +91,7 @@ class FinishAuthorizeRequest : AcquiringRequest<FinishAuthorizeResponse>(FINISH_
map.putIfNotNull(CVV, cvv)
map.putIfNotNull(EMAIL, email)
map.putIfNotNull(SOURCE, source)
map.putIfNotNull(ANDROID_PAY_TOKEN, googlePayToken)
map.putIfNotNull(ENCRYPTED_PAYMENT_DATA, encryptedToken)
map.putIfNotNull(IP, ip)
if (data != null) map.putDataIfNonNull(data)

Expand All @@ -106,7 +104,7 @@ class FinishAuthorizeRequest : AcquiringRequest<FinishAuthorizeResponse>(FINISH_

when (paymentSource) {
is CardData, is AttachedCard -> encodedCardData.validate(CARD_DATA)
is GooglePay -> googlePayToken.validate(ANDROID_PAY_TOKEN)
is GooglePay, is YandexPay -> encryptedToken.validate(ENCRYPTED_PAYMENT_DATA)
}
}

Expand All @@ -118,6 +116,11 @@ class FinishAuthorizeRequest : AcquiringRequest<FinishAuthorizeResponse>(FINISH_
super.performRequest(this, FinishAuthorizeResponse::class.java, onSuccess, onFailure)
}

override fun performRequestAsync(responseClass: Class<FinishAuthorizeResponse>): Deferred<Result<FinishAuthorizeResponse>> {
fillPaymentData()
return super.performRequestAsync(responseClass)
}

fun attachedCard(attachedCard: AttachedCard.() -> Unit): PaymentSource {
return AttachedCard().apply(attachedCard)
}
Expand All @@ -143,10 +146,14 @@ class FinishAuthorizeRequest : AcquiringRequest<FinishAuthorizeResponse>(FINISH_
}
is GooglePay -> {
data = paymentSource as GooglePay
this.googlePayToken = data.googlePayToken
this.encryptedToken = data.googlePayToken
this.source = GOOGLE_PAY
}

is YandexPay ->{
data = paymentSource as YandexPay
this.encryptedToken = data.yandexPayToken
this.source = YANDEX_PAY
}
else -> throw AcquiringSdkException(IllegalStateException("Unknown type in 'paymentSource'"))
}
}
Expand All @@ -160,5 +167,6 @@ class FinishAuthorizeRequest : AcquiringRequest<FinishAuthorizeResponse>(FINISH_
companion object {

private const val GOOGLE_PAY = "GooglePay"
private const val YANDEX_PAY = "YandexPay"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package ru.tinkoff.acquiring.sdk.requests

import ru.tinkoff.acquiring.sdk.network.AcquiringApi
import ru.tinkoff.acquiring.sdk.network.AcquiringApi.GET_TERMINAL_PAY_METHODS
import ru.tinkoff.acquiring.sdk.responses.GetTerminalPayMethodsResponse

/**
* Запрос в MAPI, проверяет доступности методов оплаты на терминале
*
* Created by Ivan Golovachev
*/
class GetTerminalPayMethodsRequest(
terminalKey: String,
paysource: Paysource = Paysource.SDK
) :
AcquiringRequest<GetTerminalPayMethodsResponse>(
"$GET_TERMINAL_PAY_METHODS?TerminalKey=$terminalKey&PaySource=$paysource") {

override val httpRequestMethod: String = AcquiringApi.API_REQUEST_METHOD_GET

override fun validate() = Unit

override fun asMap(): MutableMap<String, Any> = mutableMapOf()

override fun getToken(): String? = null

override fun execute(
onSuccess: (GetTerminalPayMethodsResponse) -> Unit,
onFailure: (Exception) -> Unit
) {
super.performRequest(this, GetTerminalPayMethodsResponse::class.java, onSuccess, onFailure)
}

enum class Paysource {
API, SDK
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,15 @@ class FinishAuthorizeResponse(
ThreeDsData(paymentId, acsUrl).apply {
md = this@FinishAuthorizeResponse.md
paReq = this@FinishAuthorizeResponse.paReq
version = threeDsVersion
version = threeDsVersion ?: "1.0.0"
}
} else if (tdsServerTransId != null && acsTransId != null) {
ThreeDsData(paymentId, acsUrl).apply {
tdsServerTransId = this@FinishAuthorizeResponse.tdsServerTransId
acsTransId = this@FinishAuthorizeResponse.acsTransId
acsRefNumber = this@FinishAuthorizeResponse.acsRefNumber
acsSignedContent = this@FinishAuthorizeResponse.acsSignedContent
version = threeDsVersion
version = threeDsVersion ?: "2.1.0"
}
} else throw AcquiringSdkException(IllegalStateException("Invalid 3DS params"))
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package ru.tinkoff.acquiring.sdk.responses

import com.google.gson.annotations.SerializedName

/**
* Ответ на запрос /v2/GetTerminalPayMethods
*
* @param terminalInfo - Характеристики терминала
*
*
* Created by Ivan Golovachev
*/
class GetTerminalPayMethodsResponse(

@SerializedName("TerminalInfo")
val terminalInfo: TerminalInfo? = null

) : AcquiringResponse()


/**
*
* @param terminalInfo - Характеристики терминала
* @param paymethods - Перечень доступных методов оплаты
* @param addCardScheme - Признак возможности сохранения карт
* @param tokenRequired - Признак необходимости подписания токеном
* @param initTokenRequired - Признак необходимости подписания токеном запроса /init
*
*
* Created by Ivan Golovachev
*/
class TerminalInfo(

@SerializedName("Paymethods")
val paymethods: List<PaymethodData> = emptyList(),

@SerializedName("AddCardScheme")
val addCardScheme: Boolean = false,

@SerializedName("TokenRequired")
val tokenRequired: Boolean = true,

@SerializedName("InitTokenRequired")
val initTokenRequired: Boolean = false
)

/**
* @param params - Перечень параметров подключения в формате ключ-значение
*/
class PaymethodData(

@SerializedName("PayMethod")
val paymethod: Paymethod? = null,

@SerializedName("Params")
val params: Map<String, String> = emptyMap()
)

enum class Paymethod {
@SerializedName("TinkoffPay")
TinkoffPay,

@SerializedName("YandexPay")
YandexPay,

@SerializedName("SBP")
SBP
}
2 changes: 2 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ POM_LICENCE_URL=https://github.com/Tinkoff/AcquiringSdkAndroid/blob/master/LICEN
POM_LICENCE_DIST=repo
POM_DEVELOPER_ID=tcs
POM_DEVELOPER_NAME=Tinkoff Credit Systems
org.gradle.daemon=true
org.gradle.jvmargs=-Xmx8096m -XX:+UseConcMarkSweepGC -Dfile.encoding=UTF-8

android.useAndroidX=true
android.enableJetifier=true
Expand Down
6 changes: 5 additions & 1 deletion gradle/versions.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ ext {

compileSdk = 31
minSdk = 21
yandexPayMinSdk = 23
targetSdk = 31
buildTools = '29.0.2'
buildTools = '30.0.3'

kotlinVersion = '1.6.10'
gradlePluginVersion = '7.1.2'
Expand All @@ -29,6 +30,9 @@ ext {
blurryVersion = '4.0.0'
bouncyCastleVersion = '1.65'
rootBeerVersion = '0.1.0'
materialVersion = '1.5.0'

mokitoKotlin = '4.0.0'

yandexPayVersion = '0.2.1'
}
Loading

0 comments on commit fb835d9

Please sign in to comment.