Refund tool
Use this example to quickly build a UI to handle refunds for your customers. Search for a user by email, render a table of their applicable charges to action, and require a confirmation before executing the refund.
How it works
info
Looking for an introduction to how to build and deploy a tool with Interval? Our Getting started tutorial walks you through the process of building this refund tool while providing a comprehensive overview of how Interval works.
First, to find the user whose charges we want to refund, we'll utilize an I/O method to request their email.
import { Action, io, ctx } from "@interval/sdk";
export default new Action(async () => {
const customerEmail = await io.input.email(
"Email of the customer to refund:"
);
});
We can then query for charges based off this email using our helper function (which just queries the database). With a single io.select.table
call, Interval can render all these charges so they can be selected to be refunded.
import { Action, io, ctx } from "@interval/sdk";
export default new Action(async () => {
const customerEmail = await io.input.email(
"Email of the customer to refund:"
);
const charges = await getCharges(customerEmail);
const chargesToRefund = await io.select.table(
"Select one or more charges to refund",
{
data: charges,
}
);
});
Finally, we can take the charges returned from io.select.table
and pass them to our refundCharge
helper function, which executes the refund. We'll also add calls to ctx.loading
to provide a nice loading bar to the user as our action executes.
import { Action, io, ctx } from "@interval/sdk";
export default new Action(async () => {
const customerEmail = await io.input.email(
"Email of the customer to refund:"
);
const charges = await getCharges(customerEmail);
const chargesToRefund = await io.select.table(
"Select one or more charges to refund",
{
data: charges,
}
);
await ctx.loading.start({
title: "Refunding charges",
// Because we specified `itemsInQueue`, Interval will render a progress bar versus an indeterminate loading indicator.
itemsInQueue: chargesToRefund.length,
});
for (const charge of chargesToRefund) {
await refundCharge(charge.id);
await ctx.loading.completeOne();
}
// Values returned from actions are automatically stored with Interval transaction logs
return { chargesRefunded: chargesToRefund.length };
});