В тестовой среде я пытаюсь подключить валидатор кредитной карты Stripe Elements
к коду, который настроен для сохранения проверенной информации о форме, а также обновления хранимой информации. Код должен имитировать checkout UX
, где пользователи могут вводить информацию о новой кредитной карте (используя форму Stripe Elements) и сохранять свою проверенную информацию, используя local storage
.
Помимо возможности сохранять свои новые карты, они могут обновлять карты, которые уже были сохранены / отображаются при загрузке.
Проблема, с которой я столкнулся, заключается в том, что я не уверен, как определить var valid = ();
, который будет зацикливать форму Stripe Elements с кодом обновления / сохранения, а также запускать два экземпляра валидатора Stripe (один для новых карти еще один - для обновления сохраненных карточек).
Вот кодовая ручка: https://codepen.io/moofawsaw/pen/jOOwbwG
$(document).ready(function() {
var stripe = Stripe("pk_test_6pRNASCoBOKtIshFeQd4XMUh");
var elements = stripe.elements();
var style = {
base: {
iconColor: "#666EE8",
color: "#31325F",
lineHeight: "40px",
fontWeight: 600,
fontSize: "16px",
"::placeholder": {
color: "#CFD7E0",
fontWeight: 400
}
}
};
var cardNumberElement = elements.create("cardNumber", {
style: style
});
cardNumberElement.mount("#cc-number");
var cardExpiryElement = elements.create("cardExpiry", {
style: style
});
cardExpiryElement.mount("#cc-exp");
var cardCvcElement = elements.create("cardCvc", {
style: style
});
cardCvcElement.mount("#cc-cvc");
function setOutcome(result) {
var successElement = document.querySelector(".success");
var errorElement = document.querySelector(".error");
successElement.classList.remove("visible");
errorElement.classList.remove("visible");
if (result.token) {
// In this example, we're simply displaying the token
successElement.querySelector(".token").textContent = result.token.id;
successElement.classList.add("visible");
// In a real integration, you'd submit the form with the token to your backend server
//var form = document.querySelector('form');
//form.querySelector('input[name="token"]').setAttribute('value', result.token.id);
//form.submit();
} else if (result.error) {
errorElement.textContent = result.error.message;
errorElement.classList.add("visible");
}
}
var cardBrandToPfClass = {
visa: "pf-visa",
mastercard: "pf-mastercard",
amex: "pf-american-express",
discover: "pf-discover",
diners: "pf-diners",
jcb: "pf-jcb",
unknown: "pf-credit-card"
};
function setBrandIcon(brand) {
var brandIconElement = document.getElementById("brand-icon");
var pfClass = "pf-credit-card";
if (brand in cardBrandToPfClass) {
pfClass = cardBrandToPfClass[brand];
}
for (var i = brandIconElement.classList.length - 1; i >= 0; i--) {
brandIconElement.classList.remove(brandIconElement.classList[i]);
}
brandIconElement.classList.add("pf");
brandIconElement.classList.add(pfClass);
}
cardNumberElement.on("change", function(event) {
// Switch brand logo
if (event.brand) {
setBrandIcon(event.brand);
}
setOutcome(event);
});
document.querySelector(".payment").addEventListener("submit", function(e) {
e.preventDefault();
var options = {};
stripe.createToken(cardNumberElement, options).then(setOutcome);
});
$(function() {
var $selectedItem;
window.localStorage.clear();
if (!localStorage.getItem("_storage")) {
localStorage.setItem("_storage", "");
}
//create localStorage item
if (localStorage.getItem("_storage")) {
$("#content").html(localStorage.getItem("_storage"));
}
//set data to localStorage function
function saveData() {
localStorage.setItem("_storage", $("#content").html());
}
$(".payment").on("click", ".btn--save", function() {
if (valid) {
var id = $("#cc-cvc").val();
var createnumb = $("#cc-number").val();
var exp = $("#cc-exp").val();
var item = "";
if (id[0]) {
for (var i = 0; i < id.length; i++) {
item += "<div>" + id[i] + "</div>";
}
} else {
item = "<div>Click update to add a card</div>";
}
$("#content").append(
'<div class="checkout__card">' +
'<div class="card__numb">' +
createnumb +
"</div>" +
"<div class='card__cvc'>" +
id +
"</div>" +
"<div class='card__exp'>" +
exp +
"</div>" +
'<button class="card__remove">Delete</button>' +
'<button class="card__update">Update</button>' +
"</div>"
);
$("#cc-number").val("");
$("#cc-exp").val("");
$("#cc-cvc").val("");
/* $(".payment").toggle();*/
saveData();
}
});
//Close out of creating a new item
/* $(".close").click(function() {
$("#cc-number").val("");
$("#cc-cvc").val("");
$(".create").toggle();
});*/
//Get inputs and open edit window to update the items:
$("#content").on("click", ".card__update", function() {
$selectedItem = $(this).closest(".checkout__card");
$(".updatenumb").val(
$(this)
.closest(".checkout__card")
.find(".card__numb")
.text()
);
$(".updateexp").val(
$(this)
.closest(".checkout__card")
.find(".card__exp")
.text()
);
$(".updatecvc").val(
$(this)
.closest(".checkout__card")
.find(".card__cvc")
.text()
);
$(".card__modal").toggle();
});
//Save changes and update the items (error:changes all items when clicked):
$(".card__modal").on("click", ".card__save", function() {
if (valid) {
var id = $(".updatecvc").val();
var numb = $(".updatenumb").val();
var exp = $(".updateexp").val();
var item = "";
if (id[0]) {
for (var i = 0; i < id.length; i++) {
item += "<div>" + id[i] + "</div>";
}
} else {
item = "<p>Click edit to add a card</p>";
}
$selectedItem.html(
'<div class="card__numb">' +
numb +
"</div>" +
"<div class='card__cvc'>" +
id +
"</div>" +
"<div class='card__exp'>" +
exp +
"</div>" +
'<button class="card__remove">Deleted(saved)</button>' +
'<button class="card__update">Updated(saved)</button>'
);
$(".updatenumb").val("");
$(".updateexp").val("");
$(".updatecvc").val("");
$(".card__modal").toggle();
saveData();
} else {}
});
//Discard any of these changes:
$(".card__discard").click(function() {
$(".updatenumb").val("");
$(".updateexp").val("");
$(".updatecvc").val("");
$(".card__modal").toggle();
});
//Delete an item:
$("#content").on("click", ".card__remove", function() {
$(this)
.closest(".checkout__card")
.remove();
saveData();
});
});
});
#content {
display: flex;
background-color: #f5f5f5;
border: 1px solid #c2c2c2;
}
.checkout__card {
display: flex;
align-items: center;
}
.card__numb,
.card__cvc,
.card__exp {
padding: 3px;
margin: 3px;
border: 1px solid;
}
payment__card,
.card__modal {
display: none;
position: absolute;
z-index: 10;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 300px;
height: 200px;
overflow: hidden;
border: 2px solid;
}
input {
border: 2px solid;
}
.field {
background: transparent;
font-weight: 400;
border: 0;
color: #31325f;
outline: none;
flex: 1;
padding-right: 10px;
padding-left: 10px;
cursor: text;
}
.field::-webkit-input-placeholder {
color: #cfd7e0;
}
.field::-moz-placeholder {
color: #cfd7e0;
}
.outcome {
float: left;
width: 100%;
padding-top: 8px;
min-height: 24px;
text-align: center;
}
.success,
.error {
display: none;
font-size: 13px;
}
.success.visible,
.error.visible {
display: inline;
}
.error {
color: #e4584c;
}
.success {
color: #666ee8;
}
.success .token {
font-weight: 500;
font-size: 13px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://js.stripe.com/v3/"></script>
<form class="payment" action="//httpbin.org/post" method="POST">
<input type="hidden" name="token" />
<div class="">
<label>
<span>Card number</span>
<div id="cc-number" class="field"></div>
</label>
<label>
<span>Expiry date</span>
<div id="cc-exp" class="field"></div>
</label>
<label>
<span>CVC</span>
<div id="cc-cvc" class="field"></div>
</label>
</div>
<button type="submit" class="btn--payment">Confirm</button>
<button type="button" class="btn--save">Save</button>
<div class="outcome">
<div class="error"></div>
<div class="success">
Success! Your Stripe token is <span class="token"></span>
</div>
</div>
</form>
<div id="container">
<div id="content">
<div class="checkout__card">
<div class="card__numb">4353 2455 2346 8236</div>
<p class="card__cvc">101</p>
<p class="card__exp">01/24</p>
<button class="card__remove">Delete</button>
<button class="card__update">Update</button>
</div>
</div>
<!-- <button class="btn--addcard">Add Card</button>-->
</div>
<div class="card__modal">
<div class="card__board">
<form class="payment" action="//httpbin.org/post" method="POST">
<input type="hidden" name="token" />
<div class="">
<label>
<span>Card number</span>
<div class="field updatenumb"></div>
</label>
<label>
<span>Expiry date</span>
<div class="field updateexp"></div>
</label>
<label>
<span>CVC</span>
<div class="field updatecvc"></div>
</label>
</div>
<button type="submit" class="btn--payment">Confirm</button>
<button type="button" class="btn--save">Save</button>
<div class="outcome">
<div class="error"></div>
<div class="success">
Success! Your Stripe token is <span class="token"></span>
</div>
</div>
</form>
<button class="card__save">Save</button>
<button class="card__discard">Discard</button>
</div>
</div>