I have a form in a Webflow website that dynamically calculates a price depending on selectors the user has chosen.
`<script>
document.addEventListener('DOMContentLoaded', function() {
const selections = document.querySelectorAll('#language, input[name="turnaround"], #timecoding, input[name="textFormat"], input[name="speakers"]');
const estimatedPriceElement = document.getElementById('estimatedPrice');
const form = document.querySelector('form'); // Adjust selector as needed
let fileSizeInMB = 0; // Initialize file size in MB, will be set by Uploadcare
// Default multipliers for selections
let defaultMultipliers = {
language: 1, // Default multiplier for language
turnaround: 1, // Default multiplier for turnaround time
timecoding: 1, // Default multiplier for timecoding
textFormat: 1, // Default multiplier for text format
speakers: 1, // Default multiplier for speakers
};
function calculatePrice() {
let priceMultiplier = 1; // Start with a multiplier of 1
selections.forEach(selection => {
if ((selection.type === 'radio' && selection.checked) || selection.type === 'select-one') {
let selectionValue = parseFloat(selection.value);
if (!isNaN(selectionValue)) {
priceMultiplier *= selectionValue;
} else {
priceMultiplier *= defaultMultipliers[selection.name] || 1;
}
}
});
let finalPrice = fileSizeInMB * priceMultiplier;
estimatedPriceElement.textContent = `$${isNaN(finalPrice) ? "N/A" : finalPrice.toFixed(2)}`;
}
selections.forEach(selection => {
selection.addEventListener('change', calculatePrice);
});
const widget = uploadcare.Widget('#uploadcareWidget');
widget.onUploadComplete(info => {
fileSizeInMB = info.size / (1024 * 1024);
calculatePrice();
});
form.addEventListener('submit', function(event) {
event.preventDefault(); // Prevent default submission
console.log("Form submit event triggered");
// Capture the project name from the form
const projectName = document.getElementById('project-name-2').value;
const priceText = estimatedPriceElement.textContent;
const price = parseInt(priceText.replace(/^\$/, '').replace(/,/g, '')) * 100; // Convert to cents
console.log("Calculated price (in cents):", price);
console.log("About to send fetch request", { price: price });
fetch('https://test-app-123456-efc60cbf5fa3.herokuapp.com/create-checkout-session', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ price: price, name: projectName }) // Include the project name here
})
.then(response => response.json())
.then(data => {
// Ensure we're accessing the 'url' property correctly
if(data.url) {
window.location.href = data.url; // Redirect to the Stripe checkout page
} else {
console.error('Session URL is undefined:', data);
}
})
.catch((error) => {
console.error('Error:', error);
});
});
});
</script>`
Which is supposed to send a POST request to the server to create "create-checkout-session":
require 'stripe'
require 'sinatra'
require 'sinatra/cors'
set :allow_origin, "****"
set :allow_methods, "GET,POST"
set :allow_headers, "content-type,if-modified-since"
set :expose_headers, "location,link"
set :cors_allow_credentials, true # If your requests are made with credentials
# This is your test secret API key.
Stripe.api_key = '****'
set :static, true
set :port, ENV['PORT'] || ****
YOUR_DOMAIN = '****'
YOUR_SUCCESS_URL = YOUR_DOMAIN + '/success.html'
YOUR_CANCEL_URL = YOUR_DOMAIN + '/cancel.html'
get '/' do
'Hello, world!'
end
post '/create-checkout-session' do
content_type :json
request_body = JSON.parse(request.body.read)
puts "Endpoint /create-checkout-session hit"
# Extract the project name from the request
project_name = request_body['name']
# Log received price for debugging
final_price = request_body['price'].to_i
if final_price <= 0
status 400 # Bad Request
return { error: 'Invalid price calculated.' }.to_json
end
# Create Stripe Checkout session with the final price
begin
session = Stripe::Checkout::Session.create({
payment_method_types: ['card'],
line_items: [{
price_data: {
currency: 'usd',
product_data: {
name: project_name || 'Custom Product', # Use the project name or a default
},
unit_amount: final_price,
},
quantity: 1,
}],
mode: 'payment',
success_url: YOUR_SUCCESS_URL,
cancel_url: YOUR_CANCEL_URL,
})
{ url: session.url }.to_json
rescue Stripe::StripeError => e
status 500
{ error: e.message }.to_json
end
end
The problem is the dynamically generated price doesn't show up in the Stripe Checkout page. The page is successfully created, but without the dynamic price.
I've tried adding a "puts" statement to show up in the console logs to check that it's successfully gone through, but it never appears. I also tried to simple change the product name rather than the price dynamically but that didn't work either.