conekta-elements
0.2.0-beta.2indexedPayment UI toolkit enabling secure card tokenization via the Conekta API, with built-in tokenizer, crypto and HTTP client, pluggable UI components and CDN-loaded card-brand icons.
Payment UI toolkit enabling secure card tokenization via the Conekta API, with built-in tokenizer, crypto and HTTP client, pluggable UI components and CDN-loaded card-brand icons.
Kotlin Multiplatform payment UI library for Android, iOS, and Web. Provides card tokenization components built on top of the Conekta API.
dependencies {
implementation("io.conekta:conekta-elements-compose:0.2.0-beta.2")
}
This includes conekta-elements-shared transitively. No need to add both.
dependencies {
implementation("io.conekta:conekta-elements-shared:0.2.0-beta.2")
}
Artifacts are published to Maven Central. No additional repository configuration required.
For GitHub Packages (pre-release builds):
// settings.gradle.kts
dependencyResolutionManagement {
repositories {
maven {
url = uri("https://maven.pkg.github.com/conekta/conekta-elements")
credentials {
username = providers.gradleProperty("gpr.user").orNull ?: System.getenv("GP_USER")
password = providers.gradleProperty("gpr.token").orNull ?: System.getenv("GP_TOKEN")
}
}
}
}
The compose module uses Coil 3 to load card brand icons from Conekta's CDN. Initialize it in your Application class:
import coil3.ImageLoader
import coil3.SingletonImageLoader
import io.conekta.compose.ConektaImageLoader
class MyApp : Application(), SingletonImageLoader.Factory {
override fun newImageLoader(context: Context): ImageLoader {
return ConektaImageLoader.newImageLoader(context)
}
}
Register in AndroidManifest.xml:
<application android:name=".MyApp" ... >
The compose module produces composeKit.xcframework, distributed as a zip asset in every GitHub release.
Add the package dependency in Xcode via File > Add Package Dependencies using the repository URL, or add a binary target in your Package.swift:
let package = Package(
...
targets: [
.binaryTarget(
name: "composeKit",
url: "https://github.com/conekta/conekta-elements/releases/download/0.2.0-beta.2/composeKit.xcframework.zip",
checksum: "e5fc1a7030756eea3f8cc4c229c178baac9369e4c3ba3238274f03824fdb02b2"
),
.target(
name: "YourTarget",
dependencies: ["composeKit"]
)
]
)
The checksum is available in checksum.txt included in the release assets.
composeKit.xcframework.zip from the latest releasecomposeKit.xcframework into your Xcode projectnpm install @conekta/elements
See webApp/README.md for full documentation.
All platforms require a Conekta public key to tokenize cards. Get yours from the Conekta Dashboard:
import { ConektaProvider, ExpressCheckout } ;
() {
(
);
}
Install tooling:
# Java (via SDKMAN)
sdk env install
# Node.js (via nvm)
nvm install
All common tasks are available via make:
# Build
make build # Clean build all modules
make build-ci # Build with configuration cache (CI)
make build-XCFramework # Build iOS XCFramework
# Test
make shared-test # Run shared module tests (Android, iOS, JS) + coverage
make compose-test
make ios-test
make lint-check
make lint-fix
make publish-local
make publish
make js-build
Or use Gradle directly:
# Compile specific targets
./gradlew :shared:compileKotlinIosSimulatorArm64
./gradlew :shared:compileKotlinJs
./gradlew :compose:compileKotlinIosArm64
# Run specific test suites
./gradlew :shared:testAndroidHostTest
./gradlew :shared:jsNodeTest
./gradlew :shared:iosSimulatorArm64Test
./gradlew :compose:testAndroidHostTest
# String resource validation
./gradlew :compose:validateStringsOrder
./gradlew :compose:validateStringsSpelling
# Coverage reports
./gradlew :shared:koverXmlReport
./gradlew :compose:koverXmlReport
# All tests across all platforms
make shared-test # shared: Android + iOS + JS + Kover coverage
make compose-test # compose: Robolectric Android UI tests + Kover coverage
# Quick verification (compile only, no tests)
./gradlew :shared:compileKotlinIosSimulatorArm64 :shared:compileKotlinJs :compose:compileKotlinIosArm64
# Full local validation (same as CI)
make lint-check && make shared-test && make compose-test
Coverage reports are generated at:
shared/build/reports/kover/ (XML + HTML)compose/build/reports/kover/ (XML + HTML)The project uses ktlint with the following configuration (.editorconfig):
@Composable functions: exempt from naming rulesmake lint-check # Verify code style
make lint-fix # Auto-fix issues
make publish-local
This publishes both shared and compose modules to ~/.m2/repository/. Consumer apps can use it by adding mavenLocal() to their repositories.
Handled by the deploy-maven-central.yml workflow on release. Requires signing keys configured as repository secrets.
Handled by the deploy.yml workflow. Requires GP_USER and GP_TOKEN environment variables.
make build-XCFramework
Produces compose/build/XCFrameworks/release/composeKit.xcframework/ with Compose resources embedded in each slice.
The CI runs on every push to main and on pull requests (.github/workflows/ci.yml):
Working example apps are available in the examples/ directory:
| Platform | Directory | Setup |
|---|---|---|
| Android |
See examples/README.md for detailed setup instructions.
| Module | Artifact | Description | Platforms |
|---|
shared | io.conekta:conekta-elements-shared | Core business logic, HTTP client, tokenizer, crypto | Android, iOS, JS |
compose | io.conekta:conekta-elements-compose | Compose Multiplatform UI components | Android, iOS |
webApp | @conekta/elements (npm) | React + TypeScript library | Web |
import io.conekta.compose.tokenizer.ConektaTokenizer
import io.conekta.elements.tokenizer.models.TokenizerConfig
import io.conekta.elements.tokenizer.models.TokenizerError
fun PaymentScreen() {
ConektaTokenizer(
config = TokenizerConfig(
publicKey = "key_xxxxx",
merchantName = "My Store",
collectCardholderName = true,
),
onSuccess = { result ->
println("Token: ${result.token}")
println("Last four: ${result.lastFour}")
},
onError = { error ->
when (error) {
is TokenizerError.ValidationError -> println("Validation: ${error.message}")
is TokenizerError.NetworkError -> println("Network: ${error.message}")
is TokenizerError.ApiError -> println("API ${error.code}: ${error.message}")
}
},
)
}
import SwiftUI
import composeKit
struct ContentView: View {
private var showingAlert = false
private var alertMessage = ""
var body: some View {
ConektaTokenizerView(
config: TokenizerConfig(
publicKey: "key_xxxxx",
merchantName: "My Store",
collectCardholderName: true
),
onSuccess: { result in
alertMessage = "Token: \(result.token)"
showingAlert = true
},
onError: { error in
if let apiError = error as? TokenizerError.TokenizerApiError {
alertMessage = "\(apiError.code): \(apiError.message)"
} else if let networkError = error as? TokenizerError.TokenizerNetworkError {
alertMessage = networkError.message
} else {
alertMessage = "Payment could not be processed."
}
showingAlert = true
}
)
}
}
| Tool | Version | Notes |
|---|
| JDK | 17 (17.0.7-tem) | Managed via .sdkmanrc |
| Node.js | 18 | Managed via .nvmrc |
| Android SDK | compileSdk 36, minSdk 24 | |
| Xcode | 15+ | iOS builds only (macOS required) |
| Kotlin | 2.1.0 | Via Gradle plugin |
conekta-elements/
├── shared/ # Core KMP module (Android, iOS, JS)
│ └── src/
│ ├── commonMain/ # Shared business logic
│ │ └── kotlin/io/conekta/elements/
│ │ ├── tokenizer/
│ │ │ ├── api/ # HTTP client + API service
│ │ │ ├── crypto/ # AES + RSA encryption (expect/actual)
│ │ │ ├── formatters/ # Card number/CVV/expiry formatters
│ │ │ ├── models/ # TokenizerConfig, TokenResult, TokenizerError
│ │ │ └── validators/ # Form validation (Luhn, expiry, CVV)
│ │ └── assets/ # CDN URLs for card brand images
│ ├── androidMain/ # JCE crypto implementation
│ ├── iosMain/ # CommonCrypto/Security implementation
│ ├── jsMain/ # crypto-js + jsencrypt implementation
│ └── commonTest/ # Shared tests
├── compose/ # Compose Multiplatform UI module (Android, iOS)
│ └── src/
│ ├── commonMain/ # Shared composables
│ │ └── kotlin/io/conekta/compose/
│ │ ├── tokenizer/ # ConektaTokenizer composable
│ │ ├── components/ # TextField, CardBrandIcon, etc.
│ │ ├── theme/ # Colors, fonts
│ │ └── i18n/ # Localization (ES/EN)
│ └── androidHostTest/ # Robolectric UI tests
├── webApp/ # React + TypeScript web library
├── examples/ # Android + iOS example apps
│ ├── android/
│ └── ios/
├── buildSrc/ # Custom Gradle tasks (string validation, resources sync)
├── Package.swift # SPM binary target config
├── Makefile # Common build commands
└── .github/workflows/ # CI pipeline
| Job | Runner | Steps |
|---|
validate_ios | macOS | iOS shared tests, verify XCFramework resources |
build_kmp | Linux | Version validation, build, shared tests, compose tests, ktlint, string validation, publish dry-run |
build_js | Linux | JS build, web tests + coverage, lint, npm publish dry-run, Chromatic |
sonarcloud | Linux | SonarQube analysis with merged coverage from KMP + JS |
examples/android/Set public key in MainActivity.kt |
| iOS | examples/ios/ | Set public key in Local.xcconfig |
Surfaced from shared tags and platforms — no rankings paid for.