Skip to content

Commit 89bce8f

Browse files
committed
feat: add client payment schema and webhook handling of payments
1 parent f1a0c93 commit 89bce8f

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

src/app/api/webhook/route.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { generateInvoiceNumber } from "@/lib/helpers/client";
44
import { getInvoiceCount } from "@/lib/helpers/invoice";
55
import { db } from "@/server/db";
66
import {
7+
clientPaymentTable,
8+
ecommerceClientTable,
79
paymentDetailsPayersTable,
810
recurringPaymentTable,
911
type requestStatusEnum,
@@ -14,6 +16,37 @@ import { and, eq, not } from "drizzle-orm";
1416
import { NextResponse } from "next/server";
1517
import { ulid } from "ulid";
1618

19+
async function addClientPayment(webhookBody: any) {
20+
await db.transaction(async (tx) => {
21+
const ecommerceClient = await tx
22+
.select()
23+
.from(ecommerceClientTable)
24+
.where(eq(ecommerceClientTable.rnClientId, webhookBody.clientId))
25+
.limit(1);
26+
27+
if (!ecommerceClient.length) {
28+
throw new ResourceNotFoundError(
29+
`No ecommerce client found with client ID: ${webhookBody.clientId}`,
30+
);
31+
}
32+
33+
const client = ecommerceClient[0];
34+
35+
await tx.insert(clientPaymentTable).values({
36+
id: ulid(),
37+
userId: client.userId,
38+
requestId: webhookBody.requestId,
39+
invoiceCurrency: webhookBody.currency,
40+
paymentCurrency: webhookBody.paymentCurrency,
41+
amount: webhookBody.amount,
42+
customerInfo: webhookBody.customerInfo || null,
43+
reference: webhookBody.reference || null,
44+
clientId: webhookBody.clientId,
45+
origin: webhookBody.origin,
46+
});
47+
});
48+
}
49+
1750
/**
1851
* Updates the request status in the database
1952
*/
@@ -132,6 +165,8 @@ export async function POST(req: Request) {
132165
txHash: body.txHash,
133166
requestScanUrl: body.explorer,
134167
});
168+
} else if (body.clientId) {
169+
await addClientPayment(body);
135170
} else {
136171
await updateRequestStatus(
137172
requestId,

src/server/db/schema.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,35 @@ export const paymentDetailsPayersTable = createTable("payment_details_payers", {
177177
createdAt: timestamp("created_at").defaultNow(),
178178
});
179179

180+
export const clientPaymentTable = createTable("client_payment", {
181+
id: text().primaryKey().notNull(),
182+
userId: text()
183+
.notNull()
184+
.references(() => userTable.id, {
185+
onDelete: "cascade",
186+
}),
187+
requestId: text().notNull(),
188+
invoiceCurrency: text().notNull(),
189+
paymentCurrency: text().notNull(),
190+
amount: text().notNull(),
191+
customerInfo: json().$type<{
192+
firstName?: string;
193+
lastName?: string;
194+
email?: string;
195+
address?: {
196+
street?: string;
197+
city?: string;
198+
state?: string;
199+
postalCode?: string;
200+
country?: string;
201+
};
202+
}>(),
203+
reference: text(),
204+
clientId: text().notNull(),
205+
origin: text(),
206+
createdAt: timestamp("created_at").defaultNow(),
207+
});
208+
180209
export const requestTable = createTable("request", {
181210
id: text().primaryKey().notNull(),
182211
type: text().notNull(),
@@ -322,6 +351,9 @@ export const ecommerceClientTable = createTable(
322351
table.userId,
323352
table.domain,
324353
),
354+
clientIdIndex: uniqueIndex("ecommerce_client_user_id_client_id_unique").on(
355+
table.rnClientId,
356+
),
325357
}),
326358
);
327359

@@ -332,6 +364,7 @@ export const userRelations = relations(userTable, ({ many }) => ({
332364
session: many(sessionTable),
333365
invoiceMe: many(invoiceMeTable),
334366
paymentDetailsPayers: many(paymentDetailsPayersTable),
367+
clientPayments: many(clientPaymentTable),
335368
}));
336369

337370
export const requestRelations = relations(requestTable, ({ one }) => ({
@@ -394,6 +427,16 @@ export const ecommerceClientRelations = relations(
394427
}),
395428
);
396429

430+
export const clientPaymentRelations = relations(
431+
clientPaymentTable,
432+
({ one }) => ({
433+
user: one(userTable, {
434+
fields: [clientPaymentTable.userId],
435+
references: [userTable.id],
436+
}),
437+
}),
438+
);
439+
397440
export const paymentDetailsRelations = relations(
398441
paymentDetailsTable,
399442
({ one, many }) => ({
@@ -430,3 +473,4 @@ export type PaymentDetailsPayers = InferSelectModel<
430473
>;
431474
export type RecurringPayment = InferSelectModel<typeof recurringPaymentTable>;
432475
export type EcommerceClient = InferSelectModel<typeof ecommerceClientTable>;
476+
export type ClientPayment = InferSelectModel<typeof clientPaymentTable>;

0 commit comments

Comments
 (0)