Card Activation and Set Pin Example
<!-- Import Scripts -->
<script src="https://widgets-sandbox.synctera.com/assets/card-activation/card-activation_v1.0.1.js"></script>
<script src="https://widgets-sandbox.synctera.com/assets/set-pin/set-pin_v1.0.1.js"></script>
<!-- OR -->
<!-- Import Production Scripts -->
<script src="https://widgets.synctera.com/assets/card-activation/card-activation_v1.0.1.js"></script>
<script src="https://widgets.synctera.com/assets/set-pin/set-pin_v1.0.1.js"></script>
.synctera-container {
display: flex;
flex-direction: column;
align-items: center;
}
.synctera-form-container {
min-width: 320px;
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
border: 1px solid #ddd;
border-radius: 4px;
padding: 1rem;
}
.synctera-header {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
}
.synctera-header-title {
font-size: 2rem;
font-weight: 700;
}
.synctera-header-subtitle {
font-size: 1rem;
}
.synctera-input-container {
position: relative;
display: flex;
flex-direction: column;
align-items: flex-start;
}
.synctera-label {
font-weight: bold;
margin-bottom: 5px;
/* These fonts will automatically be sent to the iframe (after sanitization) */
font-family: 'system-ui', '-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto',
'Helvetica Neue', 'Arial', sans-serif;
font-weight: 500;
}
.synctera-input-error {
color: #e31b0c;
font-size: 0.8rem;
}
.synctera-custom-styles {
/* Set on the web component tag */
box-sizing: border-box;
border: 1px solid #ddd;
min-width: 240px;
height: 40px;
border-radius: 4px;
padding: 0 8px;
}
.synctera-custom-styles[_hover] {
border: 1px solid #616161;
}
.synctera-custom-styles[_focus] {
border: 2px solid #2564eb;
padding: 0 7px;
}
.synctera-custom-styles[_disabled] {
background: #d3d3d3;
}
.synctera-custom-styles[_user-invalid] {
border-color: #e31b0c;
}
.synctera-custom-styles,
.synctera-placeholder {
/* These fonts will automatically be sent to the iframe (after sanitization) */
font-family: 'system-ui', '-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto',
'Helvetica Neue', 'Arial', sans-serif;
font-size: 1rem;
line-height: 1.625em;
font-weight: 400;
color: rgba(0, 0, 0, 0.87);
}
.synctera-placeholder {
position: absolute;
display: none;
top: 30px;
left: 10px;
color: rgba(0, 0, 0, 0.2);
z-index: -1;
}
.synctera-custom-styles[_blank]+.synctera-placeholder {
display: block;
}
.synctera-custom-styles[_focus]+.synctera-placeholder {
display: none;
}
.synctera-button-container {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
gap: 1rem;
}
.synctera-submit-button {
background-color: #1976d2;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
font-size: 1rem;
cursor: pointer;
transition:
background-color 0.3s,
transform 0.3s;
width: 100%;
}
.synctera-submit-button:hover {
background-color: #155fa9;
}
.synctera-submit-button:active {
transform: scale(0.97);
transition: transform 0.1s ease-in-out;
}
.synctera-submit-button:disabled {
background-color: #d3d3d3;
cursor: not-allowed;
}
.synctera-cancel-button {
background-color: #fff;
color: #333;
padding: 10px 20px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 1rem;
cursor: pointer;
transition:
background-color 0.3s,
transform 0.3s;
width: 100%;
}
.synctera-cancel-button:hover {
background-color: #e0e0e0;
}
.synctera-cancel-button:active {
transform: scale(0.97);
transition: transform 0.1s ease-in-out;
}
.synctera-cancel-button:disabled {
background-color: #d3d3d3;
cursor: not-allowed;
}
.synctera-hidden {
display: none;
}
<div id="synctera-success" class="synctera-container synctera-hidden">
<div class="synctera-form-container">Card activation was successful.</div>
</div>
<div id="card-activation-container" class="synctera-container">
<div class="synctera-form-container">
<div class="synctera-header">
<h2 class="synctera-header-title">Activate Card</h2>
<h4 class="synctera-header-subtitle">Enter your card details to activate</h4>
</div>
<div class="synctera-input-container">
<div class="synctera-label">Card Number</div>
<card-pan id="card-pan" token="hidden-token" class="synctera-custom-styles"
environment="SANDBOX"></card-pan>
<div class="synctera-placeholder">4111 1111 1111 1111</div>
<div id="card-pan-error" class="synctera-input-error synctera-hidden">
Card must be 16 digits
</div>
</div>
<div class="synctera-input-container">
<div class="synctera-label">Security Code</div>
<card-cvv id="card-cvv" class="synctera-custom-styles"></card-cvv>
<div class="synctera-placeholder">123</div>
<div id="card-cvv-error" class="synctera-input-error synctera-hidden">
Security code must be 3 digits
</div>
</div>
<div class="synctera-button-container">
<button id="card-activation-cancel-button" class="synctera-cancel-button">Cancel</button>
<button id="card-activation-submit-button" class="synctera-submit-button" disabled>
Activate
</button>
</div>
</div>
</div>
<div id="set-pin-container" class="synctera-container synctera-hidden">
<div class="synctera-form-container">
<div class="synctera-header">
<h2 class="synctera-header-title">Set Pin</h2>
<h4 class="synctera-header-subtitle">Enter your 4-digit card PIN</h4>
</div>
<div class="synctera-input-container">
<div class="synctera-label">New PIN</div>
<set-pin id="set-pin-controller" class="synctera-custom-styles" token="hidden-token"
environment="SANDBOX"></set-pin>
<div class="synctera-placeholder">1234</div>
<div id="set-pin-error" class="synctera-input-error synctera-hidden">PIN must be 4 digits</div>
</div>
<div class="synctera-input-container">
<div class="synctera-label">Confirm new PIN</div>
<set-pin id="set-pin-confirm" class="synctera-custom-styles" isConfirm></set-pin>
<div class="synctera-placeholder">1234</div>
<div id="set-pin-confirm-error" class="synctera-input-error synctera-hidden">PINs must Match</div>
</div>
<div class="synctera-button-container">
<button id="set-pin-cancel-button" class="synctera-cancel-button">Cancel</button>
<button id="set-pin-submit-button" class="synctera-submit-button" disabled>Submit</button>
</div>
</div>
</div>
const BASE_URL = 'http://your-server-url.com';
// Helpers
async function getCardToken(input, type = 'ACTIVATE', cardId) {
// Make an api call to your server to get the card token
const response = await fetch(
`${BASE_URL}/api/cardToken?widgetType=${type}&cardId=${cardId}`
);
const data = await response.json();
if (!data.widget_token) // update a error field
input.token = data.widget_token;
}
// Card Activation
let cardActivation = document.getElementById('card-pan');
let cardCvvInput = document.getElementById('card-cvv');
let cardPanError = document.getElementById('card-pan-error');
let cardCvvError = document.getElementById('card-cvv-error');
let cardActivationSubmit = document.getElementById('card-activation-submit-button');
let cardActivationCancel = document.getElementById('card-activation-cancel-button');
let cardActivationValid = false;
getCardToken(cardActivation, 'ACTIVATE', 'card-guid');
cardActivation.addEventListener('load', function () {
console.log('Card Activation Widget Loaded');
});
cardActivation.addEventListener('validity', function (e) {
// Check if the form is valid
cardActivationValid = e.target.isValid;
cardActivationSubmit.disabled = !cardActivationValid;
// Update validation warnings
if (cardActivationValid) {
cardPanError.classList.add('synctera-hidden');
cardCvvError.classList.add('synctera-hidden');
} else {
if (cardCvvInput.hasAttribute('_user-invalid')) {
cardCvvError.classList.remove('synctera-hidden');
} else {
cardCvvError.classList.add('synctera-hidden');
}
if (cardActivation.hasAttribute('_user-invalid')) {
cardPanError.classList.remove('synctera-hidden');
} else {
cardPanError.classList.add('synctera-hidden');
}
}
});
cardActivationSubmit.addEventListener('click', function () {
if (!cardActivationValid) return;
// Disable the submit button
cardActivationSubmit.disabled = true;
try {
cardActivation.submit();
} catch (e) {
console.error('Card failed to activate', e);
}
});
cardActivation.addEventListener('success', function () {
// Hide the card activation form
document.getElementById('card-activation-container').classList.add('synctera-hidden');
// Show the success messsage
document.getElementById('synctera-success').classList.remove('synctera-hidden');
setTimeout(() => {
// hide the success messsage
document.getElementById('synctera-success').classList.add('synctera-hidden');
// Show the set pin form
document.getElementById('set-pin-container').classList.remove('synctera-hidden');
}, 2000);
});
// SET PIN
let setPin = document.getElementById('set-pin-controller');
let setPinConfirmInput = document.getElementById('set-pin-confirm');
let setPinError = document.getElementById('set-pin-error')
let setPinConfirmError = document.getElementById('set-pin-confirm-error')
let setPinSubmit = document.getElementById('set-pin-submit-button');
let setPinCancel = document.getElementById('set-pin-cancel-button');
let setPinValid = false;
getCardToken(setPin, 'SET-PIN', 'card-guid');
setPin.addEventListener('load', function () {
console.log('Set Pin Widget Loaded');
});
setPin.addEventListener('validity', function (e) {
setPinValid = e.target.isValid;
setPinSubmit.disabled = !setPinValid;
// Update validation warnings
if (setPinValid) {
setPinError.classList.add('synctera-hidden')
setPinConfirmError.classList.add('synctera-hidden')
} else {
if (setPinConfirmInput.hasAttribute('_user-invalid')) {
setPinConfirmError.classList.remove('synctera-hidden')
} else {
setPinConfirmError.classList.add('synctera-hidden')
}
if (setPin.hasAttribute('_user-invalid')) {
setPinError.classList.remove('synctera-hidden')
} else {
setPinError.classList.add('synctera-hidden')
}
}
});
setPinSubmit.addEventListener('click', function () {
try {
setPin.submit();
} catch (e) {
console.error('Pin failed to submit', e);
}
});
setPin.addEventListener('success', function () {
console.log('Pin set successfully');
});
setPin.addEventListener('failure', function (e) {
loader.style.display = 'none';
console.error('Pin failed to submit', e);
});
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Activate Card & Set Pin</title>
<link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon" />
<!-- Import Scripts -->
<script type="module" src="../build/src/activate/index.js"></script>
<script type="module" src="../build/src/set-pin/index.js"></script>
<style>
.synctera-container {
display: flex;
flex-direction: column;
align-items: center;
}
.synctera-form-container {
min-width: 320px;
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
border: 1px solid #ddd;
border-radius: 4px;
padding: 1rem;
}
.synctera-header {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
}
.synctera-header-title {
font-size: 2rem;
font-weight: 700;
}
.synctera-header-subtitle {
font-size: 1rem;
}
.synctera-input-container {
position: relative;
display: flex;
flex-direction: column;
align-items: flex-start;
}
.synctera-label {
font-weight: bold;
margin-bottom: 5px;
/* These fonts will automatically be sent to the iframe (after sanitization) */
font-family: 'system-ui', '-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto',
'Helvetica Neue', 'Arial', sans-serif;
font-weight: 500;
}
.synctera-input-error {
color: #e31b0c;
font-size: 0.8rem;
}
.synctera-custom-styles {
/* Set on the web component tag */
box-sizing: border-box;
border: 1px solid #ddd;
min-width: 240px;
height: 40px;
border-radius: 4px;
padding: 0 8px;
}
.synctera-custom-styles[_hover] {
border: 1px solid #616161;
}
.synctera-custom-styles[_focus] {
border: 2px solid #2564eb;
padding: 0 7px;
}
.synctera-custom-styles[_disabled] {
background: #d3d3d3;
}
.synctera-custom-styles[_user-invalid] {
border-color: #e31b0c;
}
.synctera-custom-styles,
.synctera-placeholder {
/* These fonts will automatically be sent to the iframe (after sanitization) */
font-family: 'system-ui', '-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto',
'Helvetica Neue', 'Arial', sans-serif;
font-size: 1rem;
line-height: 1.625em;
font-weight: 400;
color: rgba(0, 0, 0, 0.87);
}
.synctera-placeholder {
position: absolute;
display: none;
top: 30px;
left: 10px;
color: rgba(0, 0, 0, 0.2);
z-index: -1;
}
.synctera-custom-styles[_blank]+.synctera-placeholder {
display: block;
}
.synctera-custom-styles[_focus]+.synctera-placeholder {
display: none;
}
.synctera-button-container {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
gap: 1rem;
}
.synctera-submit-button {
background-color: #1976d2;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
font-size: 1rem;
cursor: pointer;
transition:
background-color 0.3s,
transform 0.3s;
width: 100%;
}
.synctera-submit-button:hover {
background-color: #155fa9;
}
.synctera-submit-button:active {
transform: scale(0.97);
transition: transform 0.1s ease-in-out;
}
.synctera-submit-button:disabled {
background-color: #d3d3d3;
cursor: not-allowed;
}
.synctera-cancel-button {
background-color: #fff;
color: #333;
padding: 10px 20px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 1rem;
cursor: pointer;
transition:
background-color 0.3s,
transform 0.3s;
width: 100%;
}
.synctera-cancel-button:hover {
background-color: #e0e0e0;
}
.synctera-cancel-button:active {
transform: scale(0.97);
transition: transform 0.1s ease-in-out;
}
.synctera-cancel-button:disabled {
background-color: #d3d3d3;
cursor: not-allowed;
}
.synctera-hidden {
display: none;
}
</style>
</head>
<body>
<div id="synctera-success" class="synctera-container synctera-hidden">
<div class="synctera-form-container">Card activation was successful.</div>
</div>
<div id="card-activation-container" class="synctera-container">
<div class="synctera-form-container">
<div class="synctera-header">
<h2 class="synctera-header-title">Activate Card</h2>
<h4 class="synctera-header-subtitle">Enter your card details to activate</h4>
</div>
<div class="synctera-input-container">
<div class="synctera-label">Card Number</div>
<card-pan id="card-pan" token="hidden-token" class="synctera-custom-styles"
environment="SANDBOX"></card-pan>
<div class="synctera-placeholder">4111 1111 1111 1111</div>
<div id="card-pan-error" class="synctera-input-error synctera-hidden">
Card must be 16 digits
</div>
</div>
<div class="synctera-input-container">
<div class="synctera-label">Security Code</div>
<card-cvv id="card-cvv" class="synctera-custom-styles"></card-cvv>
<div class="synctera-placeholder">123</div>
<div id="card-cvv-error" class="synctera-input-error synctera-hidden">
Security code must be 3 digits
</div>
</div>
<div class="synctera-button-container">
<button id="card-activation-cancel-button" class="synctera-cancel-button">Cancel</button>
<button id="card-activation-submit-button" class="synctera-submit-button" disabled>
Activate
</button>
</div>
</div>
</div>
<div id="set-pin-container" class="synctera-container synctera-hidden">
<div class="synctera-form-container">
<div class="synctera-header">
<h2 class="synctera-header-title">Set Pin</h2>
<h4 class="synctera-header-subtitle">Enter your 4-digit card PIN</h4>
</div>
<div class="synctera-input-container">
<div class="synctera-label">New PIN</div>
<set-pin id="set-pin-controller" class="synctera-custom-styles" token="hidden-token"
environment="SANDBOX"></set-pin>
<div class="synctera-placeholder">1234</div>
<div id="set-pin-error" class="synctera-input-error synctera-hidden">PIN must be 4 digits</div>
</div>
<div class="synctera-input-container">
<div class="synctera-label">Confirm new PIN</div>
<set-pin id="set-pin-confirm" class="synctera-custom-styles" isConfirm></set-pin>
<div class="synctera-placeholder">1234</div>
<div id="set-pin-confirm-error" class="synctera-input-error synctera-hidden">PINs must Match</div>
</div>
<div class="synctera-button-container">
<button id="set-pin-cancel-button" class="synctera-cancel-button">Cancel</button>
<button id="set-pin-submit-button" class="synctera-submit-button" disabled>Submit</button>
</div>
</div>
</div>
<script>
const BASE_URL = 'http://your-server-url.com';
// Helpers
async function getCardToken(input, type = 'ACTIVATE', cardId) {
// Make an api call to your server to get the card token
const response = await fetch(
`${BASE_URL}/api/cardToken?widgetType=${type}&cardId=${cardId}`
);
const data = await response.json();
if (!data.widget_token) // update a error field
input.token = data.widget_token;
}
// Card Activation
let cardActivation = document.getElementById('card-pan');
let cardCvvInput = document.getElementById('card-cvv');
let cardPanError = document.getElementById('card-pan-error');
let cardCvvError = document.getElementById('card-cvv-error');
let cardActivationSubmit = document.getElementById('card-activation-submit-button');
let cardActivationCancel = document.getElementById('card-activation-cancel-button');
let cardActivationValid = false;
getCardToken(cardActivation, 'ACTIVATE', 'card-guid');
cardActivation.addEventListener('load', function () {
console.log('Card Activation Widget Loaded');
});
cardActivation.addEventListener('validity', function (e) {
// Check if the form is valid
cardActivationValid = e.target.isValid;
cardActivationSubmit.disabled = !cardActivationValid;
// Update validation warnings
if (cardActivationValid) {
cardPanError.classList.add('synctera-hidden');
cardCvvError.classList.add('synctera-hidden');
} else {
if (cardCvvInput.hasAttribute('_user-invalid')) {
cardCvvError.classList.remove('synctera-hidden');
} else {
cardCvvError.classList.add('synctera-hidden');
}
if (cardActivation.hasAttribute('_user-invalid')) {
cardPanError.classList.remove('synctera-hidden');
} else {
cardPanError.classList.add('synctera-hidden');
}
}
});
cardActivationSubmit.addEventListener('click', function () {
if (!cardActivationValid) return;
// Disable the submit button
cardActivationSubmit.disabled = true;
try {
cardActivation.submit();
} catch (e) {
console.error('Card failed to activate', e);
}
});
cardActivation.addEventListener('success', function () {
// Hide the card activation form
document.getElementById('card-activation-container').classList.add('synctera-hidden');
// Show the success messsage
document.getElementById('synctera-success').classList.remove('synctera-hidden');
setTimeout(() => {
// hide the success messsage
document.getElementById('synctera-success').classList.add('synctera-hidden');
// Show the set pin form
document.getElementById('set-pin-container').classList.remove('synctera-hidden');
}, 2000);
});
// SET PIN
let setPin = document.getElementById('set-pin-controller');
let setPinConfirmInput = document.getElementById('set-pin-confirm');
let setPinError = document.getElementById('set-pin-error')
let setPinConfirmError = document.getElementById('set-pin-confirm-error')
let setPinSubmit = document.getElementById('set-pin-submit-button');
let setPinCancel = document.getElementById('set-pin-cancel-button');
let setPinValid = false;
getCardToken(setPin, 'SET-PIN', 'card-guid');
setPin.addEventListener('load', function () {
console.log('Set Pin Widget Loaded');
});
setPin.addEventListener('validity', function (e) {
setPinValid = e.target.isValid;
setPinSubmit.disabled = !setPinValid;
// Update validation warnings
if (setPinValid) {
setPinError.classList.add('synctera-hidden')
setPinConfirmError.classList.add('synctera-hidden')
} else {
if (setPinConfirmInput.hasAttribute('_user-invalid')) {
setPinConfirmError.classList.remove('synctera-hidden')
} else {
setPinConfirmError.classList.add('synctera-hidden')
}
if (setPin.hasAttribute('_user-invalid')) {
setPinError.classList.remove('synctera-hidden')
} else {
setPinError.classList.add('synctera-hidden')
}
}
});
setPinSubmit.addEventListener('click', function () {
try {
setPin.submit();
} catch (e) {
console.error('Pin failed to submit', e);
}
});
setPin.addEventListener('success', function () {
console.log('Pin set successfully');
});
setPin.addEventListener('failure', function (e) {
loader.style.display = 'none';
console.error('Pin failed to submit', e);
});
</script>
</body>
</html>
Updated about 1 month ago