@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.
Files changed (2) hide show
  1. package/dist/index.js +78 -17
  2. 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 = 500;
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
- return Object.fromEntries(PAYMENT_LIST_JSON_FIELDS.filter((k) => src[k] !== void 0).map((k) => [k, src[k]]));
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-500 characters)",
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(jsonOutput({ ...page, data: page.data.map((pi) => listItemJson(pi, opts.includeMetadata)) }));
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.19.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.7.0",
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"