Stay Connected

Connecting you to every opportunity you need to study, teach, get certified, and build a future through French.



French Courses

Structured French language programs spanning all proficiency levels, from beginner (A1) to advanced (C1), aligned with the Common European Framework of Reference for Languages.



Graduate Scholarships

Access curated scholarship opportunities for graduate studies at accredited institutions across French- and English-speaking countries, tailored to academic merit and program eligibility



Tests & Certification

Preparation and administration support for internationally recognized language certifications, including DELF/DALF, TCF, IELTS and TOEFL



English Courses

Comprehensive English language instruction covering grammar, vocabulary, comprehension, and conversational fluency, structured to meet international proficiency standards.



Teach & Travel

Structured programs connecting candidates with teaching and cultural exchange opportunities abroad, combining professional development with immersive international experience.


French Courses Built for Exam Success

Focused French courses that prepare you for the TCF, DELF, and DALF, with guided practice in listening, reading, writing, and speaking.


0

Years of Experience

0

Students Enroled

0

Countries Reached


What our community says

Our learners share what changed for them. Your story could be next.

Kwame Asante

Tertiary Student · Accra, Ghana
Course: DELF Exam Preparation

January 2026.

“The exam preparation made a real difference.”

Structured programs connecting candidates with teaching and cultural exchange opportunities abroad, combining professional development with immersive international experience.

Esi Owusu

Recent Graduate · Kumasi, Ghana
Course: Conversational French

December 2025.

“I gained confidence in speaking French.”

What I appreciated most was the opportunity to practise speaking instead of only memorising vocabulary. The interactive sessions made learning enjoyable and helped me become more confident in conversations.


Frequently Asked Questions

Find answers about us, our courses and class schedules.

What is French Connect by Charity?

French Connect by Charity helps learners study French and prepare for the TCF, DELF, and DALF exams. We also offer guidance on opportunities such as graduate scholarships and teach-and-travel programs.

Who are the courses for?

Anyone who wants to learn French, from complete beginners to advanced speakers. You don't need any prior knowledge to start.

Do I need to know my level before joining?

No. Take our free level test to get an estimate from A1 to C1, and we'll suggest the class that fits you best.

How do the classes work?

Classes are live online, so you can join from anywhere with an internet connection. You'll learn in real time with your teacher and practice speaking, listening, reading, and writing.

Can I take the exam with French Connect?

No. We are not an official exam center. We prepare you, and you register for the exam through an approved center.

What do I need to join?

A phone, tablet, or computer with a stable internet connection, and a headset if you can. Zoom/Google Meet is usually needed for live classes.


Stay Connected

Stay in the loop. Follow our WhatsApp channel for exam updates, course news, scholarship alerts, and opportunities, straight to your phone.

Your French journey starts here.

Not sure where to begin? Take our free proficiency test to find your French level from A1 to C1 and see which classes fit you.



Fast Track, 40 hrs

● LIVE ONLINE | Beginner - Advanced

  • Runs for 4 weeks

  • Monday - Friday

  • 2 hours per session

  • Start times: 7:00 AM / 12:00 PM / 6:00 PM



Steady Pace, 18 hrs

● LIVE ONLINE | Interactive Classes

  • Runs for 6 weeks

  • Monday, Wednesday, and Friday

  • 1 hour every session

  • Start times: 10:00 AM / 3:00 PM / 4:30 PM



Speaking Club, 4 hrs

● LIVE ONLINE | Flexible Learning

  • Runs for 8 weeks

  • Saturdays only

  • 30 minutes every session

  • Start time: 8:00 AM


Private French Lessons

● ONLINE / IN-PERSON | Private Class

  • One-on-One Attention

  • Flexible Scheduling

  • Personalized Learning

  • Goal-Oriented Progress


In-Person Classes

We're not offering in-person sessions right now. Join the waitlist to be notified when they return, or start learning today with our live online classes.


Frequently Asked Questions

What types of French courses do you offer?

We offer group French classes, private lessons, and exam preparation courses tailored to different proficiency levels and learning goals.

