60 lines
1.9 KiB
TypeScript
60 lines
1.9 KiB
TypeScript
import React from 'react';
|
|
import { useTranslation } from 'react-i18next';
|
|
import toast from 'react-hot-toast';
|
|
|
|
import { createTenantPaddleCheckout } from '../../api';
|
|
import { adminPath } from '../../constants';
|
|
import { getApiErrorMessage } from '../../lib/apiError';
|
|
import { storePendingCheckout } from '../lib/billingCheckout';
|
|
|
|
export function usePackageCheckout(): {
|
|
busy: boolean;
|
|
startCheckout: (packageId: number) => Promise<void>;
|
|
} {
|
|
const { t } = useTranslation('management');
|
|
const [busy, setBusy] = React.useState(false);
|
|
|
|
const startCheckout = React.useCallback(
|
|
async (packageId: number) => {
|
|
if (busy) {
|
|
return;
|
|
}
|
|
setBusy(true);
|
|
try {
|
|
if (typeof window === 'undefined') {
|
|
throw new Error('Checkout is only available in the browser.');
|
|
}
|
|
|
|
const billingUrl = new URL(adminPath('/mobile/billing'), window.location.origin);
|
|
const successUrl = new URL(billingUrl);
|
|
successUrl.searchParams.set('checkout', 'success');
|
|
successUrl.searchParams.set('package_id', String(packageId));
|
|
const cancelUrl = new URL(billingUrl);
|
|
cancelUrl.searchParams.set('checkout', 'cancel');
|
|
cancelUrl.searchParams.set('package_id', String(packageId));
|
|
|
|
const { checkout_url, checkout_session_id } = await createTenantPaddleCheckout(packageId, {
|
|
success_url: successUrl.toString(),
|
|
return_url: cancelUrl.toString(),
|
|
});
|
|
|
|
if (checkout_session_id) {
|
|
storePendingCheckout({
|
|
packageId,
|
|
checkoutSessionId: checkout_session_id,
|
|
startedAt: Date.now(),
|
|
});
|
|
}
|
|
|
|
window.location.href = checkout_url;
|
|
} catch (err) {
|
|
toast.error(getApiErrorMessage(err, t('shop.errors.checkout', 'Checkout failed')));
|
|
setBusy(false);
|
|
}
|
|
},
|
|
[busy, t],
|
|
);
|
|
|
|
return { busy, startCheckout };
|
|
}
|