258 lines
7.5 KiB
TypeScript
258 lines
7.5 KiB
TypeScript
import Stripe from "stripe";
|
|
import { env } from "~/env.mjs";
|
|
import { TRPCError } from "@trpc/server";
|
|
import PaymentStatusEnum from "~/schemas/public/PaymentStatusEnum";
|
|
import { db } from "~/server/db";
|
|
import type { Payments, PaymentsId } from "~/schemas/public/Payments";
|
|
import OrderTypeEnum from "~/schemas/public/OrderTypeEnum";
|
|
import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum";
|
|
import { NewMail } from "~/server/services/mailer";
|
|
import { getUser } from "~/server/services/user.service";
|
|
|
|
const stripeApi = new Stripe(env.STRIPE_SECRET_KEY);
|
|
|
|
export const createIntentHandler = async ({
|
|
paymentId,
|
|
}: {
|
|
paymentId: PaymentsId;
|
|
}) => {
|
|
try {
|
|
const payment = await db
|
|
.selectFrom("payments")
|
|
.selectAll("payments")
|
|
.innerJoin("users", "users.id", "payments.userid")
|
|
.select("users.email")
|
|
.innerJoin("ordini", "ordini.ordine_id", "payments.ordine_id")
|
|
.innerJoin("prezziario", "prezziario.idprezziario", "ordini.packid")
|
|
.select(["prezziario.nome_it", "prezziario.desc_it"])
|
|
.where("id", "=", paymentId)
|
|
.executeTakeFirstOrThrow();
|
|
|
|
const paymentIntent = await stripeApi.paymentIntents.create({
|
|
amount: payment.amount_cent,
|
|
description: payment.nome_it,
|
|
currency: "eur",
|
|
//payment_method_configuration: "pmc_1P4NfjILe4KoQRqXYChFCTFj",
|
|
automatic_payment_methods: {
|
|
enabled: true,
|
|
},
|
|
metadata: {
|
|
userId: payment.userid,
|
|
servizioId: payment.servizio_id,
|
|
paymentId,
|
|
},
|
|
receipt_email: payment.email,
|
|
});
|
|
|
|
return {
|
|
clientSecret: paymentIntent.client_secret,
|
|
titolo: payment.nome_it,
|
|
prezzo: payment.amount_cent,
|
|
descrizione: payment.desc_it,
|
|
};
|
|
} catch (error) {
|
|
throw new TRPCError({
|
|
code: "INTERNAL_SERVER_ERROR",
|
|
message: "Error creating payment intent: " + (error as Error).message,
|
|
});
|
|
}
|
|
};
|
|
|
|
export const whIntentCreatedHandler = async ({
|
|
pIntentId,
|
|
paymentId,
|
|
}: {
|
|
pIntentId: Payments["intent_id"];
|
|
paymentId: PaymentsId;
|
|
}) => {
|
|
return await db
|
|
.updateTable("payments")
|
|
.set({ intent_id: pIntentId, paymentstatus: PaymentStatusEnum.processing })
|
|
.where("id", "=", paymentId)
|
|
.returning("id")
|
|
.execute();
|
|
};
|
|
|
|
export const whIntentSucceededHandler = async ({
|
|
pIntentId,
|
|
paymentId,
|
|
pm_id,
|
|
}: {
|
|
pIntentId: Payments["intent_id"];
|
|
paymentId: PaymentsId;
|
|
pm_id: string;
|
|
}) => {
|
|
try {
|
|
const paymentMethod = await stripeApi.paymentMethods.retrieve(pm_id);
|
|
|
|
await db.transaction().execute(async (trx) => {
|
|
const payment = await trx
|
|
.updateTable("payments")
|
|
.set({
|
|
paymentstatus: PaymentStatusEnum.success,
|
|
paid_at: new Date(),
|
|
paymentmethod: paymentMethod.type,
|
|
})
|
|
.where("intent_id", "=", pIntentId)
|
|
.where("payments.id", "=", paymentId)
|
|
.returning(["servizio_id", "ordine_id"])
|
|
.executeTakeFirstOrThrow();
|
|
|
|
const ordine = await trx
|
|
.selectFrom("ordini")
|
|
.selectAll("ordini")
|
|
.where("ordine_id", "=", payment.ordine_id)
|
|
.executeTakeFirstOrThrow();
|
|
|
|
await trx
|
|
.updateTable("ordini")
|
|
.where("ordine_id", "=", payment.ordine_id)
|
|
.set({
|
|
isActive: true,
|
|
})
|
|
.execute();
|
|
|
|
const servizio = await trx
|
|
.selectFrom("servizio")
|
|
.select("servizio.tipologia")
|
|
.where("servizio_id", "=", payment.servizio_id)
|
|
.executeTakeFirstOrThrow();
|
|
|
|
const utente = await getUser({
|
|
db: trx,
|
|
userId: ordine.userid,
|
|
});
|
|
|
|
switch (ordine.type) {
|
|
case OrderTypeEnum.Acconto:
|
|
await trx
|
|
.updateTable("servizio")
|
|
.where("servizio_id", "=", payment.servizio_id)
|
|
.set({
|
|
decorrenza: new Date(),
|
|
isOkAcconto: true,
|
|
})
|
|
.execute();
|
|
|
|
await NewMail({
|
|
userId: utente.id,
|
|
mailType: "generic",
|
|
to: utente.email,
|
|
subject: "Pagamento Confermato - Acconto Infoalloggi.it",
|
|
|
|
props: {
|
|
title: "Pagamento Confermato ",
|
|
noreply: true,
|
|
testo: `Il pagamento dell'acconto per il servizio ${ordine.packid} è stato confermato.`,
|
|
link: {
|
|
href: `${env.NEXT_PUBLIC_BASE_URL}/area-riservata/payment-recap/${ordine.ordine_id}`,
|
|
label: "Vai alla ricevuta",
|
|
},
|
|
},
|
|
});
|
|
break;
|
|
|
|
case OrderTypeEnum.Saldo:
|
|
await trx
|
|
.updateTable("servizio")
|
|
.where("servizio_id", "=", payment.servizio_id)
|
|
.set({
|
|
isOkSaldo: true,
|
|
isOkConsulenza:
|
|
servizio.tipologia == TipologiaPosizioneEnum.Transitorio
|
|
? true
|
|
: false,
|
|
})
|
|
.execute();
|
|
await NewMail({
|
|
userId: utente.id,
|
|
mailType: "generic",
|
|
to: utente.email,
|
|
subject: "Pagamento Confermato - Saldo Infoalloggi.it",
|
|
props: {
|
|
title: "Pagamento Confermato ",
|
|
noreply: true,
|
|
testo: `Il pagamento del saldo per il servizio ${ordine.packid} è stato confermato.`,
|
|
link: {
|
|
href: `${env.NEXT_PUBLIC_BASE_URL}/area-riservata/payment-recap/${ordine.ordine_id}`,
|
|
label: "Vai alla ricevuta",
|
|
},
|
|
},
|
|
});
|
|
break;
|
|
case OrderTypeEnum.Consulenza:
|
|
await trx
|
|
.updateTable("servizio")
|
|
.where("servizio_id", "=", payment.servizio_id)
|
|
.set({
|
|
isOkConsulenza: true,
|
|
})
|
|
.execute();
|
|
await NewMail({
|
|
userId: utente.id,
|
|
mailType: "generic",
|
|
to: utente.email,
|
|
subject: "Pagamento Confermato - Consulenza Infoalloggi.it",
|
|
props: {
|
|
title: "Pagamento Confermato ",
|
|
noreply: true,
|
|
testo: `Il pagamento per la consulenza è stato confermato.`,
|
|
link: {
|
|
href: `${env.NEXT_PUBLIC_BASE_URL}/area-riservata/payment-recap/${ordine.ordine_id}`,
|
|
label: "Vai alla ricevuta",
|
|
},
|
|
},
|
|
});
|
|
break;
|
|
case OrderTypeEnum.Altro:
|
|
// TODO: Handle other types
|
|
await NewMail({
|
|
userId: utente.id,
|
|
mailType: "pagamentoConferma",
|
|
to: utente.email,
|
|
subject: "Pagamento Confermato",
|
|
props: {
|
|
receiptHref: `${env.NEXT_PUBLIC_BASE_URL}/area-riservata/payment-recap/${ordine.ordine_id}`,
|
|
},
|
|
});
|
|
break;
|
|
}
|
|
});
|
|
return true;
|
|
} catch (error) {
|
|
throw new TRPCError({
|
|
code: "INTERNAL_SERVER_ERROR",
|
|
message: "Error updating payment intent: " + (error as Error).message,
|
|
});
|
|
}
|
|
};
|
|
|
|
export const whIntentFailedHandler = async ({
|
|
pIntentId,
|
|
}: {
|
|
pIntentId: Payments["intent_id"];
|
|
}) => {
|
|
const userId = await db
|
|
.updateTable("payments")
|
|
.set({
|
|
paymentstatus: PaymentStatusEnum.failed,
|
|
})
|
|
.returning("userid")
|
|
.where("intent_id", "=", pIntentId)
|
|
.execute();
|
|
|
|
if (userId[0]) {
|
|
const utente = await getUser({
|
|
db,
|
|
userId: userId[0].userid,
|
|
});
|
|
|
|
await NewMail({
|
|
userId: utente.id,
|
|
mailType: "pagamentoErrore",
|
|
to: utente.email,
|
|
subject: "Pagamento Fallito",
|
|
});
|
|
}
|
|
return true;
|
|
};
|