Do I need prior French knowledge to enrol?

No. We welcome beginners and advanced learners, helping each student find a course that matches their current proficiency.

Are your French classes online or in person?

Our courses offer flexible learning options, including live online classes and private lessons, depending on your chosen programme.

How long does it take to learn French?

It depends on your starting level, learning goals, and consistency. We structure our courses to help you progress at a steady pace.

Can I choose a class schedule that suits me?

Yes. We offer different schedules and learning formats to help you balance French lessons with your other commitments.


Stay Connected

Stay in the loop. Follow our WhatsApp channel for exam updates, course news, scholarship alerts, and opportunities, straight to your phone.


Free French Proficiency Test

Assess your French language skills with our CEFR-aligned test. Discover your current level instantly and receive tailored recommendations to guide your learning journey.


Loading the test...


French Proficiency Levels

A1
Beginner

A2
Elementary

B1
Intermediate

B2
Upper Intermediate

C1
Advanced

Ace Your French Exam with Confidence

Prepare for DELF, DALF, and TCF with live classes, timed mock exams, and personal feedback.


3 EXAMS COVERED

Which Exam Are You Preparing For?

Every exam has its own format and requirements. Open any one for details, or contact us for personal guidance.

Choose a goal above to see your best match.

DELF B2, DALF C1, or TCF

Usual targets: B2 for a bachelor's, C1 for a master's

Many French universities ask for a TCF score made for admissions. Others accept DELF or DALF diplomas. Each university sets its own rule, so check yours.

Read about the exam      Find your level

DELF or DALF

Choose the level that matches your ability

A diploma that never expires is the safest proof for employers. If your employer asks for a score instead, the TCF may fit better.

Read about the DELF      Find your level

DELF

Start at the level you hold today

For travel or a vacation, none of the exams is required. Visa and entry rules for tourists don't ask for French proof, so an exam is only worth it as a personal goal.

Learn more      Find your level


The exams side by side

Each of the three exams assesses all four language skills: listening, reading, writing, and speaking.

ExamLevelsValidityBest forResult
DELFA1 to B2LifelongStudy, work, personal goalsDiploma
DALFC1 to C2LifelongAdvanced university studyDiploma
TCFA1 to C2LimitedAdmissions, immigrationScore report

Check your requirement first

Rules differ by school, employer, and country, and they change. Before you register, confirm with the institution that asked for your French. Official sources:• France Education International, which runs DELF, DALF, and TCF
• The admissions or immigration page of the institution you are applying to

Last checked: October 2026.


Not sure of your level?

Take the free French level test, then come back with your result.


From here to exam day

Four steps, in this order.

1

Choose your exam
Use the picker above

2

Check your level
Take the free level test

3

Prepare in class
Join a prep class

4

Register
Book an approved exam


Frequently Asked Questions

Can I take both DELF and TCF?

Yes. They are separate exams with separate registration. Take the one your application asks for.

Do DELF results expire?

No. DELF and DALF diplomas are valid for life. TCF results are valid for a limited time.

Which exam is the easiest?

None is easier in general. Each one measures your level, so the right choice is the exam that matches your goal and your current ability.

Can I take the exam with French Connect?

No. We are not an official exam center. We prepare you, and you register for the exam through an approved center.


Ready to start?

Find your level, then join the prep class that fits your exam.


Stay Connected

Stay in the loop. Follow our WhatsApp channel for exam updates, course news, scholarship alerts, and opportunities, straight to your phone.

Lifetime-Valid French Diploma

DELF & DALF Exam Prep

Prepare confidently for your DELF and DALF exams with expert guidance, structured lessons, and targeted practice.

Never Expires
Recognized Worldwide
A1 → C2 Levels

Start Your Exam Prep in 4 Steps

Follow our simple step-by-step process, from choosing your exam to preparing confidently for test day.

1

Choose Your Exam
Select your proficiency and certification goal.

2

Assess Your Level
Identify your strengths and learning gaps.

3

