Skip to content

Instantly share code, notes, and snippets.

@gamelio-pv
Last active February 4, 2026 20:59
Show Gist options
  • Select an option

  • Save gamelio-pv/3c75f3e985ed079d30683ed739b3c54b to your computer and use it in GitHub Desktop.

Select an option

Save gamelio-pv/3c75f3e985ed079d30683ed739b3c54b to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Payvalida 3DS Implementation Example</title>
<style>
body {
font-family: sans-serif;
padding: 2rem;
max-width: 600px;
margin: 0 auto;
}
.form-group {
margin-bottom: 1rem;
}
label {
display: block;
margin-bottom: 0.5rem;
font-weight: bold;
}
input {
width: 100%;
padding: 0.5rem;
font-size: 1rem;
}
button {
background-color: #007bff;
color: white;
padding: 0.75rem 1.5rem;
border: none;
cursor: pointer;
font-size: 1rem;
}
button:hover {
background-color: #0056b3;
}
#status-log {
margin-top: 1rem;
padding: 1rem;
background: #f4f4f4;
border: 1px solid #ddd;
display: none;
}
</style>
</head>
<body>
<h1>Checkout</h1>
<!-- Simple Payment Form -->
<div id="payment-form">
<!-- Form... -->
<button id="pay-button">Pay</button>
</div>
<!-- 1. Import the SDK -->
<script src="https://3ds.payvalida.com/sdk@latest.min.js" type="module"></script>
<!-- 2. Implementation Script -->
<script type="module">
const sdkInstance = new window.PayvalidaSDK({
environment: "sandbox",
isSinglePageApp: false, // Set to true if you are handling routing in JS
threedsConfig: {
consumerAuthenticationInformation: {
transactionMode: "01",
mcc: "1234",
requestorId: "123456",
requestorName: "REQUESTOR NAME",
},
acquirerInformation: {
acquirerBin: "123456",
merchantId: "123456",
},
merchantInformation: {
merchantDescriptor: {
name: "MERCHANT DESCRIPTOR NAME",
url: "https://payvalida.com",
},
},
},
});
const payBtn = document.getElementById('pay-button');
payBtn.addEventListener('click', async () => {
payBtn.disabled = true;
log("Initializing 3DS SDK...");
const response = await sdkInstance.startAntiFraudValidator({
cardNumber: "4111111111111111",
expirationMonth: "12",
expirationYear: "2026",
cvv: "123",
token: "1234567890",
});
if (response.threeDSRequired) {
console.log('Se requiere validación 3DS');
// Guardar pvThreedsId y referenceId para usar en startThreedsValidator
const { pvThreedsId, referenceId } = response.data;
const formData = {
billAddrCity: "Medellín",
billAddrCountry: "CO",
billAddrLine1: "Calle 12345",
billAddrLine2: "Calle 12345",
billAddrPostCode: "050047",
billAddrState: "Antioquia",
cardNumber: "4111111111111111",
installments: 1,
cvv: "123",
di: "1234567890",
expirationMonth: "12",
expirationYear: "2026",
lastName: "Doe",
name: "John",
token: "1234567890",
typeDI: "CC",
cellPhone: "3141234123",
email: "support@payvalida.com",
pvThreedsId: pvThreedsId,
referenceId: referenceId,
}
// Llamando a startThreedsValidator de esta forma,
// se mostrará el desafío en el contenedor automáticamente en el centro de la pantalla
const threedsResponse = await sdkInstance.startThreedsValidator(formData);
// O si quieres usar un contenedor propio:
// const threedsResponse = await sdkInstance.startThreedsValidator(formData, 'mi-contenedor-3ds');
if (!threedsResponse.isApproved) {
console.error('Error:', threedsResponse.error);
console.error('Error Code:', threedsResponse.errorCode);
payBtn.disabled = false;
return;
}
console.log('Transacción aprobada por 3DS');
// Procesar la transacción...
payBtn.disabled = false;
return;
}
if (response.isApproved) {
console.log('Análisis de fraude aprobado');
if (response.data && response.data.kountSessionID) {
console.log('Kount Session ID:', response.data.kountSessionID);
// IMPORTANTE: Si se recibe un kountSessionID, este deberá ser enviado
// en el endpoint de transaction, de lo contrario, tu transacción será rechazada.
}
// Procesar la transacción...
payBtn.disabled = false;
return;
}
console.error('Error:', response.error);
console.error('Error Code:', response.errorCode);
payBtn.disabled = false;
return;
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment