import "@nestia/fetcher"; import { AesPkcs5 } from "@nestia/fetcher/lib/AesPkcs5"; import { payment_histories, payment_history_webhooks } from "@prisma/client"; import { IPaymentHistory } from "payment-api/lib/structures/payments/IPaymentHistory"; import { IPaymentWebhookHistory } from "payment-api/lib/structures/payments/IPaymentWebhookHistory"; import { InvalidArgument } from "tstl/exception/InvalidArgument"; import { v4 } from "uuid"; import { PaymentConfiguration } from "../../PaymentConfiguration"; import { PaymentGlobal } from "../../PaymentGlobal"; import { PaymentHistoryProvider } from "./PaymentHistoryProvider"; export namespace PaymentWebhookProvider { export const process = (vendor: "iamport" | "toss.payments") => (config: { uid: (input: Input) => string | null; fetch: (history: payment_histories) => Promise; props: (data: Data) => IPaymentHistory.IProps; }) => async (input: Input): Promise => { // NEED NOT TO DO ANYIHTNG const vendor_uid: string | null = config.uid(input); if (vendor_uid === null) return; // GET PREVIOUS HISTORY const record = await PaymentGlobal.prisma.payment_histories.findFirstOrThrow({ where: { vendor_code: vendor, vendor_uid: vendor_uid, }, ...PaymentHistoryProvider.json.select(), }); const previous: IPaymentHistory = PaymentHistoryProvider.json.transform(record); if (previous.vendor.code !== vendor) { throw new InvalidArgument( `Vendor of the payment is not "${vendor}" but "${record.vendor_code}""`, ); } // UPDATE HISTORY const data: Data = await config.fetch(record); const props: IPaymentHistory.IProps = config.props(data); const current: IPaymentHistory = await PaymentHistoryProvider.update(previous)(props); // DO WEBHOOK const webhook: payment_history_webhooks = await PaymentGlobal.prisma.payment_history_webhooks.create({ data: { id: v4(), history: { connect: { id: current.id, }, }, previous: JSON.stringify(previous), current: JSON.stringify(current), data: JSON.stringify(input), created_at: new Date(), }, }); const request: IPaymentWebhookHistory = { id: webhook.id, source: current.source, previous: previous, current: current, }; send(current, webhook, request).catch(() => {}); }; async function send( history: IPaymentHistory, webhook: payment_history_webhooks, request: IPaymentWebhookHistory, ): Promise { let status: number | null = null; let body: string | null = null; const encryption = PaymentConfiguration.ENCRYPTION_PASSWORD(); try { const response: Response = await fetch(history.webhook_url!, { method: "POST", headers: { "Content-Type": "text/plain", }, body: AesPkcs5.encrypt( JSON.stringify(request), encryption.key, encryption.iv, ), }); status = response.status; body = await response.text(); } catch {} await PaymentGlobal.prisma.payment_history_webhook_responses.create({ data: { id: v4(), webhook: { connect: { id: webhook.id, }, }, status: status, body: body, created_at: new Date(), }, }); } }