Página de pagamento da loja virtual com autenticação 3DS

Após executar o passo da criação da transação, deve ser exibido a página do lojista ao usuário. Nesta página com integração ao pagamento JavaScript e autenticação 3DS 2.0, é crucial incluir dois arquivos na página de checkout: um script JS e uma folha de estilo CSS. Esses dois arquivos são essenciais para garantir que o pagamento com autenticação 3DS 2.0 funcione corretamente. Além desses arquivos, é necessário adicionar uma tag HTML à página de pagamento (essa tag HTML será utilizada no caso de ocorrer o fluxo de 3DS method).

Seguem abaixo as URLs para download:

Script JS#

Abaixo estão as URls de homologação e produção para download:

URL para ambiente de Produção:

https://esitef.softwareexpress.com.br/js/esitefauthenticatepayment-1.0.min.js

URL para ambiente de Homologação:

https://esitef-homologacao.softwareexpress.com.br/js/esitefauthenticatepayment-1.0.min.js

Folha de estilo CSS#

Abaixo estão as URls de homologação e produção para download:

URL para ambiente de Produção:

https://esitef.softwareexpress.com.br/css/v2/threeds.css

URL para ambiente de Homologação:

https://esitef-homologacao.softwareexpress.com.br/css/v2/threeds.css

Tag div#

Abaixo está a tag div obrigatória para o funcionamento do 3DS method

<div id="divThreeDsMethodData"></div>

Os campos de cartão devem conter as classes especificadas abaixo:

ParâmetroDescriçãoFormatoObrigatório
esitef-cardnumberNúmero do cartão do comprador (PAN).< 19 NSIM
esitef-cardexpirydateData de vencimento do cartão no formato MMAA.= 4 NSIM
esitef-cardexpirymonth
& esitef-cardexpiryyear
Mês e ano de vencimento do cartão, nos formatos MM e AA, respectivamente. Esses campos podem ser enviados no lugar de esitef-cardexpirydate. Caso sejam todos enviados ao mesmo tempo, a data separada (esitef-cardexpirymonth e esitef-cardexpiryyear) terá prioridade.= 2 NSIM
esitef-cardsecuritycodeCódigo de segurança do cartão.< 5 NSIM
esitef-cardholderNome do portador do cartão. Obrigatório apenas para pagamentos com e-Rede, GetNet WS e VR AN (SmartNet).< 30 ANCOND.

Devem ser chamados duas funções durante o checkout:

startThreeDsDetalhes da chamada : Esta função deve ser chamado por meio de um evento após o preenchimento final do cartão, ela inicia o 3DS e dependendo do bin pode executar a chamada do 3DS method caso seja necessário.

esitefDoPaymentDetalhes da chamada : Esta função deve ser chamado por meio de evento após o preenchimento de todos os dados necessários para a finalização do checkout. Esta chamada irá chamar a autenticação 3ds, talvez o emissor solicite um desafio a ser executado pelo comprador. Neste caso um modal irá abrir, com o respectivo desafio. Neste cenário o lojista deve redirecionar o final da requisição para uma tela de processamento, e aguardar a resposta do aviso de status.

