Is there a “for dummies” on how to do this? This is NOT simple, like it was to setup the square payment form. In my old code, I have the following in my head:
<script type="text/javascript" src="https://js.squareup.com/v2/paymentform"></script>
<!-- link to the custom styles for SqPaymentForm -->
<style>
body, html {
background-color: #F7F8F9;
color: #373F4A;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-weight: normal;
height: 100%;
}
button {
border: 0;
font-weight: 500;
}
fieldset {
margin: 0;
padding: 0;
border: 0;
}
#form-container {
position: relative;
width: 380px;
margin: 0 auto;
top: 50%;
transform: translateY(-50%);
}
.third {
float: left;
width: calc((100% - 32px) / 3);
padding: 0;
margin: 0 16px 16px 0;
}
.third:last-of-type {
margin-right: 0;
}
/* Define how SqPaymentForm iframes should look */
.sq-input {
height: 56px;
box-sizing: border-box;
border: 1px solid #E0E2E3;
background-color: white;
border-radius: 6px;
display: inline-block;
-webkit-transition: border-color .2s ease-in-out;
-moz-transition: border-color .2s ease-in-out;
-ms-transition: border-color .2s ease-in-out;
transition: border-color .2s ease-in-out;
}
/* Define how SqPaymentForm iframes should look when they have focus */
.sq-input--focus {
border: 1px solid #4A90E2;
}
/* Define how SqPaymentForm iframes should look when they contain invalid values */
.sq-input--error {
border: 1px solid #E02F2F;
}
#sq-card-number {
margin-bottom: 16px;
}
/* Customize the "Pay with Credit Card" button */
.button-credit-card {
width: 100%;
height: 56px;
margin-top: 10px;
background: #4A90E2;
border-radius: 6px;
cursor: pointer;
display: block;
color: #FFFFFF;
font-size: 16px;
line-height: 24px;
font-weight: 700;
letter-spacing: 0;
text-align: center;
-webkit-transition: background .2s ease-in-out;
-moz-transition: background .2s ease-in-out;
-ms-transition: background .2s ease-in-out;
transition: background .2s ease-in-out;
}
.button-credit-card:hover {
background-color: #4281CB;
}
</style>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<meta name="csrf-token" content="{{ csrf_token() }}">
The body code ended up like this (I had followed the Walkthrough for SqPaymentForm):
<!-- Begin Payment Form -->
<div id="form-container row">
<div id="sq-card-number"></div>
<div class="third" id="sq-expiration-date"></div>
<div class="third" id="sq-cvv"></div>
<div class="third" id="sq-postal-code"></div>
<button id="sq-creditcard" class="button-credit-card" onclick="onGetCardNonce(event)">Pay ${{number_format($payment->due_amt, 2)}}</button>
</div>
<!-- end #form-container -->
<!-- End Payment Form -->
and the footer of my page:
{{-- Square payment form javascript --}}
<script type="text/javascript">
const idempotency_key = uuidv4();
// Create and initialize a payment form object
const paymentForm = new SqPaymentForm({
// Initialize the payment form elements
//TODO: Replace with your sandbox application ID
applicationId: "{MY_APPLICATION_ID}",
inputClass: 'sq-input',
autoBuild: false,
// Customize the CSS for SqPaymentForm iframe elements
inputStyles: [{
fontSize: '16px',
lineHeight: '24px',
padding: '16px',
placeholderColor: '#a0a0a0',
backgroundColor: 'transparent',
}],
// Initialize the credit card placeholders
cardNumber: {
elementId: 'sq-card-number',
placeholder: 'Card Number'
},
cvv: {
elementId: 'sq-cvv',
placeholder: 'CVV'
},
expirationDate: {
elementId: 'sq-expiration-date',
placeholder: 'MM/YY'
},
postalCode: {
elementId: 'sq-postal-code',
placeholder: 'Zip Code'
},
// SqPaymentForm callback functions
callbacks: {
/*
* callback function: cardNonceResponseReceived
* Triggered when: SqPaymentForm completes a card nonce request
*/
cardNonceResponseReceived: function (errors, nonce, cardData) {
if (errors) {
// Log errors from nonce generation to the browser developer console.
console.error('Encountered errors:');
errors.forEach(function (error) {
console.error(' ' + error.message);
});
alert('Encountered errors, check browser developer console for more details');
return;
}
//TODO: Replace alert with code in step 2.1
fetch('{{ $payment->id }}', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
body: JSON.stringify({
nonce: nonce,
idempotency_key: {{ $payment->id }},
patient_id: {{ $payment->patient_id }},
location_id: "{MY_LOCATION_ID}"
})
})
.catch(err => {
alert('Network error: ' + err);
})
.then(response => {
if (!response.ok) {
return response.json().then(
errorInfo => Promise.reject(errorInfo));
}
return response.json();
})
.then(data => {
console.log(data);
// display alert showing payment completed successfully
// alert('Payment completed successfully!\n Auth code: '+ data['auth_code'] + '\n');
// when alert closes, redirect to IHC receipt page
window.location.href=data['url'];
})
.catch(err => {
console.error(err);
alert('Payment failed!\n' + err['message']);
});
}
}
});
paymentForm.build();
//Generate a random UUID as an idempotency key for the payment request
// length of idempotency_key should be less than 45
function uuidv4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
// onGetCardNonce is triggered when the "Pay $1.00" button is clicked
function onGetCardNonce(event) {
// Don't submit the form until SqPaymentForm returns with a nonce
event.preventDefault();
// Request a nonce from the SqPaymentForm object
paymentForm.requestCardNonce();
}
</script>```
I figure I need to replace the body of the document with:
<form id="payment-form">
<div id="card-container"></div>
<button id="card-button" type="button">Pay $1.00</button>
</form>
<div id="payment-status-container"></div>
<!-- End Payment Form -->
and the header, should have:
<!-- link to the custom styles for SqPaymentForm -->
<script>
{{-- Initialize Web Payments SDK varialbes --}}
const appId = '{{ env('SQUARE_APPLICATION_ID') }}';
const locationId = '{{ env('SQUARE_LOCATION') }}';
// Initialize Card payment method by calling Payments.card()
// method and attaching the payment method to the DOM with card.attach() method
async function initializeCard(payments) {
const card = await payments.card();
await card.attach('#card-container');
return card;
}
document.addEventListener('DOMContentLoaded', async function () {
if (!window.Square) {
throw new Error('Square.js failed to load properly');
}
const payments = window.Square.payments(appId, locationId);
let card;
try {
card = await initializeCard(payments);
} catch (e) {
console.error('Initializing Card failed', e);
return;
}
// Step 5.2: create card payment
async function handlePaymentMethodSubmission(event, paymentMethod) {
event.preventDefault();
try {
// disable the submit button as we await tokenization and make a
// payment request.
cardButton.disabled = true;
const token = await tokenize(paymentMethod);
const paymentResults = await createPayment(token);
displayPaymentResults('SUCCESS');
console.debug('Payment Success', paymentResults);
} catch (e) {
cardButton.disabled = false;
displayPaymentResults('FAILURE');
console.error(e.message);
}
}
const cardButton = document.getElementById(
'card-button'
);
cardButton.addEventListener('click', async function (event) {
await handlePaymentMethodSubmission(event, card);
});
});
</script>
I don't have anything at the end in the footer. What else am I missing to get this thing working? I already tried to follow the migration page and that was a shit-show. Frustrated is an understatement. When I try to use the sandbox, it doesn't display the payment form and gives me an https error in the console `Unhandled Promise Rejection: WebSdkEmbedError: Web Payments SDK can only be embedded on sites that use HTTPS`
Someone please help! I'm happy to write something up if someone can help me make this work.