134 lines
3.0 KiB
TypeScript
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)
|
|
}
|
|
}
|