feat: retry failed payments

This commit is contained in:
Arman committed 2024-02-02 16:54:13 +01:00
1 parent 58bd9fc8b4
commit 431c5c2cf3
4 files changed
+110 -3

No files matched your search

+1
View File
@@ -263,6 +263,7 @@ export enum Submit {
PaymentMethodCreate = 'submit_payment_method_create',
PaymentMethodUpdate = 'submit_payment_method_update',
PaymentMethodDelete = 'submit_payment_method_delete',
RetryPayment = 'submit_retry_payment',
BillingAddressCreate = 'submit_billing_address_create',
BillingAddressUpdate = 'submit_billing_address_update',
BillingAddressDelete = 'submit_billing_address_delete',
+8 -2
View File
@@ -101,9 +101,15 @@ export async function submitStripeCard(name: string, urlRoute?: string) {
}
}
export async function confirmPayment(orgId: string, clientSecret: string, paymentMethodId: string) {
export async function confirmPayment(
orgId: string,
clientSecret: string,
paymentMethodId: string,
route?: string
) {
try {
const url = `${window.location.origin}/console/organization-${orgId}/billing`;
const url =
window.location.origin + route ? route : `/console/organization-${orgId}/billing`;
const paymentMethod = await sdk.forConsole.billing.getPaymentMethod(paymentMethodId);
@@ -3,6 +3,7 @@
import {
CardGrid,
DropList,
DropListItem,
DropListLink,
EmptySearch,
Heading,
@@ -20,13 +21,17 @@
TableScroll
} from '$lib/elements/table';
import { toLocaleDate } from '$lib/helpers/date';
import type { InvoiceList } from '$lib/sdk/billing';
import type { Invoice, InvoiceList } from '$lib/sdk/billing';
import { sdk } from '$lib/stores/sdk';
import { VARS } from '$lib/system';
import { Query } from '@appwrite.io/console';
import { onMount } from 'svelte';
import RetryPaymentModal from './retryPaymentModal.svelte';
import { trackEvent } from '$lib/actions/analytics';
let showDropdown = [];
let showRetryModal = false;
let selectedInvoice: Invoice | null = null;
let offset = 0;
let invoiceList: InvoiceList = {
@@ -122,6 +127,21 @@
event="download_invoice">
Download PDF
</DropListLink>
{#if status === 'overdue' || status === 'failed'}
<DropListItem
icon="refresh"
on:click={() => {
selectedInvoice = invoice;
showRetryModal = true;
showDropdown[i] = !showDropdown[i];
trackEvent(`click_retry_payment`, {
from: 'button',
source: 'billing_invoice_menu'
});
}}>
Retry payment
</DropListItem>
{/if}
</svelte:fragment>
</DropList>
</TableCell>
@@ -144,3 +164,7 @@
{/if}
</svelte:fragment>
</CardGrid>
{#if selectedInvoice}
<RetryPaymentModal bind:show={showRetryModal} bind:invoice={selectedInvoice} />
{/if}
@@ -0,0 +1,76 @@
<script lang="ts">
import { invalidate } from '$app/navigation';
import { FakeModal } from '$lib/components';
import { Button } from '$lib/elements/forms';
import { Dependencies } from '$lib/constants';
import type { Invoice } from '$lib/sdk/billing';
import { addNotification } from '$lib/stores/notifications';
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
import { page } from '$app/stores';
import { VARS } from '$lib/system';
import { confirmPayment } from '$lib/stores/stripe';
import { organization } from '$lib/stores/organization';
import { toLocaleDate } from '$lib/helpers/date';
const endpoint = VARS.APPWRITE_ENDPOINT ?? `${$page.url.origin}/v1`;
export let show = false;
export let invoice: Invoice;
let error: string = null;
let isButtonDisabled = false;
async function handleSubmit() {
isButtonDisabled = true;
try {
await confirmPayment(
$organization.$id,
invoice.clientSecret,
$organization.paymentMethodId
);
invalidate(Dependencies.ORGANIZATION);
invalidate(Dependencies.INVOICES);
trackEvent(Submit.RetryPayment);
addNotification({
type: 'success',
message: `Payment has been successfully processed`
});
show = false;
} catch (e) {
error = e.message;
trackError(e, Submit.RetryPayment);
} finally {
isButtonDisabled = false;
}
}
$: if (!show) {
invoice = null;
}
</script>
<FakeModal
bind:show
bind:error
state="warning"
onSubmit={handleSubmit}
size="big"
headerDivider={false}
title="Retry payment">
<!-- TODO: format currency -->
<p class="text">
Your payment of <span class="inline-tag">${invoice.amount}</span> due on {toLocaleDate(
invoice.dueAt
)} has failed. Retry your payment to avoid service interruptions with your projects.
</p>
<Button
external
link
href={`${endpoint}/organizations/${$page.params.organization}/invoices/${invoice.$id}/view`}>
View invoice
</Button>
<svelte:fragment slot="footer">
<Button text on:click={() => (show = false)}>Cancel</Button>
<Button secondary submit disabled={isButtonDisabled}>Retry</Button>
</svelte:fragment>
</FakeModal>