Skip to content

Commit 2f7cbe4

Browse files
authored
Merge pull request #1109 from trycompai/mariano/repair-stripe-endpoint
[dev] [Marfuen] mariano/repair-stripe-endpoint
2 parents 42f3317 + d0684e5 commit 2f7cbe4

2 files changed

Lines changed: 131 additions & 12 deletions

File tree

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import { stripe } from '@/actions/organization/lib/stripe';
2+
import { db } from '@comp/db';
3+
import { SubscriptionType } from '@comp/db/types';
4+
import { NextResponse } from 'next/server';
5+
import { syncStripeDataToKV } from '../syncStripeDataToKv';
6+
7+
// Type for request body
8+
interface RepairStripeDataRequest {
9+
org_id: string;
10+
stripe_sub_id: string;
11+
}
12+
13+
// Error response helper
14+
function errorResponse(message: string, status: number) {
15+
return new Response(JSON.stringify({ error: message }), {
16+
status,
17+
headers: { 'Content-Type': 'application/json' },
18+
});
19+
}
20+
21+
// Success response helper
22+
function successResponse(message: string, data?: any) {
23+
return new Response(JSON.stringify({ message, data }), {
24+
status: 200,
25+
headers: { 'Content-Type': 'application/json' },
26+
});
27+
}
28+
29+
/**
30+
* POST /api/stripe/repair
31+
*
32+
* Repairs Stripe data for an organization by:
33+
* 1. Retrieving the Stripe subscription
34+
* 2. Updating the organization with the correct customer ID
35+
* 3. Syncing the data to KV store
36+
*/
37+
export async function POST(req: Request) {
38+
// Validate authentication
39+
const retoolCompApiSecret = process.env.RETOOL_COMP_API_SECRET;
40+
if (!retoolCompApiSecret) {
41+
return errorResponse('Server configuration error: retool comp api secret not configured', 500);
42+
}
43+
44+
const authHeader = req.headers.get('authorization');
45+
const token = authHeader?.split(' ')[1];
46+
if (!token || token !== retoolCompApiSecret) {
47+
return NextResponse.json(
48+
{
49+
success: false,
50+
error: 'Unauthorized',
51+
},
52+
{ status: 401 },
53+
);
54+
}
55+
56+
// Parse and validate request body
57+
let body: RepairStripeDataRequest;
58+
try {
59+
body = await req.json();
60+
} catch (error) {
61+
return errorResponse('Invalid JSON in request body', 400);
62+
}
63+
64+
const { org_id: organizationId, stripe_sub_id: stripeSubscriptionId } = body;
65+
66+
if (!organizationId) {
67+
return errorResponse('Missing required field: org_id', 400);
68+
}
69+
70+
if (!stripeSubscriptionId) {
71+
return errorResponse('Missing required field: stripe_sub_id', 400);
72+
}
73+
74+
// Fetch organization from database
75+
const organization = await db.organization.findUnique({
76+
where: { id: organizationId },
77+
});
78+
79+
if (!organization) {
80+
return errorResponse(`Organization not found: ${organizationId}`, 404);
81+
}
82+
83+
// Retrieve Stripe subscription
84+
let subscription;
85+
try {
86+
subscription = await stripe.subscriptions.retrieve(stripeSubscriptionId);
87+
} catch (error) {
88+
return errorResponse(`Stripe subscription not found: ${stripeSubscriptionId}`, 404);
89+
}
90+
91+
// Retrieve Stripe customer
92+
let customer;
93+
try {
94+
customer = await stripe.customers.retrieve(subscription.customer as string);
95+
} catch (error) {
96+
return errorResponse(`Stripe customer not found: ${subscription.customer}`, 404);
97+
}
98+
99+
// Update organization with Stripe data
100+
const updatedOrganization = await db.organization.update({
101+
where: { id: organizationId },
102+
data: {
103+
stripeCustomerId: customer.id,
104+
subscriptionType: SubscriptionType.MANAGED,
105+
},
106+
});
107+
108+
// Sync updated data to KV store
109+
await syncStripeDataToKV(updatedOrganization.id);
110+
111+
return successResponse('Stripe data successfully repaired', {
112+
organizationId: updatedOrganization.id,
113+
stripeCustomerId: customer.id,
114+
subscriptionType: SubscriptionType.MANAGED,
115+
});
116+
}

yarn.lock

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,14 +1285,14 @@
12851285
"@types/conventional-commits-parser" "^5.0.0"
12861286
chalk "^5.3.0"
12871287

1288-
"@comp/analytics@packages/analytics":
1288+
"@comp/analytics@^workspace:packages/analytics":
12891289
version "workspace:packages/analytics"
12901290
resolved "workspace:packages/analytics"
12911291
dependencies:
12921292
posthog-js "^1.236.6"
12931293
posthog-node "^4.14.0"
12941294

