@technitsolutions/capacitor-conekta-tokenizer
v1.3.3
Published
Capacitor 8 plugin for Conekta card tokenization - create payment tokens from card details via direct API calls
Maintainers
Readme
@technitsolutions/capacitor-conekta-tokenizer
Capacitor 8 plugin for Conekta card tokenization. Creates single-use payment tokens from card details using the official Conekta JS SDK in a hidden WebView, ensuring PCI compliance and proper device fingerprinting on all platforms.
Based on capacitor-conketa by Jorge Enriquez. Modernized for Capacitor 8 with hidden WebView tokenization approach.
Why This Plugin?
Conekta's web tokenizer (ConektaCheckoutComponents.Card()) uses a zoid-based iframe that does not work on iOS because Capacitor uses the capacitor:// custom URL scheme, and zoid's cross-origin iframe communication fails with non-standard schemes. Setting iosScheme: 'https' is also not viable because WKWebView rejects registering scheme handlers for standard schemes.
This plugin solves the problem by loading the official Conekta JS SDK (conekta.js) inside a hidden WebView on native platforms. The hidden WebView uses https://conekta.com as its base URL, giving the SDK a proper HTTPS origin. This ensures device fingerprinting, anti-fraud data collection, and PCI-compliant tokenization work correctly — without any iframe or URL scheme issues.
Platform Support
| Platform | Min Version | Implementation | | -------- | --------------- | ----------------------------------- | | iOS | 15.0+ | Hidden WKWebView + Conekta JS SDK | | Android | API 23+ | Hidden WebView + Conekta JS SDK | | Web | Modern browsers | Conekta JS SDK (dynamically loaded) |
Install
npm install @technitsolutions/capacitor-conekta-tokenizer
npx cap syncUsage
import { ConektaTokenizer } from '@technitsolutions/capacitor-conekta-tokenizer';
// 1. Set your Conekta public key
await ConektaTokenizer.setPublicKey({ publicKey: 'key_xxxxxxxxxxxxxxxx' });
// 2. Create a token from card details
const { token } = await ConektaTokenizer.createToken({
name: 'John Doe',
cardNumber: '4242424242424242',
expMonth: '12',
expYear: '25',
cvc: '123',
});
console.log('Token ID:', token.id); // tok_xxxxxxxx
console.log('Live mode:', token.livemode);
console.log('Full token:', token);Error handling
When Conekta rejects the card, createToken rejects with a ConektaTokenError
that preserves the full conekta.js error envelope. Use this to triage
failures (expired card vs. bad Luhn vs. issuer rejection vs. CDN/SDK load
failure) in your observability tool of choice.
import type { ConektaTokenError } from '@technitsolutions/capacitor-conekta-tokenizer';
try {
const { token } = await ConektaTokenizer.createToken({ /* ... */ });
} catch (err) {
const e = err as ConektaTokenError;
// e.message — user-facing `message_to_purchaser`
// e.code — e.g. "conekta_js.invalid_expiration"
// e.type — e.g. "parameter_validation_error"
// e.param — offending field when Conekta reports one
// e.conektaError — full raw envelope (log to Sentry `extra`, etc.)
Sentry.captureException(e, { extra: { conektaError: e.conektaError } });
}On native platforms (iOS / Android) the same fields are surfaced through
Capacitor's error payload (code and data.conektaError), so the shape on
the JS side is consistent across all three platforms.
API
setPublicKey(...)
setPublicKey(options: SetPublicKeyOptions) => Promise<void>Set the Conekta public API key for tokenization.
| Param | Type |
| ------------- | ------------------------------------------------------------------- |
| options | SetPublicKeyOptions |
Since: 1.0.0
createToken(...)
createToken(options: CreateTokenOptions) => Promise<CreateTokenResult>Create a payment token from card details.
Sends card data directly to the Conekta API (POST https://api.conekta.io/tokens)
and returns a single-use token ID.
On rejection code says why: Conekta's own code when the card itself is
refused, or one of public_key_not_set, request_in_flight,
sdk_load_timeout, token_request_timeout, webview_not_ready,
webview_eval_failed, webview_process_terminated when tokenization could
not be attempted. All but the first two are worth retrying.
| Param | Type |
| ------------- | ----------------------------------------------------------------- |
| options | CreateTokenOptions |
Returns: Promise<CreateTokenResult>
Since: 1.0.0
warmUp()
warmUp() => Promise<IsReadyResult>Pre-warm the hidden Conekta WebView so the SDK is ready before the user
reaches the payment screen. Resolves when the SDK has loaded. Rejects
with code sdk_load_timeout if it does not load within the platform
timeout.
Returns: Promise<IsReadyResult>
Since: 1.3.1
isReady()
isReady() => Promise<IsReadyResult>Return whether the Conekta SDK has finished loading. Does not wait.
Returns: Promise<IsReadyResult>
Since: 1.3.1
Interfaces
SetPublicKeyOptions
| Prop | Type | Description | Since |
| --------------- | ------------------- | --------------------------------------------------- | ----- |
| publicKey | string | Your Conekta public API key (e.g., key_xxxxxxxx). | 1.0.0 |
CreateTokenResult
| Prop | Type | Description | Since |
| ----------- | ----------------------------------------------------- | ------------------------------ | ----- |
| token | ConektaToken | The full Conekta token object. | 1.1.0 |
ConektaToken
| Prop | Type | Description | Since |
| -------------- | -------------------- | ------------------------------------------------------- | ----- |
| id | string | The single-use payment token ID (e.g., tok_xxxxxxxx). | 1.0.0 |
| livemode | boolean | Whether this token was created in live mode. | 1.1.0 |
| used | boolean | Whether this token has already been used. | 1.1.0 |
| object | string | Object type (always "token"). | 1.1.0 |
CreateTokenOptions
| Prop | Type | Description | Since |
| ---------------- | ------------------- | ----------------------------------------------- | ----- |
| name | string | Cardholder name as it appears on the card. | 1.0.0 |
| cardNumber | string | Card number (digits only, no spaces or dashes). | 1.0.0 |
| expMonth | string | Expiration month (e.g., "01" for January). | 1.0.0 |
| expYear | string | Expiration year (e.g., "25" or "2025"). | 1.0.0 |
| cvc | string | Card verification code (3 or 4 digits). | 1.0.0 |
IsReadyResult
| Prop | Type | Description | Since |
| ----------- | -------------------- | --------------------------------------------------------------------- | ----- |
| ready | boolean | true once the hidden Conekta WebView has posted the ready signal. | 1.3.1 |
iOS Setup
No additional setup required. The plugin creates a hidden WKWebView to load the Conekta JS SDK.
Android Setup
No additional setup required. The plugin creates a hidden WebView to load the Conekta JS SDK. The INTERNET permission is declared in the plugin's manifest.
Register the Plugin
In your Capacitor app's MainActivity.java or MainActivity.kt:
import com.technit.capacitor.conekta.ConektaTokenizerPlugin
class MainActivity : BridgeActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
registerPlugin(ConektaTokenizerPlugin::class.java)
super.onCreate(savedInstanceState)
}
}How It Works
Instead of using Conekta's iframe tokenizer (which breaks on Capacitor iOS) or deprecated native SDKs, this plugin:
- Creates a hidden WebView (invisible to the user) on plugin load
- Loads the official Conekta JS SDK (
https://cdn.conekta.io/js/latest/conekta.js) withhttps://conekta.comas the base URL - When
createToken()is called, it executesConekta.Token.create()inside the hidden WebView - The SDK handles device fingerprinting, PCI compliance, and API communication
- The token result is passed back to native code via message handlers
On iOS the hidden WebView is deliberately kept inside the app's view hierarchy — 1×1 pt,
effectively transparent and not interactive. WebKit suspends the content process of a WKWebView
that is not in a window, and a suspended process silently stops answering evaluateJavaScript and
postMessage: tokenization then hangs until it times out (token_request_timeout). Do not
"simplify" this back into a detached web view.
This ensures tokens are created through Conekta's official SDK flow and are accepted for charges.
Acknowledgments
This plugin is based on the original capacitor-conketa by Jorge Enriquez, which provided the foundational architecture for Conekta card tokenization in Capacitor applications. The original plugin targeted Capacitor 2 with native Conekta SDKs.
This modernized version was created and is maintained by Technit Solutions.
License
MIT - See LICENSE for details.
