@siglume/direct-request-payment 0.4.4 → 0.4.6
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 +27 -0
- package/README.md +74 -23
- package/dist/index.cjs +5 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -2
- package/dist/index.d.ts +16 -2
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/docs/announcement-ja.md +4 -2
- package/docs/api-reference.md +80 -22
- package/docs/merchant-quickstart.md +102 -10
- package/docs/metered-statements.md +42 -4
- package/docs/pricing.md +15 -0
- package/docs/security.md +22 -10
- package/examples/express-checkout.ts +43 -6
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.6 - 2026-06-19
|
|
4
|
+
|
|
5
|
+
Patch release for the external webhook-state re-review.
|
|
6
|
+
|
|
7
|
+
- Changed webhook examples to branch Standard settled payments, Micro / Nano
|
|
8
|
+
accepted-but-unsettled usage, and metered settlement batches separately.
|
|
9
|
+
- Added Hosted Checkout settlement machine fields and metered settlement batch
|
|
10
|
+
webhook fields to TypeScript types and API docs.
|
|
11
|
+
- Clarified public Nano one-time amount limits, Micro / Nano idempotency key
|
|
12
|
+
placement, and per-batch rounding adjustment behavior.
|
|
13
|
+
- Added `pytest python_tests` to the PyPI Trusted Publishing release workflow.
|
|
14
|
+
|
|
15
|
+
## 0.4.5 - 2026-06-19
|
|
16
|
+
|
|
17
|
+
Patch release for the public beta re-review.
|
|
18
|
+
|
|
19
|
+
- Added `cursor` support to TypeScript and Python metered statement list
|
|
20
|
+
helpers, with tests that fetch a second page.
|
|
21
|
+
- Added missing TypeScript settlement batch retry fields
|
|
22
|
+
(`attempt_count`, `next_attempt_at`) and narrowed metered minor amount fields
|
|
23
|
+
to decimal strings.
|
|
24
|
+
- Clarified the public idempotency contract: one-time requirement creation uses
|
|
25
|
+
the challenge nonce / `challenge_hash` / `request_hash_v2`; the SDK does not
|
|
26
|
+
expose an unsupported requirement `idempotency_key`.
|
|
27
|
+
- Clarified Micro / Nano rounding, usage CSV `rounding_delta_minor`, provider
|
|
28
|
+
statement auth roles, and Standard vs aggregated on-chain receipt wording.
|
|
29
|
+
|
|
3
30
|
## 0.4.4 - 2026-06-19
|
|
4
31
|
|
|
5
32
|
Correctness and security hardening release for the SDRP Direct Request Payment
|
package/README.md
CHANGED
|
@@ -22,8 +22,9 @@ buyer-facing Siglume payment flow creates and pays the requirement.
|
|
|
22
22
|
|
|
23
23
|
`DirectRequestPaymentMerchantClient` requires the merchant's Siglume bearer
|
|
24
24
|
token for setup. `DirectRequestPaymentClient` requires the buyer's Siglume
|
|
25
|
-
bearer token for payment requirements
|
|
26
|
-
|
|
25
|
+
bearer token for payment requirements and buyer statements, or the provider /
|
|
26
|
+
merchant user's Siglume bearer token for provider statements. Do not use a
|
|
27
|
+
Developer Portal `cli_` API key with this package.
|
|
27
28
|
|
|
28
29
|
## Two Kinds of Buyer
|
|
29
30
|
|
|
@@ -66,12 +67,16 @@ card-style "instant" checkout for first-time buyers.
|
|
|
66
67
|
Some merchant accounts may not have the server endpoint enabled yet. In that
|
|
67
68
|
case `createCheckoutSession(...)` / `getCheckoutSession(...)` raises
|
|
68
69
|
`HostedCheckoutNotAvailableError` instead of exposing the raw rollout 404/409.
|
|
69
|
-
Keep
|
|
70
|
+
Keep the signed `direct_payment.confirmed` webhook as the durable signal, and
|
|
71
|
+
inspect its settlement machine fields before marking any order paid.
|
|
70
72
|
|
|
71
73
|
Hosted Checkout is a Siglume-hosted page that turns a "Pay with Siglume" button
|
|
72
74
|
into a completed wallet payment, then returns the shopper to your store. It
|
|
73
|
-
orchestrates the same rails as the agent flow — there is no new money movement
|
|
74
|
-
|
|
75
|
+
orchestrates the same rails as the agent flow — there is no new money movement.
|
|
76
|
+
Fulfillment still starts from the signed `direct_payment.confirmed` webhook, but
|
|
77
|
+
you must inspect the settlement machine fields before deciding whether the event
|
|
78
|
+
means Standard settled payment, Micro / Nano accepted usage, or aggregated
|
|
79
|
+
Micro / Nano settlement.
|
|
75
80
|
|
|
76
81
|
```ts
|
|
77
82
|
import { DirectRequestPaymentMerchantClient } from "@siglume/direct-request-payment";
|
|
@@ -98,9 +103,12 @@ const session = await merchant.createCheckoutSession({
|
|
|
98
103
|
});
|
|
99
104
|
redirect(session.checkout_url); // -> https://siglume.com/pay/<session_id>
|
|
100
105
|
|
|
101
|
-
// 3.
|
|
102
|
-
//
|
|
103
|
-
//
|
|
106
|
+
// 3. Handle the signed direct_payment.confirmed webhook. Fulfill Standard only
|
|
107
|
+
// when pricing_band=standard, finality=per_payment_onchain, and
|
|
108
|
+
// settlement_status=settled. Treat Micro / Nano as accepted but unsettled
|
|
109
|
+
// until the later metered settlement batch is settled.
|
|
110
|
+
// Poll merchant.getCheckoutSession(session.session_id) if you also want to
|
|
111
|
+
// show status in your own UI.
|
|
104
112
|
```
|
|
105
113
|
|
|
106
114
|
```py
|
|
@@ -130,9 +138,12 @@ session = merchant.create_checkout_session(
|
|
|
130
138
|
)
|
|
131
139
|
redirect(session["checkout_url"]) # -> https://siglume.com/pay/<session_id>
|
|
132
140
|
|
|
133
|
-
# 3.
|
|
134
|
-
#
|
|
135
|
-
#
|
|
141
|
+
# 3. Handle the signed direct_payment.confirmed webhook. Fulfill Standard only
|
|
142
|
+
# when pricing_band=standard, finality=per_payment_onchain, and
|
|
143
|
+
# settlement_status=settled. Treat Micro / Nano as accepted but unsettled
|
|
144
|
+
# until the later metered settlement batch is settled.
|
|
145
|
+
# Poll merchant.get_checkout_session(session["session_id"]) if you also want
|
|
146
|
+
# to show status in your own UI.
|
|
136
147
|
```
|
|
137
148
|
|
|
138
149
|
Siglume fixes the amount, currency, challenge, and return URLs **server-side** at
|
|
@@ -183,11 +194,19 @@ Provider revenue in the Micro and Nano bands is not settled revenue until the
|
|
|
183
194
|
weekly or monthly on-chain settlement succeeds. Siglume keeps outstanding failed
|
|
184
195
|
settlements for retry under the published policy, but does not advance or
|
|
185
196
|
guarantee provider revenue before settlement succeeds.
|
|
197
|
+
If your product cannot fulfill before provider revenue is settled, keep the
|
|
198
|
+
price in the Standard band or agree a merchant-specific contract with Siglume
|
|
199
|
+
before launch.
|
|
186
200
|
Micro / Nano budget checks reserve spending capacity only; they do not lock,
|
|
187
201
|
escrow, or guarantee the buyer's wallet balance, allowance, or settlement funds.
|
|
188
202
|
Sub-minor-unit Nano fees are accumulated with decimal precision and rounded only
|
|
189
203
|
when a settlement batch is created; see [Pricing](./docs/pricing.md) for the
|
|
190
204
|
rounding formula and `rounding_delta_minor` semantics.
|
|
205
|
+
For low-count Nano batches, integer-token settlement can make the effective
|
|
206
|
+
buyer burden per usage higher than the headline USD 0.001 protocol fee; the
|
|
207
|
+
difference is reported as batch `rounding_delta_minor`. Treat Micro / Nano
|
|
208
|
+
minor amounts as decimal strings and use a decimal library or `Decimal` for
|
|
209
|
+
accounting.
|
|
191
210
|
For operational reconciliation, expected revenue, settled revenue, retry state,
|
|
192
211
|
and CSV exports, see
|
|
193
212
|
[docs/metered-statements.md](./docs/metered-statements.md).
|
|
@@ -202,7 +221,8 @@ and CSV exports, see
|
|
|
202
221
|
- buyer-authenticated payment requirement creation
|
|
203
222
|
- prepared wallet transaction execution payloads
|
|
204
223
|
- payment requirement verification
|
|
205
|
-
- authenticated TypeScript JSON requests
|
|
224
|
+
- authenticated TypeScript JSON requests and named Python helpers for Micro /
|
|
225
|
+
Nano statement APIs
|
|
206
226
|
- signed webhook verification
|
|
207
227
|
|
|
208
228
|
It does not custody funds or manage customer wallets. Merchant setup runs through
|
|
@@ -244,9 +264,11 @@ Launch plan. The current public API does not expose a flag that forces a
|
|
|
244
264
|
JPY 500-and-under / USD 3-and-under payment into Standard immediate settlement.
|
|
245
265
|
If immediate on-chain settlement is a hard requirement, price the item in the
|
|
246
266
|
Standard band or confirm a merchant-specific contract with Siglume before
|
|
247
|
-
launch.
|
|
248
|
-
|
|
249
|
-
For
|
|
267
|
+
launch. Public Direct Payment / Hosted Checkout `amount_minor` is a positive
|
|
268
|
+
integer in minor currency units, so public one-time Nano amounts start at JPY 1
|
|
269
|
+
or USD 0.01. For Standard Payment, `fee_bps` returned on a payment requirement
|
|
270
|
+
is the authoritative fee rate for that payment in the merchant's settlement
|
|
271
|
+
currency. For Micro / Nano, the statement APIs expose `protocol_fee_minor`,
|
|
250
272
|
`gross_buyer_debit_minor`, `buyer_debit_minor`, and `rounding_delta_minor`.
|
|
251
273
|
The full fee table and the weekly / monthly settlement schedule live in
|
|
252
274
|
[docs/pricing.md](./docs/pricing.md). Statement APIs for "how much was used,
|
|
@@ -358,7 +380,7 @@ The nonce must not contain `:` because the current platform challenge format is
|
|
|
358
380
|
|
|
359
381
|
## Buyer Payment Flow
|
|
360
382
|
|
|
361
|
-
Use `DirectRequestPaymentClient`
|
|
383
|
+
Use `DirectRequestPaymentClient` here with the authenticated buyer's Siglume
|
|
362
384
|
bearer token. `SIGLUME_AUTH_TOKEN` may be used in server-side payment-confirmation
|
|
363
385
|
helpers; `SIGLUME_API_KEY` and Developer Portal `cli_` keys are not accepted.
|
|
364
386
|
|
|
@@ -507,7 +529,19 @@ const { event } = await verifyDirectRequestPaymentWebhook(
|
|
|
507
529
|
);
|
|
508
530
|
|
|
509
531
|
if (event.type === "direct_payment.confirmed") {
|
|
510
|
-
|
|
532
|
+
if (event.data.mode === "metered_settlement_batch") {
|
|
533
|
+
// Reconcile settled Micro / Nano batches by settlement_batch_id /
|
|
534
|
+
// usage_event_digest; these events do not carry an order challenge hash.
|
|
535
|
+
} else if (
|
|
536
|
+
event.data.pricing_band === "standard" &&
|
|
537
|
+
event.data.finality === "per_payment_onchain" &&
|
|
538
|
+
event.data.settlement_status === "settled"
|
|
539
|
+
) {
|
|
540
|
+
// Mark the order paid once if event.data.challenge_hash/order mapping matches.
|
|
541
|
+
} else if (event.data.pricing_band === "micro" || event.data.pricing_band === "nano") {
|
|
542
|
+
// Mark fulfilled-but-unsettled only if your business allows fulfillment
|
|
543
|
+
// before the aggregated Micro / Nano settlement succeeds.
|
|
544
|
+
}
|
|
511
545
|
}
|
|
512
546
|
```
|
|
513
547
|
|
|
@@ -523,14 +557,30 @@ verified = verify_direct_request_payment_webhook(
|
|
|
523
557
|
)
|
|
524
558
|
|
|
525
559
|
if verified["event"]["type"] == "direct_payment.confirmed":
|
|
526
|
-
|
|
527
|
-
|
|
560
|
+
data = verified["event"]["data"]
|
|
561
|
+
if data.get("mode") == "metered_settlement_batch":
|
|
562
|
+
# Reconcile settled Micro / Nano batches by settlement_batch_id /
|
|
563
|
+
# usage_event_digest; these events do not carry an order challenge hash.
|
|
564
|
+
pass
|
|
565
|
+
elif (
|
|
566
|
+
data.get("pricing_band") == "standard"
|
|
567
|
+
and data.get("finality") == "per_payment_onchain"
|
|
568
|
+
and data.get("settlement_status") == "settled"
|
|
569
|
+
):
|
|
570
|
+
# Mark the order paid once if event.data.challenge_hash/order mapping matches.
|
|
571
|
+
pass
|
|
572
|
+
elif data.get("pricing_band") in ("micro", "nano"):
|
|
573
|
+
# Mark fulfilled-but-unsettled only if your business allows fulfillment
|
|
574
|
+
# before the aggregated Micro / Nano settlement succeeds.
|
|
575
|
+
pass
|
|
528
576
|
```
|
|
529
577
|
|
|
530
578
|
New `direct_payment.confirmed` payloads include `pricing_band`,
|
|
531
|
-
`settlement_cadence`, `finality`, `protocol_fee_minor`, `settlement_status`,
|
|
532
|
-
|
|
533
|
-
|
|
579
|
+
`settlement_cadence`, `finality`, `protocol_fee_minor`, `settlement_status`,
|
|
580
|
+
`settlement_batch_id`, `chain_receipt_id`, `usage_event_digest`, `settled_at`,
|
|
581
|
+
and when available `request_hash_v2`. Use these machine fields instead of
|
|
582
|
+
inferring settlement semantics from the event name alone. Do not mark an order
|
|
583
|
+
paid from the event type alone.
|
|
534
584
|
|
|
535
585
|
## Security Rules
|
|
536
586
|
|
|
@@ -553,7 +603,8 @@ Read [docs/security.md](./docs/security.md) before going live.
|
|
|
553
603
|
- Store `SIGLUME_DIRECT_PAYMENT_CHALLENGE_SECRET` only on the merchant server.
|
|
554
604
|
- Store the returned `SIGLUME_WEBHOOK_SECRET` only on the merchant server.
|
|
555
605
|
- Persist `challenge_hash`, `requirement_id`, and fulfillment state per order.
|
|
556
|
-
- Fulfill orders only from verified webhook data, with idempotency
|
|
606
|
+
- Fulfill orders only from verified webhook data, with idempotency, after
|
|
607
|
+
checking `pricing_band`, `finality`, and `settlement_status`.
|
|
557
608
|
- Treat `fee_bps` returned by Siglume as the Standard Payment runtime fee source
|
|
558
609
|
of truth; use statement API amount fields for Micro / Nano.
|
|
559
610
|
|
package/dist/index.cjs
CHANGED
|
@@ -78,7 +78,7 @@ var DIRECT_REQUEST_PAYMENT_RECEIPT_KIND = "sdrp_direct_payment";
|
|
|
78
78
|
var DIRECT_REQUEST_PAYMENT_ALLOWANCE_RECEIPT_KIND = "sdrp_direct_payment_allowance";
|
|
79
79
|
var DIRECT_REQUEST_PAYMENT_REFERENCE_TYPE = "sdrp_direct_payment_requirement";
|
|
80
80
|
var DEFAULT_WEBHOOK_TOLERANCE_SECONDS = 300;
|
|
81
|
-
var DIRECT_REQUEST_PAYMENT_SDK_VERSION = "0.4.
|
|
81
|
+
var DIRECT_REQUEST_PAYMENT_SDK_VERSION = "0.4.6";
|
|
82
82
|
var DIRECT_REQUEST_PAYMENT_CONFIRMED_WEBHOOK_MODES = /* @__PURE__ */ new Set([DIRECT_REQUEST_PAYMENT_MODE, "metered_settlement_batch"]);
|
|
83
83
|
var SiglumeDirectRequestPaymentError = class extends Error {
|
|
84
84
|
constructor(message) {
|
|
@@ -126,7 +126,7 @@ var DirectRequestPaymentClient = class {
|
|
|
126
126
|
const authToken = options.auth_token ?? envValue("SIGLUME_AUTH_TOKEN");
|
|
127
127
|
if (!authToken) {
|
|
128
128
|
throw new SiglumeDirectRequestPaymentError(
|
|
129
|
-
"A buyer Siglume bearer token is required for Direct Request Payment API calls. Developer Portal API keys are not accepted."
|
|
129
|
+
"A buyer or provider Siglume user bearer token is required for Direct Request Payment API calls. Developer Portal API keys are not accepted."
|
|
130
130
|
);
|
|
131
131
|
}
|
|
132
132
|
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
@@ -811,6 +811,9 @@ function meteredQueryPath(path, input) {
|
|
|
811
811
|
if ("limit" in input && input.limit !== void 0) {
|
|
812
812
|
params.set("limit", String(positiveInteger(input.limit, "limit")));
|
|
813
813
|
}
|
|
814
|
+
if ("cursor" in input && input.cursor !== void 0) {
|
|
815
|
+
params.set("cursor", requireNonEmpty(input.cursor, "cursor"));
|
|
816
|
+
}
|
|
814
817
|
const query = params.toString();
|
|
815
818
|
return query ? `${path}?${query}` : path;
|
|
816
819
|
}
|