Android Htech - Movil

SDK Htech para aplicaciones Android.

Requisitos


NombreValor
minSdk23 (Android 6.0)
compileSdk recomendado35 o superior.
Java / JVM target11
Version Kotlin2.1.0 o superior
UIJetpack Compose (Material 3)
PermisosINTERNET

Antes de usar el SDK tu backend debe generar un orderId con el proceso begin transaction (para pagos) o begin-transaction-create-card (para guardar tarjeta). El SDK nunca crea órdenes: solo captura la tarjeta y procesa la orden que le indiques.


Nunca generes el orderId desde la app ni guardes llaves/credenciales de Htech en el código del cliente.


Instalacion.


Asegúrate de tener mavenCentral() en tus repositorios (settings.gradle.kts):

dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
    }
}

Si utilizas Kotlin DSL:

dependencies {
    implementation("com.htech:sdk:1.0.0")
}

Si utilizas Groovy:

dependencies {
    implementation 'com.htech:sdk:1.0.0'
}

Si utilizas el Version catalog (toml):

[versions]
htechSdk = "1.0.0"

[libraries]
htech-sdk = { group = "com.htech", name = "sdk", version.ref = "htechSdk" }


Ambientes: Sandbox y Produccion.

El SDK está en modo Sandbox por default, lo que te permite hacer transacciones de prueba antes de pasar a producción. Para cobros reales crea la instancia con isSandboxMode = false.


⚠️

El orderId debe pertenecer al mismo ambiente que el SDK. Una orden creada en sandbox no funcionará con isSandboxMode = false y viceversa.


📘

Recomendacion

Controla el ambiente con BuildConfig para no publicar por error una versión apuntando a sandbox:


val htech by lazy { Htech(isSandboxMode = BuildConfig.DEBUG) }

Integracion.


El SDK ofrece dos formas de integrarse. Elige según cuánto control necesitas sobre la UI:


Pantalla CompletaWidget
UIEl SDK abre su propia pantallaSe inserta dentro de tu pantalla Compose
Esfuerzo de integraciónMínimo (una llamada suspend)Medio (controller + callbacks)
Control del botón "Pagar"Del SDKTuyo (controller.processPayment())
Requiere ComposeNo (solo una ComponentActivity)Sí
3D SecureAutomáticoAutomático (el widget pasa a pantalla completa)

Integración en pantalla completa


Crear la instancia.

import com.htech.sdk.Htech

val htech by lazy { Htech() }                       // Sandbox
val htech by lazy { Htech(isSandboxMode = false) }  // Producción

Pago con tarjeta nueva - makePayment

Todas las funciones son suspend: llámalas desde una corrutina (lifecycleScope, viewModelScope o rememberCoroutineScope() en Compose). Reciben una ComponentActivity (por ejemplo AppCompatActivity o ComponentActivity) para abrir la pantalla de pago y devuelven el resultado cuando la pantalla se cierra.


lifecycleScope.launch {
    val response = htech.makePayment(
        orderId = orderId,              // obtenido de tu backend (begin transaction)
        activity = this@MainActivity,
        isDarkTheme = false,            // opcional, default false
    )

    if (response.isSuccess) {
        val authorization = response.payload["authorizationNumber"] as? String
        // Mostrar confirmación
    } else {
        val reason = response.payload["responseDescription"] as? String
        // Mostrar error / permitir reintento
    }
}

Pago con tarjeta guardada - makePaymentByToken

Muestra la pantalla de pago con la tarjeta tokenizada asociada a la orden (el usuario confirma el CVV).


lifecycleScope.launch {
    val response = htech.makePaymentByToken(
        orderId = orderId,
        activity = this@MainActivity,
        isDarkTheme = false,            // requerido en esta función
    )
}

Guardar tarjeta - saveCard

Requiere un orderId generado con begin-transaction-create-card.


lifecycleScope.launch {
    val result = htech.saveCard(
        orderId = orderId,
        activity = this@MainActivity,
        isDarkTheme = false,
    )

    if (result.isSuccess) {
        // Tarjeta guardada
    } else {
        Log.w("Htech", "No se guardó la tarjeta: ${result.message}")
    }
}

Integración con widget embebido


Composable que renderiza los campos de tarjeta dentro de tu propia pantalla. Tú controlas cuándo validar y cuándo cobrar mediante un HtechFieldController.

Ejemplo:


import com.htech.sdk.HtechCardFieldType
import com.htech.sdk.HtechCardFieldWidget
import com.htech.sdk.HtechFieldController
import com.htech.sdk.HtechWidgetStatus

