@itpay/cli 0.1.8 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/itp +81 -3
- package/package.json +1 -1
package/bin/itp
CHANGED
|
@@ -3422,6 +3422,15 @@ async function renderHumanAction(action, flags = {}) {
|
|
|
3422
3422
|
return { rendered: false, mode: "json-local-qr", outputs: [localPath] };
|
|
3423
3423
|
}
|
|
3424
3424
|
}
|
|
3425
|
+
if (!qrImageURL && shouldGenerateLocalQRFromActionURL(action, mode, flags)) {
|
|
3426
|
+
const localPath = await prepareLocalQRFromActionURL(action, flags, mode !== "file" && !flags.qr_file && !process.env.ITP_QR_FILE);
|
|
3427
|
+
if (localPath) {
|
|
3428
|
+
attachAgentLocalQR(action, localPath);
|
|
3429
|
+
annotateHumanActionPresentation(action, "");
|
|
3430
|
+
persistHumanAction(action, flags);
|
|
3431
|
+
return { rendered: false, mode: "json-local-url-qr", outputs: [localPath] };
|
|
3432
|
+
}
|
|
3433
|
+
}
|
|
3425
3434
|
return { rendered: false, mode: flags.json ? "json" : mode };
|
|
3426
3435
|
}
|
|
3427
3436
|
const host = String(process.env.ITP_HOST || flags.host || "").toLowerCase();
|
|
@@ -3435,9 +3444,18 @@ async function renderHumanAction(action, flags = {}) {
|
|
|
3435
3444
|
persistHumanAction(action, flags);
|
|
3436
3445
|
return { rendered: false, mode: localPath ? "agent-local-image-qr" : "agent-image-qr", host, outputs: [localPath || "preferred_qr_url"] };
|
|
3437
3446
|
}
|
|
3438
|
-
|
|
3447
|
+
if (shouldGenerateLocalQRFromActionURL(action, mode, flags)) {
|
|
3448
|
+
const localPath = await prepareLocalQRFromActionURL(action, flags, true);
|
|
3449
|
+
if (localPath) {
|
|
3450
|
+
attachAgentLocalQR(action, localPath);
|
|
3451
|
+
annotateHumanActionPresentation(action, "");
|
|
3452
|
+
persistHumanAction(action, flags);
|
|
3453
|
+
return { rendered: false, mode: "agent-local-url-qr", host, outputs: [localPath] };
|
|
3454
|
+
}
|
|
3455
|
+
}
|
|
3456
|
+
process.stderr.write(`No QR image available. Open action URL: ${action.url}\n`);
|
|
3439
3457
|
persistHumanAction(action, flags);
|
|
3440
|
-
return { rendered: false, mode: "agent-url-fallback", host, outputs: ["
|
|
3458
|
+
return { rendered: false, mode: "agent-url-fallback", host, outputs: ["action_url"] };
|
|
3441
3459
|
}
|
|
3442
3460
|
|
|
3443
3461
|
const renderResult = { rendered: false, mode, outputs: [] };
|
|
@@ -3461,7 +3479,19 @@ async function renderHumanAction(action, flags = {}) {
|
|
|
3461
3479
|
renderResult.outputs.push(file);
|
|
3462
3480
|
if (mode === "file") return renderResult;
|
|
3463
3481
|
} else {
|
|
3464
|
-
|
|
3482
|
+
const localPath = shouldGenerateLocalQRFromActionURL(action, mode, flags)
|
|
3483
|
+
? await prepareLocalQRFromActionURL(action, flags, false)
|
|
3484
|
+
: "";
|
|
3485
|
+
if (localPath) {
|
|
3486
|
+
attachAgentLocalQR(action, localPath);
|
|
3487
|
+
annotateHumanActionPresentation(action, "");
|
|
3488
|
+
process.stderr.write(`Alipay action QR image: ${localPath}\n`);
|
|
3489
|
+
renderResult.rendered = true;
|
|
3490
|
+
renderResult.outputs.push(localPath);
|
|
3491
|
+
if (mode === "file") return renderResult;
|
|
3492
|
+
} else {
|
|
3493
|
+
process.stderr.write(`No QR image available. Open action URL: ${action.url}\n`);
|
|
3494
|
+
}
|
|
3465
3495
|
}
|
|
3466
3496
|
}
|
|
3467
3497
|
|
|
@@ -3535,6 +3565,12 @@ function shouldPrepareLocalQRForJSON(mode, flags = {}, action = {}) {
|
|
|
3535
3565
|
return false;
|
|
3536
3566
|
}
|
|
3537
3567
|
|
|
3568
|
+
function shouldGenerateLocalQRFromActionURL(action = {}, mode = "", flags = {}) {
|
|
3569
|
+
if (!action?.url) return false;
|
|
3570
|
+
if (action.kind === "auth_qr") return true;
|
|
3571
|
+
return mode === "file" || Boolean(flags.qr_file || process.env.ITP_QR_FILE);
|
|
3572
|
+
}
|
|
3573
|
+
|
|
3538
3574
|
async function prepareLocalQRFile(action, qrImageURL, flags = {}, optional = false) {
|
|
3539
3575
|
if (!qrImageURL) return "";
|
|
3540
3576
|
const file = flags.qr_file || process.env.ITP_QR_FILE || defaultQRFilePath(action, qrImageURL);
|
|
@@ -3550,11 +3586,37 @@ async function prepareLocalQRFile(action, qrImageURL, flags = {}, optional = fal
|
|
|
3550
3586
|
return file;
|
|
3551
3587
|
}
|
|
3552
3588
|
|
|
3589
|
+
async function prepareLocalQRFromActionURL(action, flags = {}, optional = false) {
|
|
3590
|
+
if (!action?.url) return "";
|
|
3591
|
+
const file = flags.qr_file || process.env.ITP_QR_FILE || defaultGeneratedQRFilePath(action);
|
|
3592
|
+
try {
|
|
3593
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
3594
|
+
await QRCode.toFile(file, action.url, {
|
|
3595
|
+
type: "png",
|
|
3596
|
+
errorCorrectionLevel: "M",
|
|
3597
|
+
margin: 2,
|
|
3598
|
+
width: 512
|
|
3599
|
+
});
|
|
3600
|
+
} catch (error) {
|
|
3601
|
+
if (!optional) throw error;
|
|
3602
|
+
action.local_qr_error = safeErrorMessage(error);
|
|
3603
|
+
return "";
|
|
3604
|
+
}
|
|
3605
|
+
action.local_qr_path = file;
|
|
3606
|
+
action.local_qr_mime = "image/png";
|
|
3607
|
+
return file;
|
|
3608
|
+
}
|
|
3609
|
+
|
|
3553
3610
|
function defaultQRFilePath(action, qrImageURL) {
|
|
3554
3611
|
const id = sanitizeFilename(action?.payment_intent_id || action?.id || "qr");
|
|
3555
3612
|
return path.join(os.tmpdir(), `itp-${id}.${qrFileExtension(qrImageURL, action)}`);
|
|
3556
3613
|
}
|
|
3557
3614
|
|
|
3615
|
+
function defaultGeneratedQRFilePath(action) {
|
|
3616
|
+
const id = sanitizeFilename(action?.payment_intent_id || action?.id || "qr");
|
|
3617
|
+
return path.join(os.tmpdir(), `itp-${id}.png`);
|
|
3618
|
+
}
|
|
3619
|
+
|
|
3558
3620
|
function qrFileExtension(qrImageURL, action = {}) {
|
|
3559
3621
|
const mime = qrMimeType(qrImageURL, action);
|
|
3560
3622
|
if (mime === "image/png") return "png";
|
|
@@ -3620,6 +3682,22 @@ function attachAgentQRImage(action, qrImageURL, localPath = "") {
|
|
|
3620
3682
|
return action;
|
|
3621
3683
|
}
|
|
3622
3684
|
|
|
3685
|
+
function attachAgentLocalQR(action, localPath = "") {
|
|
3686
|
+
if (!action || !localPath) return action;
|
|
3687
|
+
if (!Array.isArray(action.display)) {
|
|
3688
|
+
action.display = [];
|
|
3689
|
+
}
|
|
3690
|
+
if (!action.display.some((item) => item?.type === "image" && item?.local_path === localPath)) {
|
|
3691
|
+
action.display.push({
|
|
3692
|
+
type: "image",
|
|
3693
|
+
format: "png",
|
|
3694
|
+
local_path: localPath,
|
|
3695
|
+
instructions: "Render this local QR image for the human to scan. It encodes the ItPay human action URL, not a provider raw QR payload."
|
|
3696
|
+
});
|
|
3697
|
+
}
|
|
3698
|
+
return action;
|
|
3699
|
+
}
|
|
3700
|
+
|
|
3623
3701
|
async function downloadQRImage(qrImageURL, file, flags = {}) {
|
|
3624
3702
|
const controller = new AbortController();
|
|
3625
3703
|
const timer = setTimeout(() => controller.abort(), apiTimeoutMs(flags));
|