This page details the events, implementation examples, and recommendations on how to act upon receiving and processing these events, facilitating a seamless integration into your payment system.
DEUNA handles standardized events via postMessage
to report on transaction progress, improving the user experience and ensuring secure transactions.
Event handling is crucial for the proper functioning of DEUNA SDKs.
JavaScript postMessage function
The JavaScript postMessage
function is crucial for secure communication between iFrames and windows in web applications. It's especially important in the context of online payments, where protecting user data is essential.
The JavaScript postMessage
function allows systems to securely exchange information between the payment system and the merchant's website, ensuring that sensitive data, such as credit card information, is handled with the utmost security.
Event table
Evento | Meta-Payload | Descripción |
---|---|---|
VaultStarted | None | Emitted when the widget has loaded and the user can now interact with the page elements. |
VaultSaveSuccess | - createdCard : bankName (string)- cardId (string)- company (string)- firstSix (string)- lastFour (string)- userId (string)- storedCard (boolean)storecard is true if the card was selected from the user's saved cards.False if it is new | Issued when the creation of a card in DEUNA is successfully completed. |
VaultSaveError | - errorMessage - errorCode | Triggered when an error occurs in card creation. |
VaultFailed | - errorCode - errorMessage | For general errors during loading. |
VaultProcessing | N/A | Emit when the user clicks on the action button and while the DEUNA API responds. |
onBinDetected | Provided as metadata - card_bin : card BIN- card_brand : card brandThis data will only be sent if:- BIN is entered -System detects the BIN entryIt is subsequently deleted.No metadata will be sent to inform the merchant not to send it in the transaction. | Issued upon recognizing any change in the BIN entry. |
onInstallmentSelected | parsedData.data?.metadata?.plan_option_id This ID contains the selected installment option that should be sent in the Purchase API | This event is emitted when the user selects an option from the installments dropdown.. |
vaultSaveClick | N/A | Issued when the user clicks the continue/pay button. |
paymentMethodsCardNumberEntered | N/A | Issued when the user finishes adding all the card digits. |
paymentMethodsCardNumberInitiated | N/A | Issued when the user selects the card number field. |
paymentMethodsCardExpirationDateInitiated | N/A | Emitted when the user selects the expiration date field. |
paymentMethodsCardExpirationDateEntered | N/A | Emitted when the user finishes adding the expiration date. |
paymentMethodsCardSecurityCodeInitiated | N/A | Emitted when the user selects the CVV field. |
paymentMethodsCardSecurityCodeEntered | N/A | Issued when the user finishes adding the CVV. |
paymentMethodsCardNameInitiated | N/A | Issued when the user selects the cardholder name field. |
paymentMethodsCardNameEntered | N/A | Issued when the user adds at least two words separated by a space (without special characters or numbers). |
Reproduce VaultSaveError
and VaultFailed
:
- Change the public key for another value after the
elements
URL charges. - Use the test card
1354 1001 4004 955
Examples
Compare the postMessage event examples:
window.addEventListener("message", (event) => {
// Verify message origin for safety
if (event.origin !== "URL_DE_CONFIANZA") {
return;
}
// Procesar el evento recibido
switch (event.data.type) {
case 'VaultStarted':
console.log("VaultStarted: Click to Pay está listo para la interacción.");
// Impement actions after payment process is started
break;
case 'VaultSaveSuccess':
const cardId = event.data.metadata.createdCard.id;
console.log(`VaultSaveSuccess: Tarjeta guardada con éxito. ID de la tarjeta: ${cardId}`);
// Manage card creation success and procede to payment process
break;
case 'VaultSaveError':
case 'VaultFailed':
const errorCode = event.data.metadata.errorCode;
const errorMessage = event.data.metadata.errorMessage;
console.error(`${event.data.type}: Error en el proceso. Código: ${errorCode}, Mensaje: ${errorMessage}`);
// Manage errors in card saving or other general error
break;
case 'VaultProcessing':
console.log("VaultProcessing: Procesando pago con DEUNA.");
// Implement actions while payment is processing
break;
case 'onBinDetected':
// When user inputs first six digits of card
const cardBrand = event.data?.metadata?.cardBrand;
case 'onInstallmentSelected':
// When user selects quantity of installments
const planOptionId = event.data.metadata.plan_option_id;
case 'onBinEmpty':
// Cuando el usuario limpia el BIN
default:
console.warn(`Evento no reconocido: ${event.data.type}`);
// Manage non specified cases
break;
}
});
// Step 1: Implement the following delegates: WKNavigationDelegate, WKUIDelegate
// Step 2: Define the webView and override the window.open behaviour
let configuration = WKWebViewConfiguration()
private var webView: WKWebView?
var scriptSource = """
window.open = function(open) {
return function(url, name, features) {
location.href = url; // or window.location.replace(url)
};
}(window.open);
"""
// Step 3: Initialize the webView
/// Loads the web view with the specified URL.
/// Parameter urlString: The URL string to load.
func loadUrl(urlString: String) {
let userScript = WKUserScript(
source: scriptSource,
injectionTime: .atDocumentStart,
forMainFrameOnly: false
)
self.configuration.preferences.javaScriptEnabled = true
self.configuration.preferences.javaScriptCanOpenWindowsAutomatically = true
self.configuration.userContentController.addUserScript(userScript)
self.configuration.userContentController.add(self, name: "deuna") // IMPORTANT the name "deuna"
self.webView = WKWebView(
frame: view.bounds,
configuration: self.configuration
)
self.webView!.navigationDelegate = self
if let url = URL(string: urlString) {
let request = URLRequest(url: url)
self.webView?.load(request)
}
}
// Step 4: Define the function to listen when the URL of the widget
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
view.addSubview(webView)
self.adjustScrolling(webView: webView)
}
// Listen to the PostMessages
// Gets the data from the script message as Foundation Data.
// - Parameter message: The script message.
// - Returns: The data from the script message, if available.
func getMessageData(message: WKScriptMessage) -> Foundation.Data? {
guard let jsonString = message.body as? String else {
return nil
}
return jsonString.data(using: .utf8)
}
/// Handler for receiving JavaScript messages.
///
/// - Parameters:
/// - userContentController: The user content controller.
/// - message: The message received.
func userContentController(
_ userContentController: WKUserContentController,
didReceive message: WKScriptMessage
) {
// Attempt to decode the received JSON message
guard let jsonData = getMessageData(message: message) else {
return
}
do {
// Decode the JSON message
let decoder = JSONDecoder()
// listen the post message data
} catch {
}
}
// Step 1: Create and show the WebView
lateinit var webView: WebView
private fun initialize() {
webView = findViewById(R.id.deuna_webview)
}
// Step 2: Enable JS and pass over the interface to listen the postMessages and show the URL
// Load the URL in the WebView
@SuppressLint("SetJavaScriptEnabled")
fun loadUrl(url: String) {
webView.settings.apply {
domStorageEnabled = true
javaScriptEnabled = true
setSupportMultipleWindows(true) // Enable support for multiple windows
}
// Add JavascriptInterface
webView.addJavascriptInterface(WebViewBridge(), "android") // IMPORTANT the name "android"
webView.webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
// When the page finishes loading, the Web View is shown and the loader is hidden
}
}
webView.loadUrl(url)
}
// Step 3: To create a class with a postMessage function using the @javascriptInterface annotation and listen for post message events
// Class to handle communication between the WebView and the native Android code
class WebViewBridge {
/**
* The postMessage function is called when a message is received from JavaScript code in a WebView.
* The message is parsed and the corresponding callbacks are called based on the event type.
*/
@JavascriptInterface
fun postMessage(message: String) {
try {
val json = JSONObject(message)
// listen the post message events
} catch (e: Exception) {
Log.d("WebViewBridge", "postMessage: $e")
}
}
abstract fun handleEvent(message: String)
}
Post-event capture actions
After capturing an event, start a process in your backend to make a call to Crear Pago.
This ensures the effective completion of the payment transaction, following our security and data handling guidelines