Personalización de estilos mediante CustomStyle
Introducción
Esta documentación te proporcionará información detallada sobre cómo poder editar la apariencia de tu Payment Widget , Payment Vault o Payment Link. Está dirigida a desarrolladores y comercios interesados en adaptar la apariencia del widget de pagos de acuerdo a sus necesidades específicas.
Requisitos Previos
Antes de comenzar, asegúrese de contar con las siguientes informaciones:
- API keys 🔑
- Merchant ID 🪪
- Identifica las vistas o estilos que desees personalizar y ajusta el archivo JSON incluyendo todos tus requerimientos 💅
Para mayor claridad, a continuación encontrarás el JSON por secciones, debes combinarlos en un solo JSON para enviar todas las configuraciones deseadas.
Configuración de Estilos Básicos
Puedes cambiar colores de fondo, textos y botones. Todo esto incluyendo los siguientes campos en el JSON. Los colores los manejamos en HEX.
{
"theme": {
"colors": {
"primaryTextColor": "#323237",
"backgroundSecondary": "#FFFFFF",
"backgroundPrimary": "#FFFFFF",
"buttonPrimaryFill": "#17171A",
"buttonPrimaryHover": "#69696E",
"buttonPrimaryText": "#FFFFFF",
"buttonPrimaryActive": "#5F529E"
}
}
}
Ejemplo
Vista One Time Password (OTP)
La vista OTP solicita al usuario ingresar un código de un solo uso enviado a su correo electrónico o teléfono (recordar que esta funcionalidad es opcional). Esta sección detalla cómo personalizar elementos clave, como el encabezado, los botones de cambio de canal y la opción de continuar como invitado.
{
"OtpPage": {
"overrides": {
"Header": {
"props": {
"overrides": {
"Logo": {
"props": {
"url": "https://live.staticflickr.com/6164/6144091654_cbc351c8e2_b.jpg"
}
}
}
}
},
"Headings": {
"props": {
"title": "Ingresa el código de verificación",
"description": "Para ver tus tarjetas guardadas ingresa el código enviado a"
}
},
"OtpChangeChannelButton": {
"props": {
"description": {
"sms": "Enviar código por correo",
"email": "Enviar código por SMS"
}
}
},
"ContinueAsGuestButton": {
"props": {
"description": "Continuar sin ingresar el código"
}
}
}
}
}
Ejemplo
Vista Principal
La vista principal es donde los usuarios interactúan con los elementos principales. Esta sección proporciona una guía sobre cómo configurar y personalizar los patrones de información de la tarjeta, los términos y condiciones, y los botones de pago.
{
"CardInfoPattern": {
"title": "Pago con tarjeta de crédito o débit",
"subtitle": {
"content": "Ingresa los datos de tu tarjeta"
}
},
"CardPattern": {
"translations": {
"es": {
"inputs": {
"identityNumber": {
"label": "Número de documento"
},
"identityDocument": {
"label": {
"CO": "CO: Cédula / Doc de identidad",
"CL": "CL: RUT/DNI",
"EC": "EC: Cédula / Doc de identidad",
"MX": "MX: Otro documetnto",
"BR": "BR: CPF/ CNPJ del titular",
"AR": "AR: DNI / Doc de identidad",
"UY": "UY: Cédula / Doc de identidad"
}
},
"cardNumber": {
"label": "Número de tarjeta"
},
"cardHolder": {
"label": "Nombre en la tarjeta"
},
"installment": {
"label": "Selecciona las cuotas",
"withoutInstallments": "Sin cuotas"
}
}
}
}
},
"TermsConditionsPattern": {
"showForGuest": true,
"showForAuth": false,
"legalMessage": "Al continuar aceptas las",
"connectorText": "y",
"hideCompanyDisclaimer": false
},
"PaymentButtonPattern": {
"label": "Pagar",
"showOrderTotal": true,
"styles": {
"padding": "10px 20px",
"borderRadius": "25px"
}
},
"PoweredByPattern": {
"url": "https://images-staging.getduna.com/checkout_modular/deuna-logo-sm.svg",
"imageStyle": { "width": "50px", "height": "200px" },
"hide": true
}
}
}
Ejemplo
Vista Usuarios Autenticado
Esta vista se muestra una vez el usuario se ha autenticado a través de OTP o fue autenticado de manera "frictionless" con nuestra tecnología de device fingerprint. Es en esta vista donde los usuarios interactúan con sus tarjetas previamente guardadas. Esta sección proporciona una guía sobre cómo configurar y personalizar los patrones de información de la tarjeta y gestión de la misma.
{
"UserCardPattern": {
"translations": {
"es": {
"addNewCard": {
"info": "Agregar una tarjeta"
},
"moreOptions": {
"payWith": "Tarjeta seleccionada"
},
"paymentMethods": {
"seeAllMyCards": "Ver tarjetas guardadas",
"expiredCard": "Tarjeta expirada",
"warningExpiredCard": "Selecciona un método de pago disponible",
"confirmDeleteMethodTitle": "Eliminar esta tarjeta",
"deleteMainText": "Eliminar",
"confirmDeleteMethodAccept": "Confirmar",
"confirmDeleteMethodCancel": "Cancelar",
"confirmDeleteMethod": "Ten en cuenta que al eliminarla no podrás restaurarla."
}
}
}
}
}
Ejemplo
Estructura completa CustomStyle
El archivo CSSStyleFile contiene la configuración de estilos para Payment Widget o Payment Vault. A continuación, se presenta una descripción detallada de los componentes editables y personalizables.
Ejemplo de una estructura JSON válida para la configuración de estilos:
{
"theme": {
"colors": {
"primaryTextColor": "#323237",
"backgroundSecondary": "#FFFFFF",
"backgroundPrimary": "#FFFFFF",
"buttonPrimaryFill": "#17171A",
"buttonPrimaryHover": "#69696E",
"buttonPrimaryText": "#FFFFFF",
"buttonPrimaryActive": "#5F529E"
}
},
"OtpPage": {
"overrides": {
"Header": {
"props": {
"overrides": {
"Logo": {
"props": {
"url": "https://live.staticflickr.com/6164/6144091654_cbc351c8e2_b.jpg"
}
}
}
}
},
"Headings": {
"props": {
"title": "Ingresa el código de verificación",
"description": "Para ver tus tarjetas guardadas ingresa el código enviado a"
}
},
"OtpChangeChannelButton": {
"props": {
"description": {
"sms": "Enviar código por correo",
"email": "Enviar código por SMS"
}
}
},
"ContinueAsGuestButton": {
"props": {
"description": "Continuar sin ingresar el código"
}
}
}
},
"CardInfoPattern": {
"title": "Pago con tarjeta de crédito o débito",
"subtitle": {
"content": "Ingresa los datos de tu tarjeta"
}
},
"CardPattern": {
"translations": {
"es": {
"inputs": {
"identityNumber": {
"label": "Número de documento"
},
"identityDocument": {
"label": {
"CO": "CO: Cédula / Doc de identidad",
"CL": "CL: RUT/DNI",
"EC": "EC: Cédula / Doc de identidad",
"MX": "MX: Otro documento",
"BR": "BR: CPF/ CNPJ del titular",
"AR": "AR: DNI / Doc de identidad",
"UY": "UY: Cédula / Doc de identidad"
}
},
"cardNumber": {
"label": "Número de tarjeta"
},
"cardHolder": {
"label": "Nombre en la tarjeta"
},
"installment": {
"label": "Selecciona las cuotas",
"withoutInstallments": "Sin cuotas"
}
}
}
}
},
"TermsConditionsPattern": {
"showForGuest": true,
"showForAuth": false,
"legalMessage": "Al continuar aceptas las",
"connectorText": "y",
"hideCompanyDisclaimer": false
},
"PaymentButtonPattern": {
"label": "Pagar",
"showOrderTotal": true,
"styles": {
"padding": "10px 20px",
"borderRadius": "25px"
}
},
"PoweredByPattern": {
"url": "https://images-staging.getduna.com/checkout_modular/deuna-logo-sm.svg",
"imageStyle": { "width": "50px", "height": "200px" },
"hide": true
},
"UserCardPattern": {
"translations": {
"es": {
"addNewCard": {
"info": "Agregar una tarjeta"
},
"moreOptions": {
"payWith": "Tarjeta seleccionada"
},
"paymentMethods": {
"seeAllMyCards": "Ver tarjetas guardadas",
"expiredCard": "Tarjeta expirada",
"warningExpiredCard": "Selecciona un método de pago disponible",
"confirmDeleteMethodTitle": "Eliminar esta tarjeta",
"deleteMainText": "Eliminar",
"confirmDeleteMethodAccept": "Confirmar",
"confirmDeleteMethodCancel": "Cancelar",
"confirmDeleteMethod": "Ten en cuenta que al eliminarla no podrás restaurarla."
}
}
}
}
}
Definición de cada una de las propiedades
Propiedad | Objeto | Descripción |
---|---|---|
theme | Objeto | Objeto que define la configuración global del tema para colores y estilos. |
theme.colors.primaryTextColor | String | Color primario del texto. |
theme.colors.backgroundSecondary | String | Color de fondo en la vista de OTP. |
theme.colors.backgroundPrimary | String | Color de fondo en la vista principal. |
theme.colors.buttonPrimaryFill | String | Color de relleno del botón principal. |
theme.colors.buttonPrimaryHover | String | Color de relleno del botón principal al pasar el cursor. |
theme.colors.buttonPrimaryText | String | Color del texto del botón principal. |
theme.colors.buttonPrimaryActive | String | Color de relleno del botón principal al hacer clic. |
HeaderPattern | Objeto | Objeto que define sobrescrituras para el encabezado. |
HeaderPattern.overrides | Objeto | Contiene sobrescrituras específicas para componentes del encabezado. |
HeaderPattern.overrides.Logo | Objeto | Objeto que define propiedades para el componente del logo. |
HeaderPattern.overrides.Logo.props.url | String | URL del logo que se mostrará en el encabezado. |
CardInfoPattern | Objeto | Objeto que define la información de la tarjeta. |
CardInfoPattern.title | String | Título de la sección de información de la tarjeta. |
CardInfoPattern.subtitle.content | String | Contenido del subtítulo. |
UpperTagPattern | Objeto | Objeto que define una etiqueta superior personalizada. |
UpperTagPattern.title | String | Título de la etiqueta superior. |
UpperTagPattern.description | String | Descripción de la etiqueta superior. |
UpperTagPattern.iconColor | String | Color del icono de la etiqueta superior. |
UpperTagPattern.style | Objeto | Estilo de la etiqueta superior, como color(color de texto), box-shadow, margin-top y backgroundColor. |
UserCardPattern | Objeto | Objeto que define traducciones y configuraciones para la gestión de tarjetas de usuario. |
UserCardPattern.translations.es | Objeto | Traducciones al español para componentes de gestión de tarjetas de usuario. |
UserCardPattern.translations.es.addNewCard.info | String | Texto para la opción "Agregar nueva tarjeta". |
UserCardPattern.translations.es.moreOptions.payWith | String | Texto para la opción "Pagar con". |
UserCardPattern.translations.es.paymentMethods.seeAllMyCards | String | Texto para ver todas las tarjetas guardadas. |
UserCardPattern.translations.es.paymentMethods.expiredCard | String | Texto que indica una tarjeta expirada. |
UserCardPattern.translations.es.paymentMethods.warningExpiredCard | String | Mensaje de advertencia para seleccionar un método de pago válido. |
UserCardPattern.translations.es.paymentMethods.confirmDeleteMethodTitle | String | Título para el modal de confirmación de eliminación de una tarjeta. |
UserCardPattern.translations.es.paymentMethods.deleteMainText | String | Texto principal para la opción de eliminar. |
UserCardPattern.translations.es.paymentMethods.confirmDeleteMethodAccept | String | Texto para el botón de aceptar en la confirmación de eliminación. |
UserCardPattern.translations.es.paymentMethods.confirmDeleteMethodCancel | String | Texto para el botón de cancelar en la confirmación de eliminación. |
UserCardPattern.translations.es.paymentMethods.confirmDeleteMethod | String | Mensaje indicando que la eliminación es irreversible. |
CardPattern | Objeto | Objeto que define traducciones y configuraciones para campos de entrada de tarjeta. |
CardPattern.translations.es.inputs.identityNumber.label | String | Etiqueta personalizada para el campo del número de identidad. |
CardPattern.translations.es.inputs.identityDocument.label | Objeto | Etiquetas personalizadas para los documentos de identidad en diferentes países. |
CardPattern.translations.es.inputs.identityDocument.label.CO | String | Etiqueta para Colombia: Cédula / Doc de identidad. |
CardPattern.translations.es.inputs.identityDocument.label.CL | String | Etiqueta para Chile: RUT/DNI. |
CardPattern.translations.es.inputs.identityDocument.label.EC | String | Etiqueta para Ecuador: Cédula / Doc de identidad. |
CardPattern.translations.es.inputs.identityDocument.label.MX | String | Etiqueta para México: Número de RFC. |
CardPattern.translations.es.inputs.identityDocument.label.BR | String | Etiqueta para Brasil: CPF/CNPJ del titular. |
CardPattern.translations.es.inputs.identityDocument.label.AR | String | Etiqueta para Argentina: DNI / Doc de identidad. |
CardPattern.translations.es.inputs.identityDocument.label.UY | String | Etiqueta para Uruguay: Cédula / Doc de identidad. |
CardPattern.translations.es.inputs.cardNumber.label | String | Etiqueta personalizada para el campo del número de tarjeta. |
cardHolder | Objeto | Objeto que define la etiqueta para el campo del nombre del titular de la tarjeta. |
cardHolder.label | String | Etiqueta personalizada para el campo del nombre del titular de la tarjeta. |
installment | Objeto | Objeto que define la etiqueta para el campo de cuotas. |
installment.label | String | Etiqueta personalizada para el campo de cuotas. |
installment.withoutInstallments | String | Texto para indicar que no hay cuotas. |
LowerTagPattern | Objeto | Objeto que define una etiqueta inferior personalizada. |
LowerTagPattern.title | String | Título de la etiqueta inferior. |
LowerTagPattern.description | String | Descripción de la etiqueta inferior. |
LowerTagPattern.iconColor | String | Color del icono de la etiqueta inferior. |
LowerTagPattern.style | Objeto | Estilo de la etiqueta superior, como color(color de texto), box-shadow y backgroundColor. |
TermsConditionsPattern | Objeto | Objeto que define la configuración de los términos y condiciones. |
TermsConditionsPattern.showForGuest | Boolean | Indica si se muestran los términos y condiciones para usuarios invitados. |
TermsConditionsPattern.showForAuth | Boolean | Indica si se muestran los términos y condiciones para usuarios autenticados. |
TermsConditionsPattern.legalMessage | String | Mensaje legal personalizado. |
TermsConditionsPattern.connectorText | String | Texto conector en los términos y condiciones. |
TermsConditionsPattern.hideCompanyDisclaimer | Boolean | Indica si se oculta la exención de responsabilidad de la empresa. |
PaymentButtonPattern | Objeto | Objeto que define la etiqueta, estilo y configuración del botón de pago. |
PaymentButtonPattern.label | String | Texto para el botón de pago. |
PaymentButtonPattern.showOrderTotal | Boolean | Indica si se muestra el total del pedido en el formulario. |
PaymentButtonPattern.styles | Objeto | Estilo del botón de pago, como el padding y el radio del borde. |
PaymentButtonPattern.styles.padding | String | Padding del botón de pago. |
PaymentButtonPattern.styles.borderRadius | String | Radio de borde del botón de pago. |
PoweredByPattern | Objeto | Objeto que define estilo y configuración del disclaimer Power by DEUNA. |
PoweredByPattern.hide | Boolean | Indica si se oculta la marca "Powered by". |
PoweredByPattern.url | String | URL del logo que se mostrará en Power By. |
PoweredByPattern.imageStyle | Objeto | Estilo del logo de Power By, width y height. |
OtpPage | Objeto | Objeto que define sobrescrituras para la página de OTP. |
OtpPage.overrides | Objeto | Contiene sobrescrituras específicas para componentes de la página de OTP. |
OtpPage.overrides.Header | Objeto | Objeto que define sobrescrituras relacionadas con el encabezado para la página de OTP. |
OtpPage.overrides.Header.props | Objeto | Propiedades para el encabezado, como la URL del logo. |
OtpPage.overrides.Header.props.url | String | URL del logo que se mostrará en la página de OTP. |
OtpPage.overrides.Headings | Objeto | Objeto que define el título y la descripción para la página de OTP. |
OtpPage.overrides.Headings.title | String | Título personalizado para la página de OTP. |
OtpPage.overrides.Headings.description | String | Texto descriptivo para la página de OTP. |
OtpPage.overrides.OtpChangeChannelButton | Objeto | Objeto que define la descripción para el botón de cambio de canal OTP. |
OtpPage.overrides.OtpChangeChannelButton.description | Objeto | Descripciones para enviar OTP por SMS o correo electrónico. |
OtpPage.overrides.OtpChangeChannelButton.description.sms | String | Descripción personalizada para enviar OTP por SMS. |
OtpPage.overrides.OtpChangeChannelButton.description.email | String | Descripción personalizada para enviar OTP por correo electrónico. |
OtpPage.overrides.ContinueAsGuestButton | Objeto | Objeto que define la descripción para el botón "continuar como invitado". |
OtpPage.overrides.ContinueAsGuestButton.description | String | Texto descriptivo para continuar como invitado. |
Implementación
Existen dos maneras de usar el CustomStyle:
-
Configuración única de uso por defecto: en caso el comercio quiera personalizar su widget de manera default, puede seguir los siguientes pasos:
- Crea un theme usando esta API: https://docs.deuna.com/reference/create-theme
-
Soporte de múltiples configuraciones: en caso el comercio quiera tener múltiples themes, DEUNA lo soporta. Esto usualmente se usa cuando el comercio quiere mostrar nuestros widgets con un look and feel diferente por segmentación. Un ejemplo es: sus usuarios premium/vip que para sus usuarios regulares. Para lograr esto, seguir los siguientes pasos:
- Puedes crear múltiples themes usando esta API: https://docs.deuna.com/reference/create-theme
- A cada
theme
le puedes asignar un nombre, por ejemplo:name
:Prime users
name
:Regular users
- A cada
- En la respuesta de esa API, vas a obtener un
id
que va a ser el identificador único de ese theme. Este es un UUID. - Luego, al momento de que el comercio vaya a inicializar nuestros widgets ya sea vía URL o vía nuestros SDKs, puede pasar el
id
deltheme
- Ejemplo SDK: https://docs.deuna.com/docs/integracion-payment-widget-ios#par%C3%A1metros
- Ejemplo URL: Aquí como luciría tu URL con el customFile añadido en integración via URL:
https://elements.sandbox.deuna.io/click_to_pay?publicApiKey=${apiKey}&firstName=${encodeURIComponent(firstname)}&lastName=${encodeURIComponent(lastname)}&email=${encodeURIComponent(email)}&cssFile=UUID_FROM_DEUNA
https://elements.sandbox.deuna.io/vault?publicApiKey=${apiKey}&firstName=${encodeURIComponent(firstname)}&lastName=${encodeURIComponent(lastname)}&email=${encodeURIComponent(email)}&cssFile=UUID_FROM_DEUNA
https://pay.sandbox.deuna.io/now/{{order_token}}?cssFile=UUID_FROM_DEUNA
- Puedes crear múltiples themes usando esta API: https://docs.deuna.com/reference/create-theme
-
Override de los themes usando directamente el CustomStyle JSON al momento de inicializar los widgets: algunos comercios requieren poder cambiar el look-and-feel dependiendo del bin, franquicia, etc. de la tarjeta que ingrese el usuario, por ejemplo. Para esto, nuestros widgets emite un postMessage / callback event con la información de la tarjeta y sobre esto puede el comercio override los CustomStyles.
-
// Recibir el evento de la información de la tarjeta window.addEventListener('message', (event) => { let firstParsedData; if (typeof event.data === 'string') { firstParsedData = JSON.parse(event.data); } else { firstParsedData = event.data; } // La información de la tarjeta viene en el "parsedData" en el campo "metadata" /* metadata: { cardBin: number, cardBran: string } */ const parsedData = JSON.parse(firstParsedData); // Este evento se dispara cuando el usuario escribe los primeros 6 dígitos de su tarjeta if ( parsedData && parsedData.type === "onBinDetected" ) { iframeRef.current?.contentWindow?.postMessage( JSON.stringify({ type: "setCustomCSS", data: getCustomCSS(parsedData) }), '*' ); } }); const cardBrands = { Mastercard: '#E94F37', Visa: '#04264E' }; // Ejemplo de función helper de getCustomCSS export const getCustomCSS = (parsedData: any) => ({ theme: { colors: { primaryTextColor: "#023047", backgroundSecondary: "#8ECAE6", backgroundPrimary: "#8ECAE6", buttonPrimaryFill: "#FFB703", buttonPrimaryHover: "#FFB703", buttonPrimaryText: "#000000", buttonPrimaryActive: "#FFB703" } }, CardInfoPattern: { title: "Ingresa los datos de tu tarjeta", subtitle: { content: "Ingresa los datos de tu tarjeta 🔅" } }, UpperTagPattern: { title: "Tienes 10% de descuento", description: `Debido a que tu tarjeta es ${parsedData.data?.metadata?.cardBrand}, tienes descuento`, style: { color: '#F6F7EB', backgroundColor: `${(cardBrands as any)[parsedData.data?.metadata?.cardBrand]}` } }, UserCardPattern: { translations: { es: { addNewCard: { info: "Agregar nueva tarjeta 🙂" }, moreOptions: { payWith: "👀 Pagar con" } } } }, CardPattern: { translations: { es: { inputs: { identityNumber: { label: "this is a custom label" }, cardNumber: { label: "This is a number custom" }, cardHolder: { label: "This is a holder custom" } } } } }, TermsConditionsPattern: { showForGuest: false, showForAuth: false, legalMessage: "Al continuar, estás aceptando nuestras", connectorText: "and", hideCompanyDisclaimer: true }, PaymentButtonPattern: { label: "Pagar", showOrderTotal: true, styles: { padding: "10px 20px", borderRadius: "25px" } }, LegalInfoPattern: { hidePoweredBy: true } });
-
Ejemplo de una Customización por CustomStyle
Puedes ver en este apartado cómo este CSSCustomFile va a modificar la apariencia de nuestro Vault. Fíjate en las propiedades descritas en este archivo JSON:
{
"theme": {
"colors": {
"buttonPrimaryFill": "#8A2BE2"
}
},
"CardInfoPattern": {
"title": "¡Dale vida a tu compra!🤩",
"header": {
"content": "Introduce los detalles de tu tarjeta aquí."
}
},
"TermsConditionsPattern": {
"showForGuest": true,
"showForAuth": false,
"hideCompanyDisclaimer": true
},
"PaymentButtonPattern": {
"label": "Pagar",
"showOrderTotal": true,
"styles": {
"padding": "10px 20px",
"borderRadius": "25px"
},
"PoweredByPattern": {
"hide": true
}
}
}
Updated 3 days ago