Enrol in Prep Classes
Choose your preferred course and schedule.

4

Start Your Preparation
Practise with mock exams and guidance.


Frequently Asked Questions

How do I enrol in DELF/DALF exam preparation?

Simply complete our enrolment form, choose your preferred preparation course, and we’ll guide you through the next steps.

Can French Connect register me for the official exam?

No. We provide exam preparation, but you must register separately through an authorised DELF/DALF examination centre.

Do I need prior French knowledge to join?

No. We help you choose the right preparation level based on your current proficiency and target DELF/DALF exam.


Ready to start?

Find your level, then join the prep class that fits your exam.


In-Person Classes

We're not offering in-person sessions right now. Join the waitlist to be notified when they return, or start learning today with our live online classes.


Stay Connected

Stay in the loop. Follow our WhatsApp channel for exam updates, course news, scholarship alerts, and opportunities, straight to your phone.

Your French Level, Officially Assessed

TCF Exam Prep

Prepare for your TCF exam with expert guidance, focused practice, and proven strategies to help you achieve your target score.

Valid for 2 Years
Study & Immigration
A1 → C2 Levels

Start Your Exam Prep in 4 Steps

Follow our simple step-by-step process, from choosing your exam to preparing confidently for test day.

1

Choose Your Exam
Select your proficiency and certification goal.

2

Assess Your Level
Identify your strengths and learning gaps.

3

Enrol in Prep Classes
Choose your preferred course and schedule.

4

Start Your Preparation
Practise with mock exams and guidance.


Frequently Asked Questions

How do I enrol in TCF exam preparation?

Complete our enrolment form, tell us your target score and preferred TCF exam, and we’ll guide you through the next steps.

Can French Connect register me for the official TCF exam?

No. We provide TCF exam preparation, but you must register separately through an authorised examination centre.

Which TCF exam should I prepare for?

It depends on your goal. We’ll help you identify the appropriate TCF version, whether for university admission, immigration, or other official requirements.


Ready to start?

Find your level, then join the prep class that fits your exam.


In-Person Classes

We're not offering in-person sessions right now. Join the waitlist to be notified when they return, or start learning today with our live online classes.


Stay Connected

Stay in the loop. Follow our WhatsApp channel for exam updates, course news, scholarship alerts, and opportunities, straight to your phone.

LIVE ONLINE | Beginner - Advanced

Fast Track, 40 hrs

Learn French faster with interactive live online lessons designed to build your confidence and fluency in just 4 weeks.

Max 10 Students / Class
A1-C1 CEFR Levels
12 Lessons

Course Format

4 Weeks · 40 Hours · Live Online · Beginner to Advanced


Week 1: Enrolment & Foundations


Lesson 1: Enrolment, placement assessment, course orientation, and platform setup.Lesson 2: French alphabet, pronunciation, greetings, and introductions.Lesson 3: Numbers, dates, everyday vocabulary, and basic expressions.



Week 2: Grammar & Communication


Lesson 4: Basic grammar, articles, pronouns, and present-tense verbs.Lesson 5: Sentence construction, asking questions, and answering correctly.Lesson 6: Everyday conversations, shopping, directions, and ordering food.



Week 3: Practical French & Fluency


Lesson 7: Listening comprehension, reading, and guided speaking.Lesson 8: Past and future tenses, descriptions, and expressing opinions.Lesson 9: Real-life conversations, role-play, and spoken presentations.



Week 4: Mastery & Certification


Lesson 10: Advanced grammar, writing, fluency practice, and revision.Lesson 11: Final assessment — speaking, listening, reading, and writing.Lesson 12: Results, individual feedback, course completion, and certificate award.


Course Delivery


Duration: 4 weeks
Total lessons: 12 key learning milestones
Total course hours: 40 hours
Schedule: Monday–Friday, 2 hours per session
Delivery: Live online classes
Completion: Final assessment and certificate for eligible learners

Note: The 12 lessons are key milestones within the 20-session, 40-hour programme. Additional sessions will support practice, revision, and assessments.


