Files
fnx_web/svelte/src/layout/checkout/CheckoutLib.ts

134 lines
3.0 KiB
TypeScript

import type { countries } from "country-data-list";
import { get_endpoint, subscription_periods, type Subscription } from "lib/NovaAPI";
export type CheckoutState = {
// undefined means the user has not picked yet, null means they chose to
// only deposit credit without starting a subscription
subscription: Subscription | null | undefined
months: number
country: typeof countries.all[0]
provider: PaymentProvider
amount: number
vat: number
name: string
}
// The price of the chosen subscription period in euro. The deposit can't be
// lower than this
export const plan_price = (state: CheckoutState): number => {
if (!state.subscription) {
return 0
}
return state.subscription.monthly_fee * state.months *
subscription_periods.find(p => p.months === state.months).discount / 1e6
}
export type PaymentProvider = {
icon: string
name: string
label: string
crypto?: boolean
need_name?: boolean
country_filter?: string[]
};
export const payment_providers: PaymentProvider[] = [
{
icon: "paypal",
name: "paypal",
label: "PayPal",
}, {
icon: "bancontact",
name: "bancontact",
label: "Bancontact",
need_name: true,
country_filter: ["BE"],
}, {
icon: "eps",
name: "eps",
label: "EPS",
need_name: true,
country_filter: ["AT"],
}, {
icon: "ideal",
name: "ideal",
label: "iDEAL",
need_name: true,
country_filter: ["NL"],
}, {
icon: "p24",
name: "p24",
label: "Przelewy24",
need_name: true,
country_filter: ["PL"],
}, {
icon: "trustly",
name: "trustly",
label: "Trustly",
need_name: true,
country_filter: ["AT", "DE", "DK", "EE", "ES", "FI", "GB", "LT", "LV", "NL", "NO", "SE"]
}, {
icon: "bitcoin",
name: "btc",
label: "Bitcoin",
crypto: true,
}, {
icon: "dogecoin",
name: "doge",
label: "Dogecoin",
crypto: true,
}, {
icon: "monero",
name: "xmr",
label: "Monero",
crypto: true,
}, {
icon: "litecoin",
name: "ltc",
label: "Litecoin",
crypto: true,
},
]
export const checkout = async (state: CheckoutState) => {
// Whether the deposit covers the subscription is checked by the server,
// which knows how much credit is already on the account
if (state.amount < 10) {
alert("Amount needs to be at least €10")
return
} else if (state.provider.need_name && !state.name) {
alert("Name is required for this provider")
return
}
const form = new FormData()
form.set("amount", String(state.amount * 1e6))
form.set("network", state.provider.name)
form.set("country", state.country.alpha3)
if (state.provider.need_name) {
form.set("name", state.name)
}
// The server activates the subscription when the invoice is paid
if (state.subscription) {
form.set("subscription", state.subscription.id)
form.set("subscription_months", String(state.months))
}
try {
const resp = await fetch(
get_endpoint() + "/user/invoice",
{ method: "POST", body: form },
)
if (resp.status >= 400) {
let json = await resp.json()
throw json.message
}
window.location = (await resp.json()).checkout_url
} catch (err) {
alert(err)
}
}