Skip to main content

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.

Get started with this example
interval.com

Try it out

To create a fresh project based off this example, run:

npx create-interval-app --template=refund-charges
The full source code for this tool can also be found in our examples repo.

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 Interval, { io, ctx } from "@interval/sdk";
import "dotenv/config"; // loads environment variables from .env

const interval = new Interval({
apiKey: process.env.INTERVAL_KEY,
actions: {
refund_user: async () => {
const customerEmail = await io.input.email(
"Email of the customer to refund:"
);
console.log("Email:", customerEmail);
},
},
});

// Establishes a persistent connection between Interval and your app.
interval.listen();

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 Interval, { io, ctx } from "@interval/sdk";
import "dotenv/config"; // loads environment variables from .env
import { getCharges, refundCharge } from "./payments";

const interval = new Interval({
apiKey: process.env.INTERVAL_KEY,
actions: {
refund_user: async () => {
const customerEmail = await io.input.email(
"Email of the customer to refund:"
);

console.log("Email:", customerEmail);

const charges = await getCharges(customerEmail);

const chargesToRefund = await io.select.table(
"Select one or more charges to refund",
{
data: charges,
}
);
},
},
});

// Establishes a persistent connection between Interval and your app.
interval.listen();

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.

src/index.ts
import Interval, { io, ctx } from "@interval/sdk";
import "dotenv/config"; // loads environment variables from .env
import { getCharges, refundCharge } from "./payments";

const interval = new Interval({
apiKey: process.env.INTERVAL_KEY,
actions: {
refund_user: async () => {
const customerEmail = await io.input.email(
"Email of the customer to refund:"
);

console.log("Email:", customerEmail);

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 };
},
},
});

// Establishes a persistent connection between Interval and your app.
interval.listen();

API methods used

Was this section useful?

548 Market St PMB 31323
San Francisco, CA 94104

© 2022

Join our mailing list

Every Friday we send an email with the latest from Interval, including events, product updates, SDK releases, and more.