Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Adds token device flow #131

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ class OneTapFragment : Fragment(), LifecycleListener {
button.setOnClickListener {
activity?.apply {
CardFormWithFragment.Builder.withAccessToken(
"TEST-3510478914010328-072812-fca99ed95a163ad9a0640d390f899c6b-798240981",
"MLA", "test_flow")
"APP_USR-7092-091618-d06c56436d6949fa2c8401f8186074b4-786856560",
"MLB", "test_flow")
.setThirdPartyCard(true, true)
.build()
.start(supportFragmentManager, REQUEST_CODE, R.id.container)
Expand Down
2 changes: 1 addition & 1 deletion buildSrc/src/main/java/Versions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ object Versions {
const val kotlin = "1.3.71"
const val kotlinCoroutines = "1.3.0"
const val picassoDiskCache = "1.+"
const val pxAddons = "4.+"
const val pxAddons = "LOCAL-4.98.0-13122021163435873"
const val andesUi = "3.+"

// Tests
Expand Down
2 changes: 2 additions & 0 deletions cardform/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ android {
buildTypes {
debug {
buildConfigField "String", "API_ENVIRONMENT", "\"production\""
buildConfigField "String", "GATEWAY_ENVIRONMENT", "\"\""
buildConfigField "boolean", "HTTP_CLIENT_LOG", "true"
}

release {
buildConfigField "String", "API_ENVIRONMENT", "\"production\""
buildConfigField "String", "GATEWAY_ENVIRONMENT", "\"\""
buildConfigField "boolean", "HTTP_CLIENT_LOG", "false"
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ open class CardForm : Parcelable {
val cardInfo: CardInfoDto?
val acceptThirdPartyCard: Boolean
val activateCard: Boolean
val tokenizationFlowEnabled: Boolean

protected constructor(builder: Builder) {
siteId = builder.siteId
Expand All @@ -41,6 +42,7 @@ open class CardForm : Parcelable {
cardInfo = builder.cardInfo
acceptThirdPartyCard = builder.acceptThirdPartyCard
activateCard = builder.activateCard
tokenizationFlowEnabled = builder.tokenizationFlowEnabled
}

protected constructor(parcel: Parcel) {
Expand All @@ -54,6 +56,7 @@ open class CardForm : Parcelable {
cardInfo = parcel.readParcelable(CardInfoDto::class.java.classLoader)
acceptThirdPartyCard = parcel.readByte() != 0.toByte()
activateCard = parcel.readByte() != 0.toByte()
tokenizationFlowEnabled = parcel.readByte() != 0.toByte()
}

open fun start(activity: AppCompatActivity, requestCode: Int) {
Expand Down Expand Up @@ -110,6 +113,9 @@ open class CardForm : Parcelable {
var activateCard: Boolean = true
private set

var tokenizationFlowEnabled = true
private set

open fun setExcludedTypes(excludedTypes: List<String>) = apply {
this.excludedTypes = excludedTypes
}
Expand All @@ -121,6 +127,8 @@ open class CardForm : Parcelable {
this.activateCard = activateCard
}

open fun setTokenizationFlowEnabled(enabled: Boolean) = apply { tokenizationFlowEnabled = enabled }

fun <T : CardFormService> setCardFormHandler(handlerIntent: CardFormIntent<T>) = apply { cardFormIntent = handlerIntent }

protected fun setPublicKey(publicKey: String) = apply { this.publicKey = publicKey }
Expand Down Expand Up @@ -153,6 +161,7 @@ open class CardForm : Parcelable {
parcel.writeParcelable(cardInfo, flags)
parcel.writeByte(if(acceptThirdPartyCard) 1 else 0)
parcel.writeByte(if(activateCard) 1 else 0)
parcel.writeByte(if(tokenizationFlowEnabled) 1 else 0)
}

override fun describeContents() = 0
Expand All @@ -169,4 +178,4 @@ open class CardForm : Parcelable {
override fun newArray(size: Int) = arrayOfNulls<CardForm?>(size)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.mercadolibre.android.cardform.data.model.response

internal data class AssociatedCard(
internal data class AssociatedCardDM(
val dateCreated: String,
val dateLastTimeUsed: String,
val dateLastUpdated: String,
Expand All @@ -12,5 +12,6 @@ internal data class AssociatedCard(
val paymentMethod: PaymentMethod,
val siteId: String,
val status: String,
val userId: Int
)
val userId: Int,
val enrollmentSuggested: Boolean
)
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package com.mercadolibre.android.cardform.data.model.response

import android.os.Parcelable
import com.mercadopago.android.px.addons.tokenization.TokenizationResponse
import kotlinx.android.parcel.Parcelize

@Parcelize
data class CardResultDto(
val cardId: String,
val bin: String,
val paymentType: String,
val lastFourDigits: String
) : Parcelable
val lastFourDigits: String,
val tokenizationResponse: TokenizationResponse? = null
) : Parcelable
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package com.mercadolibre.android.cardform.data.model.response

import com.mercadolibre.android.cardform.data.model.body.CardHolder

internal data class CardToken(
internal data class CardTokenDM(
val cardNumberLength: Int,
val cardholder: CardHolder,
val dateCreated: String,
Expand All @@ -20,4 +20,4 @@ internal data class CardToken(
val securityCodeLength: Int,
val status: String,
val esc: String?
)
)

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.mercadolibre.android.cardform.data.repository

import com.mercadolibre.android.cardform.base.ResponseCallback
import com.mercadolibre.android.cardform.data.model.request.AssociatedCardParam
import com.mercadolibre.android.cardform.data.model.response.AssociatedCard
import com.mercadolibre.android.cardform.data.model.response.AssociatedCardDM
import com.mercadolibre.android.cardform.domain.model.params.AssociateCardParam

internal interface CardAssociationRepository {
suspend fun associateCard(param: AssociatedCardParam): ResponseCallback<AssociatedCard>
}
suspend fun associateCard(param: AssociateCardParam): ResponseCallback<AssociatedCardDM>
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import com.mercadolibre.android.cardform.data.model.body.AssociatedCardBody
import com.mercadolibre.android.cardform.data.model.body.Features
import com.mercadolibre.android.cardform.data.model.body.IssuerBody
import com.mercadolibre.android.cardform.data.model.body.PaymentMethodBody
import com.mercadolibre.android.cardform.data.model.request.AssociatedCardParam
import com.mercadolibre.android.cardform.data.service.CardAssociationService
import com.mercadolibre.android.cardform.domain.model.params.AssociateCardParam
import kotlinx.coroutines.withContext

internal class CardAssociationRepositoryImpl(
Expand All @@ -19,7 +19,7 @@ internal class CardAssociationRepositoryImpl(
private val contextProvider: CoroutineContextProvider = CoroutineContextProvider()
) : CardAssociationRepository {

override suspend fun associateCard(param: AssociatedCardParam) =
override suspend fun associateCard(param: AssociateCardParam) =
withContext(contextProvider.IO) {
runCatching {
associationService.associateCard(
Expand All @@ -38,4 +38,4 @@ internal class CardAssociationRepositoryImpl(
).resolveRetrofitResponse()
}.fold(::Success, ::Failure)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.mercadolibre.android.cardform.data.model.response.RegisterCard
import com.mercadolibre.android.cardform.data.service.CardService
import com.mercadolibre.android.cardform.network.exceptions.ExcludePaymentException
import com.mercadolibre.android.cardform.data.model.body.CardInfoDto
import com.mercadolibre.android.cardform.domain.CardRepository
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
Expand Down Expand Up @@ -65,4 +66,4 @@ internal class CardRepositoryImpl(
}
}.await()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,20 @@ import com.mercadolibre.android.cardform.base.Response.Failure
import com.mercadolibre.android.cardform.base.resolveRetrofitResponse
import com.mercadolibre.android.cardform.data.model.body.CardInfoBody
import com.mercadolibre.android.cardform.data.service.TokenizeService
import com.mercadolibre.android.cardform.domain.CardTokenRepository
import kotlinx.coroutines.withContext

internal class TokenizeRepositoryImpl(
internal class CardTokenRepositoryImpl(
private val tokenizeService: TokenizeService,
private val contextProvider: CoroutineContextProvider = CoroutineContextProvider()
) : TokenizeRepository {
) : CardTokenRepository {

override suspend fun tokenizeCard(cardInfoBody: CardInfoBody) =
override suspend fun get(cardInfoBody: CardInfoBody) =
withContext(contextProvider.IO) {
runCatching {
tokenizeService
.createTokenAsync(cardInfoBody)
.resolveRetrofitResponse()
}.fold(::Success, ::Failure)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.mercadolibre.android.cardform.data.repository

import com.mercadolibre.android.cardform.base.Response
import com.mercadolibre.android.cardform.base.ResponseCallback
import com.mercadolibre.android.cardform.domain.TokenDeviceRepository
import com.mercadopago.android.px.addons.TokenDeviceBehaviour
import com.mercadopago.android.px.addons.tokenization.Tokenize

internal class TokenDeviceRepositoryImpl(
private val flowId: String,
private val sessionId: String,
private val tokenDeviceBehaviour: TokenDeviceBehaviour
) : TokenDeviceRepository {

override val isFeatureAvailable: Boolean
get() = tokenDeviceBehaviour.isFeatureAvailable

override fun get(cardId: String): ResponseCallback<Tokenize> {
return Response.Success(tokenDeviceBehaviour.getTokenize(flowId, cardId).sessionId(sessionId))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,16 @@ package com.mercadolibre.android.cardform.data.service

import com.mercadolibre.android.cardform.BuildConfig
import com.mercadolibre.android.cardform.data.model.body.AssociatedCardBody
import com.mercadolibre.android.cardform.data.model.response.AssociatedCard
import com.mercadolibre.android.cardform.data.model.response.AssociatedCardDM
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.POST
import retrofit2.http.Query

private const val ENVIRONMENT = BuildConfig.API_ENVIRONMENT

internal interface CardAssociationService {
@POST("/$ENVIRONMENT/px_mobile/v1/card")
suspend fun associateCard(
@Body associatedCardBody: AssociatedCardBody
): Response<AssociatedCard>
}
): Response<AssociatedCardDM>
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@ internal interface CardService {

@GET("/{environment}/px_mobile/v1/card")
suspend fun getCardInfoAsync(
@Path("environment") environment : String,
@Query("bin") bin : String,
@Query("site_id") siteId : String,
@Query("excluded_payment_types") excludedPaymentTypes : List<String>? = null,
@Query("odr") odrFlag : Boolean = true
@Path("environment") environment: String,
@Query("bin") bin: String,
@Query("site_id") siteId: String,
@Query("excluded_payment_types") excludedPaymentTypes: List<String>? = null,
@Query("odr") odrFlag: Boolean = true
): Response<RegisterCard>

@POST("/{environment}/px_mobile/v1/card/marketplace")
suspend fun getCardInfoAsyncFromMarketplace(
@Path("environment") environment : String,
@Body cardInfo: CardInfoDto
@Path("environment") environment: String,
@Body cardInfo: CardInfoDto
): Response<RegisterCard>
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ internal interface FinishInscriptionService {
suspend fun getFinishInscription(
@Body finishInscriptionBody: FinishInscriptionBody
): Response<FinishInscriptionData>
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@ import com.mercadolibre.android.cardform.BuildConfig
import com.mercadolibre.android.cardform.data.model.response.initinscription.InscriptionDataModel
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Query

private const val ENVIRONMENT = BuildConfig.API_ENVIRONMENT

internal interface InscriptionService {

@GET("/$ENVIRONMENT/px_mobile/v1/card_webpay/inscription/init")
suspend fun getInscription(
): Response<InscriptionDataModel>
}
suspend fun getInscription(): Response<InscriptionDataModel>
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package com.mercadolibre.android.cardform.data.service

import com.mercadolibre.android.cardform.BuildConfig
import com.mercadolibre.android.cardform.data.model.body.CardInfoBody
import com.mercadolibre.android.cardform.data.model.response.CardToken
import com.mercadolibre.android.cardform.data.model.response.CardTokenDM
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.POST
import retrofit2.http.Query

internal interface TokenizeService {
@POST("/v1/card_tokens")

@POST("/v1/card_tokens/${BuildConfig.GATEWAY_ENVIRONMENT}")
suspend fun createTokenAsync(
@Body cardInfoBody: CardInfoBody
): Response<CardToken>
}
): Response<CardTokenDM>
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@ package com.mercadolibre.android.cardform.di

import android.content.Context
import com.mercadolibre.android.cardform.CardForm
import com.mercadolibre.android.cardform.di.module.*
import com.mercadolibre.android.cardform.di.module.BehaviourModule
import com.mercadolibre.android.cardform.di.module.LocalRepositoryModule
import com.mercadolibre.android.cardform.di.module.NetworkModule
import com.mercadolibre.android.cardform.di.module.RepositoryModule
import com.mercadolibre.android.cardform.di.module.ServiceModule
import com.mercadolibre.android.cardform.di.module.TrackerModule
import com.mercadolibre.android.cardform.di.module.UseCaseModule
import com.mercadolibre.android.cardform.di.module.ViewModelModule

internal class Dependencies {

Expand Down Expand Up @@ -31,11 +38,13 @@ internal class Dependencies {
cardForm.siteId,
cardForm.excludedTypes,
cardForm.flowId,
cardForm.sessionId,
cardForm.cardInfo,
cardForm.acceptThirdPartyCard,
cardForm.activateCard
cardForm.activateCard,
behaviourModule!!
)
useCaseModule = UseCaseModule(repositoryModule!!)
useCaseModule = UseCaseModule(cardForm, repositoryModule!!)
localPreferences = LocalRepositoryModule(context.applicationContext)
trackerModule = TrackerModule(
cardForm.siteId,
Expand Down Expand Up @@ -67,4 +76,4 @@ internal class Dependencies {
companion object {
val instance: Dependencies by lazy { Dependencies() }
}
}
}
Loading