Files
medreport_mrb2b/app/api/montonio/verify-token/route.ts
2025-07-18 16:10:13 +03:00

106 lines
2.4 KiB
TypeScript

import { NextResponse } from 'next/server';
import jwt from 'jsonwebtoken';
import { z } from 'zod';
import { enhanceRouteHandler } from '@kit/next/routes';
import { getLogger } from '@kit/shared/logger';
interface MontonioOrderToken {
uuid: string;
accessKey: string;
merchantReference: string;
merchantReferenceDisplay: string;
paymentStatus:
| 'PAID'
| 'FAILED'
| 'CANCELLED'
| 'PENDING'
| 'EXPIRED'
| 'REFUNDED';
paymentMethod: string;
grandTotal: number;
currency: string;
senderIban?: string;
senderName?: string;
paymentProviderName?: string;
paymentLinkUuid: string;
iat: number;
exp: number;
}
const BodySchema = z.object({
token: z.string(),
});
export const POST = enhanceRouteHandler(
async ({ request }) => {
const logger = await getLogger();
const body = await request.json();
const namespace = 'montonio.verify-token';
const activeCartId = request.cookies.get('_medusa_cart_id')?.value;
console.info('cart id', activeCartId);
try {
const { token } = BodySchema.parse(body);
const secretKey = process.env.MONTONIO_SECRET_KEY as string;
if (!secretKey) {
logger.error(
{
name: namespace,
},
`Missing MONTONIO_SECRET_KEY`,
);
throw new Error('Server misconfiguration.');
}
const decoded = jwt.verify(token, secretKey, {
algorithms: ['HS256'],
}) as MontonioOrderToken;
const [, cartId] = decoded.merchantReferenceDisplay.split(':');
console.info('active cart id parsed', {cartId, activeCartId, decoded:decoded.merchantReferenceDisplay});
if (cartId !== activeCartId) {
throw new Error('Invalid cart id');
}
logger.info(
{
name: namespace,
status: decoded.paymentStatus,
orderId: decoded.uuid,
},
`Successfully verified Montonio token.`,
);
return NextResponse.json({
status: decoded.paymentStatus,
});
} catch (error) {
logger.error(
{
name: namespace,
error,
},
`Failed to verify Montonio token`,
);
const message = error instanceof Error ? error.message : 'Invalid token';
return NextResponse.json(
{
error: message,
},
{
status: 400,
},
);
}
},
{
auth: false,
},
);