Ready to fast-track your French?

Join our intensive 4-week French course and start speaking with confidence.



Private French Lessons

● ONLINE / IN-PERSON | Private Class

  • One-on-One Attention

  • Flexible Scheduling

  • Personalized Learning

  • Goal-Oriented Progress


Stay Connected

Stay in the loop. Follow our WhatsApp channel for exam updates, course news, scholarship alerts, and opportunities, straight to your phone.

LIVE ONLINE | Interactive Classes

Steady Pace, 18 hrs

Improve your French with interactive live online classes. Build your vocabulary, and strengthen communication skills over 6 weeks.

6 Weeks
Mon, Wed & Fri
18 One-Hour Sessions

Course Format

6 Weeks · 18 Hours · Live Online · Interactive Classes


Week 1: Getting Started


Lesson 1: Enrolment, course orientation, and level assessment.Lesson 2: French alphabet, pronunciation, greetings, and introductions.Lesson 3: Numbers, dates, and everyday expressions.



Week 2: Building the Basics


Lesson 4: French nouns, articles, pronouns, and basic grammar.Lesson 5: Common vocabulary and sentence construction.Lesson 6: Introducing yourself, asking questions, and answering.



Week 3: Everyday Communication


Lesson 7: Talking about family, work, studies, and hobbies.Lesson 8: Ordering food, shopping, and asking for directions.Lesson 9: Present-tense verbs and everyday conversations.



Week 4: Developing Fluency


Lesson 10: Describing people, places, and daily routines.Lesson 11: Listening comprehension and reading practice.Lesson 12: Guided conversations and pronunciation improvement.



Week 5: Expanding Your Skills


Lesson 13: Past and future expressions.Lesson 14: Expressing opinions, preferences, and needs.Lesson 15: Role-play, practical dialogue, and writing exercises.



Week 6: Revision & Certification


Lesson 16: Grammar revision and conversation practice.Lesson 17: Final assessment — speaking, listening, reading, and writing.Lesson 18: Feedback, results, and certificate award for eligible learners.


Course Delivery


Duration: 6 weeks
Total lessons: 18
Total course hours: 18 hours
Schedule: Monday, Wednesday, and Friday
Delivery: Live online interactive classes
Class times: 10:00 AM, 3:00 PM, or 4:30 PM

This format assumes one lesson per session, with a gradual progression from beginner foundations to practical communication. Advanced-level learners may need a separate, level-adjusted syllabus.


Ready to fast-track your French?

Join our intensive 4-week French course and start speaking with confidence.



Private French Lessons

● ONLINE / IN-PERSON | Private Class

  • One-on-One Attention

  • Flexible Scheduling

  • Personalized Learning

  • Goal-Oriented Progress


Stay Connected

Stay in the loop. Follow our WhatsApp channel for exam updates, course news, scholarship alerts, and opportunities, straight to your phone.


Create your account

Join French Connect and start learning French with Charity.

Already have an account? Log in

