This is the template project that's checked out and configured when you run the bando-up command from ljsthw-bandolier. This is where the code really lives.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
bandolier-template/client/components/Stripe.svelte

148 lines
3.5 KiB

<script>
import { createEventDispatcher, onMount } from "svelte";
import api from "$/client/api.js";
import { stripe_public, base_host } from "$/client/config.js";
import Spinner from "$/client/components/Spinner.svelte";
import { fade } from "svelte/transition";
import { inject_remote } from "$/client/components/Source.svelte";
export let appearance = {
theme: 'flat',
variables: {
borderRadius: "5px", // hate this
}
};
const dispatch = createEventDispatcher();
let state = "loading"; // loading, ready,
let stripe;
let elements;
let error_message = "Please correct the form errors.";
const initialize_stripe = async (data) => {
await inject_remote(document, "https://js.stripe.com/v3/", () => {
stripe = Stripe(stripe_public.client_id);
});
// initializing stripe
const { clientSecret } = data;
elements = stripe.elements({ appearance, clientSecret });
const paymentElement = elements.create("payment");
paymentElement.mount("#payment-element");
}
const configure_payment = async () => {
// need to setup stripe first
const [status, data] = await api.post("/api/payments/stripe");
if(status === 200) {
await initialize_stripe(data);
state = "ready";
} else {
state = "error";
dispatch("error", data);
}
}
const handle_error = (error) => {
state = "error";
if (error.type === "card_error" || error.type === "validation_error") {
// can't dispatch error here because stripe handles these?
console.log("Stripe error", error);
error_message = error.message || "Please correct the form errors.";
} else {
dispatch("error", error);
}
}
const handle_submit = async () => {
state = "submit";
dispatch("click");
const { error } = await stripe.confirmPayment({
elements,
confirmParams: {
return_url: `${base_host}/api/payments/stripe`,
}
});
if(error) {
handle_error(error);
} else {
state = "submit_done";
}
}
onMount(configure_payment);
</script>
<style>
#load-cover {
min-height: 40ex;
display: flex;
justify-content: center;
align-items: center;
}
#load-cover > p {
color: var(--value4);
}
#payment-form {
background-color: var(--value9);
color: var(--value0);
padding: 0.5rem;
border-radius: var(--border-radius);
}
#payment-form button#submit {
color: var(--value9);
background-color: var(--value0);
margin-top: 0.5rem;
}
#stripe-notice {
width: 100%;
text-align: center;
color: var(--value3);
font-size: 0.8em;
}
error {
max-width: 400px;
}
</style>
<div>
<form id="payment-form">
<div class="stacked">
<div id="load-cover" class="layer" class:top={ state === "loading"}>
{#if state === "loading"}
<p out:fade|local={{ delay: 1000}}>Preparing payment form...</p>
{/if}
</div>
<div id="payment-element" class="layer">
<!--Stripe.js injects the Payment Element-->
</div>
</div>
<br>
{#if state === "error"}
<error in:fade|local={{ delay: 1000}}>
{ error_message }
</error>
{/if}
<button disabled={ state === "submit" } id="submit" on:click|preventDefault={ handle_submit }>
{#if state === "submit"}
<Spinner size="24" color="#fff"/>
{:else}
Pay with Credit Card
{/if}
</button>
<div id="stripe-notice">Credit cards securely processed by <a href="https://stripe.com">Stripe</a>.</div>
</form>
</div>