- examples/big-suite: E-Commerce 10 functions, 6 layers, real depends_on - provider: nodejs packages now wrapped in ESM zip (buildJSDeployZip) - provider: loadPackageLiteral reads raw file, nodejs zip via source_dir - all 10 functions verified working: python/node/ruby/go runtimes
71 lines
2.0 KiB
JavaScript
71 lines
2.0 KiB
JavaScript
// Валидирует платёжные данные перед созданием заказа
|
|
|
|
exports.handler = async (ctx) => {
|
|
const req = ctx.request;
|
|
|
|
if (!req.body) {
|
|
return {
|
|
status: 400,
|
|
body: JSON.stringify({ error: "request body required" }),
|
|
headers: { "Content-Type": "application/json" },
|
|
};
|
|
}
|
|
|
|
let data;
|
|
try {
|
|
data = typeof req.body === 'string' ? JSON.parse(req.body) : req.body;
|
|
} catch {
|
|
return {
|
|
status: 400,
|
|
body: JSON.stringify({ error: "invalid JSON" }),
|
|
headers: { "Content-Type": "application/json" },
|
|
};
|
|
}
|
|
|
|
const errors = [];
|
|
|
|
// card_number: 16 цифр
|
|
const card = String(data.card_number || "").replace(/\s/g, "");
|
|
if (!/^\d{16}$/.test(card)) errors.push("card_number must be 16 digits");
|
|
|
|
// cvv: 3 цифры
|
|
const cvv = String(data.cvv || "");
|
|
if (!/^\d{3}$/.test(cvv)) errors.push("cvv must be 3 digits");
|
|
|
|
// expiry: MM/YY
|
|
const expiry = String(data.expiry || "");
|
|
if (!/^(0[1-9]|1[0-2])\/\d{2}$/.test(expiry)) errors.push("expiry must be MM/YY");
|
|
else {
|
|
const [mm, yy] = expiry.split("/").map(Number);
|
|
const now = new Date();
|
|
const exp = new Date(2000 + yy, mm - 1);
|
|
if (exp < now) errors.push("card is expired");
|
|
}
|
|
|
|
// amount
|
|
const amount = Number(data.amount);
|
|
if (!amount || amount <= 0) errors.push("amount must be positive number");
|
|
if (amount > 10000) errors.push("amount exceeds limit 10000");
|
|
|
|
if (errors.length > 0) {
|
|
return {
|
|
status: 422,
|
|
body: JSON.stringify({ valid: false, errors }),
|
|
headers: { "Content-Type": "application/json" },
|
|
};
|
|
}
|
|
|
|
// Маскируем карту в ответе
|
|
const maskedCard = `****-****-****-${card.slice(-4)}`;
|
|
return {
|
|
body: JSON.stringify({
|
|
valid: true,
|
|
masked_card: maskedCard,
|
|
amount,
|
|
currency: data.currency || "USD",
|
|
token: `pay_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
|
|
}),
|
|
headers: { "Content-Type": "application/json" },
|
|
};
|
|
};
|