(function () { /* ===== SETTINGS: fill these in ===== */ const SUPABASE_URL = "https://bpufouhrgehavhotdkie.supabase.co"; const SUPABASE_KEY = "sb_publishable_ZdIJi07nwN5WBA8oSOimfQ_Wt8ZrpgZ"; const CONFIRM_REDIRECT = "https://fcbyc.carrd.co/"; const LOGIN_PAGE = "https://fcbyc.carrd.co/#login"; /* ==================================== */ function start() { const supabase = window.__fcClient || (window.__fcClient = window.supabase.createClient(SUPABASE_URL, SUPABASE_KEY)); const form = document.getElementById("fc-form"); const msg = document.getElementById("fc-msg"); const btn = document.getElementById("fc-submit"); const pass = document.getElementById("fc-password"); const confirmPass = document.getElementById("fc-confirm"); document.getElementById("fc-login-link").href = LOGIN_PAGE; document.getElementById("fc-toggle").addEventListener("click", (e) => { const show = pass.type === "password"; pass.type = show ? "text" : "password"; confirmPass.type = show ? "text" : "password"; e.target.textContent = show ? "Hide" : "Show"; }); function showMsg(text, ok) { msg.className = "fc-msg " + (ok ? "fc-ok" : "fc-error"); msg.textContent = text; } form.addEventListener("submit", async (e) => { e.preventDefault(); e.stopPropagation(); msg.className = "fc-msg"; if (document.getElementById("fc-website").value) return; const fullName = document.getElementById("fc-name").value.trim(); const email = document.getElementById("fc-email").value.trim(); const password = pass.value; if (fullName.length < 2) return showMsg("Please enter your full name.", false); if (!/^\S+@\S+\.\S+$/.test(email)) return showMsg("Please enter a valid email address.", false); if (password.length < 8) return showMsg("Your password must be at least 8 characters.", false); if (password !== confirmPass.value) return showMsg("The two passwords do not match.", false); btn.disabled = true; btn.textContent = "Creating account..."; const { data, error } = await supabase.auth.signUp({ email, password, options: { data: { full_name: fullName }, emailRedirectTo: CONFIRM_REDIRECT, }, }); btn.disabled = false; btn.textContent = "Create account"; if (error) { return showMsg(error.message, false); } /* Supabase returns no error for an email that is already registered, but the identities list comes back empty. */ if (data.user && data.user.identities && data.user.identities.length === 0) { return showMsg("This email is already registered. Please log in instead.", false); } form.reset(); showMsg("Account created. Check your email and click the confirmation link to activate it.", true); }, true); } function showLoadError() { var m = document.getElementById("fc-msg"); if (m) { m.className = "fc-msg fc-error"; m.textContent = "The signup service could not load. Please refresh the page and try again."; } } /* Load the Supabase library first, then start the form logic once it is ready */ if (window.supabase && window.supabase.createClient) { start(); } else { var lib = document.createElement("script"); lib.src = "https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2"; lib.onload = start; lib.onerror = showLoadError; document.head.appendChild(lib); } })();

Welcome back

Log in to access your French Connect lessons.

Do not have an account yet? Sign up

