import { TRPCError } from "@trpc/server" import { z } from "zod" import { env } from "@/env/server" import { protectedProcedure } from "@/server/trpc" import { getSasToken } from "../../getSasToken" import { getOTPState } from "../getOTPState" import { parseSASVerifyOtpError, type VerifyOtpGeneralError, } from "./verifyOtpError" const inputSchema = z.object({ otp: z.string(), }) const outputSchema = z.object({ status: z.enum([ "VERIFIED", "ABUSED", "EXPIRED", "PENDING", "RETRY", "SENT", "NULL", "NOTSENT", ]), referenceId: z.string().uuid().optional(), databaseUUID: z.string().uuid().optional(), }) export const verifyOtp = protectedProcedure .input(inputSchema) .output(outputSchema) .mutation(async function ({ input }) { const sasAuthToken = await getSasToken() if (!sasAuthToken) { throw createError("AUTH_TOKEN_NOT_FOUND") } const verifyResponse = await fetchVerifyOtp(input) console.log( "[SAS] verifyOTP", verifyResponse.status, verifyResponse.statusText ) if (verifyResponse.status > 499) { console.error("[SAS] verifyOTP error", await verifyResponse.text()) throw new TRPCError({ code: "SERVICE_UNAVAILABLE", message: "Error from downstream SAS service", }) } const data = await verifyResponse.json() console.log("[SAS] verifyOTP data", data) const result = outputSchema.safeParse(data) if (!result.success) { console.error("[SAS] verifyOTP error", result.error) throw createError(data) } console.log("[SAS] verifyOTP success") console.log("[SAS] verifyOTP responding", result.data) return result.data }) async function fetchVerifyOtp(input: z.infer) { const sasAuthToken = await getSasToken() const { referenceId, databaseUUID } = await getOTPState() return await fetch( `${env.SAS_API_ENDPOINT}/api/scandic-partnership/customer/verify-otp`, { method: "POST", headers: { "Content-Type": "application/json", "Ocp-Apim-Subscription-Key": env.SAS_OCP_APIM, Authorization: `Bearer ${sasAuthToken}`, }, body: JSON.stringify({ referenceId: referenceId, otpCode: input.otp, databaseUUID: databaseUUID, }), } ) } function createError( errorBody: | { status: string error: string errorCode: number databaseUUID: string } | Error | VerifyOtpGeneralError ): TRPCError { const errorInfo = parseSASVerifyOtpError(errorBody) return new TRPCError({ code: "BAD_REQUEST", cause: errorInfo, }) }