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/BTCPay.svelte

119 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>