Abaixo está um exemplo de uma página integrada com o pagamento JavaScript do Carat:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Coleta de dados de cartão via JS</title>
<script type="text/javascript"
src="https://esitef-homologacao.softwareexpress.com.br/js/esitefauthenticatepayment-1.0.min.js"></script>
<script type="text/javascript"
src="https://esitef-homologacao.softwareexpress.com.br/lojateste/loja/js/lib/jquery.min.js"></script>
<script type="text/javascript"
src="https://esitef-homologacao.softwareexpress.com.br/lojateste/loja/js/lib/jquery.payment.js"></script>
<script type="text/javascript"
src="https://esitef-homologacao.softwareexpress.com.br/lojateste/loja/js/lib/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://esitef-homologacao.softwareexpress.com.br/css/v2/style.css">
<link rel="stylesheet" href="https://esitef-homologacao.softwareexpress.com.br/css/font-awesome.min.css"/>
<link rel="stylesheet" href="https://esitef-homologacao.softwareexpress.com.br/css/v2/payment.css">
<link rel="stylesheet" href="https://esitef-homologacao.softwareexpress.com.br/css/v2/payment-credit.css"/>
<link rel="stylesheet" href="https://esitef-homologacao.softwareexpress.com.br/css/v2/bootstrap.min.css"/>
<link rel="stylesheet" href="https://esitef-homologacao.softwareexpress.com.br/css/v2/error.css">
<link rel="stylesheet" href="https://esitef-homologacao.softwareexpress.com.br/css/v2/authentication.css">
<link rel="stylesheet" href="https://esitef-homologacao.softwareexpress.com.br/css/v2/threeds.css"/>
<script type="text/javascript">
$(document).ready(function() {
/* limpa cartao da consulta bin */
$("#card-number").val('');
$("#bin-card-expiration-month").val('');
$("#bin-card-expiration-year").val('');
$("#bin-security-code").val('');
$(".payment-checked-number").hide();
$(".payment-error-number").hide();
$(".bin-payment-checked-due").hide();
$(".bin-payment-error-due").hide();
$(".bin-payment-checked-security-code").hide();
$(".bin-payment-error-security-code").hide();
$(".payment-checked-holdername").hide();
$(".payment-error-holdername").hide();
$("#card-number").removeClass('has-error-input');
$('#card-number').payment('restrictNumeric');
/* inicializacao das restricoes dos campos */
$('#bin-card-expiration-year').payment('restrictNumeric');
$('#bin-card-expiration-month').payment('restrictNumeric');
$('#bin-security-code').payment('restrictNumeric');
$("#bin-security-code").payment('formatCardCVC');
$("#card-number").on('blur', function() {
result = isFieldSizeValid($(this).val(), 16, null);
updateIconSignAndInput("#card-number", ".payment-checked-number", ".payment-error-number", (result));
if(result){
threedMethod();
}
enableConfirmButton(result);
});
$('#bin-security-code').on('blur', function() {
result = isFieldSizeValid($(this).val(), 3, null);
updateIconSignAndInput("#bin-security-code", ".bin-payment-checked-security-code", ".bin-payment-error-security-code", result);
});
$('#bin-security-code').on('keyup', function() {
result = isFieldSizeValid($(this).val(), 3, null);
updateIconSignAndInput("#bin-security-code", ".bin-payment-checked-security-code", ".bin-payment-error-security-code", result);
$(this).removeClass("has-error-input");
/* Mostra o check verdinho e muda o foco pro proximo campo */
if ($(this).val().length == 4) {
updateIconSignAndInput("#bin-security-code", ".bin-payment-checked-security-code", ".bin-payment-error-security-code", true);
}
enableConfirmButton(result);
});
$('#bin-card-expiration-month').on('keyup', function() {
var cleanedValue = $(this).val().replace(/[^0-9]+/g, '');
$(this).val(cleanedValue);
if ($(this).val().length == 2) {
$("#bin-card-expiration-year").focus();
}
enableConfirmButton(result);
});
$("#bin-card-expiration-month").on('blur', function() {
result = isFieldSizeValid($(this).val(), 2, null);
resultMonth = isValidMonth($(this).val());
updateIconSignAndInput("#bin-card-expiration-month", ".bin-payment-checked-due", ".bin-payment-error-due", (result && resultMonth));
/* caso especial para data de vencimento */
if (!isFieldSizeValid($("#bin-card-expiration-year").val(), 2, null)) {
$(".bin-payment-checked-due").hide();
$(".bin-payment-error-due").show();
}
enableConfirmButton(result);
});
$('#bin-card-expiration-year').on('keyup', function() {
var cleanedValue = $(this).val().replace(/[^0-9]+/g, '');
$(this).val(cleanedValue);
result = isFieldSizeValid($(this).val(), 2, null);
updateIconSignAndInput("#bin-card-expiration-year", ".bin-payment-checked-due", ".bin-payment-error-due", result);
enableConfirmButton(result);
});
$('#bin-card-expiration-year').on('blur', function() {
result = isFieldSizeValid($(this).val(), 2, null);
updateIconSignAndInput("#bin-card-expiration-year", ".bin-payment-checked-due", ".bin-payment-error-due", result);
/* caso especial para data de vencimento */
if (!isValidMonth($("#bin-card-expiration-month").val()) || !isFieldSizeValid($("#bin-card-expiration-month").val(), 2, null)) {
$(".bin-payment-checked-due").hide();
$(".bin-payment-error-due").show();
}
enableConfirmButton(result);
});
$("#card-holdername").on('blur', function() {
result = isFieldSizeValid($(this).val(), 1, null);
updateIconSignAndInput("#card-holdername", ".payment-checked-holdername", ".payment-error-holdername", (result));
enableConfirmButton(result);
});
});
function enableConfirmButton(result){
if (result && isAllFieldsOK()) {
$(".step-confirm").prop("disabled", false);
} else {
$(".step-confirm").prop("disabled", true);
}
}
function updateIconSignAndInput(inputSelector, iconSelectorOK, iconSelectorError, validation) {
if (validation) {
$(iconSelectorOK).show();
$(iconSelectorError).hide();
$(inputSelector).removeClass("has-error-input");
} else {
$(iconSelectorOK).hide();
$(iconSelectorError).show();
$(inputSelector).addClass("has-error-input");
}
}
function resetIconSignAndInput(inputSelector, iconSelectorOK, iconSelectorError, validation) {
$(iconSelectorOK).hide();
$(iconSelectorError).hide();
$(inputSelector).removeClass("has-error-input");
}
function isFieldSizeValid(value, minSize, maxSize) {
if (value.length >= minSize) {
/* verifica se maxSize foi passado nao nulo */
if (maxSize) {
if (value.length <= maxSize) {
return true;
} else {
return false;
}
}
return true;
}
return false;
}
function isValidMonth(value) {
if (value <= 12 && value > 0) {
return true;
}
return false;
}
function isAllFieldsOK() {
if ($("#card-number").is(":visible")
&& !$(".payment-checked-number").is(":visible")) {
return false;
}
if ($("#bin-card-expiration-year").is(":visible")
&& !$(".bin-payment-checked-due").is(":visible")) {
return false;
}
if ($("#bin-security-code").is(":visible")
&& !$(".bin-payment-checked-security-code").is(":visible")) {
return false;
}
if ($("#card-expiration-year").is(":visible")
&& $("#card-expiration-year").val().length < 2) {
return false;
}
if ($("#card-expiration-month").is(":visible")
&& $("#card-expiration-month").val().length < 2) {
return false;
}
if ($("#security-code").is(":visible")
&& $("#security-code").val().length < 3) {
return false;
}
if ($("#card-holdername").is(":visible")
&& $("#card-holdername").val().length == 0) {
return false;
}
return true;
}
function findGetParameter(parameterName) {
var result = null,
tmp = [];
var items = location.search.substr(1).split("&");
for (var index = 0; index < items.length; index++) {
tmp = items[index].split("=");
if (tmp[0] === parameterName) result = decodeURIComponent(tmp[1]);
}
return result;
}
function myPay() {
var request = {
onSuccess: function(response) {
var responseValue = JSON.stringify(response);
localStorage.setItem('resultSuccess', responseValue);
if (response.payment.status == 'PPC') {
window.location = 'loja-pag-pendente-3ds-mpi.html?nit='+ findGetParameter('nit');
} else {
window.location = 'loja-sucesso-3ds-mpi.html';
}
},
onProcessing: function() {
window.location = 'loja-pag-pendente-3ds-mpi.html?nit='+ findGetParameter('nit');
},
onFailure: function(response) {
var responseValue = JSON.stringify(response);
localStorage.setItem('resultFailure', responseValue);
window.location = 'loja-fracasso-js.html';
},
onInvalid: function(response) {
var message = response[0].field + ' ' + response[0].cause;
for (var i = 1; i < response.length; i++) {
message += ', ' + response[i].field + ' ' + response[i].cause;
}
document.getElementById('resultInvalid').innerHTML = message;
},
nit: findGetParameter('nit'),
payToken: findGetParameter('payToken'),
merchantId: findGetParameter('merchantId'),
authenticate: 'true'
};
esitefDoPayment(request);
}
function threedMethod() {
var request = {
onSuccess: function(response) {
var responseValue = JSON.stringify(response);
},
onFailure: function(response) {
var responseValue = JSON.stringify(response);
console.log("Error 3ds method: "+ responseValue);
},
onInvalid: function(response) {
var message = response[0].field + ' ' + response[0].cause;
for (var i = 1; i < response.length; i++) {
message += ', ' + response[i].field + ' ' + response[i].cause;
}
document.getElementById('resultInvalid').innerHTML = message;
},
nit: findGetParameter('nit'),
payToken: findGetParameter('payToken'),
merchantId: findGetParameter('merchantId'),
authorizerId: findGetParameter('authorizerId')
};
startThreeDs(request);
}
</script>
</head>
<body>
<form id="pagamentoForm" name="pagamentoForm" method="POST">
<div class="row">
<div class="payment-input col-md-12 col-sm-12 col-xs-12" id="payment-input-card" style="">
<div class="payment-input-box payment-input-box-pf col-md-offset-2 col-sm-offset-1 col-md-10 col-sm-10 col-xs-12">
<div class="row">
<div class="input-title col-md-12 col-sm-12">
<span class="glyphicon glyphicon-credit-card input-title-icon col-md-1 col-sm-1 col-xs-1"></span>
<span class="input-title-value">Informe os dados do seu cartão</span>
</div>
</div>
<div class="input-box-left col-md-6 col-sm-7 col-xs-12 ">
<div class="row" id="cardnumber-box">
<div class="input-card-number col-md-11 col-sm-11 col-xs-12">
<label for="card-number" class="col-md-12 col-sm-12 col-xs-12 input-label">
Número do Cartão *
</label>
<div class="col-md-7 col-sm-7 col-xs-10 box-card-number">
<input type="tel" id="card-number" maxlength="19" autocomplete="off"
placeholder="•••• •••• •••• ••••"
class="form-control col-md-5 col-sm-5 col-xs-5 esitef-cardnumber">
</div>
<span class="glyphicon glyphicon-ok col-md-1 col-sm-1 col-xs-1 payment-checked payment-checked-number"
style="display: block;"></span>
<span class="fa fa-exclamation col-md-1 col-sm-1 col-xs-1 payment-error payment-error-number"
style="display: none;"></span>
</div>
</div>
<div id="box-dados-extra-cartao">
<div class="row">
<div id="input-bin-due-date-security-code"
class="input-bin-due-date-security-code col-md-6 col-sm-6 col-xs-12">
<label for="bin-card-expiration-month"
class="col-md-12 col-sm-12 col-xs-12 input-label input-label-due">Data de
Validade&nbsp;<span data-toggle="tooltip" data-placement="top" title=""
data-original-title="A data de validade está localizada na frente do seu cartão. Informe o mês e o ano (MM/AA).">[?]</span>
</label>
<div class="col-md-4 col-sm-5 col-xs-5 box-due-date">
<input type="tel" class="form-control esitef-cardexpirymonth" autocomplete="off"
id="bin-card-expiration-month" placeholder="••" maxlength="2">
</div>
<span class="col-md-1 col-sm-1 col-xs-2 bar-due">/</span>
<div class="col-md-4 col-sm-5 col-xs-5 box-due-date">
<input type="tel" class="form-control esitef-cardexpiryyear" autocomplete="off"
id="bin-card-expiration-year" placeholder="••" maxlength="2">
</div>
<span id="bin-payment-checked-due"
class="glyphicon glyphicon-ok col-md-1 col-sm-1 col-xs-1 payment-checked bin-payment-checked-due"
style="display: block;"></span>
<span id="bin-date-checked-error"
class="fa fa-exclamation col-md-1 col-sm-1 col-xs-1 payment-error bin-payment-error-due"
style="display: none;"></span>
</div>
<div id="input-bin-security-code"
class="input-bin-security-code col-md-6 col-sm-6 col-xs-12">
<label for="bin-security-code"
class="col-md-12 col-sm-12 col-xs-12 input-label input-bin-label-security-code">Código
de segurança
<span id="bin-security-code-tooltip" data-toggle="tooltip" data-placement="top"
title=""
data-original-title="<div><p style='font-weight: bold; margin: 0 0 0 1rem;'>Código de segurança</p><div style='display: flex; text-align: center; align-items: center;'><img src='/images/v2/tooltip-security-in.png' class='img-responsive'/><p>Número de <span style='color:red;' >3 a 4 dígitos </span> no verso do cartão</p></div></div>"> [?] </span>
</label>
<div class="box-bin-security-code col-md-4 col-sm-5 col-xs-11">
<input type="tel"
class="col-md-5 col-sm-5 col-xs-5 form-control esitef-cardsecuritycode"
id="bin-security-code" maxlength="5" autocomplete="off" placeholder="•••">
</div>
<span id="bin-security-code-checked-ok"
class="glyphicon glyphicon-ok col-md-1 col-sm-1 col-xs-1 payment-checked bin-payment-checked-security-code"
style="display: block;"></span>
<span id="bin-security-code-checked-error"
class="fa fa-exclamation col-md-1 col-sm-1 col-xs-1 payment-error bin-payment-error-security-code"
style="display: none;"></span>
</div>
</div>
</div>
<div class="row" id="cardholdername-box">
<div class="input-card-holdername col-md-11 col-sm-11 col-xs-12">
<label for="card-holdername" class="col-md-12 col-sm-12 col-xs-12 input-label">
Nome(com está no cartão) *
</label>
<div class="col-md-7 col-sm-7 col-xs-10 box-card-holdername">
<input type="tel" id="card-holdername" autocomplete="off"
class="form-control col-md-5 col-sm-5 col-xs-5 esitef-cardholder">
</div>
<span class="glyphicon glyphicon-ok col-md-1 col-sm-1 col-xs-1 payment-checked payment-checked-holdername"
style="display: block;"></span>
<span class="fa fa-exclamation col-md-1 col-sm-1 col-xs-1 payment-error payment-error-holdername"
style="display: none;"></span>
</div>
</div>
</div>
<div class="input-box-right col-md-4 col-sm-5 col-xs-12">
<div class="row visible-xs col-xs-12">
<div class="cod-xs-12 site-seguro-dados-cartao">
<img src="/images/v2/site-seguro-icon.png"
class="site-seguro-dados-cartao-card-icon img-responsive" alt="SITE 100% SEGURO">
<span>SITE 100% SEGURO</span>
</div>
</div>
<div class="col-md-12 col-sm-12 col-xs-12 step-button-submit payment-button-submit ">
<button type="button" id="step-confirm" onclick="myPay()"
class="step-confirm btn btn-success col-md-12 col-sm-12 col-xs-12 btn-loader"
disabled="">
CONFIRMAR PAGAMENTO
<span class="glyphicon glyphicon-menu-right step-confirm-icon step-confirm-icon-payment"
aria-hidden="true"></span>
</button>
<div class="col-md-12 col-sm-12 col-xs-12 next-step-container">
<span class="next-step">
Próximo Passo:
</span>
<span id="nextStepValue" class="next-step-value">
&nbsp;
Validação de Pagamento
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
<p id="resultInvalid" style="color:red"></p>
<div id="divThreeDsMethodData">
</div>
<div class="modal fade" id="myModal" role="dialog" tabindex="-1" aria-labelledby="exampleModalLabel" aria-modal="true">
</div>
</body>
</html>

