@siglume/direct-request-payment 0.4.2 → 0.4.4
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/CHANGELOG.md +33 -0
- package/README.md +34 -10
- package/dist/index.cjs +120 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +142 -1
- package/dist/index.d.ts +142 -1
- package/dist/index.js +120 -6
- package/dist/index.js.map +1 -1
- package/docs/announcement-ja.md +12 -12
- package/docs/api-reference.md +236 -11
- package/docs/merchant-quickstart.md +65 -7
- package/docs/metered-statements.md +433 -0
- package/docs/pricing.md +87 -27
- package/docs/security.md +44 -8
- package/examples/express-checkout.ts +12 -30
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.4 - 2026-06-19
|
|
4
|
+
|
|
5
|
+
Correctness and security hardening release for the SDRP Direct Request Payment
|
|
6
|
+
SDK manual and public helpers.
|
|
7
|
+
|
|
8
|
+
- Clarified that Standard / Micro / Nano are selected by amount, removed the
|
|
9
|
+
unsupported "force Standard for immediate finality" implication, and changed
|
|
10
|
+
Hosted Checkout Standard examples to Standard-band amounts.
|
|
11
|
+
- Removed the Express sample route that accepted a buyer `Authorization` header
|
|
12
|
+
on the merchant server; human web checkout now redirects through Hosted
|
|
13
|
+
Checkout, while agent payment remains buyer-side direct API/tool work.
|
|
14
|
+
- Documented Micro / Nano decimal fee rounding, `rounding_delta_minor`, budget
|
|
15
|
+
reservation versus token locking, no guaranteed `past_due` collection, HTTP
|
|
16
|
+
result accounting, and operational status handling.
|
|
17
|
+
- Added typed TypeScript and named Python helpers for Micro / Nano statement
|
|
18
|
+
APIs.
|
|
19
|
+
- Added `request_hash_v2` helpers/docs and documented the new
|
|
20
|
+
requirement/webhook machine fields for pricing band, settlement cadence,
|
|
21
|
+
finality, protocol fee, and settlement status.
|
|
22
|
+
- Hardened TS/Python integer and `checkout_allowed_origins` validation.
|
|
23
|
+
|
|
24
|
+
## 0.4.3 - 2026-06-19
|
|
25
|
+
|
|
26
|
+
Documentation-only release for SDRP Micro / Nano operations.
|
|
27
|
+
|
|
28
|
+
- Added the Micro / Nano Statements and Notices manual, covering buyer and
|
|
29
|
+
provider statement APIs, CSV export, final debit notices, the close-plus-3-day
|
|
30
|
+
debit site, past-due blocks, sanitized failure fields, and support references.
|
|
31
|
+
- Expanded API reference, merchant quickstart, security, pricing, and Japanese
|
|
32
|
+
announcement docs so integrators can reconcile settled, unsettled, retrying,
|
|
33
|
+
and past-due Micro / Nano revenue without relying on private platform fields.
|
|
34
|
+
- No wire-format or runtime behavior changes.
|
|
35
|
+
|
|
3
36
|
## 0.4.2 - 2026-06-19
|
|
4
37
|
|
|
5
38
|
Documentation completeness release. No wire-format or API changes; 0.4.x clients
|
package/README.md
CHANGED
|
@@ -89,7 +89,7 @@ await merchant.setupMerchant({
|
|
|
89
89
|
// 2. Per order: create a session and redirect the shopper to checkout_url.
|
|
90
90
|
const session = await merchant.createCheckoutSession({
|
|
91
91
|
merchant: "your_merchant_key",
|
|
92
|
-
amount_minor:
|
|
92
|
+
amount_minor: 1200, // server-fixed; the browser cannot change it
|
|
93
93
|
currency: "JPY",
|
|
94
94
|
nonce: order.id, // unique per order
|
|
95
95
|
success_url: "https://www.your-shop.com/thanks",
|
|
@@ -121,7 +121,7 @@ merchant.setup_merchant(
|
|
|
121
121
|
# 2. Per order: create a session and redirect the shopper to checkout_url.
|
|
122
122
|
session = merchant.create_checkout_session(
|
|
123
123
|
merchant="your_merchant_key",
|
|
124
|
-
amount_minor=
|
|
124
|
+
amount_minor=1200, # server-fixed; the browser cannot change it
|
|
125
125
|
currency="JPY",
|
|
126
126
|
nonce=order["id"], # unique per order
|
|
127
127
|
success_url="https://www.your-shop.com/thanks",
|
|
@@ -183,6 +183,14 @@ Provider revenue in the Micro and Nano bands is not settled revenue until the
|
|
|
183
183
|
weekly or monthly on-chain settlement succeeds. Siglume keeps outstanding failed
|
|
184
184
|
settlements for retry under the published policy, but does not advance or
|
|
185
185
|
guarantee provider revenue before settlement succeeds.
|
|
186
|
+
Micro / Nano budget checks reserve spending capacity only; they do not lock,
|
|
187
|
+
escrow, or guarantee the buyer's wallet balance, allowance, or settlement funds.
|
|
188
|
+
Sub-minor-unit Nano fees are accumulated with decimal precision and rounded only
|
|
189
|
+
when a settlement batch is created; see [Pricing](./docs/pricing.md) for the
|
|
190
|
+
rounding formula and `rounding_delta_minor` semantics.
|
|
191
|
+
For operational reconciliation, expected revenue, settled revenue, retry state,
|
|
192
|
+
and CSV exports, see
|
|
193
|
+
[docs/metered-statements.md](./docs/metered-statements.md).
|
|
186
194
|
|
|
187
195
|
## What This SDK Covers
|
|
188
196
|
|
|
@@ -194,6 +202,7 @@ guarantee provider revenue before settlement succeeds.
|
|
|
194
202
|
- buyer-authenticated payment requirement creation
|
|
195
203
|
- prepared wallet transaction execution payloads
|
|
196
204
|
- payment requirement verification
|
|
205
|
+
- authenticated TypeScript JSON requests to Micro / Nano statement APIs
|
|
197
206
|
- signed webhook verification
|
|
198
207
|
|
|
199
208
|
It does not custody funds or manage customer wallets. Merchant setup runs through
|
|
@@ -226,15 +235,23 @@ amounts differ.
|
|
|
226
235
|
|
|
227
236
|
| Payment amount | Applied automatically | What you select | Fee | Settlement |
|
|
228
237
|
| --- | --- | --- | --- | --- |
|
|
229
|
-
| Over JPY 500 / over USD 3.00
|
|
230
|
-
| JPY 50-500 /
|
|
231
|
-
| Under JPY
|
|
238
|
+
| Over JPY 500 / over USD 3.00 | Standard Payment | Select one Standard plan: Launch, Starter, Growth, or Pro | Launch: JPY 0 / USD 0 monthly, 1.8%; Starter: JPY 980 / USD 6 monthly, 1.0%; Growth: JPY 2,980 / USD 18 monthly, 0.7%; Pro: JPY 9,800 / USD 60 monthly, 0.5%. Minimum JPY 30 / USD 0.20 per payment. | Settled on-chain immediately after the payment confirms |
|
|
239
|
+
| JPY 50-500 / over USD 0.30 and up to USD 3.00 | Micro Payment | Applied automatically by amount | USD 0.01 / Tx, about JPY 2 | Weekly settlement - see [Settlement schedule](./docs/pricing.md#settlement-schedule) |
|
|
240
|
+
| Under JPY 50 / up to USD 0.30 | Nano Payment | Applied automatically by amount | USD 0.001 / usage, about JPY 0.2 | Monthly settlement - see [Settlement schedule](./docs/pricing.md#settlement-schedule) |
|
|
232
241
|
|
|
233
242
|
A merchant billing mandate is required before accepting payments, even on the
|
|
234
|
-
Launch plan.
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
243
|
+
Launch plan. The current public API does not expose a flag that forces a
|
|
244
|
+
JPY 500-and-under / USD 3-and-under payment into Standard immediate settlement.
|
|
245
|
+
If immediate on-chain settlement is a hard requirement, price the item in the
|
|
246
|
+
Standard band or confirm a merchant-specific contract with Siglume before
|
|
247
|
+
launch. For Standard Payment, `fee_bps` returned on a payment requirement is the
|
|
248
|
+
authoritative fee rate for that payment in the merchant's settlement currency.
|
|
249
|
+
For Micro / Nano, the statement APIs expose `protocol_fee_minor`,
|
|
250
|
+
`gross_buyer_debit_minor`, `buyer_debit_minor`, and `rounding_delta_minor`.
|
|
251
|
+
The full fee table and the weekly / monthly settlement schedule live in
|
|
252
|
+
[docs/pricing.md](./docs/pricing.md). Statement APIs for "how much was used,
|
|
253
|
+
when will it close, when can it debit, and what is settled" are documented in
|
|
254
|
+
[docs/metered-statements.md](./docs/metered-statements.md).
|
|
238
255
|
|
|
239
256
|
## Merchant Setup: One SDK Call
|
|
240
257
|
|
|
@@ -510,6 +527,11 @@ if verified["event"]["type"] == "direct_payment.confirmed":
|
|
|
510
527
|
pass
|
|
511
528
|
```
|
|
512
529
|
|
|
530
|
+
New `direct_payment.confirmed` payloads include `pricing_band`,
|
|
531
|
+
`settlement_cadence`, `finality`, `protocol_fee_minor`, `settlement_status`, and
|
|
532
|
+
when available `request_hash_v2`. Use these machine fields instead of inferring
|
|
533
|
+
settlement semantics from the event name alone.
|
|
534
|
+
|
|
513
535
|
## Security Rules
|
|
514
536
|
|
|
515
537
|
- Keep the challenge secret on the merchant server only.
|
|
@@ -532,7 +554,8 @@ Read [docs/security.md](./docs/security.md) before going live.
|
|
|
532
554
|
- Store the returned `SIGLUME_WEBHOOK_SECRET` only on the merchant server.
|
|
533
555
|
- Persist `challenge_hash`, `requirement_id`, and fulfillment state per order.
|
|
534
556
|
- Fulfill orders only from verified webhook data, with idempotency.
|
|
535
|
-
- Treat `fee_bps` returned by Siglume as the runtime fee source
|
|
557
|
+
- Treat `fee_bps` returned by Siglume as the Standard Payment runtime fee source
|
|
558
|
+
of truth; use statement API amount fields for Micro / Nano.
|
|
536
559
|
|
|
537
560
|
## Compatibility Notes
|
|
538
561
|
|
|
@@ -549,6 +572,7 @@ Read [docs/security.md](./docs/security.md) before going live.
|
|
|
549
572
|
- [Merchant quickstart](./docs/merchant-quickstart.md)
|
|
550
573
|
- [API reference](./docs/api-reference.md)
|
|
551
574
|
- [Pricing](./docs/pricing.md)
|
|
575
|
+
- [Micro / Nano statements and notices](./docs/metered-statements.md)
|
|
552
576
|
- [Security guide](./docs/security.md)
|
|
553
577
|
- [Merchant setup example](./examples/setup-merchant.ts)
|
|
554
578
|
- [Express checkout example](./examples/express-checkout.ts)
|
package/dist/index.cjs
CHANGED
|
@@ -38,6 +38,7 @@ __export(src_exports, {
|
|
|
38
38
|
DIRECT_REQUEST_PAYMENT_RECEIPT_KIND: () => DIRECT_REQUEST_PAYMENT_RECEIPT_KIND,
|
|
39
39
|
DIRECT_REQUEST_PAYMENT_RECURRING_CHALLENGE_SCHEME: () => DIRECT_REQUEST_PAYMENT_RECURRING_CHALLENGE_SCHEME,
|
|
40
40
|
DIRECT_REQUEST_PAYMENT_REFERENCE_TYPE: () => DIRECT_REQUEST_PAYMENT_REFERENCE_TYPE,
|
|
41
|
+
DIRECT_REQUEST_PAYMENT_SDK_VERSION: () => DIRECT_REQUEST_PAYMENT_SDK_VERSION,
|
|
41
42
|
DirectRequestPaymentClient: () => DirectRequestPaymentClient,
|
|
42
43
|
DirectRequestPaymentMerchantClient: () => DirectRequestPaymentMerchantClient,
|
|
43
44
|
HostedCheckoutNotAvailableError: () => HostedCheckoutNotAvailableError,
|
|
@@ -58,6 +59,7 @@ __export(src_exports, {
|
|
|
58
59
|
createExternal402RecurringChallenge: () => createExternal402RecurringChallenge,
|
|
59
60
|
directRequestPaymentChallengeHash: () => directRequestPaymentChallengeHash,
|
|
60
61
|
directRequestPaymentRequestHash: () => directRequestPaymentRequestHash,
|
|
62
|
+
directRequestPaymentRequestHashV2: () => directRequestPaymentRequestHashV2,
|
|
61
63
|
parseDirectRequestPaymentChallenge: () => parseDirectRequestPaymentChallenge,
|
|
62
64
|
parseDirectRequestPaymentWebhookEvent: () => parseDirectRequestPaymentWebhookEvent,
|
|
63
65
|
verifyDirectRequestPaymentChallenge: () => verifyDirectRequestPaymentChallenge,
|
|
@@ -76,6 +78,8 @@ var DIRECT_REQUEST_PAYMENT_RECEIPT_KIND = "sdrp_direct_payment";
|
|
|
76
78
|
var DIRECT_REQUEST_PAYMENT_ALLOWANCE_RECEIPT_KIND = "sdrp_direct_payment_allowance";
|
|
77
79
|
var DIRECT_REQUEST_PAYMENT_REFERENCE_TYPE = "sdrp_direct_payment_requirement";
|
|
78
80
|
var DEFAULT_WEBHOOK_TOLERANCE_SECONDS = 300;
|
|
81
|
+
var DIRECT_REQUEST_PAYMENT_SDK_VERSION = "0.4.4";
|
|
82
|
+
var DIRECT_REQUEST_PAYMENT_CONFIRMED_WEBHOOK_MODES = /* @__PURE__ */ new Set([DIRECT_REQUEST_PAYMENT_MODE, "metered_settlement_batch"]);
|
|
79
83
|
var SiglumeDirectRequestPaymentError = class extends Error {
|
|
80
84
|
constructor(message) {
|
|
81
85
|
super(message);
|
|
@@ -132,7 +136,7 @@ var DirectRequestPaymentClient = class {
|
|
|
132
136
|
this.auth_token = authToken;
|
|
133
137
|
this.base_url = (options.base_url ?? envValue("SIGLUME_API_BASE") ?? DEFAULT_SIGLUME_API_BASE).replace(/\/+$/, "");
|
|
134
138
|
this.timeout_ms = Math.max(1, Math.trunc(options.timeout_ms ?? 15e3));
|
|
135
|
-
this.user_agent = options.user_agent ??
|
|
139
|
+
this.user_agent = options.user_agent ?? `@siglume/direct-request-payment/${DIRECT_REQUEST_PAYMENT_SDK_VERSION}`;
|
|
136
140
|
this.fetch_impl = fetchImpl;
|
|
137
141
|
}
|
|
138
142
|
async createPaymentRequirement(input) {
|
|
@@ -180,6 +184,53 @@ var DirectRequestPaymentClient = class {
|
|
|
180
184
|
async executeAllowanceTransaction(requirement, options = {}) {
|
|
181
185
|
return this.executePreparedTransaction(buildAllowanceExecutionPayload(requirement, options));
|
|
182
186
|
}
|
|
187
|
+
async getBuyerMeteredSummary(input = {}) {
|
|
188
|
+
return this.request(
|
|
189
|
+
"GET",
|
|
190
|
+
meteredQueryPath("/sdrp/metered/my-summary", input)
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
async listBuyerUsageEvents(input = {}) {
|
|
194
|
+
return this.request(
|
|
195
|
+
"GET",
|
|
196
|
+
meteredQueryPath("/sdrp/metered/my-usage-events", input)
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
async listBuyerSettlementBatches(input = {}) {
|
|
200
|
+
return this.request(
|
|
201
|
+
"GET",
|
|
202
|
+
meteredQueryPath("/sdrp/metered/my-settlement-batches", input)
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
async getProviderMeteredSummary(input = {}) {
|
|
206
|
+
return this.request(
|
|
207
|
+
"GET",
|
|
208
|
+
meteredQueryPath("/sdrp/metered/provider/summary", input)
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
async listProviderUsageEvents(input = {}) {
|
|
212
|
+
return this.request(
|
|
213
|
+
"GET",
|
|
214
|
+
meteredQueryPath("/sdrp/metered/provider/usage-events", input)
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
async listProviderSettlementBatches(input = {}) {
|
|
218
|
+
return this.request(
|
|
219
|
+
"GET",
|
|
220
|
+
meteredQueryPath("/sdrp/metered/provider/settlement-batches", input)
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
async getProviderSettlementBatch(settlement_batch_id, input = {}) {
|
|
224
|
+
return this.request(
|
|
225
|
+
"GET",
|
|
226
|
+
meteredQueryPath(
|
|
227
|
+
`/sdrp/metered/provider/settlement-batches/${encodeURIComponent(
|
|
228
|
+
requireNonEmpty(settlement_batch_id, "settlement_batch_id")
|
|
229
|
+
)}`,
|
|
230
|
+
input
|
|
231
|
+
)
|
|
232
|
+
);
|
|
233
|
+
}
|
|
183
234
|
async request(method, path, json_body) {
|
|
184
235
|
const controller = new AbortController();
|
|
185
236
|
const timeout = setTimeout(() => controller.abort(), this.timeout_ms);
|
|
@@ -237,7 +288,7 @@ var DirectRequestPaymentMerchantClient = class {
|
|
|
237
288
|
this.auth_token = authToken;
|
|
238
289
|
this.base_url = (options.base_url ?? envValue("SIGLUME_API_BASE") ?? DEFAULT_SIGLUME_API_BASE).replace(/\/+$/, "");
|
|
239
290
|
this.timeout_ms = Math.max(1, Math.trunc(options.timeout_ms ?? 15e3));
|
|
240
|
-
this.user_agent = options.user_agent ??
|
|
291
|
+
this.user_agent = options.user_agent ?? `@siglume/direct-request-payment/${DIRECT_REQUEST_PAYMENT_SDK_VERSION}`;
|
|
241
292
|
this.fetch_impl = fetchImpl;
|
|
242
293
|
}
|
|
243
294
|
async setupMerchant(input) {
|
|
@@ -530,6 +581,16 @@ async function directRequestPaymentRequestHash(input) {
|
|
|
530
581
|
const material = `${normalizeMerchant(input.merchant)}${positiveInteger(input.amount_minor, "amount_minor")}${normalizeCurrency(input.currency)}${requireNonEmpty(input.challenge, "challenge")}`;
|
|
531
582
|
return sha256Prefixed(material);
|
|
532
583
|
}
|
|
584
|
+
async function directRequestPaymentRequestHashV2(input) {
|
|
585
|
+
const material = JSON.stringify({
|
|
586
|
+
amount_minor: positiveInteger(input.amount_minor, "amount_minor"),
|
|
587
|
+
challenge: requireNonEmpty(input.challenge, "challenge"),
|
|
588
|
+
currency: normalizeCurrency(input.currency),
|
|
589
|
+
merchant: normalizeMerchant(input.merchant),
|
|
590
|
+
version: 2
|
|
591
|
+
});
|
|
592
|
+
return sha256Prefixed(material);
|
|
593
|
+
}
|
|
533
594
|
function buildPaymentExecutionPayload(requirement, options = {}) {
|
|
534
595
|
return buildPreparedTransactionExecutionPayload(requirement, requirement.transaction_request, {
|
|
535
596
|
receipt_kind: DIRECT_REQUEST_PAYMENT_RECEIPT_KIND,
|
|
@@ -603,8 +664,10 @@ function parseDirectRequestPaymentWebhookEvent(payload) {
|
|
|
603
664
|
occurred_at: requireNonEmpty(stringOrNull(event.occurred_at) ?? "", "webhook occurred_at"),
|
|
604
665
|
data: { ...data }
|
|
605
666
|
};
|
|
606
|
-
if (parsed.type === "direct_payment.confirmed" && parsed.data.mode
|
|
607
|
-
throw new SiglumeWebhookPayloadError(
|
|
667
|
+
if (parsed.type === "direct_payment.confirmed" && !DIRECT_REQUEST_PAYMENT_CONFIRMED_WEBHOOK_MODES.has(String(parsed.data.mode ?? ""))) {
|
|
668
|
+
throw new SiglumeWebhookPayloadError(
|
|
669
|
+
"direct_payment.confirmed webhook must carry a supported Direct Request Payment mode."
|
|
670
|
+
);
|
|
608
671
|
}
|
|
609
672
|
return parsed;
|
|
610
673
|
}
|
|
@@ -658,6 +721,13 @@ function normalizeToken(value) {
|
|
|
658
721
|
}
|
|
659
722
|
return token;
|
|
660
723
|
}
|
|
724
|
+
function normalizeMeteredPlanType(value) {
|
|
725
|
+
const planType = requireNonEmpty(value, "plan_type").toLowerCase();
|
|
726
|
+
if (planType === "micro" || planType === "nano") {
|
|
727
|
+
return planType;
|
|
728
|
+
}
|
|
729
|
+
throw new SiglumeDirectRequestPaymentError("plan_type must be micro or nano.");
|
|
730
|
+
}
|
|
661
731
|
function normalizeAllowedCurrencies(value) {
|
|
662
732
|
const normalized = {};
|
|
663
733
|
if (Array.isArray(value)) {
|
|
@@ -695,7 +765,15 @@ function normalizeOriginList(value) {
|
|
|
695
765
|
"each checkout_allowed_origins entry must be an absolute origin such as https://shop.example.com."
|
|
696
766
|
);
|
|
697
767
|
}
|
|
698
|
-
|
|
768
|
+
if (url.username || url.password) {
|
|
769
|
+
throw new SiglumeDirectRequestPaymentError("checkout_allowed_origins entries must not include userinfo.");
|
|
770
|
+
}
|
|
771
|
+
if (!isAllowedCheckoutOriginScheme(url)) {
|
|
772
|
+
throw new SiglumeDirectRequestPaymentError(
|
|
773
|
+
"checkout_allowed_origins entries must use https, except http is allowed for localhost, 127.0.0.1, or [::1]."
|
|
774
|
+
);
|
|
775
|
+
}
|
|
776
|
+
const origin = url.origin.toLowerCase();
|
|
699
777
|
if (!seen.has(origin)) {
|
|
700
778
|
seen.add(origin);
|
|
701
779
|
origins.push(origin);
|
|
@@ -703,8 +781,44 @@ function normalizeOriginList(value) {
|
|
|
703
781
|
}
|
|
704
782
|
return origins;
|
|
705
783
|
}
|
|
784
|
+
function isAllowedCheckoutOriginScheme(url) {
|
|
785
|
+
if (url.protocol === "https:") {
|
|
786
|
+
return Boolean(url.hostname);
|
|
787
|
+
}
|
|
788
|
+
if (url.protocol !== "http:") {
|
|
789
|
+
return false;
|
|
790
|
+
}
|
|
791
|
+
const hostname = url.hostname.toLowerCase();
|
|
792
|
+
return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "[::1]" || hostname === "::1";
|
|
793
|
+
}
|
|
794
|
+
function meteredQueryPath(path, input) {
|
|
795
|
+
const params = new URLSearchParams();
|
|
796
|
+
if (input.plan_type !== void 0) {
|
|
797
|
+
params.set("plan_type", normalizeMeteredPlanType(input.plan_type));
|
|
798
|
+
}
|
|
799
|
+
if (input.token_symbol !== void 0) {
|
|
800
|
+
params.set("token_symbol", normalizeToken(input.token_symbol));
|
|
801
|
+
}
|
|
802
|
+
if ("status" in input && input.status !== void 0) {
|
|
803
|
+
params.set("status", requireNonEmpty(input.status, "status"));
|
|
804
|
+
}
|
|
805
|
+
if ("listing_id" in input && input.listing_id !== void 0) {
|
|
806
|
+
params.set("listing_id", requireNonEmpty(input.listing_id, "listing_id"));
|
|
807
|
+
}
|
|
808
|
+
if ("capability_key" in input && input.capability_key !== void 0) {
|
|
809
|
+
params.set("capability_key", requireNonEmpty(input.capability_key, "capability_key"));
|
|
810
|
+
}
|
|
811
|
+
if ("limit" in input && input.limit !== void 0) {
|
|
812
|
+
params.set("limit", String(positiveInteger(input.limit, "limit")));
|
|
813
|
+
}
|
|
814
|
+
const query = params.toString();
|
|
815
|
+
return query ? `${path}?${query}` : path;
|
|
816
|
+
}
|
|
706
817
|
function positiveInteger(value, name) {
|
|
707
|
-
|
|
818
|
+
if (typeof value !== "number") {
|
|
819
|
+
throw new SiglumeDirectRequestPaymentError(`${name} must be a positive safe integer.`);
|
|
820
|
+
}
|
|
821
|
+
const parsed = value;
|
|
708
822
|
if (!Number.isSafeInteger(parsed) || parsed <= 0) {
|
|
709
823
|
throw new SiglumeDirectRequestPaymentError(`${name} must be a positive safe integer.`);
|
|
710
824
|
}
|