Ecossistema
Zod
Schemas de validação em runtime para bodies de pagamento e payloads de webhook. Dependência: zod.
Create payment
import { z } from "zod";
export const createPaymentSchema = z
.object({
amount_cents: z.number().int().positive().optional(),
amount: z.number().positive().optional(),
description: z.string().max(140).optional(),
external_id: z.string().min(1).max(128).optional(),
expires_in: z.number().int().min(60).max(86400).optional(),
customer: z
.object({
name: z.string().optional(),
email: z.string().email().optional(),
document: z.string().optional(),
phone: z.string().optional(),
})
.optional(),
metadata: z.record(z.unknown()).optional(),
})
.refine((d) => d.amount_cents != null || d.amount != null, {
message: "Informe amount_cents ou amount",
});
type CreatePayment = z.infer<typeof createPaymentSchema>;Webhook v2
import { z } from "zod";
export const webhookV2Schema = z.object({
id: z.string(),
type: z.string(),
api_version: z.literal("v2"),
created: z.number(),
created_at: z.string(),
livemode: z.boolean(),
data: z.object({
object: z.object({
id: z.string(),
status: z.enum(["pending", "paid", "expired", "failed", "refunded"]),
amount_cents: z.number(),
external_id: z.string().nullable().optional(),
}).passthrough(),
}),
source: z.literal("hyzepay"),
});
// após validar HMAC:
const event = webhookV2Schema.parse(JSON.parse(rawBody));
if (event.type === "payment.paid" && event.data.object.status === "paid") {
// liberar produto
}Sempre valide a assinatura HMAC no raw body antes de fazer parse com Zod.