diff --git a/src/templates/payment_form.html b/src/templates/payment_form.html index 19732a03a2df9e17029deb1a8da06c5c639babf1..c4348c5e31b1e35b0a6e82f0a76b018a4b099029 100644 --- a/src/templates/payment_form.html +++ b/src/templates/payment_form.html @@ -7,159 +7,156 @@ <script type="text/javascript" src="web.squarecdn.com/v1/square.js"></script> {# bring the location IDs into javascript so the next bits know about them #} -<script type="text/javascript"> - -var appId = "{{ app_id }}"; -var locationId = "{{ loc_id }}"; -var amount = "{{ payment.amount }}"; - -async function initializeCard(payments) { - const card = await payments.card(); - await card.attach('#card-container'); - return card; -} - -// Call this function to send a payment token, buyer name, and other details -// to the project server code so that a payment can be created with -// Payments API -async function createPayment(token, verificationToken) { - const csrfToken = document.querySelector('input[name=csrfmiddlewaretoken]').value; - const body = JSON.stringify({ - locationId, - sourceId: token, - verificationToken: verificationToken, - }); +<script type="text/javascript"> - // if (verificationToken !== undefined) { - // body.verificationToken = verificationToken; - // } - - const paymentResponse = await fetch(location.href, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-CSRFToken': csrfToken, - }, - body, - credentials: 'same-origin', - }); + var appId = "{{ app_id }}"; + var locationId = "{{ loc_id }}"; + var amount = "{{ payment.amount }}"; - return paymentResponse.json(); -} - -// This function tokenizes a payment method. -// The ‘error’ thrown from this async function denotes a failed tokenization, -// which is due to buyer error (such as an expired card). It is up to the -// developer to handle the error and provide the buyer the chance to fix -// their mistakes. -async function tokenize(paymentMethod) { - const tokenResult = await paymentMethod.tokenize(); - if (tokenResult.status === 'OK') { - return tokenResult.token; - } else { - let errorMessage = `Tokenization failed-status: ${tokenResult.status}`; - if (tokenResult.errors) { - errorMessage += ` and errors: ${JSON.stringify( - tokenResult.errors - )}`; - } - throw new Error(errorMessage); + async function initializeCard(payments) { + const card = await payments.card(); + await card.attach('#card-container'); + return card; } -} - -async function verifyBuyer(payments, token) { - const verificationDetails = { - amount: '{{ payment.amount }}', - /* collected from the buyer */ - billingContact: {}, - currencyCode: 'AUD', - intent: 'CHARGE', - }; - - const verificationResults = await payments.verifyBuyer( - token, - verificationDetails - ); - - return verificationResults.token; -} - -// Helper method for displaying the Payment Status on the screen. -// status is either SUCCESS or FAILURE; -function displayPaymentResults(status) { - const cardButton = document.getElementById( - 'card-button' - ); - if (status === 'SUCCESS') { - cardButton.classList.remove('failure'); - cardButton.classList.add('success'); - cardButton.innerText = 'Payment successful! Redirecting...'; - } else { - cardButton.classList.remove('success'); - cardButton.classList.add('failure'); - cardButton.innerText = 'Payment failed :( Refreshing...'; - } -} + // Call this function to send a payment token, buyer name, and other details + // to the project server code so that a payment can be created with + // Payments API + async function createPayment(token, verificationToken) { + const csrfToken = document.querySelector('input[name=csrfmiddlewaretoken]').value; + const body = JSON.stringify({ + locationId, + sourceId: token, + verificationToken: verificationToken, + }); + + const paymentResponse = await fetch(location.href, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-CSRFToken': csrfToken, + }, + body, + credentials: 'same-origin', + }); + + return paymentResponse.json(); + } -document.addEventListener('DOMContentLoaded', async function() { - const loader = document.getElementById('spinner'); - const cardButton = document.getElementById( - 'card-button' - ); + // This function tokenizes a payment method. + // The ‘error’ thrown from this async function denotes a failed tokenization, + // which is due to buyer error (such as an expired card). It is up to the + // developer to handle the error and provide the buyer the chance to fix + // their mistakes. + async function tokenize(paymentMethod) { + const tokenResult = await paymentMethod.tokenize(); + if (tokenResult.status === 'OK') { + return tokenResult.token; + } else { + let errorMessage = `Tokenization failed-status: ${tokenResult.status}`; + if (tokenResult.errors) { + errorMessage += ` and errors: ${JSON.stringify( + tokenResult.errors + )}`; + } + throw new Error(errorMessage); + } + } - cardButton.disabled = true; - if (!window.Square) { - throw new Error('Square.js failed to load properly'); + async function verifyBuyer(payments, token) { + const verificationDetails = { + amount: '{{ payment.amount }}', + /* collected from the buyer */ + billingContact: {}, + currencyCode: 'AUD', + intent: 'CHARGE', + }; + + const verificationResults = await payments.verifyBuyer( + token, + verificationDetails + ); + + return verificationResults.token; } - const payments = window.Square.payments(appId, locationId); - let card; - try { - card = await initializeCard(payments); - loader.style.display = 'none'; - cardButton.disabled = false; - } catch (e) { - console.error('Initializing Card failed', e); - return; + + // Helper method for displaying the Payment Status on the screen. + // status is either SUCCESS or FAILURE; + function displayPaymentResults(status) { + const cardButton = document.getElementById( + 'card-button' + ); + if (status === 'SUCCESS') { + cardButton.classList.remove('failure'); + cardButton.classList.add('success'); + cardButton.innerText = 'Payment successful! Redirecting...'; + } else { + cardButton.classList.remove('success'); + cardButton.classList.add('failure'); + cardButton.innerText = 'Payment failed :( Refreshing...'; + } } - async function handlePaymentMethodSubmission(event, paymentMethod, shouldVerify = true) { - event.preventDefault(); - const token = await tokenize(paymentMethod); + + document.addEventListener('DOMContentLoaded', async function () { + const loader = document.getElementById('spinner'); + const cardButton = document.getElementById( + 'card-button' + ); + cardButton.disabled = true; - cardButton.innerText = "Processing..."; - - let verificationToken; - if (shouldVerify) { - verificationToken = await verifyBuyer( - payments, - token - ); + if (!window.Square) { + throw new Error('Square.js failed to load properly'); } - - const paymentResults = await createPayment(token, verificationToken); - if (paymentResults.success) { - displayPaymentResults('SUCCESS'); - setTimeout( - function(){window.location.href = "{{ payment.completed_url }}";}, 3000 - ); - } else { + const payments = window.Square.payments(appId, locationId); + let card; + try { + card = await initializeCard(payments); + loader.style.display = 'none'; cardButton.disabled = false; - displayPaymentResults('FAILURE'); - console.error(paymentResults.errors); - setTimeout( - function(){window.location.href = "{{ payment.completed_url }}";}, 3000 - ); + } catch (e) { + console.error('Initializing Card failed', e); + return; } - console.debug('Payment Success', paymentResults); - } + async function handlePaymentMethodSubmission(event, paymentMethod, shouldVerify = true) { + event.preventDefault(); + const token = await tokenize(paymentMethod); + + cardButton.disabled = true; + cardButton.innerText = "Processing..."; + + let verificationToken; + if (shouldVerify) { + verificationToken = await verifyBuyer( + payments, + token + ); + } + + const paymentResults = await createPayment(token, verificationToken); + if (paymentResults.success) { + displayPaymentResults('SUCCESS'); + setTimeout( + function () { window.location.href = "{{ payment.completed_url }}"; }, 3000 + ); + } else { + cardButton.disabled = false; + displayPaymentResults('FAILURE'); + console.error(paymentResults.errors); + setTimeout( + function () { window.location.href = "{{ payment.completed_url }}"; }, 3000 + ); + } + console.debug('Payment Success', paymentResults); - cardButton.addEventListener('click', async function(event) { - await handlePaymentMethodSubmission(event, card, true); - }); + } + + cardButton.addEventListener('click', async function (event) { + await handlePaymentMethodSubmission(event, card, true); + }); -}); + }); </script> <link rel="stylesheet" type="text/css" href="{% static 'squarepay.css' %}"> @@ -173,16 +170,16 @@ document.addEventListener('DOMContentLoaded', async function() { <div class="form-header"> <span class="tips {% if payment.is_paid %}error{% endif %}">{% block tips %} {% if payment.is_paid %} - <p><b>It appears you have already successfully attempted this payment.</b> - {% if payment.completed_url %} - <br><br>Perhaps you were meaning to find <a href="{{ payment.completed_url }}">this page</a>. - {% endif %} - </p> + <p><b>It appears you have already successfully attempted this payment.</b> + {% if payment.completed_url %} + <br><br>Perhaps you were meaning to find <a href="{{ payment.completed_url }}">this page</a>. + {% endif %} + </p> {% else %} - <b><i>Please fill in your card details below.</i></b> + <b><i>Please fill in your card details below.</i></b> {% endif %} </span> -{% endblock %} + {% endblock %} <noscript> <span class="tips error">Please enable javascript to use the payment form.</span> @@ -203,7 +200,12 @@ document.addEventListener('DOMContentLoaded', async function() { <div id="form-container" class="payment-info"> <div class="float-container"> {% csrf_token %} - <div id=spinner class="lds-ellipsis" id="payment-form"><div></div><div></div><div></div><div></div></div> + <div id=spinner class="lds-ellipsis" id="payment-form"> + <div></div> + <div></div> + <div></div> + <div></div> + </div> <form id="payment-form"> <div id="card-container"></div> <button id="card-button" type="button">Pay {{ amount }}</button> @@ -213,4 +215,4 @@ document.addEventListener('DOMContentLoaded', async function() { </div> </div> </div> -{% endblock %} +{% endblock %} \ No newline at end of file