@Composable
fun CheckoutScreen(orderId: String) {
    val controller = remember { HtechFieldController() }
    var isFormValid by remember { mutableStateOf(false) }
    var isProcessing by remember { mutableStateOf(false) }

    Column(Modifier.padding(16.dp)) {
        HtechCardFieldWidget(
            orderId = orderId,
            controller = controller,
            type = HtechCardFieldType.WIDGET,
            isSandboxMode = true,
            isDarkTheme = isSystemInDarkTheme(),
            onValidForm = { isValid, errors ->
                isFormValid = isValid
                // errors.numCard / errors.date / errors.cvv == true indica campo con error
            },
            onProcessPayment = { isProcessing = true },
            onPaymentResult = { response ->
                isProcessing = false
                if (response.isSuccess) { /* éxito */ } else { /* rechazo */ }
            },
            onError = { message ->
                isProcessing = false
                // Error de configuración, orderId inválido o WebView desactualizado
            },
            on3dsChallengeOpen = { isOpen -> /* opcional: analytics / UI */ },
            onGetWidgetStatus = { status ->
                // START_LOADING / FINISH_LOADING: útil para mostrar un skeleton
            },
        )

        Button(
            enabled = isFormValid && !isProcessing,
            onClick = { controller.processPayment() },
        ) { Text("Pagar") }
    }
}

Parametros:


ParametroTipoRequeridoDescripcion
orderIdStringNo*Orden a cobrar. *Si no lo envías aquí, debes enviarlo en processPayment(orderId).
controllerHtechFieldControllerSiPermite disparar validación y pago.
typeHtechCardFieldTypeSiTipo de vista.
isSandboxModeBooleanNoDefault true. Usa false en producción.
isDarkThemeBooleanNoDefault false.
onPaymentResult(HtechResponse) -> UnitSiResultado final del pago.
onValidForm(Boolean, HtechFormValid) -> UnitSi
Estado de validación del formulario.
onError(String) -> UnitSiErrores de integración/configuración
onProcessPayment(() -> Unit)?NoEl pago comenzó a procesarse.
on3dsChallengeOpen((Boolean) -> Unit)?No
Se abrió (true) o cerró (false) el reto 3DS.
onGetWidgetStatus((HtechWidgetStatus) -> Unit)?NoEl usuario cerró el formulario
modifierModifierNoEl ancho es fillMaxWidth; la altura la define el type.

Tipo de widget.


TipoUso
WIDGETCampos de tarjeta nueva, compacto
PAYMENT_TOKEN_WIDGETPago con tarjeta guardada o token y la UI de tipo CardField.
CHECKOUTFormulario de tarjeta nueva completo
CHECKOUT_PAYMENT_TOKENFormulario de tarjeta guardada completo
PAYMENT_TOKENVista completa de pago con token, con su propio botón

HtechFieldController.


Metodo/PropiedadDescripcion
processPayment(orderId: String? = null)Inicia el pago. La respuesta llega por onPaymentResult.
validateForm()Fuerza la validación. La respuesta llega por onValidForm.
dispose()Libera el controller. Solo cuando el widget ya no está en pantalla.
isAttachedtrue si está vinculado a un widget montado.
isDisposedtrue después de dispose().

Notas:

  • Un controller solo puede estar vinculado a un widget a la vez.
  • No uses un controller después de dispose(); lanza IllegalStateException.
  • No llames dispose() mientras el widget está montado.
  • Cuando el banco solicita autenticación 3DS, el widget pasa automáticamente a pantalla completa y regresa a su lugar al terminar. Durante el reto el botón "atrás" está bloqueado. No necesitas hacer nada adicional; on3dsChallengeOpen es solo informativo.

Respuesta - HtechResponse.


data class HtechResponse(
    val isSuccess: Boolean,
    val payload: Map<String, Any?>
)

Estructura de payload:

AtributoTipoDescripcion
responseCodeStringCódigo de respuesta del procesador.
responseDescriptionStringDescripción legible del resultado/rechazo.
authorizationNumberStringNúmero de autorización (solo pagos aprobados).
referenceNumberStringReferencia de la transacción.
statusString"approved" o "rejected".
orderMapid, amount, currency.
cardMaptoken de la tarjeta.

ℹ️

Si el usuario cierra la pantalla o hay un error de configuración, payload puede venir vacío. Usa siempre accesos seguros (as?).





Did this page help you?