This is the code that runs https://bandolier.learnjsthehardway.com/ for you to review. It uses the https://git.learnjsthehardway.com/learn-javascript-the-hard-way/bandolier-template to create the documentation for the project.
https://bandolier.learnjsthehardway.com/
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.
118 lines
3.3 KiB
118 lines
3.3 KiB
<svelte:head>
|
|
<link rel="dns-prefetch" href="{ btcpay_url }">
|
|
<link rel="preconnect" href="{ btcpay_url }">
|
|
</svelte:head>
|
|
|
|
<script>
|
|
import { createEventDispatcher } from 'svelte';
|
|
import Source from './Source.svelte';
|
|
let loading_btc = false;
|
|
const dispatch = createEventDispatcher();
|
|
import Spinner from './Spinner.svelte';
|
|
import { fake_payments, btcpay_url } from '$/client/config.js';
|
|
import { log } from "$/client/logging.js";
|
|
|
|
export let product;
|
|
export let amount = product.price;
|
|
export let disabled = false;
|
|
let sys_primary_id = "";
|
|
let internal_id = "";
|
|
|
|
const btcpay_enter = (what) => {
|
|
log.debug("btcpay_enter", what);
|
|
loading_btc = false;
|
|
dispatch('loading', {});
|
|
}
|
|
|
|
const btcpay_leave = async (what) => {
|
|
log.debug("btcpay_leave", what);
|
|
loading_btc = false;
|
|
const resp = await fetch('/api/payments/btcpay', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json'},
|
|
body: JSON.stringify({ sys_primary_id, internal_id })
|
|
});
|
|
|
|
if(resp.status !== 200) {
|
|
const text = await resp.text();
|
|
dispatch("error", text);
|
|
} else {
|
|
const invoice = await resp.json();
|
|
console.log("invoice response is", invoice);
|
|
|
|
// TODO: confirm returned invoice ids match the requested ones
|
|
let payment = {
|
|
system: 'btcpay',
|
|
internal_id,
|
|
sys_primary_id,
|
|
status: invoice.status === "Settled" ? 'complete' : 'pending'
|
|
};
|
|
|
|
console.log("btcpay sending client", payment);
|
|
dispatch(payment.status === 'complete' ? 'finished' : 'canceled', payment);
|
|
}
|
|
}
|
|
|
|
const btcpay_submit = async () => {
|
|
if(disabled) return;
|
|
|
|
if(fake_payments) {
|
|
// do a fake thing just to work on the UI
|
|
log.debug("fake_payments set, sending finished event");
|
|
dispatch('finished', { system: 'btcpay', invoice_id: 'FAKE', sys_primary_id: 11234, status: 'complete'});
|
|
} else if(sys_primary_id) {
|
|
// already have an invoice going so just open it again
|
|
loading_btc = true;
|
|
window.btcpay.showInvoice(sys_primary_id);
|
|
} else {
|
|
loading_btc = true;
|
|
// looks like this is fresh, get a new invoice to pay
|
|
const resp = await fetch(`/api/payments/btcpay?amount=${ amount }`);
|
|
const data = await resp.json();
|
|
|
|
if(resp.status !== 200) {
|
|
dispatch("error", data);
|
|
} else {
|
|
// TODO: handle response errors from here
|
|
window.btcpay.onModalWillEnter(btcpay_enter);
|
|
window.btcpay.onModalWillLeave(btcpay_leave);
|
|
|
|
sys_primary_id = data.sys_primary_id;
|
|
internal_id = data.internal_id;
|
|
|
|
window.btcpay.showInvoice(sys_primary_id);
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style>
|
|
button.btcpay-submit {
|
|
display: flex;
|
|
flex-direction: row;
|
|
justify-content: center;
|
|
align-items: center;
|
|
cursor: pointer;
|
|
width: 100%;
|
|
margin-bottom: 0.5rem;
|
|
background-color: var(--color-bg-secondary);
|
|
color: var(--color);
|
|
}
|
|
|
|
.bitcoin-logo {
|
|
max-height: 1rem;
|
|
color: #fff;
|
|
width: unset;
|
|
margin-left: 0.5rem;
|
|
}
|
|
</style>
|
|
|
|
<Source src={ btcpay_url } />
|
|
|
|
<button type="button" on:click|preventDefault={ btcpay_submit } data-testid="btcpay-submit" class="btcpay-submit" alt="Pay with ₿itcoin">
|
|
{#if loading_btc}
|
|
<Spinner />
|
|
{:else}
|
|
Pay with <img alt="Bitcoin" class="bitcoin-logo" src="/images/Bitcoin_logo.svg">
|
|
{/if}
|
|
</button>
|
|
|