Pontos importantes da implementação exemplo acima:

  • Import do js para autenticação do 3DS:
<script type="text/javascript" src="https://esitef-homologacao.softwareexpress.com.br/js/esitefauthenticatepayment-1.0.min.js"></script>
  • Import do css para autenticação do 3DS:
<link rel="stylesheet" href="https://esitef-homologacao.softwareexpress.com.br/css/v2/threeds.css" />
  • Chamada a função startThreeDs. Saiba mais. (a chamada está dentro da função threedMethod) ao preencher o campo card-number com tamanho 16:
$("#card-number").on('blur', function() {
result = isFieldSizeValid($(this).val(), 16, null);
updateIconSignAndInput("#card-number", ".payment-checked-number", ".payment-error-number", (result));
if(result){
threedMethod();
}
enableConfirmButton(result);
});
  • Implementação da criação da request e chamada do startThreeDs:
function threedMethod() {
var request = {
onSuccess: function(response) {
var responseValue = JSON.stringify(response);
},
onFailure: function(response) {
var responseValue = JSON.stringify(response);
console.log("Error 3ds method: "+ responseValue);
},
onInvalid: function(response) {
var message = response[0].field + ' ' + response[0].cause;
for (var i = 1; i < response.length; i++) {
message += ', ' + response[i].field + ' ' + response[i].cause;
}
document.getElementById('resultInvalid').innerHTML = message;
},
nit: findGetParameter('nit'),
payToken: findGetParameter('payToken'),
merchantId: findGetParameter('merchantId'),
authorizerId: findGetParameter('authorizerId')
};
startThreeDs(request);
}
  • Implementação da criação da request e chamada do esitefDoPayment:
