Skip to content

Commit bbe1704

Browse files
committed
Add Stripe stablecoin webhook for v2 thin events
- New /api/stripe/stablecoin/webhook endpoint with STRIPE_STABLECOIN_WEBHOOK_SECRET - Move v2 handlers (recipient account, outbound payment) from connect to stablecoin
1 parent 2682129 commit bbe1704

File tree

7 files changed

+91
-1
lines changed

7 files changed

+91
-1
lines changed

apps/web/.env.example

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,4 +184,5 @@ HUBSPOT_CLIENT_SECRET=
184184

185185
# Stablecoin payout
186186
STRIPE_FINANCIAL_ACCOUNT_ID=
187-
STRIPE_PAYMENT_METHOD_ID=
187+
STRIPE_PAYMENT_METHOD_ID=
188+
STRIPE_STABLECOIN_WEBHOOK_SECRET=

apps/web/app/(ee)/api/stripe/connect/webhook/outbound-payment-failed.ts renamed to apps/web/app/(ee)/api/stripe/stablecoin/webhook/outbound-payment-failed.ts

File renamed without changes.

apps/web/app/(ee)/api/stripe/connect/webhook/outbound-payment-posted.ts renamed to apps/web/app/(ee)/api/stripe/stablecoin/webhook/outbound-payment-posted.ts

File renamed without changes.

apps/web/app/(ee)/api/stripe/connect/webhook/outbound-payment-returned.ts renamed to apps/web/app/(ee)/api/stripe/stablecoin/webhook/outbound-payment-returned.ts

File renamed without changes.

apps/web/app/(ee)/api/stripe/connect/webhook/recipient-account-closed.ts renamed to apps/web/app/(ee)/api/stripe/stablecoin/webhook/recipient-account-closed.ts

File renamed without changes.

apps/web/app/(ee)/api/stripe/connect/webhook/recipient-configuration-updated.ts renamed to apps/web/app/(ee)/api/stripe/stablecoin/webhook/recipient-configuration-updated.ts

File renamed without changes.
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { stripe } from "@/lib/stripe";
2+
import { log } from "@dub/utils";
3+
import { logAndRespond } from "app/(ee)/api/cron/utils";
4+
import Stripe from "stripe";
5+
import { outboundPaymentFailed } from "./outbound-payment-failed";
6+
import { outboundPaymentPosted } from "./outbound-payment-posted";
7+
import { outboundPaymentReturned } from "./outbound-payment-returned";
8+
import { recipientAccountClosed } from "./recipient-account-closed";
9+
import { recipientConfigurationUpdated } from "./recipient-configuration-updated";
10+
11+
const relevantEvents = new Set([
12+
"v2.core.account.closed",
13+
"v2.core.account[configuration.recipient].updated",
14+
"v2.money_management.outbound_payment.posted",
15+
"v2.money_management.outbound_payment.returned",
16+
"v2.money_management.outbound_payment.failed",
17+
]);
18+
19+
const webhookSecret = process.env.STRIPE_STABLECOIN_WEBHOOK_SECRET;
20+
21+
// POST /api/stripe/stablecoin/webhook – Stripe Stablecoin webhooks
22+
export const POST = async (req: Request) => {
23+
const body = await req.text();
24+
const signature = req.headers.get("Stripe-Signature");
25+
26+
if (!signature) {
27+
return logAndRespond("Missing Stripe-Signature header.");
28+
}
29+
30+
if (!webhookSecret) {
31+
return logAndRespond(
32+
"STRIPE_STABLECOIN_WEBHOOK_SECRET environment variable is not set.",
33+
{
34+
status: 500,
35+
},
36+
);
37+
}
38+
39+
let event: Stripe.Event;
40+
41+
try {
42+
event = stripe.webhooks.constructEvent(body, signature, webhookSecret);
43+
} catch (error) {
44+
return logAndRespond(`[Webhook error]:${error.message}`, {
45+
status: 400,
46+
});
47+
}
48+
49+
if (!relevantEvents.has(event.type)) {
50+
return logAndRespond(`Unsupported event ${event.type}, skipping...`);
51+
}
52+
53+
let response = "OK";
54+
try {
55+
switch (event.type) {
56+
// @ts-ignore
57+
case "v2.core.account.closed":
58+
response = await recipientAccountClosed(event);
59+
break;
60+
// @ts-ignore
61+
case "v2.core.account[configuration.recipient].updated":
62+
response = await recipientConfigurationUpdated(event);
63+
break;
64+
// @ts-ignore
65+
case "v2.money_management.outbound_payment.posted":
66+
response = await outboundPaymentPosted(event);
67+
break;
68+
// @ts-ignore
69+
case "v2.money_management.outbound_payment.returned":
70+
response = await outboundPaymentReturned(event);
71+
break;
72+
// @ts-ignore
73+
case "v2.money_management.outbound_payment.failed":
74+
response = await outboundPaymentFailed(event);
75+
break;
76+
}
77+
} catch (error) {
78+
await log({
79+
message: `/api/stripe/stablecoin/webhook webhook failed (${event.type}). Error: ${error.message}`,
80+
type: "errors",
81+
});
82+
83+
return logAndRespond(`[Webhook error]: ${error.message}`, {
84+
status: 400,
85+
});
86+
}
87+
88+
return logAndRespond(`[${event.type}]: ${response}`);
89+
};

0 commit comments

Comments
 (0)