(function () { /* ===== SETTINGS ===== */ var SUPABASE_URL = "https://bpufouhrgehavhotdkie.supabase.co"; var SUPABASE_KEY = "sb_publishable_ZdIJi07nwN5WBA8oSOimfQ_Wt8ZrpgZ"; var DASHBOARD_URL = "https://fcbyc.carrd.co/#dashboard"; var RESET_REDIRECT = "https://fcbyc.carrd.co/?reset=1"; var SIGNUP_PAGE = "https://fcbyc.carrd.co/#signup"; /* ===================== */ var linkError = window.location.hash.indexOf("error_code") > -1; var isRecovery = window.location.hash.indexOf("type=recovery") > -1 || window.location.search.indexOf("reset=1") > -1; var tokenHash = new URLSearchParams(window.location.search).get("token_hash"); function start() { var client = window.__fcClient || (window.__fcClient = window.supabase.createClient(SUPABASE_URL, SUPABASE_KEY)); var root = document.getElementById("fc-login"); var msg = document.getElementById("fcl-msg"); var title = document.getElementById("fcl-title"); var sub = document.getElementById("fcl-sub"); var foot = document.getElementById("fcl-foot"); var loginForm = document.getElementById("fcl-login"); var forgotForm = document.getElementById("fcl-forgot"); var resetForm = document.getElementById("fcl-reset"); var pass = document.getElementById("fcl-password"); document.getElementById("fcl-signup-link").href = SIGNUP_PAGE; function showMsg(text, ok) { msg.className = "fc-msg " + (ok ? "fc-ok" : "fc-error"); msg.textContent = text; } function clearMsg() { msg.className = "fc-msg"; msg.textContent = ""; } function showPanel(which) { clearMsg(); loginForm.hidden = which !== "login"; forgotForm.hidden = which !== "forgot"; resetForm.hidden = which !== "reset"; foot.hidden = which === "reset"; if (which === "login") { title.textContent = "Welcome back"; sub.textContent = "Log in to access your French Connect lessons."; } else if (which === "forgot") { title.textContent = "Reset your password"; sub.textContent = "Enter your email and we will send you a link to choose a new password."; } else { title.textContent = "Choose a new password"; sub.textContent = "Enter a new password for your account."; } } function validEmail(v) { return /^\S+@\S+\.\S+$/.test(v); } function hasRecoverySession(session) { try { var part = session.access_token.split(".")[1].replace(/-/g, "+").replace(/_/g, "/"); var claims = JSON.parse(atob(part)); var amr = claims.amr || []; for (var i = 0; i < amr.length; i++) { if (amr[i].method === "recovery") return true; } } catch (err) {} return false; } function jump() { setTimeout(function () { root.scrollIntoView({ behavior: "smooth", block: "center" }); }, 700); } function expiredReset() { showPanel("forgot"); showMsg("This reset link has expired or was already used. Enter your email to get a new one.", false); } document.getElementById("fcl-toggle").addEventListener("click", function (e) { var show = pass.type === "password"; pass.type = show ? "text" : "password"; e.target.textContent = show ? "Hide" : "Show"; }); document.getElementById("fcl-to-forgot").addEventListener("click", function () { document.getElementById("fcl-forgot-email").value = document.getElementById("fcl-email").value; showPanel("forgot"); }); document.getElementById("fcl-to-login").addEventListener("click", function () { showPanel("login"); }); loginForm.addEventListener("submit", async function (e) { e.preventDefault(); e.stopPropagation(); clearMsg(); var email = document.getElementById("fcl-email").value.trim(); var password = pass.value; if (!validEmail(email)) return showMsg("Please enter a valid email address.", false); if (!password) return showMsg("Please enter your password.", false); var btn = document.getElementById("fcl-login-btn"); btn.disabled = true; btn.textContent = "Logging in..."; var result = await client.auth.signInWithPassword({ email: email, password: password }); btn.disabled = false; btn.textContent = "Log in"; if (result.error) { var m = result.error.message || "Login failed. Please try again."; if (m.toLowerCase().indexOf("not confirmed") > -1) { m = "Please confirm your email first. Check your inbox for the confirmation link."; } return showMsg(m, false); } showMsg("Logged in. Taking you to your dashboard...", true); window.location.href = DASHBOARD_URL; }, true); forgotForm.addEventListener("submit", async function (e) { e.preventDefault(); e.stopPropagation(); clearMsg(); var email = document.getElementById("fcl-forgot-email").value.trim(); if (!validEmail(email)) return showMsg("Please enter a valid email address.", false); var btn = document.getElementById("fcl-forgot-btn"); btn.disabled = true; btn.textContent = "Sending..."; var result = await client.auth.resetPasswordForEmail(email, { redirectTo: RESET_REDIRECT }); btn.disabled = false; btn.textContent = "Send reset link"; if (result.error) return showMsg(result.error.message, false); showMsg("If that email has an account, a reset link is on its way. Check your inbox and spam folder.", true); }, true); resetForm.addEventListener("submit", async function (e) { e.preventDefault(); e.stopPropagation(); clearMsg(); var p1 = document.getElementById("fcl-new").value; var p2 = document.getElementById("fcl-new2").value; if (p1.length < 8) return showMsg("Your password must be at least 8 characters.", false); if (p1 !== p2) return showMsg("The two passwords do not match.", false); if (tokenHash) { var verified = await client.auth.verifyOtp({ token_hash: tokenHash, type: "recovery" }); if (verified.error) return expiredReset(); tokenHash = null; } var current = await client.auth.getSession(); if (!current.data || !current.data.session) { return expiredReset(); } var btn = document.getElementById("fcl-reset-btn"); btn.disabled = true; btn.textContent = "Updating..."; var result = await client.auth.updateUser({ password: p1 }); btn.disabled = false; btn.textContent = "Update password"; if (result.error) return showMsg(result.error.message, false); await client.auth.signOut(); try { window.history.replaceState(null, "", window.location.pathname + "#login"); } catch (err) {} showPanel("login"); showMsg("Password updated. Please log in with your new password.", true); }, true); client.auth.onAuthStateChange(function (event) { if (event === "PASSWORD_RECOVERY") { showPanel("reset"); jump(); } }); if (linkError) { showPanel("forgot"); showMsg("That reset link has expired or was already used. Enter your email to get a new one.", false); jump(); } else if (isRecovery) { showPanel("reset"); jump(); } client.auth.getSession().then(function (res) { if (!linkError && res.data && res.data.session && hasRecoverySession(res.data.session)) { showPanel("reset"); jump(); } }); } function showLoadError() { var m = document.getElementById("fcl-msg"); if (m) { m.className = "fc-msg fc-error"; m.textContent = "The login service could not load. Please refresh the page and try again."; } } /* Load the Supabase library first, then start the form logic once it is ready */ if (window.supabase && window.supabase.createClient) { start(); } else { var lib = document.createElement("script"); lib.src = "https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2"; lib.onload = start; lib.onerror = showLoadError; document.head.appendChild(lib); } })();
(function () { /* ===== SETTINGS: replace these values ===== */ var STRIPE_PUBLISHABLE_KEY = "pk_test_51URdwFRfTAzAmuAgrH9jwBIuVk8eJMTvDULp08b6wiif05CfLEwZeGjfB3T1nrbRMMsMpyNPaVhIwQePLTPWFG9400WWolxVje"; var CHECKOUT_ENDPOINT = "https://bpufouhrgehavhotdkie.supabase.co/functions/v1/quick-handler"; var SUPABASE_ANON_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImJwdWZvdWhyZ2VoYXZob3Rka2llIiwicm9sZSI6ImFub24iLCJpYXQiOjE3OTE4MzQ1OTcsImV4cCI6MjEwNzQxMDU5N30.gdn-sB92l9mHO5ZZXXMYqT21vXg-YDSljJrzRpobnb8"; /* ========================================== */ function showError(text) { var m = document.getElementById("fc-checkout-msg"); if (m) { m.textContent = text; m.style.display = "block"; } } async function start() { try { var stripe = Stripe(STRIPE_PUBLISHABLE_KEY); var appearance = { "theme": "stripe", "labels": "auto", "inputs": "condensed", "variables": { "borderRadius": "4px", "colorBackground": "#fdfcf2", "colorDanger": "#df1b41", "colorPrimary": "#000770", "colorSuccess": "#00c853", "colorText": "#30313d", "fontFamily": "default", "fontSizeBase": "16px", "spacingUnit": "4px" } }; var clientSecret = fetch(CHECKOUT_ENDPOINT, { method: "POST", headers: { "Authorization": "Bearer " + SUPABASE_ANON_KEY } }) .then(function (response) { return response.json(); }) .then(function (json) { console.log("Endpoint response:", json); return json.client_secret; }); var checkout = stripe.initCheckoutFormSdk({ clientSecret: clientSecret, appearance: appearance }); var form = checkout.createForm({ layout: "expanded" }); form.mount("#checkout-form"); var loadActionsResult = await checkout.loadActions(); if (loadActionsResult.type === "success") { form.on("confirm", async function (event) { try { await loadActionsResult.actions.confirm({ formConfirmEvent: event }); } catch (error) { console.error("Payment confirmation error:", error); showError("Your payment could not be confirmed. Please try again."); } }); } else { console.error("loadActions failed:", loadActionsResult.error); showError("The payment form could not load. Please refresh the page and try again."); } } catch (error) { console.error("Checkout setup error:", error); showError("The payment form could not load. Please refresh the page and try again."); } } if (window.Stripe && typeof window.Stripe === "function") { start(); } else { var lib = document.createElement("script"); lib.src = "https://js.stripe.com/dahlia/stripe.js"; lib.onload = start; lib.onerror = function () { showError("The payment form could not load. Please refresh the page and try again."); }; document.head.appendChild(lib); } })();