function myPay() {
var request = {
onSuccess: function(response) {
var responseValue = JSON.stringify(response);
localStorage.setItem('resultSuccess', responseValue);
if (response.payment.status == 'PPC') {
window.location = 'loja-pag-pendente-3ds-mpi.html?nit='+ findGetParameter('nit');
} else {
window.location = 'loja-sucesso-3ds-mpi.html';
}
},
onProcessing: function() {
window.location = 'loja-pag-pendente-3ds-mpi.html?nit='+ findGetParameter('nit');
},
onFailure: function(response) {
var responseValue = JSON.stringify(response);
localStorage.setItem('resultFailure', responseValue);
window.location = 'loja-fracasso-js.html';
},
onInvalid: function(response) {
var message = response[0].field + ' ' + response[0].cause;
for (var i = 1; i < response.length; i++) {
message += ', ' + response[i].field + ' ' + response[i].cause;
}
document.getElementById('resultInvalid').innerHTML = message;
},
nit: findGetParameter('nit'),
payToken: findGetParameter('payToken'),
merchantId: findGetParameter('merchantId'),
authenticate: 'true'
};
esitefDoPayment(request);
}
  • Implementação da div com id ="divThreeDsMethodData" para a execução do 3DS method:
<div id ="divThreeDsMethodData"></div>