Add landing page

This commit is contained in:
Jennie Robinson Faber 2025-11-03 11:17:51 +00:00
parent 3fea484585
commit bce86ee840
47 changed files with 7119 additions and 439 deletions

View file

@ -1,158 +1,232 @@
// HelcimPay.js integration composable
export const useHelcimPay = () => {
let checkoutToken = null
let secretToken = null
let checkoutToken = null;
let secretToken = null;
// Initialize HelcimPay.js session
const initializeHelcimPay = async (customerId, customerCode, amount = 0) => {
try {
const response = await $fetch('/api/helcim/initialize-payment', {
method: 'POST',
const response = await $fetch("/api/helcim/initialize-payment", {
method: "POST",
body: {
customerId,
customerCode,
amount
}
})
amount,
},
});
if (response.success) {
checkoutToken = response.checkoutToken
secretToken = response.secretToken
return true
checkoutToken = response.checkoutToken;
secretToken = response.secretToken;
return true;
}
throw new Error('Failed to initialize payment session')
throw new Error("Failed to initialize payment session");
} catch (error) {
console.error('Payment initialization error:', error)
throw error
console.error("Payment initialization error:", error);
throw error;
}
}
};
// Initialize payment for event ticket purchase
const initializeTicketPayment = async (
eventId,
email,
amount,
eventTitle = null,
) => {
try {
const response = await $fetch("/api/helcim/initialize-payment", {
method: "POST",
body: {
customerId: null,
customerCode: email, // Use email as customer code for event tickets
amount,
metadata: {
type: "event_ticket",
eventId,
email,
eventTitle,
},
},
});
if (response.success) {
checkoutToken = response.checkoutToken;
secretToken = response.secretToken;
return {
success: true,
checkoutToken: response.checkoutToken,
};
}
throw new Error("Failed to initialize ticket payment session");
} catch (error) {
console.error("Ticket payment initialization error:", error);
throw error;
}
};
// Show payment modal
const showPaymentModal = () => {
return new Promise((resolve, reject) => {
if (!checkoutToken) {
reject(new Error('Payment not initialized. Call initializeHelcimPay first.'))
return
reject(
new Error("Payment not initialized. Call initializeHelcimPay first."),
);
return;
}
// Add custom CSS to fix Helcim overlay styling
if (!document.getElementById("helcim-overlay-fix")) {
const style = document.createElement("style");
style.id = "helcim-overlay-fix";
style.textContent = `
/* Fix Helcim iframe overlay - the second parameter to appendHelcimPayIframe controls this */
/* Target all fixed position divs that might be the overlay */
body > div[style*="position: fixed"][style*="inset: 0"],
body > div[style*="position:fixed"][style*="inset:0"] {
background-color: rgba(0, 0, 0, 0.75) !important;
}
`;
document.head.appendChild(style);
}
// Load HelcimPay.js modal script
if (!window.appendHelcimPayIframe) {
console.log('HelcimPay script not loaded, loading now...')
const script = document.createElement('script')
script.src = 'https://secure.helcim.app/helcim-pay/services/start.js'
script.async = true
console.log("HelcimPay script not loaded, loading now...");
const script = document.createElement("script");
script.src = "https://secure.helcim.app/helcim-pay/services/start.js";
script.async = true;
script.onload = () => {
console.log('HelcimPay script loaded successfully!')
console.log('Available functions:', Object.keys(window).filter(key => key.includes('Helcim') || key.includes('helcim')))
console.log('appendHelcimPayIframe available:', typeof window.appendHelcimPayIframe)
openModal(resolve, reject)
}
console.log("HelcimPay script loaded successfully!");
console.log(
"Available functions:",
Object.keys(window).filter(
(key) => key.includes("Helcim") || key.includes("helcim"),
),
);
console.log(
"appendHelcimPayIframe available:",
typeof window.appendHelcimPayIframe,
);
openModal(resolve, reject);
};
script.onerror = () => {
reject(new Error('Failed to load HelcimPay.js'))
}
document.head.appendChild(script)
reject(new Error("Failed to load HelcimPay.js"));
};
document.head.appendChild(script);
} else {
console.log('HelcimPay script already loaded, calling openModal')
openModal(resolve, reject)
console.log("HelcimPay script already loaded, calling openModal");
openModal(resolve, reject);
}
})
}
});
};
// Open the payment modal
const openModal = (resolve, reject) => {
try {
console.log('Trying to open modal with checkoutToken:', checkoutToken)
if (typeof window.appendHelcimPayIframe === 'function') {
console.log("Trying to open modal with checkoutToken:", checkoutToken);
if (typeof window.appendHelcimPayIframe === "function") {
// Set up event listener for HelcimPay.js responses
const helcimPayJsIdentifierKey = 'helcim-pay-js-' + checkoutToken
const helcimPayJsIdentifierKey = "helcim-pay-js-" + checkoutToken;
const handleHelcimPayEvent = (event) => {
console.log('Received window message:', event.data)
console.log("Received window message:", event.data);
if (event.data.eventName === helcimPayJsIdentifierKey) {
console.log('HelcimPay event received:', event.data)
console.log("HelcimPay event received:", event.data);
// Remove event listener to prevent multiple responses
window.removeEventListener('message', handleHelcimPayEvent)
if (event.data.eventStatus === 'SUCCESS') {
console.log('Payment success:', event.data.eventMessage)
window.removeEventListener("message", handleHelcimPayEvent);
// Close the Helcim modal
if (typeof window.removeHelcimPayIframe === "function") {
window.removeHelcimPayIframe();
}
if (event.data.eventStatus === "SUCCESS") {
console.log("Payment success:", event.data.eventMessage);
// Parse the JSON string eventMessage
let paymentData
let paymentData;
try {
paymentData = JSON.parse(event.data.eventMessage)
console.log('Parsed payment data:', paymentData)
paymentData = JSON.parse(event.data.eventMessage);
console.log("Parsed payment data:", paymentData);
} catch (parseError) {
console.error('Failed to parse eventMessage:', parseError)
reject(new Error('Invalid payment response format'))
return
console.error("Failed to parse eventMessage:", parseError);
reject(new Error("Invalid payment response format"));
return;
}
// Extract transaction details from nested data structure
const transactionData = paymentData.data?.data || {}
console.log('Transaction data:', transactionData)
const transactionData = paymentData.data?.data || {};
console.log("Transaction data:", transactionData);
resolve({
success: true,
transactionId: transactionData.transactionId,
cardToken: transactionData.cardToken,
cardLast4: transactionData.cardNumber ? transactionData.cardNumber.slice(-4) : undefined,
cardType: transactionData.cardType || 'unknown'
})
} else if (event.data.eventStatus === 'ABORTED') {
console.log('Payment aborted:', event.data.eventMessage)
reject(new Error(event.data.eventMessage || 'Payment failed'))
} else if (event.data.eventStatus === 'HIDE') {
console.log('Modal closed without completion')
reject(new Error('Payment cancelled by user'))
cardLast4: transactionData.cardNumber
? transactionData.cardNumber.slice(-4)
: undefined,
cardType: transactionData.cardType || "unknown",
});
} else if (event.data.eventStatus === "ABORTED") {
console.log("Payment aborted:", event.data.eventMessage);
reject(new Error(event.data.eventMessage || "Payment failed"));
} else if (event.data.eventStatus === "HIDE") {
console.log("Modal closed without completion");
reject(new Error("Payment cancelled by user"));
}
}
}
};
// Add event listener
window.addEventListener('message', handleHelcimPayEvent)
window.addEventListener("message", handleHelcimPayEvent);
// Open the HelcimPay iframe modal
console.log('Calling appendHelcimPayIframe with token:', checkoutToken)
window.appendHelcimPayIframe(checkoutToken, true)
console.log('appendHelcimPayIframe called, waiting for window messages...')
console.log("Calling appendHelcimPayIframe with token:", checkoutToken);
window.appendHelcimPayIframe(checkoutToken, true);
console.log(
"appendHelcimPayIframe called, waiting for window messages...",
);
// Add timeout to clean up if no response
setTimeout(() => {
console.log('60 seconds passed, cleaning up event listener...')
window.removeEventListener('message', handleHelcimPayEvent)
reject(new Error('Payment timeout - no response received'))
}, 60000)
console.log("60 seconds passed, cleaning up event listener...");
window.removeEventListener("message", handleHelcimPayEvent);
reject(new Error("Payment timeout - no response received"));
}, 60000);
} else {
reject(new Error('appendHelcimPayIframe function not available'))
reject(new Error("appendHelcimPayIframe function not available"));
}
} catch (error) {
console.error('Error opening modal:', error)
reject(error)
console.error("Error opening modal:", error);
reject(error);
}
}
};
// Process payment verification
const verifyPayment = async () => {
try {
return await showPaymentModal()
return await showPaymentModal();
} catch (error) {
throw error
throw error;
}
}
};
// Cleanup tokens
const cleanup = () => {
checkoutToken = null
secretToken = null
}
checkoutToken = null;
secretToken = null;
};
return {
initializeHelcimPay,
initializeTicketPayment,
verifyPayment,
cleanup
}
}
cleanup,
};
};