Created
May 6, 2020 16:22
-
-
Save Tchangang/a697e047e548dbb69d2834820c6cce62 to your computer and use it in GitHub Desktop.
Front to handle card info
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var stripe = Stripe("xxxxxxxxxxxxxxxxxxx"); | |
var elements = stripe.elements(); | |
var style = { | |
base: { | |
color: "#32325d", | |
fontFamily: 'Arial, sans-serif', | |
fontSmoothing: "antialiased", | |
fontSize: "16px", | |
"::placeholder": { | |
color: "#32325d" | |
} | |
}, | |
invalid: { | |
fontFamily: 'Arial, sans-serif', | |
color: "#fa755a", | |
iconColor: "#fa755a" | |
} | |
}; | |
var card = elements.create("card", { style: style }); | |
// Stripe injects an iframe into the DOM | |
card.mount("#card-element"); | |
card.on("change", function (event) { | |
// Disable the Pay button if there are no card details in the Element | |
document.querySelector("button").disabled = event.empty; | |
document.querySelector("#card-errors").textContent = event.error ? event.error.message : ""; | |
}); | |
// Show a spinner on payment submission | |
function setLoading(isLoading) { | |
if (isLoading) { | |
// Disable the button and show a spinner | |
document.querySelector("button").disabled = true; | |
document.querySelector("#spinner").classList.remove("hidden"); | |
document.querySelector("#button-text").classList.add("hidden"); | |
} else { | |
document.querySelector("button").disabled = false; | |
document.querySelector("#spinner").classList.add("hidden"); | |
document.querySelector("#button-text").classList.remove("hidden"); | |
} | |
} | |
var form = document.getElementById("payment-form"); | |
form.addEventListener("submit", async function(event) { | |
event.preventDefault(); | |
setLoading(true); | |
// Complete payment when the submit button is clicked | |
const paymentMethod = await stripe.createPaymentMethod({ type: 'card', card }); // Create paymentMethod directly on stripe | |
console.log(paymentMethod); | |
try { | |
// Attach payment method to customer | |
const paymentAttached = await (await fetch("http://localhost:4242/attachpayment", { method: "POST", headers: { | |
"Content-Type": "application/json" | |
}, body: JSON.stringify({ | |
id: paymentMethod.paymentMethod.id, | |
}) | |
})).json(); | |
console.log('paymentAttached', paymentAttached); | |
// Create subscription | |
const subscriptionCreated = await (await fetch("http://localhost:4242/subscription", { method: "POST", headers: { | |
"Content-Type": "application/json" | |
}, body: JSON.stringify({ | |
id: paymentMethod.paymentMethod.id, | |
}) | |
})).json(); | |
console.log('subscriptionCreated', subscriptionCreated); | |
// If we use a card that need sca (4000002500003155), we need to confirm the payment | |
const { latest_invoice } = subscriptionCreated; | |
const { payment_intent } = latest_invoice; | |
if (payment_intent) { | |
const { client_secret, status } = payment_intent; | |
if (['requires_source_action', 'requires_payment_method', 'requires_confirmation'].includes(status)) { | |
const result = await stripe.confirmCardPayment(client_secret); // confirm payment there -> stripe will display a modal to continue | |
if (result.error) { | |
setLoading(false); // stop spinner there | |
alert(result.error); | |
return; | |
} | |
} | |
} | |
const subscriptionUpdated = await (await fetch("http://localhost:4242/subscription/".concat(subscriptionCreated.id), { method: "GET", headers: { | |
"Content-Type": "application/json" | |
}})).json(); | |
console.log('subscriptionUpdated', subscriptionUpdated); | |
setLoading(false); // stop spinner there | |
alert('subscription ready'); | |
} catch (e) { | |
setLoading(false); // stop spinner there | |
console.log('error', e); | |
alert(e.message); | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Variables */ | |
* { | |
box-sizing: border-box; | |
} | |
body { | |
font-family: -apple-system, BlinkMacSystemFont, sans-serif; | |
font-size: 16px; | |
-webkit-font-smoothing: antialiased; | |
display: flex; | |
justify-content: center; | |
align-content: center; | |
height: 100vh; | |
width: 100vw; | |
} | |
form { | |
width: 30vw; | |
min-width: 500px; | |
align-self: center; | |
box-shadow: 0px 0px 0px 0.5px rgba(50, 50, 93, 0.1), | |
0px 2px 5px 0px rgba(50, 50, 93, 0.1), 0px 1px 1.5px 0px rgba(0, 0, 0, 0.07); | |
border-radius: 7px; | |
padding: 40px; | |
} | |
input { | |
border-radius: 6px; | |
margin-bottom: 6px; | |
padding: 12px; | |
border: 1px solid rgba(50, 50, 93, 0.1); | |
height: 44px; | |
font-size: 16px; | |
width: 100%; | |
background: white; | |
} | |
.result-message { | |
line-height: 22px; | |
font-size: 16px; | |
} | |
.result-message a { | |
color: rgb(89, 111, 214); | |
font-weight: 600; | |
text-decoration: none; | |
} | |
.hidden { | |
display: none; | |
} | |
.card-error { | |
color: rgb(105, 115, 134); | |
text-align: left; | |
font-size: 13px; | |
line-height: 17px; | |
margin-top: 12px; | |
} | |
#card-element { | |
border-radius: 4px 4px 0 0 ; | |
padding: 12px; | |
border: 1px solid rgba(50, 50, 93, 0.1); | |
height: 44px; | |
width: 100%; | |
background: white; | |
} | |
#payment-request-button { | |
margin-bottom: 32px; | |
} | |
/* Buttons and links */ | |
button { | |
background: #5469d4; | |
color: #ffffff; | |
font-family: Arial, sans-serif; | |
border-radius: 0 0 4px 4px; | |
border: 0; | |
padding: 12px 16px; | |
font-size: 16px; | |
font-weight: 600; | |
cursor: pointer; | |
display: block; | |
transition: all 0.2s ease; | |
box-shadow: 0px 4px 5.5px 0px rgba(0, 0, 0, 0.07); | |
width: 100%; | |
} | |
button:hover { | |
filter: contrast(115%); | |
} | |
button:disabled { | |
opacity: 0.5; | |
cursor: default; | |
} | |
/* spinner/processing state, errors */ | |
.spinner, | |
.spinner:before, | |
.spinner:after { | |
border-radius: 50%; | |
} | |
.spinner { | |
color: #ffffff; | |
font-size: 22px; | |
text-indent: -99999px; | |
margin: 0px auto; | |
position: relative; | |
width: 20px; | |
height: 20px; | |
box-shadow: inset 0 0 0 2px; | |
-webkit-transform: translateZ(0); | |
-ms-transform: translateZ(0); | |
transform: translateZ(0); | |
} | |
.spinner:before, | |
.spinner:after { | |
position: absolute; | |
content: ""; | |
} | |
.spinner:before { | |
width: 10.4px; | |
height: 20.4px; | |
background: #5469d4; | |
border-radius: 20.4px 0 0 20.4px; | |
top: -0.2px; | |
left: -0.2px; | |
-webkit-transform-origin: 10.4px 10.2px; | |
transform-origin: 10.4px 10.2px; | |
-webkit-animation: loading 2s infinite ease 1.5s; | |
animation: loading 2s infinite ease 1.5s; | |
} | |
.spinner:after { | |
width: 10.4px; | |
height: 10.2px; | |
background: #5469d4; | |
border-radius: 0 10.2px 10.2px 0; | |
top: -0.1px; | |
left: 10.2px; | |
-webkit-transform-origin: 0px 10.2px; | |
transform-origin: 0px 10.2px; | |
-webkit-animation: loading 2s infinite ease; | |
animation: loading 2s infinite ease; | |
} | |
@-webkit-keyframes loading { | |
0% { | |
-webkit-transform: rotate(0deg); | |
transform: rotate(0deg); | |
} | |
100% { | |
-webkit-transform: rotate(360deg); | |
transform: rotate(360deg); | |
} | |
} | |
@keyframes loading { | |
0% { | |
-webkit-transform: rotate(0deg); | |
transform: rotate(0deg); | |
} | |
100% { | |
-webkit-transform: rotate(360deg); | |
transform: rotate(360deg); | |
} | |
} | |
@media only screen and (max-width: 600px) { | |
form { | |
width: 80vw; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8" /> | |
<title>Accept a card payment</title> | |
<meta name="description" content="A demo of a card payment on Stripe" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1" /> | |
<link rel="stylesheet" href="global.css" /> | |
<script src="https://js.stripe.com/v3/"></script> | |
<script src="./client.js" defer></script> | |
</head> | |
<body> | |
<form id="payment-form"> | |
<div> | |
<h1>LaGrowthMachine</h1> | |
</div> | |
<div id="card-element"><!--Stripe.js injects the Card Element--></div> | |
<button id="submit"> | |
<div class="spinner hidden" id="spinner"></div> | |
<span id="button-text">Pay</span> | |
</button> | |
</form> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment