Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export async function balanceAvailable(event: Stripe.Event) {
availableBalance = Math.floor(availableBalance / 100) * 100;
}

const payout = await stripe.payouts.create(
const stripePayout = await stripe.payouts.create(
{
amount: availableBalance,
currency,
Expand All @@ -93,7 +93,7 @@ export async function balanceAvailable(event: Stripe.Event) {
);

console.log(
`Stripe payout created for partner ${partner.email} (${stripeAccount}): ${payout.id} (${currencyFormatter(payout.amount / 100, { maximumFractionDigits: 2, currency })})`,
`Stripe payout created for partner ${partner.email} (${stripeAccount}): ${stripePayout.id} (${currencyFormatter(stripePayout.amount / 100, { maximumFractionDigits: 2, currency: stripePayout.currency })})`,
);

const transfers = await stripe.transfers.list({
Expand All @@ -114,12 +114,12 @@ export async function balanceAvailable(event: Stripe.Event) {
},
},
data: {
stripePayoutId: payout.id,
stripePayoutId: stripePayout.id,
},
});

console.log(
`Updated ${updatedPayouts.count} payouts for partner ${partner.email} (${stripeAccount}) to have the stripePayoutId: ${payout.id}`,
`Updated ${updatedPayouts.count} payouts for partner ${partner.email} (${stripeAccount}) to have the stripePayoutId: ${stripePayout.id}`,
);

if (partner.email) {
Expand All @@ -129,7 +129,11 @@ export async function balanceAvailable(event: Stripe.Event) {
email: partner.email,
react: PartnerPayoutWithdrawalInitiated({
email: partner.email,
amount: payout.amount,
payout: {
amount: stripePayout.amount,
currency: stripePayout.currency,
arrivalDate: stripePayout.arrival_date,
},
}),
});

Expand Down
23 changes: 23 additions & 0 deletions apps/web/app/(ee)/api/stripe/connect/webhook/payout-paid.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { sendEmail } from "@dub/email";
import PartnerPayoutWithdrawalCompleted from "@dub/email/templates/partner-payout-withdrawal-completed";
import { prisma } from "@dub/prisma";
import Stripe from "stripe";

Expand Down Expand Up @@ -39,4 +41,25 @@ export async function payoutPaid(event: Stripe.Event) {
console.log(
`Updated ${updatedPayouts.count} payouts for partner ${partner.email} (${stripeAccount}) to "completed" status`,
);

if (partner.email) {
const sentEmail = await sendEmail({
variant: "notifications",
subject: "Your funds have been transferred to your bank account",
email: partner.email,
react: PartnerPayoutWithdrawalCompleted({
email: partner.email,
payout: {
amount: stripePayout.amount,
currency: stripePayout.currency,
arrivalDate: stripePayout.arrival_date,
traceId: stripePayout.trace_id as string | null,
},
}),
});

console.log(
`Sent email to partner ${partner.email} (${stripeAccount}): ${JSON.stringify(sentEmail, null, 2)}`,
);
}
}
114 changes: 114 additions & 0 deletions packages/email/src/templates/partner-payout-withdrawal-completed.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { currencyFormatter, DUB_WORDMARK } from "@dub/utils";
import {
Body,
Container,
Head,
Heading,
Html,
Img,
Link,
Preview,
Section,
Tailwind,
Text,
} from "@react-email/components";
import { Footer } from "../components/footer";

// Send this email after payout.paid webhook is received
export default function PartnerPayoutWithdrawalCompleted({
email = "[email protected]",
payout = {
amount: 45590,
currency: "usd",
arrivalDate: 1722163200,
traceId: "DUB-PARTN-ABCD-XYZ-123456",
},
}: {
email: string;
payout: {
amount: number;
currency: string;
arrivalDate: number;
traceId: string | null;
};
}) {
const amountInDollars = currencyFormatter(payout.amount / 100, {
currency: payout.currency,
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});

const fiveBusinessDaysFromArrivalDate = (() => {
let date = new Date(payout.arrivalDate * 1000);
let businessDays = 0;
while (businessDays < 5) {
date.setDate(date.getDate() + 1);
// Skip weekends (0 = Sunday, 6 = Saturday)
if (date.getDay() !== 0 && date.getDay() !== 6) {
businessDays++;
}
}
return date.toLocaleDateString("en-US", {
month: "short",
day: "numeric",
});
})();

return (
<Html>
<Head />
<Preview>Your funds have been transferred to your bank account</Preview>
<Tailwind>
<Body className="mx-auto my-auto bg-white font-sans">
<Container className="mx-auto my-10 max-w-[600px] rounded border border-solid border-neutral-200 px-10 py-5">
<Section className="mt-8">
<Img src={DUB_WORDMARK} height="32" alt="Dub" />
</Section>

<Heading className="mx-0 my-7 p-0 text-lg font-medium text-black">
Your funds have been transferred to your bank account
</Heading>

<Text className="text-sm leading-6 text-neutral-600">
<span className="font-semibold text-neutral-800">
{amountInDollars}
</span>{" "}
has been transferred from your Stripe Express account to your
connected bank account.
</Text>

<Text className="text-sm leading-6 text-neutral-600">
Banks can take up to 5 business days to process payouts. Wait
until{" "}
<span className="font-semibold text-neutral-800">
{fiveBusinessDaysFromArrivalDate}
</span>{" "}
and then contact your bank
{payout.traceId
? ` using the following trace ID (reference number):`
: "."}
</Text>

{payout.traceId && (
<Text className="break-all font-mono text-sm text-purple-600">
{payout.traceId}
</Text>
)}

<Text className="text-sm leading-6 text-neutral-600">
If you still have any questions, contact{" "}
<Link
href="https://support.stripe.com/express"
className="font-medium text-black underline"
>
Stripe support
</Link>
.
</Text>
<Footer email={email} />
</Container>
</Body>
</Tailwind>
</Html>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,21 @@ import { Footer } from "../components/footer";
// Send this email after initiating a Stripe payout to the partner
export default function PartnerPayoutWithdrawalInitiated({
email = "[email protected]",
amount = 45590,
payout = {
amount: 45590,
currency: "usd",
arrivalDate: 1722163200,
},
}: {
email: string;
amount: number;
payout: {
amount: number;
currency: string;
arrivalDate: number;
};
}) {
const amountInDollars = currencyFormatter(amount / 100, {
const amountInDollars = currencyFormatter(payout.amount / 100, {
currency: payout.currency,
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
Expand All @@ -47,13 +56,20 @@ export default function PartnerPayoutWithdrawalInitiated({
<span className="font-semibold text-neutral-800">
{amountInDollars}
</span>{" "}
is being transferred to your bank account.
is being transferred from your Stripe Express account to your
connected bank account.
</Text>

<Text className="text-sm leading-6 text-neutral-600">
Depending on your bank's location, this process can{" "}
The funds are expected to arrive in your bank account by{" "}
<span className="font-semibold text-neutral-800">
can take anywhere between 1-14 business days
{new Date(payout.arrivalDate * 1000).toLocaleDateString(
"en-US",
{
month: "short",
day: "numeric",
},
)}
</span>
. If there are any delays, please contact{" "}
<Link
Expand Down