Skip to content

Commit

Permalink
Merge pull request #230 from tinkoff-mobile-tech/v2.13.1
Browse files Browse the repository at this point in the history
V2.13.1
  • Loading branch information
jQwout authored Apr 3, 2023
2 parents 68c2fc3 + 6f4c9a5 commit 3e184ab
Show file tree
Hide file tree
Showing 38 changed files with 602 additions and 122 deletions.
5 changes: 5 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 @@ -284,6 +284,11 @@ class AcquiringSdk(
*/
var isDeveloperMode = false

/**
* Позволяет переключать SDK на иной апи-контур, работает только в дебаг режиме
*/
var customUrl : String? = null


/**
* Логирует сообщение
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ package ru.tinkoff.acquiring.sdk.exceptions
*
* @author Mariya Chernyadieva
*/
class AcquiringSdkException(throwable: Throwable) : RuntimeException(throwable.message, throwable)
class AcquiringSdkException(throwable: Throwable, paymentId: Long? = null) : RuntimeException(throwable.message, throwable)
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright © 2020 Tinkoff Bank
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package ru.tinkoff.acquiring.sdk.exceptions

import ru.tinkoff.acquiring.sdk.models.enums.ResponseStatus

/**
* Исключение, выбрасываемое в случае, когда ожидание статуса платежа истекло
*
* @author i.golovachev
*/
class AcquiringSdkTimeoutException(
val throwable: Throwable,
val paymentId: Long?,
val status: ResponseStatus?,
) : RuntimeException(throwable.message, throwable)
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ enum class ResponseStatus {
REFUNDED,
PARTIAL_REFUNDED,
REJECTED,
DEADLINE_EXPIRED,
UNKNOWN,
LOOP_CHECKING,
COMPLETED,
Expand All @@ -57,6 +58,8 @@ enum class ResponseStatus {

private const val TDS_CHECKING_STRING = "3DS_CHECKING"
private const val TDS_CHECKED_STRING = "3DS_CHECKED"
val successStatuses = setOf(CONFIRMED,AUTHORIZED)
fun checkSuccessStatuses(status: ResponseStatus) : Boolean = status in successStatuses

@JvmStatic
fun fromString(stringValue: String): ResponseStatus {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,40 @@ object AcquiringApi {
/**
* Коды ошибок, сообщение которых можно показать конечным пользователям
*/
val errorCodesForUserShowing = listOf("53", "206", "224", "225", "252", "99", "101",
"1006", "1012", "1013", "1014", "1015", "1030", "1033", "1034", "1035", "1036", "1037", "1038",
"1039", "1040", "1041", "1042", "1043", "1051", "1054", "1057", "1065", "1082", "1089", "1091", "1096")
val errorCodesForUserShowing = listOf(
"53",
"206",
"224",
"225",
"252",
"99",
"101",
"1006",
"1012",
"1013",
"1014",
"1015",
"1030",
"1033",
"1034",
"1035",
"1036",
"1037",
"1038",
"1039",
"1040",
"1041",
"1042",
"1043",
"1051",
"1054",
"1057",
"1065",
"1082",
"1089",
"1091",
"1096"
)

/**
* Коды ошибок, вызванные временными неполадками системы
Expand Down Expand Up @@ -94,13 +125,22 @@ object AcquiringApi {
*/
fun getUrl(apiMethod: String): String {
return if (useV1Api(apiMethod)) {
if (AcquiringSdk.isDeveloperMode) API_URL_DEBUG_OLD else API_URL_RELEASE_OLD
if (AcquiringSdk.isDeveloperMode)
useCustomOrDefault(API_URL_DEBUG_OLD, AcquiringSdk.customUrl, "rest")
else
API_URL_RELEASE_OLD
} else {
if (AcquiringSdk.isDeveloperMode) API_URL_DEBUG else API_URL_RELEASE
if (AcquiringSdk.isDeveloperMode)
useCustomOrDefault(API_URL_DEBUG, AcquiringSdk.customUrl)
else
API_URL_RELEASE
}
}

internal fun useV1Api(apiMethod: String): Boolean {
return oldMethodsList.contains(apiMethod)
}

private fun useCustomOrDefault(default: String, custom: String?, oldOrV2: String = "v2") =
custom?.let { "$it/$oldOrV2" } ?: default
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ internal class NetworkClient {
onFailure(
AcquiringApiException(
result,
"${result.message ?: ""} ${result.details ?: ""}"
makeNetworkErrorMessage(result.message, result.details)
)
)
}
Expand Down Expand Up @@ -185,6 +185,10 @@ internal class NetworkClient {
return URL(builder.toString())
}

private fun makeNetworkErrorMessage(message : String?, details: String?): String {
return setOf(message.orEmpty(), details.orEmpty()).joinToString()
}

companion object {

fun createGson(): Gson {
Expand Down
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
VERSION_NAME=2.13.0
VERSION_CODE=20
VERSION_NAME=2.13.1
VERSION_CODE=21
GROUP=ru.tinkoff.acquiring

POM_DESCRIPTION=Library which allows you to use internet acquiring in your android app
Expand Down
3 changes: 3 additions & 0 deletions sample/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ android {
useJUnitPlatform()
}
}
lintOptions {
disable 'NetworkSecurityConfig'
}
}

dependencies {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package ru.tinkoff.acquiring.sample
import android.app.Application
import android.content.Context
import ru.tinkoff.acquiring.sample.utils.SessionParams
import ru.tinkoff.acquiring.sample.utils.SettingsSdkManager
import ru.tinkoff.acquiring.sample.utils.TerminalsManager
import ru.tinkoff.acquiring.sdk.AcquiringSdk
import ru.tinkoff.acquiring.sdk.TinkoffAcquiring
Expand All @@ -36,6 +37,7 @@ class SampleApplication : Application() {
initSdk(this, TerminalsManager.init(this).selectedTerminal)
AcquiringSdk.isDeveloperMode = true
AcquiringSdk.isDebug = true
AcquiringSdk.customUrl = SettingsSdkManager(this).customUrl
}

override fun onTerminate() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ import android.view.View
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.activity.result.ActivityResult
import androidx.activity.result.IntentSenderRequest
import androidx.activity.result.contract.ActivityResultContracts
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
Expand All @@ -34,6 +37,7 @@ import ru.tinkoff.acquiring.sample.models.Book
import ru.tinkoff.acquiring.sample.models.BooksRegistry
import ru.tinkoff.acquiring.sample.models.Cart
import ru.tinkoff.acquiring.sdk.AcquiringSdk
import ru.tinkoff.acquiring.sdk.TinkoffAcquiring
import ru.tinkoff.acquiring.sdk.models.options.screen.PaymentOptions
import ru.tinkoff.acquiring.sdk.payment.PaymentProcess.Companion.configure
import ru.tinkoff.acquiring.yandexpay.models.YandexPayData
Expand All @@ -55,6 +59,11 @@ class DetailsActivity : PayableActivity() {

private var book: Book? = null

private val paymentContract =
registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result: ActivityResult ->
handlePaymentResult(result.resultCode, result.data)
}

public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

Expand Down Expand Up @@ -84,7 +93,11 @@ class DetailsActivity : PayableActivity() {

val buttonBuy = findViewById<TextView>(R.id.btn_buy_now)
buttonBuy.setOnClickListener {
initPayment()
//Стандартный метод проведения оплаты с получением результата в OnActivityResult
//initPayment()

//Метод проведения оплаты с получением результата в ActivityResultAPI
initActivityResultAPIPayment()
}

val sbpButton = findViewById<View>(R.id.btn_fps_pay)
Expand All @@ -100,6 +113,12 @@ class DetailsActivity : PayableActivity() {
fillViews()
}

private fun initActivityResultAPIPayment() {
val pendingIntent = getPaymentPendingIntent()
val intentSenderRequest = IntentSenderRequest.Builder(pendingIntent).build()
paymentContract.launch(intentSenderRequest)
}

override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.details_menu, menu)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,15 @@ import android.view.MenuItem
import android.widget.ListView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import ru.tinkoff.acquiring.sample.R
import ru.tinkoff.acquiring.sample.SampleApplication
import ru.tinkoff.acquiring.sample.adapters.BooksListAdapter
import ru.tinkoff.acquiring.sample.models.Book
import ru.tinkoff.acquiring.sample.models.BooksRegistry
import ru.tinkoff.acquiring.sample.service.PaymentNotificationIntentService
import ru.tinkoff.acquiring.sample.service.PriceNotificationReceiver
import ru.tinkoff.acquiring.sample.ui.environment.AcqEnvironmentDialog
import ru.tinkoff.acquiring.sample.utils.PaymentNotificationManager
import ru.tinkoff.acquiring.sample.utils.SessionParams
import ru.tinkoff.acquiring.sample.utils.SettingsSdkManager
import ru.tinkoff.acquiring.sample.utils.TerminalsManager
import ru.tinkoff.acquiring.sdk.TinkoffAcquiring.Companion.EXTRA_CARD_ID
Expand Down Expand Up @@ -126,6 +124,10 @@ class MainActivity : AppCompatActivity(), BooksListAdapter.BookDetailsClickListe
AboutActivity.start(this)
true
}
R.id.menu_action_environment -> {
AcqEnvironmentDialog().show(supportFragmentManager, AttachCardManuallyDialogFragment.TAG)
true
}
R.id.menu_action_static_qr -> {
openStaticQrScreen()
true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,31 +18,34 @@ package ru.tinkoff.acquiring.sample.ui

import android.annotation.SuppressLint
import android.app.AlertDialog
import android.app.PendingIntent
import android.content.Intent
import android.os.Bundle
import android.view.MenuItem
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.fragment.app.commit
import ru.tinkoff.acquiring.sample.R
import ru.tinkoff.acquiring.sample.SampleApplication
import ru.tinkoff.acquiring.sample.utils.SessionParams
import ru.tinkoff.acquiring.sample.utils.SettingsSdkManager
import ru.tinkoff.acquiring.sample.utils.TerminalsManager
import ru.tinkoff.acquiring.sdk.AcquiringSdk.Companion.log
import ru.tinkoff.acquiring.sdk.TinkoffAcquiring
import ru.tinkoff.acquiring.sdk.TinkoffAcquiring.Companion.EXTRA_PAYMENT_ID
import ru.tinkoff.acquiring.sdk.TinkoffAcquiring.Companion.RESULT_ERROR
import ru.tinkoff.acquiring.sdk.exceptions.AcquiringSdkTimeoutException
import ru.tinkoff.acquiring.sdk.localization.AsdkSource
import ru.tinkoff.acquiring.sdk.localization.Language
import ru.tinkoff.acquiring.sdk.models.AsdkState
import ru.tinkoff.acquiring.sdk.models.GooglePayParams
import ru.tinkoff.acquiring.sdk.models.options.screen.PaymentOptions
import ru.tinkoff.acquiring.sdk.payment.PaymentListener
import ru.tinkoff.acquiring.sdk.payment.PaymentListenerAdapter
import ru.tinkoff.acquiring.sdk.payment.PaymentState
import ru.tinkoff.acquiring.sdk.utils.GooglePayHelper
import ru.tinkoff.acquiring.sdk.utils.Money
import ru.tinkoff.acquiring.sdk.utils.getLongOrNull
import ru.tinkoff.acquiring.yandexpay.YandexButtonFragment
import ru.tinkoff.acquiring.yandexpay.addYandexResultListener
import ru.tinkoff.acquiring.yandexpay.createYandexPayButtonFragment
Expand Down Expand Up @@ -138,6 +141,10 @@ open class PayableActivity : AppCompatActivity() {
tinkoffAcquiring.openPaymentScreen(this, createPaymentOptions(), PAYMENT_REQUEST_CODE)
}

protected fun getPaymentPendingIntent(): PendingIntent {
return tinkoffAcquiring.getPaymentPendingIntent(this, createPaymentOptions(), PAYMENT_REQUEST_CODE)
}

protected fun openDynamicQrScreen() {
tinkoffAcquiring.openDynamicQrScreen(this, createPaymentOptions(), DYNAMIC_QR_PAYMENT_REQUEST_CODE)
}
Expand Down Expand Up @@ -264,26 +271,24 @@ open class PayableActivity : AppCompatActivity() {
}
}

private fun handlePaymentResult(resultCode: Int, data: Intent?) {
protected fun handlePaymentResult(resultCode: Int, data: Intent?) {
when (resultCode) {
RESULT_OK -> onSuccessPayment()
RESULT_CANCELED -> Toast.makeText(this, R.string.payment_cancelled, Toast.LENGTH_SHORT).show()
RESULT_ERROR -> {
Toast.makeText(this, R.string.payment_failed, Toast.LENGTH_SHORT).show()
(data?.getSerializableExtra(TinkoffAcquiring.EXTRA_ERROR) as? Throwable)?.printStackTrace()
commonErrorHandler(data)
}
}
}

private fun handleYandexPayResult(resultCode: Int, data: Intent?) {
protected fun handleYandexPayResult(resultCode: Int, data: Intent?) {
when (resultCode) {
RESULT_OK -> {
acqFragment?.options = createPaymentOptions()
}
RESULT_CANCELED -> Toast.makeText(this, R.string.payment_cancelled, Toast.LENGTH_SHORT).show()
RESULT_ERROR -> {
Toast.makeText(this, R.string.payment_failed, Toast.LENGTH_SHORT).show()
(data?.getSerializableExtra(TinkoffAcquiring.EXTRA_ERROR) as? Throwable)?.printStackTrace()
commonErrorHandler(data)
}
}
}
Expand Down Expand Up @@ -357,6 +362,33 @@ open class PayableActivity : AppCompatActivity() {
isProgressShowing = false
}


private fun commonErrorHandler(data: Intent?) {
val error = getErrorFromIntent(data)
val paymentIdFromIntent = data?.getLongOrNull(EXTRA_PAYMENT_ID)
val message = configureToastMessage(error, paymentIdFromIntent)
log("toast message: $message")
error?.printStackTrace()
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}

private fun getErrorFromIntent(data: Intent?): Throwable? {
return (data?.getSerializableExtra(TinkoffAcquiring.EXTRA_ERROR) as? Throwable)
}

private fun configureToastMessage(error: Throwable?, paymentId: Long?): String {
val acqSdkTimeout = error as? AcquiringSdkTimeoutException
val payment = paymentId ?: acqSdkTimeout?.paymentId
val status = acqSdkTimeout?.status
return buildString {
append(getString(R.string.payment_failed))
append(" ")
payment?.let { append("paymentId: $it") }
append(" ")
status?.let { append("status: $it") }
}
}

companion object {

const val PAYMENT_REQUEST_CODE = 1
Expand Down
Loading

0 comments on commit 3e184ab

Please sign in to comment.