// Noryk Gateway. Execute com Node.js 24 no servidor, nunca no navegador. const apiKey = process.env.NORYK_API_KEY; const idempotencyKey = process.env.IDEMPOTENCY_KEY; const base = new URL(process.env.NORYK_BASE_URL || 'https://gateway.noryk.finance'); if (!apiKey || !idempotencyKey) throw new Error('Configure NORYK_API_KEY e a IDEMPOTENCY_KEY já persistida para este pedido.'); if (/[\x00-\x20\x7f]/.test(apiKey)) throw new Error('A credencial não pode conter espaços ou caracteres de controle.'); if (!/^[a-zA-Z0-9_.:-]{8,128}$/.test(idempotencyKey) || /[\r\n]/.test(idempotencyKey)) throw new Error('IDEMPOTENCY_KEY deve ter de 8 a 128 caracteres permitidos.'); if (base.username || base.password || base.search || base.hash || base.pathname !== '/') throw new Error('NORYK_BASE_URL deve conter apenas a origem da API, sem credenciais, caminho ou parâmetros.'); if (base.protocol !== 'https:' && !(base.protocol === 'http:' && ['localhost', '127.0.0.1', '[::1]'].includes(base.hostname))) throw new Error('Use HTTPS; HTTP é permitido somente no desenvolvimento local.'); try { const response = await fetch(new URL('/v1/charges', base), { method: 'POST', redirect: 'error', signal: AbortSignal.timeout(15000), headers: { Authorization: `Bearer ${apiKey}`, 'Content-Type': 'application/json', 'Idempotency-Key': idempotencyKey, }, body: JSON.stringify({ amountCents: 10000, description: 'Pedido 000001' }), }); const result = await response.json(); if (!response.ok) { console.error({ code: result.error?.code || 'HTTP_ERROR', requestId: result.error?.requestId || response.headers.get('x-request-id'), httpStatus: response.status }); process.exitCode = 1; } else { if (!result || Array.isArray(result) || typeof result.id !== 'string' || !result.id.trim() || typeof result.status !== 'string' || !result.status || result.amountCents !== 10000) throw new Error('Incomplete confirmation'); // Persista result.id junto da chave do pedido no seu banco. // Exiba result.qrCode ao pagador; é o texto Pix copia e cola, simulado no sandbox. console.log({ id: result.id, status: result.status, amountCents: result.amountCents, feeCents: result.feeCents, netCents: result.netCents }); } } catch { console.error('Resultado sem confirmação. Preserve o mesmo corpo e a chave persistida; consulte a operação antes de tentar novamente.'); process.exitCode = 1; }