-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add premium routes and handle webhook
- Loading branch information
Showing
14 changed files
with
474 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export const bypassMiddleware = [ | ||
"/checkout/", | ||
"/webhook/", | ||
"/premium/" | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
export const premiumCount = { | ||
FREE: 0, | ||
SILVER: 1, | ||
GOLD: 4, | ||
DIAMOND: 6 | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import { FastifyReply, FastifyRequest } from "fastify"; | ||
import prisma from "../../lib/prisma.js"; | ||
|
||
export async function guild(request: FastifyRequest, reply: FastifyReply) { | ||
const params = request.params as { id: string }; | ||
const body = request.body as { | ||
data: { | ||
guildId: string; | ||
}[], | ||
premiumCount: number; | ||
} | ||
|
||
const data = await prisma.subscription.update({ | ||
where: { | ||
userId: params.id | ||
}, | ||
data: { | ||
premiumGuild: { | ||
set: body.data | ||
}, | ||
premiumCount: { | ||
set: body.premiumCount | ||
} | ||
}, | ||
select: { | ||
premiumGuild: true, | ||
userId: true | ||
} | ||
}) | ||
|
||
if (data.premiumGuild.length < body.data.length) { | ||
await prisma.subscription.update({ | ||
where: { | ||
userId: params.id | ||
}, | ||
data: { | ||
premiumCount: { | ||
set: body.data.length - data.premiumGuild.length + body.premiumCount | ||
} | ||
} | ||
}) | ||
} | ||
|
||
return reply.send({ | ||
data: data.userId | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { FastifyPluginAsync } from "fastify" | ||
import { tier } from "./tier.js"; | ||
import { guild } from "./guild.js"; | ||
|
||
const route: FastifyPluginAsync = async (fastify, opts): Promise<void> => { | ||
fastify.get("/tier/:id", tier) | ||
fastify.post("/guild/:id", guild) | ||
} | ||
|
||
export default route; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { FastifyReply, FastifyRequest } from "fastify"; | ||
import prisma from "../../lib/prisma.js"; | ||
|
||
export async function tier(request: FastifyRequest, reply: FastifyReply) { | ||
const params = request.params as { id: string }; | ||
|
||
const subscription = await prisma.subscription.findFirst({ | ||
where: { | ||
userId: params.id | ||
}, | ||
select: { | ||
premiumTier: true, | ||
premiumCount: true, | ||
premiumGuild: true | ||
} | ||
}) | ||
|
||
const tier = subscription ? subscription.premiumTier : "FREE"; | ||
const count = subscription ? subscription.premiumCount : 0; | ||
|
||
return reply.send({ | ||
data: { | ||
tier: tier, | ||
count: count, | ||
premiumGuild: subscription?.premiumGuild | ||
} | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { FastifyPluginAsync } from "fastify" | ||
import { paymentComplete } from "./paymentComplete.js"; | ||
import { recurringEnd } from "./recurringEnd.js"; | ||
|
||
const route: FastifyPluginAsync = async (fastify, opts): Promise<void> => { | ||
fastify.post("/payment-complete", paymentComplete) | ||
fastify.post("/recurring-end", recurringEnd) | ||
} | ||
|
||
export default route; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import { FastifyReply, FastifyRequest } from "fastify"; | ||
import { PaymentCompleteWebhook } from "../../typings/index.js"; | ||
import prisma from "../../lib/prisma.js"; | ||
import { premiumCount } from "../../constant/premiumCount.js"; | ||
import crypto from "crypto"; | ||
|
||
export async function paymentComplete(request: FastifyRequest, reply: FastifyReply) { | ||
const body = request.body as PaymentCompleteWebhook; | ||
|
||
const bodyHash = crypto | ||
.createHash('sha256') | ||
.update(JSON.stringify(request.body), 'utf-8') | ||
.digest('hex'); | ||
|
||
const finalHash = crypto.createHmac('sha256', process.env.TEBEX_SECRET as string) | ||
.update(bodyHash) | ||
.digest('hex'); | ||
|
||
if (finalHash !== request.headers["x-signature"]) { | ||
return reply.notFound(); | ||
} | ||
|
||
// used for verifying the webhook | ||
if (body.type === "validation.webhook") { | ||
return reply.send({ | ||
"id": body.id | ||
}); | ||
} | ||
|
||
const subscription = await prisma.subscription.findFirst({ | ||
where: { | ||
userId: body.subject.customer.username.id | ||
} | ||
}) | ||
|
||
const tierBody = body.subject.products[0].name.toUpperCase() as keyof typeof premiumCount; | ||
const oldTier = subscription ? subscription.premiumTier : "FREE"; | ||
const newTier = (premiumCount[oldTier] > premiumCount[tierBody]) ? oldTier : tierBody; | ||
|
||
await prisma.subscription.upsert({ | ||
where: { | ||
userId: body.subject.customer.username.id | ||
}, | ||
create: { | ||
purchasedAt: new Date(), | ||
userId: body.subject.customer.username.id, | ||
premiumCount: premiumCount[tierBody], | ||
premiumTier: newTier | ||
}, | ||
update: { | ||
purchasedAt: new Date(), | ||
premiumCount: { | ||
increment: premiumCount[tierBody], | ||
}, | ||
premiumTier: newTier | ||
} | ||
}) | ||
|
||
return reply.send({ | ||
"id": body.id | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { FastifyReply, FastifyRequest } from "fastify"; | ||
import { RecurringEndWebhook } from "../../typings/index.js"; | ||
import prisma from "../../lib/prisma.js"; | ||
import crypto from "crypto"; | ||
|
||
export async function recurringEnd(request: FastifyRequest, reply: FastifyReply) { | ||
const body = request.body as RecurringEndWebhook; | ||
|
||
const bodyHash = crypto | ||
.createHash('sha256') | ||
.update(JSON.stringify(request.body), 'utf-8') | ||
.digest('hex'); | ||
|
||
const finalHash = crypto.createHmac('sha256', process.env.TEBEX_SECRET as string) | ||
.update(bodyHash) | ||
.digest('hex'); | ||
|
||
if (finalHash !== request.headers["x-signature"]) { | ||
return reply.notFound(); | ||
} | ||
|
||
// used for verifying the webhook | ||
if (body.type === "validation.webhook") { | ||
return reply.send({ | ||
"id": body.id | ||
}); | ||
} | ||
|
||
await prisma.subscription.update({ | ||
where: { | ||
userId: body.subject.initial_payment.customer.username.id | ||
}, | ||
data: { | ||
premiumGuild: { | ||
set: [] | ||
} | ||
} | ||
}) | ||
|
||
await prisma.subscription.delete({ | ||
where: { | ||
userId: body.subject.initial_payment.customer.username.id | ||
}, | ||
include: { | ||
premiumGuild: true, | ||
} | ||
}) | ||
|
||
return reply.send({ | ||
"id": body.id | ||
}); | ||
} |
Oops, something went wrong.