@vonpay/checkout-cli 0.17.0 → 0.19.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/README.md +20 -6
- package/dist/index.js +1397 -334
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -49,9 +49,13 @@ All commands are namespaced under `vonpay checkout`:
|
|
|
49
49
|
| `vonpay checkout payment-intents get <id>` | Read a payment intent back — the first step whenever a payment's outcome was unclear |
|
|
50
50
|
| `vonpay checkout payment-intents capture <id>` | Capture an authorized intent (full or partial) |
|
|
51
51
|
| `vonpay checkout payment-intents void <id>` | Void an authorized intent before capture |
|
|
52
|
+
| `vonpay checkout payment-intents list` | List payment intents, newest first, with filters (`--outcome`, `--store`, `--metadata key=value`, `--created-gte` / `--created-lt`, …); `--all` reads every page, up to 10,000 payments unless `--max-items` says otherwise. Next page: the same filters and window plus `--starting-after` (the cursor lasts 24 hours). Read-only. `--json` prints each payment's status, outcome, amount, card, store and decline fields, not your metadata (the same fields the MCP server shows an agent); add `--include-metadata` for every field |
|
|
53
|
+
| `vonpay checkout payment-intents summary` | Approval and decline rates, counts and amounts, as the dashboard counts payment attempts (`--group-by day,store`, `--time-zone`). A rate with no traffic shows as no data, never 0%. A summary is kept 45 s: for fresh numbers change the window or wait. Read-only |
|
|
52
54
|
| `vonpay checkout refunds create` | Refund a captured intent (`--payment-intent`) or a settled transaction (`--transaction`), full or partial — pass exactly one |
|
|
53
55
|
| `vonpay checkout refunds list` | List one payment's refunds and its refund totals (`--payment-intent` or `--transaction`) |
|
|
54
56
|
| `vonpay checkout tokens create` | Create a payment-method token for saved-card / MIT flows |
|
|
57
|
+
| `vonpay checkout subscription-products list` | List your subscription products, newest first, each with its price, how often it renews and the terms a sign-up on it states (`--product-ref`, `--status active\|archived`, `--limit`, `--starting-after`). Read-only |
|
|
58
|
+
| `vonpay checkout subscription-products terms <product>` | Read one product's renewal terms (by id or reference): the disclosure to show next to the order button before the sign-up charge, its price phrase and terms version. `--amount` for an intro first payment in minor units. Read-only |
|
|
55
59
|
| `vonpay checkout capabilities` | Show what this merchant's binder supports |
|
|
56
60
|
| `vonpay checkout trigger <event>` | Trigger a synthetic webhook event against your local endpoint (`charge.*`, `refund.failed`, `payment_intent.*`, `mirror.order.created`, `subscription.*`, `merchant.card_testing_suspected`, `session.*`; `vonpay checkout trigger --help` lists them all) |
|
|
57
61
|
| `vonpay checkout listen` | Stream live webhook delivery attempts; optionally re-forward each to a local URL with `--forward-to` |
|
|
@@ -60,7 +64,9 @@ All commands are namespaced under `vonpay checkout`:
|
|
|
60
64
|
|
|
61
65
|
Run `vonpay checkout <command> --help` for full flag reference.
|
|
62
66
|
|
|
63
|
-
> **`listen --forward-to` signs forwarded events with the v1 webhook scheme** — a single `x-vonpay-signature: t=<unix-seconds>,v1=<hex>` header, with the HMAC-SHA256 computed over `${t}.${rawBody}` and a fresh `t` stamped at forward time. There is no separate timestamp header. Verify them in your local handler with `vonpay.webhooks.constructEvent(rawBody, signatureHeader, secret)`.
|
|
67
|
+
> **`listen --forward-to` signs forwarded events with the v1 webhook scheme** — a single `x-vonpay-signature: t=<unix-seconds>,v1=<hex>` header, with the HMAC-SHA256 computed over `${t}.${rawBody}` and a fresh `t` stamped at forward time. There is no separate timestamp header. Verify them in your local handler with `vonpay.webhooks.constructEvent(rawBody, signatureHeader, secret)`.
|
|
68
|
+
|
|
69
|
+
> **The signing secret for `listen --forward-to` and `trigger`** is never your API key. Each run makes a new random secret (`whsec_…`) and prints it at the start: copy it into your local handler. To keep the same secret across runs (for a handler that reads it from `.env`), pin one with `--signing-secret <secret>` or the environment variable `VONPAY_CLI_SIGNING_SECRET` (the flag wins). A pinned secret must be at least 16 characters and must not be an API key. For `trigger`, pinning is the usual way: the event is sent at once, so your handler must already know the secret. Production deliveries are keyed by your endpoint's own signing secret (`whsec_…` from the dashboard); the listen stream does not expose it, so the CLI uses its own.
|
|
64
70
|
|
|
65
71
|
### Common flags
|
|
66
72
|
|
|
@@ -75,17 +81,23 @@ An error that says `Next action: reconcile`, or `Retry withheld`, means the paym
|
|
|
75
81
|
|
|
76
82
|
### Live-key safety
|
|
77
83
|
|
|
78
|
-
Commands that move money or cannot be undone on a live key — `payment-intents create`, `payment-intents capture`, `payment-intents void`, `refunds create`, `trigger` (which
|
|
84
|
+
Commands that move money or cannot be undone on a live key — `payment-intents create`, `payment-intents capture`, `payment-intents void`, `refunds create`, `sessions create` (a payment page a buyer can pay), `trigger` (which sends a synthetic event as if from Von Payments) and `listen` (which shows live payment events and, with `--forward-to`, sends each on) — **ask a person to confirm at the terminal** when the key is `vp_sk_live_*`. The command shows what it is about to do (the action, the payment intent or transaction, the amount where known, where a session sends the buyer, the idempotency key, the API host when it is not the default, the key's first characters) and proceeds only if you type `confirm`. Anything else cancels, and nothing is sent. Every value is printed on one line, cleaned of escapes and hidden characters, so a value cannot add a line that reads like part of the prompt; an idempotency key that is not letters, digits and `_ : . -` (at most 64 characters) reads `[custom key withheld]`.
|
|
85
|
+
|
|
86
|
+
A live `refunds create` first looks up and shows the original payment (or, with `--transaction`, its session), what was already refunded and what is still refundable; a lookup that fails refuses. A live refund by `--transaction` needs `--session-id <vp_cs_*>`, and the transaction must be that session's single payment.
|
|
79
87
|
|
|
80
|
-
With a live key and **no interactive terminal** (stdin and stdout must both be a terminal), these commands refuse. This is deliberate: scripts, CI jobs and AI agents driving a shell cannot confirm a live money action. Use a sandbox key (`vp_sk_test_*`) for automation. `--confirm-live` no longer confirms anything on these commands (a flag can be typed by whoever drives the shell); it is still accepted so it is not an error, and is hidden from `--help`.
|
|
88
|
+
With a live key and **no interactive terminal** (stdin and stdout must both be a terminal), these commands refuse. This is deliberate: scripts, CI jobs and AI agents driving a shell cannot confirm a live money action. Use a sandbox key (`vp_sk_test_*`) for automation. `--confirm-live` no longer confirms anything on these commands (a flag can be typed by whoever drives the shell); it is still accepted so it is not an error, and is hidden from `--help`.
|
|
89
|
+
|
|
90
|
+
**What the typed confirmation is, and is not.** It stops ordinary scripted and agent use: a script, a CI job or an AI agent driving an ordinary shell cannot answer it. It is **not** a wall against a program built to get around it — a program that fakes a terminal can type `confirm` — and it does nothing against an agent that can read your API key (from the environment, `~/.vonpay/config.json` or a `.env` file) and call the API without this CLI. **Do not give an AI agent a shell where a live secret key can be read.** Give it a sandbox key, or a restricted key holding only the permissions it needs (a restricted key also starts with `vp_sk_`; for example only `payment_intents.read` for an agent that reads reports).
|
|
81
91
|
|
|
82
92
|
Sandbox keys (`vp_sk_test_*`) are never asked.
|
|
83
93
|
|
|
84
|
-
The money commands always send an idempotency key
|
|
94
|
+
The money commands always send an idempotency key. **On a live key you must pass `--idempotency-key`** (the command refuses without one, before anything is sent): a generated key would make a second run of the same command a second charge or refund. Choose one key per intended action (for example `order_1042:refund`) and reuse it to retry. On a sandbox key one is generated when you leave it out and printed to stderr before anything is sent.
|
|
85
95
|
|
|
86
96
|
**No live key on disk.** `login` and `init` refuse a live key (`init` used to write one to `.env` with `--force`). Give your app its live key through your deployment's secret store or environment.
|
|
87
97
|
|
|
88
|
-
**A live key is only sent to a Von Payments API host** (`https://checkout.vonpay.com` or `https://checkout-staging.vonpay.com`). If `VONPAY_BASE_URL` or `baseUrl` in `~/.vonpay/config.json` points anywhere else, live-key commands refuse (before any confirmation is asked), and `doctor` skips its key-carrying probe and says why. For a proxy you run yourself, set `VONPAY_ALLOW_CUSTOM_BASE_URL=1
|
|
98
|
+
**A live key is only sent to a Von Payments API host** (`https://checkout.vonpay.com` or `https://checkout-staging.vonpay.com`). If `VONPAY_BASE_URL` or `baseUrl` in `~/.vonpay/config.json` points anywhere else, live-key commands refuse (before any confirmation is asked), and `doctor` skips its key-carrying probe and says why. For a proxy you run yourself, set `VONPAY_ALLOW_CUSTOM_BASE_URL=1` **and** pass `--allow-custom-base-url` on each command (it is accepted after any command); either alone is refused. The environment variable, like the base URL it unlocks, can be left behind by someone else and would then apply to every later command; the flag has to be typed on each command, where it shows. Whoever controls your shell can do both, which is why the money commands still need a person at the terminal and show the API host they will use. The variable is read from the real environment only (the CLI loads no `.env` file). Sandbox keys are not restricted, but a base URL with a user name or password in it, or one that is not a valid URL, is refused for every key.
|
|
99
|
+
|
|
100
|
+
**A local audit log of every command (on by default).** Each command appends one line to `~/.vonpay/audit/cli-YYYY-MM-DD.jsonl` (UTC date; the folder is readable only by you, each file `0600`): when, which command, test or live key, a key fingerprint, and what happened — `sent`, `local` (a command that sends nothing to the API, such as `login` or `trigger`), `approved` (a person typed `confirm`), `declined`, `withheld` (no person at a terminal), `lookup_refused`, `refused_local` (including a command line the CLI cannot parse, such as an unknown command or option) or `error` (including `interrupted` for Ctrl-C and `internal_error` for a crash) — with the API's error code and request id when there is one, and for money commands the amount, currency and payment, transaction or session id. A money command also writes a `pending` line just before it sends, so a run that is killed mid-send still leaves a trace. **The key fingerprint is the key's first 12 and last 4 characters.** The first 12 are `vp_sk_live_` or `vp_sk_test_` plus one character of the secret, so the log holds 5 of your key's secret characters — enough to tell your keys apart, not enough to use one. A key with a prefix the SDK does not know is written as `[unknown key]` and a short hash instead, with none of its characters. It never holds a request body, metadata, a reason or note, a description, a URL, an email, card data, an idempotency key, the full key, the command line you typed or any other free text; an id, error code or request id that does not have the API's exact shape is written as a fixed placeholder. After an incident, read it to see what was run on this machine — by you, a script or an AI agent — and what happened. `VONPAY_AUDIT_DIR` moves it, `VONPAY_AUDIT_LOG=off` turns it off, and files older than `VONPAY_AUDIT_RETENTION_DAYS` (1–365, default 30) are deleted when a command starts. The folder must be your own real folder: a symbolic link, or a folder another user owns, is refused (with one warning). A day's file holds at most 50 MiB, and the last 5 MiB are kept for money lines: once the file reaches 45 MiB only `pending`, `approved` and `budget_refused` lines, and `sent` / `error` lines of a command that moves money, are written (one warning on stderr), so a loop of cheap refused calls cannot crowd out a later money record. A sandbox key's lines never use those last 5 MiB, so a sandbox loop cannot use them up either. When even a money line no longer fits, the file ends with ONE final line, `{"ts":"…","surface":"cli","version":"…","outcome":"log_full"}`, and nothing more is written to it that day (one more warning). The key's mode is the Node SDK's `keyMode`: `test`, `live`, `publishable_test`, `publishable_live` or `unknown` (held to the live-key rules). If the log cannot be written, the command warns once on stderr and carries on.
|
|
89
101
|
|
|
90
102
|
`trigger` and `listen --forward-to` never follow a redirect from your endpoint: a 3xx answer is reported as a failure, so the signed event is never re-sent somewhere else.
|
|
91
103
|
|
|
@@ -122,7 +134,9 @@ vonpay checkout refunds create --transaction vp_tx_test_abc123
|
|
|
122
134
|
# What does my binder support?
|
|
123
135
|
vonpay checkout capabilities
|
|
124
136
|
|
|
125
|
-
# Trigger a session.succeeded webhook against localhost:3000
|
|
137
|
+
# Trigger a session.succeeded webhook against localhost:3000. Pin the signing secret your
|
|
138
|
+
# local handler verifies with (the same value in its .env), or copy the one each run prints.
|
|
139
|
+
export VONPAY_CLI_SIGNING_SECRET=whsec_your_local_dev_secret
|
|
126
140
|
vonpay checkout trigger session.succeeded --url http://localhost:3000/webhooks/vonpay
|
|
127
141
|
# --url must be this machine; to go through a tunnel (ngrok, Cloudflare Tunnel), add --url-tunnel
|
|
128
142
|
vonpay checkout trigger session.succeeded --url https://abc123.ngrok.app/webhooks/vonpay --url-tunnel
|