I’m trying to implement the Payment Form in a website that I have built and am hosting via Netlify.
I have followed the walkthrough successfully outside of Netlify but when I try to move the content from the walkthrough onto my Netlify site I am running into 404 errors hitting the payment function.
I have modified the site code or the script to move the server.js
file into the /functions/
folder that Netlify requires to make the script available and tried to update the paths to match. I have also added serverless-http
per Netlify’s instructions on hosting express.js apps via Netlify functions. Here is the content of my server.js file:
const express = require('express');
const serverless = require('serverless-http');
const bodyParser = require('body-parser');
const { Client, Environment, ApiError } = require('square');
const app = express();
const port = 3000;
// Set the Access Token which is used to authorize to a merchant
const accessToken = '{REMOVED_ACCESS_TOKEN}';
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(__dirname));
// Initialized the Square api client:
// Set sandbox environment for testing purpose
// Set access token
const client = new Client({
environment: Environment.Sandbox,
accessToken: accessToken,
});
app.post('.netlify/functions/process-payment', async (req, res) => {
const requestParams = req.body;
// Charge the customer's card
const paymentsApi = client.paymentsApi;
const requestBody = {
sourceId: requestParams.nonce,
amountMoney: {
amount: 100, // $1.00 charge
currency: 'USD'
},
locationId: requestParams.location_id,
idempotencyKey: requestParams.idempotency_key,
};
try {
const response = await paymentsApi.createPayment(requestBody);
res.status(200).json({
'title': 'Payment Successful',
'result': response.result
});
} catch(error) {
let errorResult = null;
if (error instanceof ApiError) {
errorResult = error.errors;
} else {
errorResult = error;
}
res.status(500).json({
'title': 'Payment Failure',
'result': errorResult
});
}
});
app.listen(
port,
() => console.log(`listening on - http://localhost:${port}`)
);
module.exports.handler = serverless(app);
This it the payment form code I am using.
<div id="form-container">
<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 $1.00</button>
</div> <!-- end #form-container -->
<script type="text/javascript">
//TODO: paste code from step 2.1.1
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: "sandbox-sq0idb-MYmeor4LAw5C0tBRgJ0uBQ",
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: 'Postal'
},
// 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('/.netlify/functions/process-payment', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
nonce: nonce,
idempotency_key: idempotency_key,
location_id: "LVEKPR22VWSXS"
})
})
.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);
alert('Payment complete successfully!\nCheck browser developer console for more details');
})
.catch(err => {
console.error(err);
alert('Payment failed to complete!\nCheck browser developer console for more details');
});
}
}
});
//TODO: paste code from step 1.1.4
//TODO: paste code from step 1.1.5
paymentForm.build();
//TODO: paste code from step 2.1.2
//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>
Can anyone help explain why I am seeing a 404 error? I have confirmed that Netlify is deploying the server.js file so it should be available but I can’t figure out how to tell the payment form where the script is located.