1295-
"@comp/app@apps/app", "@comp/app@workspace:*":
1295+
"@comp/app@^workspace:apps/app", "@comp/app@workspace:*":
12961296
version "workspace:apps/app"
12971297
resolved "workspace:apps/app"
12981298
devDependencies:
@@ -1330,7 +1330,9 @@
13301330
"@browserbasehq/sdk" "^2.5.0"
13311331
"@calcom/atoms" "^1.0.102-framer"
13321332
"@calcom/embed-react" "^1.5.3"
1333+
dependencies:
13331334
"@comp/db" "workspace:*"
1335+
dependencies:
13341336
"@date-fns/tz" "^1.2.0"
13351337
"@dnd-kit/core" "^6.3.1"
13361338
"@dnd-kit/modifiers" "^9.0.0"
@@ -1401,18 +1403,19 @@
14011403
zaraz-ts "^1.2.0"
14021404
zustand "^5.0.3"
14031405

1404-
"@comp/db@packages/db", "@comp/db@workspace:*":
1406+
"@comp/db@^workspace:packages/db", "@comp/db@workspace:*":
14051407
version "workspace:packages/db"
14061408
resolved "workspace:packages/db"
14071409
devDependencies:
14081410
"@comp/tsconfig" "workspace:*"
1411+
devDependencies:
14091412
prisma "^6.9.0"
14101413
ts-node "^10.9.2"
14111414
typescript "^5.8.3"
14121415
dependencies:
14131416
"@prisma/client" "6.9.0"
14141417

1415-
"@comp/email@packages/email":
1418+
"@comp/email@^workspace:packages/email":
14161419
version "workspace:packages/email"
14171420
resolved "workspace:packages/email"
14181421
devDependencies:
@@ -1432,7 +1435,7 @@
14321435
react-email "^4.0.15"
14331436
responsive-react-email "^0.0.5"
14341437

1435-
"@comp/framework-editor@apps/framework-editor":
1438+
"@comp/framework-editor@^workspace:apps/framework-editor":
14361439
version "workspace:apps/framework-editor"
14371440
resolved "workspace:apps/framework-editor"
14381441
devDependencies:
@@ -1462,7 +1465,7 @@
14621465
tippy.js "^6.3.7"
14631466
zod "3.25.67"
14641467

1465-
"@comp/integrations@packages/integrations":
1468+
"@comp/integrations@^workspace:packages/integrations":
14661469
version "workspace:packages/integrations"
14671470
resolved "workspace:packages/integrations"
14681471
devDependencies:
@@ -1485,14 +1488,14 @@
14851488
stoppable "^1.1.0"
14861489
zod "3.25.67"
14871490

1488-
"@comp/kv@packages/kv":
1491+
"@comp/kv@^workspace:packages/kv":
14891492
version "workspace:packages/kv"
14901493
resolved "workspace:packages/kv"
14911494
dependencies:
14921495
"@upstash/redis" "^1.34.2"
14931496
server-only "0.0.1"
14941497

1495-
"@comp/portal@apps/portal":
1498+
"@comp/portal@^workspace:apps/portal":
14961499
version "workspace:apps/portal"
14971500
resolved "workspace:apps/portal"
14981501
devDependencies:
@@ -1523,7 +1526,7 @@
15231526
next "15.4.0-canary.85"
15241527
react-email "^4.0.15"
15251528

1526-
"@comp/trust@apps/trust":
1529+
"@comp/trust@^workspace:apps/trust":
15271530
version "workspace:apps/trust"
15281531
resolved "workspace:apps/trust"
15291532
devDependencies:
@@ -1545,11 +1548,11 @@
15451548
lucide-react "^0.518.0"
15461549
next "15.4.0-canary.85"
15471550

1548-
"@comp/tsconfig@packages/tsconfig", "@comp/tsconfig@workspace:*":
1551+
"@comp/tsconfig@^workspace:packages/tsconfig", "@comp/tsconfig@workspace:*":
15491552
version "workspace:packages/tsconfig"
15501553
resolved "workspace:packages/tsconfig"
15511554

1552-
"@comp/ui@packages/ui", "@comp/ui@workspace:*":
1555+
"@comp/ui@^workspace:packages/ui", "@comp/ui@workspace:*":
15531556
version "workspace:packages/ui"
15541557
resolved "workspace:packages/ui"
15551558
devDependencies:
@@ -1632,7 +1635,7 @@
16321635
use-debounce "^10.0.4"
16331636
vaul "^0.9.6"
16341637

1635-
"@comp/utils@packages/utils", "@comp/utils@workspace:*":
1638+
"@comp/utils@^workspace:packages/utils", "@comp/utils@workspace:*":
16361639
version "workspace:packages/utils"
16371640
resolved "workspace:packages/utils"
16381641
devDependencies:

0 commit comments

Comments
 (0)