@vonpay/checkout-cli 0.19.0 → 0.21.0
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/dist/index.js +78 -17
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -851,6 +851,7 @@ var FIELD_PRINTERS = {
|
|
|
851
851
|
currentStatus: (e) => e.currentStatus ? `Current status: ${str(e.currentStatus)}` : null,
|
|
852
852
|
rejectReason: (e) => e.rejectReason ? `Reject reason: ${str(e.rejectReason)}` : null,
|
|
853
853
|
paymentIntent: (e) => e.paymentIntent ? `Payment intent: ${str(e.paymentIntent)}` : null,
|
|
854
|
+
paymentIntentStatus: (e) => e.paymentIntentStatus ? `Payment intent status: ${str(e.paymentIntentStatus)}` : null,
|
|
854
855
|
// refund_target_is_duplicate: the SDK has already checked this is a
|
|
855
856
|
// transaction id (vp_tx_*), so it is safe to echo as a command.
|
|
856
857
|
refundInstead: (e) => e.refundInstead ? `Refund instead: vonpay checkout refunds create --transaction ${str(e.refundInstead)}` : null,
|
|
@@ -1357,7 +1358,7 @@ function parseMetadata(pairs) {
|
|
|
1357
1358
|
return out;
|
|
1358
1359
|
}
|
|
1359
1360
|
var METADATA_FILTER_KEY = /^[A-Za-z0-9_.:-]{1,64}$/;
|
|
1360
|
-
var METADATA_FILTER_VALUE_MAX =
|
|
1361
|
+
var METADATA_FILTER_VALUE_MAX = 128;
|
|
1361
1362
|
function assertMetadataFilterKey(key, flag) {
|
|
1362
1363
|
if (!METADATA_FILTER_KEY.test(key)) {
|
|
1363
1364
|
throw new Error(
|
|
@@ -1377,6 +1378,41 @@ function parseMetadataFilter(raw, flag) {
|
|
|
1377
1378
|
return { [key]: value };
|
|
1378
1379
|
}
|
|
1379
1380
|
|
|
1381
|
+
// src/utils/processor-detail.ts
|
|
1382
|
+
import { SAFE_CODE_PATTERN, SAFE_CONNECTION_ID_PATTERN, safeValueOrWithheld } from "@vonpay/checkout-node";
|
|
1383
|
+
var INCLUDE_PROCESSOR_DETAIL_HELP = "With --json: also print the card processor's own answer (untrusted text), every try with its connection name, the connection's name, and the card's first six digits";
|
|
1384
|
+
var PROCESSOR_DETAIL_KEYS = ["processorResponse", "attempts", "attemptsStatus"];
|
|
1385
|
+
function cardForDisplay(card) {
|
|
1386
|
+
if (card === null || typeof card !== "object" || Array.isArray(card)) return card;
|
|
1387
|
+
const c = card;
|
|
1388
|
+
return { brand: c.brand ?? null, last4: c.last4 ?? null };
|
|
1389
|
+
}
|
|
1390
|
+
function attemptSummary(a) {
|
|
1391
|
+
return {
|
|
1392
|
+
connectionId: safeValueOrWithheld(a.processorConnection?.id, SAFE_CONNECTION_ID_PATTERN),
|
|
1393
|
+
result: safeValueOrWithheld(a.result, SAFE_CODE_PATTERN),
|
|
1394
|
+
declineCode: safeValueOrWithheld(a.declineCode, SAFE_CODE_PATTERN),
|
|
1395
|
+
outcome: safeValueOrWithheld(a.outcome, SAFE_CODE_PATTERN)
|
|
1396
|
+
};
|
|
1397
|
+
}
|
|
1398
|
+
function attemptsStatusForDisplay(value) {
|
|
1399
|
+
return safeValueOrWithheld(value, SAFE_CODE_PATTERN);
|
|
1400
|
+
}
|
|
1401
|
+
function connectionForDisplay(connection) {
|
|
1402
|
+
if (connection === null || typeof connection !== "object" || Array.isArray(connection)) return connection;
|
|
1403
|
+
return { id: connection.id ?? null };
|
|
1404
|
+
}
|
|
1405
|
+
function withoutProcessorDetail(obj, includeProcessorDetail) {
|
|
1406
|
+
const src = obj;
|
|
1407
|
+
if (includeProcessorDetail) return src;
|
|
1408
|
+
const out = { ...src };
|
|
1409
|
+
for (const k of PROCESSOR_DETAIL_KEYS) delete out[k];
|
|
1410
|
+
if ("card" in out) out.card = cardForDisplay(out.card);
|
|
1411
|
+
if ("processorConnection" in out) out.processorConnection = connectionForDisplay(out.processorConnection);
|
|
1412
|
+
return out;
|
|
1413
|
+
}
|
|
1414
|
+
var PROCESSOR_DETAIL_NEEDS_JSON = "--include-processor-detail is used with --json.";
|
|
1415
|
+
|
|
1380
1416
|
// src/commands/payment-reports.ts
|
|
1381
1417
|
import chalk8 from "chalk";
|
|
1382
1418
|
import { formatMinorUnits as formatMinorUnits2 } from "@vonpay/checkout-node";
|
|
@@ -1429,12 +1465,24 @@ var PAYMENT_LIST_JSON_FIELDS = [
|
|
|
1429
1465
|
"declineCode",
|
|
1430
1466
|
"action",
|
|
1431
1467
|
"ruleCode",
|
|
1432
|
-
"networkAdvice"
|
|
1468
|
+
"networkAdvice",
|
|
1469
|
+
// Each try as the safe summary only (connection id, result, decline code, outcome), and
|
|
1470
|
+
// whether that list is the full record. --include-processor-detail prints the whole tries.
|
|
1471
|
+
"attempts",
|
|
1472
|
+
"attemptsStatus"
|
|
1433
1473
|
];
|
|
1434
|
-
function listItemJson(pi, includeMetadata) {
|
|
1435
|
-
if (includeMetadata) return pi;
|
|
1474
|
+
function listItemJson(pi, includeMetadata, includeProcessorDetail) {
|
|
1436
1475
|
const src = pi;
|
|
1437
|
-
|
|
1476
|
+
const out = includeMetadata ? { ...src } : Object.fromEntries(PAYMENT_LIST_JSON_FIELDS.filter((k) => src[k] !== void 0).map((k) => [k, src[k]]));
|
|
1477
|
+
if (includeProcessorDetail) {
|
|
1478
|
+
if (src.processorResponse !== void 0) out.processorResponse = src.processorResponse;
|
|
1479
|
+
return out;
|
|
1480
|
+
}
|
|
1481
|
+
const safe = withoutProcessorDetail(out, false);
|
|
1482
|
+
if (src.attemptsStatus !== void 0) safe.attemptsStatus = attemptsStatusForDisplay(src.attemptsStatus);
|
|
1483
|
+
if (pi.attempts === null) safe.attempts = null;
|
|
1484
|
+
else if (Array.isArray(pi.attempts)) safe.attempts = pi.attempts.map(attemptSummary);
|
|
1485
|
+
return safe;
|
|
1438
1486
|
}
|
|
1439
1487
|
var ALL_DEFAULT_MAX_ITEMS = 1e4;
|
|
1440
1488
|
function stoppedAtDefaultCap() {
|
|
@@ -1449,6 +1497,7 @@ function buildListParams(opts) {
|
|
|
1449
1497
|
if (opts.startingAfter !== void 0) params.startingAfter = opts.startingAfter;
|
|
1450
1498
|
if (opts.maxItems !== void 0 && !opts.all) throw new Error("--max-items is used with --all.");
|
|
1451
1499
|
if (opts.includeMetadata && !opts.json) throw new Error("--include-metadata is used with --json.");
|
|
1500
|
+
if (opts.includeProcessorDetail && !opts.json) throw new Error(PROCESSOR_DETAIL_NEEDS_JSON);
|
|
1452
1501
|
const maxItems = opts.maxItems !== void 0 ? positiveWholeNumber(opts.maxItems, "--max-items") : opts.all ? ALL_DEFAULT_MAX_ITEMS : void 0;
|
|
1453
1502
|
return { params, ...maxItems !== void 0 ? { maxItems } : {} };
|
|
1454
1503
|
}
|
|
@@ -1513,7 +1562,7 @@ var FILTER_HELP = {
|
|
|
1513
1562
|
createdLt: "End of the window, exclusive (default: now). At most 31 days after the start (7 with summary --group-by hour)",
|
|
1514
1563
|
outcome: "Only these outcomes, comma-separated (e.g. bank_declined,refused_before_bank)",
|
|
1515
1564
|
store: "Only payments for this connected store hostname (e.g. shop.example.com)",
|
|
1516
|
-
metadata: "Only payments with this metadata tag, key=value (ONE tag; key 1-64 of letters, digits, _ . : -; value 1-
|
|
1565
|
+
metadata: "Only payments with this metadata tag, key=value (ONE tag; key 1-64 of letters, digits, _ . : -; value 1-128 characters)",
|
|
1517
1566
|
cardBrand: "Only these card brands, comma-separated (visa, mastercard, amex, discover, unionpay, jcb, diners, unknown)",
|
|
1518
1567
|
currency: "Only payments in this currency (e.g. USD)",
|
|
1519
1568
|
initiator: "merchant (merchant-initiated charges on a saved card) or customer",
|
|
@@ -1540,7 +1589,7 @@ function addPaymentReportCommands(intents) {
|
|
|
1540
1589
|
).option("--max-items <n>", `With --all: stop after this many payments (default ${ALL_DEFAULT_MAX_ITEMS})`).option(
|
|
1541
1590
|
"--json",
|
|
1542
1591
|
"Output JSON: each payment's status, outcome, amount, card, store and decline fields \u2014 not your metadata (with --all: one JSON array)"
|
|
1543
|
-
).option("--include-metadata", "With --json: print every field of each payment, your metadata included").action(async (opts) => {
|
|
1592
|
+
).option("--include-metadata", "With --json: print every field of each payment, your metadata included (not the processor detail: see --include-processor-detail)").option("--include-processor-detail", INCLUDE_PROCESSOR_DETAIL_HELP).action(async (opts) => {
|
|
1544
1593
|
let built;
|
|
1545
1594
|
try {
|
|
1546
1595
|
built = buildListParams(opts);
|
|
@@ -1557,7 +1606,7 @@ function addPaymentReportCommands(intents) {
|
|
|
1557
1606
|
});
|
|
1558
1607
|
if (opts.json) {
|
|
1559
1608
|
const items = [];
|
|
1560
|
-
for await (const pi of pager) items.push(listItemJson(pi, opts.includeMetadata));
|
|
1609
|
+
for await (const pi of pager) items.push(listItemJson(pi, opts.includeMetadata, opts.includeProcessorDetail));
|
|
1561
1610
|
spinner.stop();
|
|
1562
1611
|
console.log(jsonOutput(items));
|
|
1563
1612
|
if (opts.maxItems === void 0 && items.length >= ALL_DEFAULT_MAX_ITEMS) console.error(stoppedAtDefaultCap());
|
|
@@ -1578,7 +1627,12 @@ function addPaymentReportCommands(intents) {
|
|
|
1578
1627
|
const page = await client.paymentIntents.list(built.params);
|
|
1579
1628
|
spinner.stop();
|
|
1580
1629
|
if (opts.json) {
|
|
1581
|
-
console.log(
|
|
1630
|
+
console.log(
|
|
1631
|
+
jsonOutput({
|
|
1632
|
+
...page,
|
|
1633
|
+
data: page.data.map((pi) => listItemJson(pi, opts.includeMetadata, opts.includeProcessorDetail))
|
|
1634
|
+
})
|
|
1635
|
+
);
|
|
1582
1636
|
return;
|
|
1583
1637
|
}
|
|
1584
1638
|
for (const line of paymentListLines(page)) console.log(line);
|
|
@@ -1619,6 +1673,9 @@ function addPaymentReportCommands(intents) {
|
|
|
1619
1673
|
}
|
|
1620
1674
|
|
|
1621
1675
|
// src/commands/payment-intents.ts
|
|
1676
|
+
function refuseProcessorDetailWithoutJson(opts) {
|
|
1677
|
+
if (opts.includeProcessorDetail && !opts.json) exitWithCliError(PROCESSOR_DETAIL_NEEDS_JSON, chalk9.red(PROCESSOR_DETAIL_NEEDS_JSON));
|
|
1678
|
+
}
|
|
1622
1679
|
var MIT_INITIATORS = ["merchant", "customer"];
|
|
1623
1680
|
var MIT_REASONS = [
|
|
1624
1681
|
"recurring",
|
|
@@ -1754,7 +1811,8 @@ function paymentIntentsCommand() {
|
|
|
1754
1811
|
).option("--buyer-email <email>", "Buyer email for this charge").option(
|
|
1755
1812
|
"--idempotency-key <key>",
|
|
1756
1813
|
"Idempotency key for this charge. Reuse the SAME key to retry the same charge safely. REQUIRED on a live key; on a sandbox key generated (and printed) when omitted"
|
|
1757
|
-
).addOption(retiredConfirmLiveOption()).option("--json", "Output raw JSON").action(async (raw) => {
|
|
1814
|
+
).addOption(retiredConfirmLiveOption()).option("--json", "Output raw JSON").option("--include-processor-detail", INCLUDE_PROCESSOR_DETAIL_HELP).action(async (raw) => {
|
|
1815
|
+
refuseProcessorDetailWithoutJson(raw);
|
|
1758
1816
|
const apiKey = requireApiKey();
|
|
1759
1817
|
const opts = { ...raw, amount: minorUnitsOrExit(raw.amount, "--amount") };
|
|
1760
1818
|
const captureMethod = opts.captureMethod?.toLowerCase();
|
|
@@ -1796,7 +1854,7 @@ function paymentIntentsCommand() {
|
|
|
1796
1854
|
});
|
|
1797
1855
|
spinner.stop();
|
|
1798
1856
|
if (opts.json) {
|
|
1799
|
-
console.log(jsonOutput(intent));
|
|
1857
|
+
console.log(jsonOutput(withoutProcessorDetail(intent, opts.includeProcessorDetail)));
|
|
1800
1858
|
} else {
|
|
1801
1859
|
console.log(chalk9.green("\u2713 Payment intent created"));
|
|
1802
1860
|
printPaymentIntent(intent);
|
|
@@ -1808,14 +1866,15 @@ function paymentIntentsCommand() {
|
|
|
1808
1866
|
});
|
|
1809
1867
|
intents.command("get").description(
|
|
1810
1868
|
"Read a payment intent back \u2014 the way to check a payment whose outcome was unclear before doing anything else"
|
|
1811
|
-
).argument("<id>", "Payment intent ID (vpi_*)").option("--json", "Output raw JSON").action(async (id, opts) => {
|
|
1869
|
+
).argument("<id>", "Payment intent ID (vpi_*)").option("--json", "Output raw JSON").option("--include-processor-detail", INCLUDE_PROCESSOR_DETAIL_HELP).action(async (id, opts) => {
|
|
1870
|
+
refuseProcessorDetailWithoutJson(opts);
|
|
1812
1871
|
const client = makeCheckoutClient();
|
|
1813
1872
|
const spinner = startSpinner("Fetching payment intent...");
|
|
1814
1873
|
try {
|
|
1815
1874
|
const intent = await client.paymentIntents.retrieve(id);
|
|
1816
1875
|
spinner.stop();
|
|
1817
1876
|
if (opts.json) {
|
|
1818
|
-
console.log(jsonOutput(intent));
|
|
1877
|
+
console.log(jsonOutput(withoutProcessorDetail(intent, opts.includeProcessorDetail)));
|
|
1819
1878
|
} else {
|
|
1820
1879
|
printPaymentIntent(intent);
|
|
1821
1880
|
}
|
|
@@ -1830,8 +1889,9 @@ function paymentIntentsCommand() {
|
|
|
1830
1889
|
).option(
|
|
1831
1890
|
"--idempotency-key <key>",
|
|
1832
1891
|
"Idempotency key. Reuse the SAME key to retry safely. REQUIRED on a live key; on a sandbox key generated (and printed) when omitted"
|
|
1833
|
-
).addOption(retiredConfirmLiveOption()).option("--json", "Output raw JSON").action(
|
|
1892
|
+
).addOption(retiredConfirmLiveOption()).option("--json", "Output raw JSON").option("--include-processor-detail", INCLUDE_PROCESSOR_DETAIL_HELP).action(
|
|
1834
1893
|
async (id, opts) => {
|
|
1894
|
+
refuseProcessorDetailWithoutJson(opts);
|
|
1835
1895
|
const apiKey = requireApiKey();
|
|
1836
1896
|
const amountToCapture = optionalMinorUnitsOrExit(
|
|
1837
1897
|
opts.amountToCapture,
|
|
@@ -1865,7 +1925,7 @@ function paymentIntentsCommand() {
|
|
|
1865
1925
|
);
|
|
1866
1926
|
spinner.stop();
|
|
1867
1927
|
if (opts.json) {
|
|
1868
|
-
console.log(jsonOutput(intent));
|
|
1928
|
+
console.log(jsonOutput(withoutProcessorDetail(intent, opts.includeProcessorDetail)));
|
|
1869
1929
|
} else {
|
|
1870
1930
|
const captureLabel = amountToCapture !== void 0 ? ` (partial: ${formatMinorUnits3(amountToCapture, intent.currency)})` : "";
|
|
1871
1931
|
console.log(chalk9.green(`\u2713 Payment intent captured${captureLabel}`));
|
|
@@ -1880,8 +1940,9 @@ function paymentIntentsCommand() {
|
|
|
1880
1940
|
intents.command("void").description("Void an authorized (uncaptured) payment intent").argument("<id>", "Payment intent ID (vpi_*)").option(
|
|
1881
1941
|
"--idempotency-key <key>",
|
|
1882
1942
|
"Idempotency key. Reuse the SAME key to retry safely. REQUIRED on a live key; on a sandbox key generated (and printed) when omitted"
|
|
1883
|
-
).addOption(retiredConfirmLiveOption()).option("--json", "Output raw JSON").action(
|
|
1943
|
+
).addOption(retiredConfirmLiveOption()).option("--json", "Output raw JSON").option("--include-processor-detail", INCLUDE_PROCESSOR_DETAIL_HELP).action(
|
|
1884
1944
|
async (id, opts) => {
|
|
1945
|
+
refuseProcessorDetailWithoutJson(opts);
|
|
1885
1946
|
const apiKey = requireApiKey();
|
|
1886
1947
|
refuseUnsafeLiveDestination(apiKey);
|
|
1887
1948
|
const idempotencyKey = idempotencyKeyFor(opts.idempotencyKey, "void", apiKey);
|
|
@@ -1904,7 +1965,7 @@ function paymentIntentsCommand() {
|
|
|
1904
1965
|
const intent = await client.paymentIntents.void(id, { idempotencyKey });
|
|
1905
1966
|
spinner.stop();
|
|
1906
1967
|
if (opts.json) {
|
|
1907
|
-
console.log(jsonOutput(intent));
|
|
1968
|
+
console.log(jsonOutput(withoutProcessorDetail(intent, opts.includeProcessorDetail)));
|
|
1908
1969
|
} else {
|
|
1909
1970
|
console.log(chalk9.green("\u2713 Payment intent voided"));
|
|
1910
1971
|
printPaymentIntent(intent);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vonpay/checkout-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "Von Payments CLI — developer tools for checkout integration",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"node": ">=20"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@vonpay/checkout-node": "^4.
|
|
23
|
+
"@vonpay/checkout-node": "^4.9.0",
|
|
24
24
|
"commander": "^13.0.0",
|
|
25
25
|
"chalk": "^5.4.0",
|
|
26
26
|
"ora": "^8.2.0"
|