@vonpay/checkout-cli 0.4.0 → 0.4.1
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 +1 -1
- package/dist/commands/trigger.d.ts.map +1 -1
- package/dist/commands/trigger.js +11 -6
- package/dist/commands/trigger.js.map +1 -1
- package/dist/utils/listen-forward.d.ts +13 -7
- package/dist/utils/listen-forward.d.ts.map +1 -1
- package/dist/utils/listen-forward.js +21 -14
- package/dist/utils/listen-forward.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -43,7 +43,7 @@ All commands are namespaced under `vonpay checkout`:
|
|
|
43
43
|
|
|
44
44
|
Run `vonpay checkout <command> --help` for full flag reference.
|
|
45
45
|
|
|
46
|
-
> **`listen --forward-to` signs forwarded events with the v1 scheme**
|
|
46
|
+
> **`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)`. For this local forward loop the signing secret is your API key; production deliveries are keyed by your per-endpoint signing secret (`whsec_…`). This is a known limitation of local forwarding — the platform exposes no per-subscription signing secret on the listen stream, so the forwarder cannot reproduce the production secret.
|
|
47
47
|
|
|
48
48
|
### Common flags
|
|
49
49
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trigger.d.ts","sourceRoot":"","sources":["../../src/commands/trigger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,eAAO,MAAM,gBAAgB,qJAOnB,CAAC;AACX,KAAK,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAWxD,UAAU,cAAc;IACtB,KAAK,EAAE,cAAc,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,YAAY,CAC1B,KAAK,EAAE,cAAc,EACrB,IAAI,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/D,cAAc,CA4BhB;AAED,wBAAgB,cAAc,IAAI,OAAO,
|
|
1
|
+
{"version":3,"file":"trigger.d.ts","sourceRoot":"","sources":["../../src/commands/trigger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,eAAO,MAAM,gBAAgB,qJAOnB,CAAC;AACX,KAAK,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAWxD,UAAU,cAAc;IACtB,KAAK,EAAE,cAAc,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,YAAY,CAC1B,KAAK,EAAE,cAAc,EACrB,IAAI,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/D,cAAc,CA4BhB;AAED,wBAAgB,cAAc,IAAI,OAAO,CA+ExC"}
|
package/dist/commands/trigger.js
CHANGED
|
@@ -63,18 +63,23 @@ export function triggerCommand() {
|
|
|
63
63
|
const apiKey = requireApiKey();
|
|
64
64
|
const payload = buildPayload(event, opts);
|
|
65
65
|
const body = JSON.stringify(payload);
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
// v1 webhook signature contract: ONE `x-vonpay-signature` header of
|
|
67
|
+
// shape `t=<unix-seconds>,v1=<hex>`, HMAC-SHA256 over `${t}.${body}`.
|
|
68
|
+
// There is no separate timestamp header. For this local trigger the
|
|
69
|
+
// signing secret is your API key (verify with
|
|
70
|
+
// `constructEvent(rawBody, signatureHeader, apiKey)`).
|
|
71
|
+
const t = Math.floor(Date.now() / 1000);
|
|
72
|
+
const v1 = createHmac("sha256", apiKey)
|
|
73
|
+
.update(`${t}.${body}`)
|
|
68
74
|
.digest("hex");
|
|
69
|
-
const
|
|
75
|
+
const signatureHeader = `t=${t},v1=${v1}`;
|
|
70
76
|
const spinner = ora(`Sending ${event} to ${opts.url}...`).start();
|
|
71
77
|
try {
|
|
72
78
|
const response = await fetch(opts.url, {
|
|
73
79
|
method: "POST",
|
|
74
80
|
headers: {
|
|
75
81
|
"Content-Type": "application/json",
|
|
76
|
-
"
|
|
77
|
-
"X-VonPay-Timestamp": timestamp,
|
|
82
|
+
"x-vonpay-signature": signatureHeader,
|
|
78
83
|
"User-Agent": "VonPay-Webhook/1.0 (CLI trigger)",
|
|
79
84
|
},
|
|
80
85
|
body,
|
|
@@ -89,7 +94,7 @@ export function triggerCommand() {
|
|
|
89
94
|
}
|
|
90
95
|
console.log(chalk.dim(` Session: ${payload.sessionId}`));
|
|
91
96
|
console.log(chalk.dim(` Amount: ${payload.amount} ${payload.currency}`));
|
|
92
|
-
console.log(chalk.dim(`\n Verify with: vonpay.webhooks.constructEvent(rawBody,
|
|
97
|
+
console.log(chalk.dim(`\n Verify with: vonpay.webhooks.constructEvent(rawBody, signatureHeader, apiKey)`));
|
|
93
98
|
}
|
|
94
99
|
catch (err) {
|
|
95
100
|
spinner.stop();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trigger.js","sourceRoot":"","sources":["../../src/commands/trigger.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"trigger.js","sourceRoot":"","sources":["../../src/commands/trigger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,mBAAmB;IACnB,gBAAgB;IAChB,0BAA0B;IAC1B,uBAAuB;IACvB,0BAA0B;IAC1B,gBAAgB;CACR,CAAC;AAGX,MAAM,eAAe,GAAmC;IACtD,mBAAmB,EAAE,WAAW;IAChC,gBAAgB,EAAE,QAAQ;IAC1B,0BAA0B,EAAE,WAAW;IACvC,uBAAuB,EAAE,QAAQ;IACjC,0BAA0B,EAAE,WAAW;IACvC,gBAAgB,EAAE,SAAS;CAC5B,CAAC;AAeF,MAAM,UAAU,YAAY,CAC1B,KAAqB,EACrB,IAAgE;IAEhE,MAAM,eAAe,GAAG,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;IAC5D,MAAM,QAAQ,GAAG,KAAK,KAAK,gBAAgB,CAAC;IAC5C,oEAAoE;IACpE,mDAAmD;IACnD,MAAM,cAAc,GAClB,KAAK,KAAK,mBAAmB;QAC7B,KAAK,KAAK,0BAA0B;QACpC,QAAQ,CAAC;IACX,MAAM,OAAO,GAAmB;QAC9B,KAAK;QACL,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,gBAAgB,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;QACvE,UAAU,EAAE,iBAAiB,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;QACvD,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,IAAI;QAC3B,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,KAAK;QAChC,MAAM,EAAE,eAAe,CAAC,KAAK,CAAC;QAC9B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC;IACF,IAAI,cAAc,EAAE,CAAC;QACnB,OAAO,CAAC,aAAa,GAAG,YAAY,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;IACjE,CAAC;IACD,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,CAAC,QAAQ,GAAG,WAAW,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;IAC3D,CAAC;IACD,IAAI,eAAe,EAAE,CAAC;QACpB,OAAO,CAAC,eAAe,GAAG,YAAY,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;IACnE,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,IAAI,OAAO,CAAC,SAAS,CAAC;SAC1B,WAAW,CAAC,0CAA0C,CAAC;SACvD,QAAQ,CAAC,SAAS,EAAE,eAAe,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;SAClE,cAAc,CAAC,aAAa,EAAE,yDAAyD,CAAC;SACxF,MAAM,CAAC,mBAAmB,EAAE,mBAAmB,CAAC;SAChD,MAAM,CAAC,kBAAkB,EAAE,uBAAuB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;SAC3E,MAAM,CAAC,mBAAmB,EAAE,eAAe,CAAC;SAC5C,MAAM,CAAC,KAAK,EAAE,KAAa,EAAE,IAAI,EAAE,EAAE;QACpC,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,KAAuB,CAAC,EAAE,CAAC;YACxD,OAAO,CAAC,KAAK,CACX,KAAK,CAAC,GAAG,CACP,kBAAkB,KAAK,gBAAgB,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACrE,CACF,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,YAAY,CAAC,KAAuB,EAAE,IAAI,CAAC,CAAC;QAC5D,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACrC,oEAAoE;QACpE,sEAAsE;QACtE,oEAAoE;QACpE,8CAA8C;QAC9C,uDAAuD;QACvD,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QACxC,MAAM,EAAE,GAAG,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC;aACpC,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;aACtB,MAAM,CAAC,KAAK,CAAC,CAAC;QACjB,MAAM,eAAe,GAAG,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;QAE1C,MAAM,OAAO,GAAG,GAAG,CAAC,WAAW,KAAK,OAAO,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC;QAElE,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE;gBACrC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,oBAAoB,EAAE,eAAe;oBACrC,YAAY,EAAE,kCAAkC;iBACjD;gBACD,IAAI;gBACJ,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;aACpC,CAAC,CAAC;YAEH,OAAO,CAAC,IAAI,EAAE,CAAC;YAEf,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;gBAChB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,KAAK,gBAAgB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACxE,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,MAAM,CACV,KAAK,KAAK,sBAAsB,QAAQ,CAAC,MAAM,WAAW,CAC3D,CACF,CAAC;YACJ,CAAC;YAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;YAC1D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;YAC3E,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,GAAG,CACP,mFAAmF,CACpF,CACF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,EAAE,CAAC;YACf,IAAI,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;gBACxD,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,IAAI,CAAC,GAAG,6BAA6B,CAAC,CAAC,CAAC;YAC9E,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CACX,KAAK,CAAC,GAAG,CACP,sBAAsB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CACjE,CACF,CAAC;YACJ,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -8,12 +8,14 @@ import type { ForwardOutcome } from "./listen-output.js";
|
|
|
8
8
|
*
|
|
9
9
|
* 1. Fetches the full event record via GET /v1/webhook_events/:id
|
|
10
10
|
* (the public webhook-event read endpoint)
|
|
11
|
-
* 2.
|
|
12
|
-
*
|
|
13
|
-
* `
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
11
|
+
* 2. Signs it with the v1 webhook contract — a single
|
|
12
|
+
* `x-vonpay-signature: t=<unix-seconds>,v1=<hex>` header whose
|
|
13
|
+
* HMAC-SHA256 is computed over `${t}.${body}` (the same shape the
|
|
14
|
+
* SDK's `webhooks.constructEvent` verifies). For this local dev loop
|
|
15
|
+
* the signing secret is your API key, so verify with
|
|
16
|
+
* `webhooks.constructEvent(rawBody, signatureHeader, yourApiKey)`.
|
|
17
|
+
* 3. POSTs to the local URL with that single header, matching the live
|
|
18
|
+
* delivery shape. The `t` is stamped HERE, at forward time — see the
|
|
17
19
|
* `forwardPayload` body for the fresh-timestamp rationale.
|
|
18
20
|
*
|
|
19
21
|
* Bounded by a per-forward timeout (default 5s) and never retries —
|
|
@@ -26,7 +28,11 @@ import type { ForwardOutcome } from "./listen-output.js";
|
|
|
26
28
|
interface ForwardOptions {
|
|
27
29
|
/** Local URL to POST the payload to. */
|
|
28
30
|
url: URL;
|
|
29
|
-
/**
|
|
31
|
+
/** Secret used to key the v1 HMAC. The listen stream exposes no
|
|
32
|
+
* per-endpoint signing secret, so for this local forward loop the API
|
|
33
|
+
* key (vp_sk_*) is used as a stand-in — verify the forwarded delivery
|
|
34
|
+
* with `constructEvent(rawBody, signatureHeader, sameKey)`. Production
|
|
35
|
+
* deliveries are keyed by the per-endpoint signing secret (whsec_…). */
|
|
30
36
|
signingSecret: string;
|
|
31
37
|
/** Per-forward timeout. Default 5_000. */
|
|
32
38
|
timeoutMs?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listen-forward.d.ts","sourceRoot":"","sources":["../../src/utils/listen-forward.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD
|
|
1
|
+
{"version":3,"file":"listen-forward.d.ts","sourceRoot":"","sources":["../../src/utils/listen-forward.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,UAAU,cAAc;IACtB,wCAAwC;IACxC,GAAG,EAAE,GAAG,CAAC;IACT;;;;6EAIyE;IACzE,aAAa,EAAE,MAAM,CAAC;IACtB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,MAAM,EAAE,WAAW,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,cAAc,CAAC,CAsEzB"}
|
|
@@ -6,21 +6,29 @@ import { createHmac } from "node:crypto";
|
|
|
6
6
|
*/
|
|
7
7
|
export async function forwardPayload(payload, opts) {
|
|
8
8
|
const body = JSON.stringify(payload);
|
|
9
|
-
// Stamp the moment we forward — NOT the server's original
|
|
9
|
+
// Stamp `t` at the moment we forward — NOT the server's original
|
|
10
10
|
// delivery-attempt time. The CLI is the *re-sender* for this local
|
|
11
11
|
// delivery: the dev's handler calls `webhooks.constructEvent`, which
|
|
12
|
-
// rejects any `
|
|
13
|
-
// original timestamp (carried on the SSE
|
|
14
|
-
// routinely minutes old — retries,
|
|
15
|
-
// dev scrolled back through — so
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
12
|
+
// rejects any `t` outside the freshness window (>5 min old / >30 sec
|
|
13
|
+
// future). The server's original timestamp (carried on the SSE
|
|
14
|
+
// `webhook.attempt` frame) is routinely minutes old — retries,
|
|
15
|
+
// processing lag, a transcript the dev scrolled back through — so
|
|
16
|
+
// replaying it would trip the window. A fresh `t` here matches Stripe
|
|
17
|
+
// CLI's re-sign posture. Unlike the old bare-hex shape, `t` IS folded
|
|
18
|
+
// into the HMAC per the v1 contract (`${t}.${body}`).
|
|
19
|
+
const t = Math.floor(Date.now() / 1000);
|
|
20
|
+
// v1 signature contract (vonpay-checkout/docs/webhook-signature-v1.md):
|
|
21
|
+
// ONE header `x-vonpay-signature: t=<unix-seconds>,v1=<hex>`, HMAC-SHA256
|
|
22
|
+
// over `${t}.${body}`. There is NO separate timestamp header. Rotation
|
|
23
|
+
// (multiple `v1=` entries) does not apply to this synthetic local loop —
|
|
24
|
+
// we sign with a single secret (the API key). When the server ships a
|
|
25
|
+
// per-subscription signing secret on the SSE `webhook.attempt` frame,
|
|
26
|
+
// sign with that here instead of the API key. (The 0.0.0.0 loopback
|
|
27
|
+
// warning already shipped in forward-to.ts.)
|
|
28
|
+
const v1 = createHmac("sha256", opts.signingSecret)
|
|
29
|
+
.update(`${t}.${body}`)
|
|
23
30
|
.digest("hex");
|
|
31
|
+
const signatureHeader = `t=${t},v1=${v1}`;
|
|
24
32
|
const timeoutMs = opts.timeoutMs ?? 5_000;
|
|
25
33
|
const localController = new AbortController();
|
|
26
34
|
const timeoutId = setTimeout(() => localController.abort(), timeoutMs);
|
|
@@ -31,8 +39,7 @@ export async function forwardPayload(payload, opts) {
|
|
|
31
39
|
method: "POST",
|
|
32
40
|
headers: {
|
|
33
41
|
"Content-Type": "application/json",
|
|
34
|
-
"
|
|
35
|
-
"X-VonPay-Timestamp": timestamp,
|
|
42
|
+
"x-vonpay-signature": signatureHeader,
|
|
36
43
|
"User-Agent": "vonpay-cli-listen",
|
|
37
44
|
},
|
|
38
45
|
body,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listen-forward.js","sourceRoot":"","sources":["../../src/utils/listen-forward.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"listen-forward.js","sourceRoot":"","sources":["../../src/utils/listen-forward.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vonpay/checkout-cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Von Payments CLI — developer tools for checkout integration",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"commander": "^13.0.0",
|
|
19
19
|
"chalk": "^5.4.0",
|
|
20
20
|
"ora": "^8.2.0",
|
|
21
|
-
"@vonpay/checkout-node": "0.9.
|
|
21
|
+
"@vonpay/checkout-node": "0.9.1"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"typescript": "^5.7.0",
|