@siglume/direct-request-payment 0.4.3 → 0.4.5

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/docs/pricing.md CHANGED
@@ -26,16 +26,21 @@ quoted per currency.
26
26
 
27
27
  | Payment amount | Applied automatically | What you select | Fee | Settlement |
28
28
  | --- | --- | --- | --- | --- |
29
- | Over JPY 500 / over USD 3.00, or whenever immediate finality is required | 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 |
29
+ | 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 |
30
30
  | 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 | Aggregated and settled **weekly** (see [Settlement schedule](#settlement-schedule)) |
31
31
  | Under JPY 50 / up to USD 0.30 | Nano Payment | Applied automatically by amount | USD 0.001 / usage, about JPY 0.2 | Aggregated and settled **monthly** (see [Settlement schedule](#settlement-schedule)) |
32
32
 
33
33
  Standard Payment settles per payment. Micro Payment and Nano Payment are
34
34
  aggregated and settled in account-assigned weekly / monthly slots - see
35
35
  [Settlement schedule](#settlement-schedule) for how each band closes, when the
36
- pre-debit notice site elapses, when revenue becomes settled, and how rejected
36
+ pre-debit notice window elapses, when revenue becomes settled, and how rejected
37
37
  requests behave.
38
38
 
39
+ The current public API chooses the band from `amount_minor`; it does not expose
40
+ `settlement_mode: "immediate"` or `require_immediate_finality: true`. If a
41
+ merchant needs immediate on-chain finality, the payment amount must be in the
42
+ Standard band or the merchant must have a separately agreed platform contract.
43
+
39
44
  For the operational statement APIs, CSV export, buyer past-due blocks, and the
40
45
  field-by-field meaning of `scheduled_debit_at`, `not_before_attempt_at`,
41
46
  `execution_status`, and `buyer_period_ref`, see
@@ -52,10 +57,13 @@ Per-payment fees are deducted at settlement, so the merchant receives the net
52
57
  amount for each payment. Monthly base fees are collected separately through the
53
58
  merchant billing mandate.
54
59
 
55
- The same fee schedule applies in JPY and USD. The Siglume platform returns
56
- `fee_bps` in the merchant's settlement currency on every payment requirement, so
57
- the SDK never has to know which currency table to read it just trusts the
58
- value Siglume returns.
60
+ The same Standard Payment percentage schedule applies in JPY and USD. For
61
+ Standard Payment, the Siglume platform returns `fee_bps` in the merchant's
62
+ settlement currency on the payment requirement, so the SDK never has to know
63
+ which currency table to read — it just trusts the value Siglume returns. For
64
+ Micro / Nano, the authoritative fee fields are the statement API amounts:
65
+ `protocol_fee_minor`, `gross_buyer_debit_minor`, `buyer_debit_minor`, and
66
+ `rounding_delta_minor`.
59
67
 
60
68
  ## Settlement schedule
61
69
 
@@ -65,8 +73,8 @@ confirmed payment turns into money in your settlement wallet.
65
73
  | Band | Cadence | Period | You are paid |
66
74
  | --- | --- | --- | --- |
67
75
  | Standard Payment | Per payment | n/a | On-chain, immediately after each payment confirms |
68
- | Micro Payment | Weekly | Account-assigned fixed weekly slot in the buyer settlement timezone; the assigned close time is visible through the statement APIs | After the period closes and the roughly 3-day pre-debit notice site has elapsed, in aggregated on-chain settlement(s) grouped per buyer, payee, token, and period |
69
- | Nano Payment | Monthly | Account-assigned fixed monthly slot in the buyer settlement timezone; the assigned close time is visible through the statement APIs | After the period closes and the roughly 3-day pre-debit notice site has elapsed, in aggregated on-chain settlement(s) grouped per buyer, payee, token, and period |
76
+ | Micro Payment | Weekly | Account-assigned fixed weekly slot in the buyer settlement timezone; the assigned close time is visible through the statement APIs | After the period closes and the roughly 3-day pre-debit notice window has elapsed, in aggregated on-chain settlement(s) grouped per buyer, payee, token, and period |
77
+ | Nano Payment | Monthly | Account-assigned fixed monthly slot in the buyer settlement timezone; the assigned close time is visible through the statement APIs | After the period closes and the roughly 3-day pre-debit notice window has elapsed, in aggregated on-chain settlement(s) grouped per buyer, payee, token, and period |
70
78
 
71
79
  ### Micro weekly settlement
72
80
 
@@ -80,7 +88,7 @@ confirmed payment turns into money in your settlement wallet.
80
88
  payments — grouped per buyer, payee, token, and period — into on-chain
81
89
  settlement(s). Siglume sends the final debit notice first; the on-chain debit
82
90
  is not attempted until the scheduled attempt time after an approximately
83
- 3-day pre-debit notice site (`not_before_attempt_at`).
91
+ 3-day pre-debit notice window (`not_before_attempt_at`).
84
92
  - **Revenue recognition.** A Micro payment is final only once its weekly
85
93
  settlement confirms on-chain. Until then it is accrued, not settled.
86
94
 
@@ -96,7 +104,7 @@ confirmed payment turns into money in your settlement wallet.
96
104
  payments — grouped per buyer, payee, token, and period — into on-chain
97
105
  settlement(s). Siglume sends the final debit notice first; the on-chain debit
98
106
  is not attempted until the scheduled attempt time after an approximately
99
- 3-day pre-debit notice site (`not_before_attempt_at`).
107
+ 3-day pre-debit notice window (`not_before_attempt_at`).
100
108
  - **Revenue recognition.** A Nano payment is final only once its monthly
101
109
  settlement confirms on-chain.
102
110
 
@@ -115,14 +123,18 @@ confirmed payment turns into money in your settlement wallet.
115
123
  - Outstanding amounts remain attached to the failed settlement and are retried
116
124
  under this policy. They are not settled revenue, and Siglume does not advance,
117
125
  guarantee, or insure provider revenue before on-chain settlement succeeds.
126
+ - A `past_due` batch remains recorded until operator resolution or requeue, but
127
+ this does not guarantee collection from the buyer or payment to the provider.
118
128
 
119
129
  ### Rejected / no-charge behavior
120
130
 
121
131
  Micro and Nano run a budget check before the buyer's paid request is fulfilled:
122
132
 
123
- - A buyer's wallet budget is consumed at the **gross amount** (your price plus
124
- the protocol fee), held from the moment a request is accepted until its
125
- settlement confirms.
133
+ - A buyer's wallet budget reservation is consumed at the **gross amount** (your
134
+ price plus the protocol fee) from acceptance until settlement confirms. This
135
+ is a reservation against Siglume spending limits; it does not lock, escrow,
136
+ preserve, or guarantee the buyer's token balance, allowance, BudgetVault
137
+ authorization, or payment source.
126
138
  - If the buyer's budget, scope, or amount band does not allow a request, it is
127
139
  **rejected with no charge**: the request is not fulfilled, no amount is
128
140
  accrued, and nothing is added to a settlement. A buyer near their budget
@@ -137,10 +149,42 @@ Micro and Nano run a budget check before the buyer's paid request is fulfilled:
137
149
  The cadence is fixed: **Micro settles weekly, Nano settles monthly**, and a
138
150
  payment is final only after its on-chain settlement confirms. Micro and Nano are
139
151
  automatic amount bands, not customer-selected options. The account-assigned
140
- period boundaries, roughly 3-day pre-debit notice site, and current retry policy
152
+ period boundaries, roughly 3-day pre-debit notice window, and current retry policy
141
153
  above are the public behavior as of 2026-06-18. Treat the platform's statement
142
- status, `not_before_attempt_at`, and `fee_bps` response as authoritative rather
143
- than hard-coding local revenue recognition.
154
+ status, `not_before_attempt_at`, Standard `fee_bps`, and Micro / Nano statement
155
+ amount fields as authoritative rather than hard-coding local revenue
156
+ recognition.
157
+
158
+ ## Micro / Nano Amount Rounding
159
+
160
+ Micro / Nano fees are stored internally as decimal minor-unit values so
161
+ sub-yen and sub-cent Nano fees are not silently rounded per usage event. The
162
+ current settlement rule is:
163
+
164
+ ```text
165
+ provider_usage_amount_minor = sum(provider price minor units for accepted usage)
166
+ protocol_fee_minor = sum(Micro/Nano fixed protocol fee minor units for accepted usage)
167
+ gross_buyer_debit_minor = provider_usage_amount_minor + protocol_fee_minor
168
+ buyer_debit_minor = ceil(gross_buyer_debit_minor)
169
+ rounding_delta_minor = buyer_debit_minor - gross_buyer_debit_minor
170
+ ```
171
+
172
+ Rounding happens once when the settlement batch is created, not per usage event.
173
+ The rounding mode is ceiling to the next integer token minor unit because
174
+ on-chain settlement cannot debit fractional JPYC/USDC minor units. The positive
175
+ `rounding_delta_minor` is part of the buyer debit for that batch and is retained
176
+ as a rounding adjustment in Siglume's settlement accounting; it is not provider
177
+ revenue. Providers should reconcile their revenue with
178
+ `provider_receivable_minor`, `settled_provider_receivable_minor`,
179
+ `unsettled_provider_receivable_minor`, and
180
+ `past_due_provider_receivable_minor`, not with `buyer_debit_minor`.
181
+
182
+ For low-count Nano batches, the integer ceiling can make the effective buyer
183
+ burden per usage higher than the headline USD 0.001 / usage protocol fee. The
184
+ decimal protocol fee remains visible as `protocol_fee_minor`; the difference
185
+ created by integer-token settlement is visible as `rounding_delta_minor` on the
186
+ batch. JavaScript integrations should not sum Micro / Nano minor amounts with
187
+ `number`; use a decimal library. Python integrations should use `Decimal`.
144
188
 
145
189
  ## Statement APIs and Notices
146
190
 
@@ -154,14 +198,15 @@ Use [Micro / Nano Statements and Notices](./metered-statements.md) to integrate:
154
198
  - provider usage-event CSV export,
155
199
  - buyer summaries for open-period estimated debit and past-due blocks,
156
200
  - sanitized public failure reasons and support references,
157
- - the fixed final notice plus close-plus-3-day debit site.
201
+ - the fixed final notice plus close-plus-3-day debit window.
158
202
 
159
203
  ## SDK Behavior
160
204
 
161
205
  The SDK does not calculate merchant invoices or enforce plan limits locally.
162
206
  Instead, it exposes billing-related values returned by Siglume, including
163
- `fee_bps` on a payment requirement. This keeps merchant billing centralized in
164
- the Siglume platform and avoids stale client-side pricing logic.
207
+ Standard Payment `fee_bps` on a payment requirement and Micro / Nano statement
208
+ amount fields. This keeps merchant billing centralized in the Siglume platform
209
+ and avoids stale client-side pricing logic.
165
210
 
166
211
  ## Supported Use Cases
167
212
 
@@ -179,4 +224,5 @@ The Siglume API and merchant registry may still expose the legacy `billing_plan`
179
224
  value `free` for the Launch tier. Treat `free` as a wire-compatibility key, not a
180
225
  public plan name. (Until 2026-06-12 the Launch plan included a free monthly
181
226
  allowance of 100 payments; that allowance has been retired — the platform
182
- `fee_bps` response is always the source of truth.)
227
+ Standard `fee_bps` response and Micro / Nano statement amount fields are always
228
+ the source of truth.)
package/docs/security.md CHANGED
@@ -61,6 +61,11 @@ bare, lowercased origins and deduped. A return URL that is not on an allowed
61
61
  origin is rejected, so an attacker cannot point a session at an arbitrary
62
62
  redirect target.
63
63
 
64
+ Production allowlist entries must use `https`. Development `http` entries are
65
+ accepted only for `http://localhost`, `http://127.0.0.1`, or `http://[::1]`
66
+ (with optional ports). Userinfo such as `https://user@shop.example.com` is
67
+ rejected so an attacker cannot rely on origin-spoofing URL forms.
68
+
64
69
  For a Hosted Checkout session, Siglume authors the amount, currency, challenge,
65
70
  and return URLs server-side at session creation. The browser cannot tamper with
66
71
  the price or the redirect target, and the raw challenge is never exposed to the
@@ -114,6 +119,12 @@ Fulfill exactly once per order. Store at least:
114
119
  Duplicate webhook deliveries and manual redelivery can occur. A duplicate
115
120
  webhook with the same requirement id must not ship the order twice.
116
121
 
122
+ The public requirement-create API does not accept an `idempotency_key` field.
123
+ For one-time external checkout, the durable idempotency material is the
124
+ merchant-authored challenge nonce plus the returned `challenge_hash` /
125
+ `request_hash_v2`. Reuse the same order-attempt nonce when reconciling a retry;
126
+ mint a new nonce only for a new payment attempt.
127
+
117
128
  ## Micro / Nano Statement Privacy
118
129
 
119
130
  Micro Payment and Nano Payment introduce operational statement APIs and CSV
@@ -149,13 +160,18 @@ Direct Request Payment is not:
149
160
  - a platform balance
150
161
  - a card payment fallback
151
162
 
152
- Each payment is an individual wallet payment backed by an on-chain receipt. Small
153
- payments in the Micro and Nano amount bands are aggregated and settled on
154
- account-assigned weekly / monthly slots instead of one transaction at a time
155
- (see the [pricing guide](./pricing.md#settlement-schedule)), but they are still
156
- wallet payments, not a stored balance. Before a small payment is fulfilled,
157
- Siglume checks the buyer's wallet budget and fails closed when it is invalid, so
158
- a rejected request is never charged. Provider revenue for Micro and Nano remains
159
- unsettled until the aggregated on-chain settlement succeeds; Siglume does not
160
- advance or guarantee revenue when a buyer's balance, allowance, BudgetVault
161
- authorization, cap, or on-chain transaction fails.
163
+ Standard Payment is settled individually with its own on-chain receipt. Micro
164
+ and Nano usage events are included in an aggregated settlement batch, and the
165
+ batch is backed by an on-chain receipt. They are still wallet payments, not a
166
+ stored balance. Before a small payment is fulfilled, Siglume checks the buyer's
167
+ wallet budget and fails closed when it is invalid, so a rejected request is
168
+ never charged. Provider revenue for Micro and Nano remains unsettled until the
169
+ aggregated on-chain settlement succeeds; Siglume does not advance or guarantee
170
+ revenue when a buyer's balance, allowance, BudgetVault authorization, cap, or
171
+ on-chain transaction fails.
172
+
173
+ A Micro / Nano budget reservation is not a token lock, escrow, or payment
174
+ guarantee. It reserves room against Siglume spending limits only. A later
175
+ settlement can still fail if the buyer no longer has sufficient balance,
176
+ allowance, BudgetVault authorization, or cap room; `past_due` records the issue
177
+ but does not guarantee eventual collection or provider payment.
@@ -1,13 +1,15 @@
1
1
  import express from "express";
2
2
  import {
3
- createDirectRequestPaymentChallenge,
4
- DirectRequestPaymentClient,
3
+ DirectRequestPaymentMerchantClient,
5
4
  verifyDirectRequestPaymentWebhook,
6
5
  } from "@siglume/direct-request-payment";
7
6
 
8
7
  const app = express();
9
8
  const port = Number(process.env.PORT || 3000);
10
9
  const merchantKey = process.env.SIGLUME_DIRECT_PAYMENT_MERCHANT || "example_merchant";
10
+ const siglumeMerchant = new DirectRequestPaymentMerchantClient({
11
+ auth_token: process.env.SIGLUME_MERCHANT_AUTH_TOKEN,
12
+ });
11
13
 
12
14
  // Use JSON for normal routes. Use raw body only on the webhook route.
13
15
  app.use((req, res, next) => {
@@ -35,49 +37,29 @@ app.post("/checkout/siglume/start", asyncRoute(async (req, res) => {
35
37
  }
36
38
 
37
39
  order.payment_attempt = Number(order.payment_attempt || 0) + 1;
38
- const challenge = await createDirectRequestPaymentChallenge({
40
+ const session = await siglumeMerchant.createCheckoutSession({
39
41
  merchant: merchantKey,
40
42
  amount_minor: order.amount_minor,
41
43
  currency: order.currency,
42
- secret: process.env.SIGLUME_DIRECT_PAYMENT_CHALLENGE_SECRET!,
43
44
  nonce: `${order.id}-attempt_${order.payment_attempt}`,
45
+ success_url: `${process.env.SHOP_PUBLIC_ORIGIN || "https://shop.example.com"}/thanks`,
46
+ cancel_url: `${process.env.SHOP_PUBLIC_ORIGIN || "https://shop.example.com"}/cart`,
47
+ metadata: { order_id: order.id },
44
48
  });
45
49
 
46
- order.siglume_challenge_hash = challenge.challenge_hash;
50
+ order.siglume_challenge_hash = session.challenge_hash;
51
+ order.siglume_checkout_session_id = session.session_id;
47
52
  order.siglume_payment_status = "pending";
48
53
 
49
54
  res.json({
50
55
  order_id: order.id,
51
56
  amount_minor: order.amount_minor,
52
57
  currency: order.currency,
53
- siglume_challenge: challenge.challenge,
58
+ checkout_url: session.checkout_url,
59
+ session_id: session.session_id,
54
60
  });
55
61
  }));
56
62
 
57
- app.post("/checkout/siglume/pay", asyncRoute(async (req, res) => {
58
- const order = orders.get(String(req.body.order_id || ""));
59
- if (!order) {
60
- res.status(404).json({ error: "order_not_found" });
61
- return;
62
- }
63
-
64
- // In production, obtain this from the authenticated buyer's Siglume session
65
- // or a hosted Siglume payment confirmation flow. Do not use a merchant secret
66
- // to charge a customer wallet.
67
- const siglume = new DirectRequestPaymentClient({
68
- auth_token: String(req.headers.authorization || "").replace(/^Bearer\s+/i, ""),
69
- });
70
-
71
- const requirement = await siglume.createPaymentRequirement({
72
- merchant: merchantKey,
73
- amount_minor: order.amount_minor,
74
- currency: order.currency,
75
- challenge: String(req.body.siglume_challenge || ""),
76
- });
77
-
78
- res.json({ requirement });
79
- }));
80
-
81
63
  app.post("/siglume/webhook", express.raw({ type: "application/json" }), asyncRoute(async (req, res) => {
82
64
  const header = String(req.headers["siglume-signature"] || "");
83
65
  const { event } = await verifyDirectRequestPaymentWebhook(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@siglume/direct-request-payment",
3
- "version": "0.4.3",
3
+ "version": "0.4.5",
4
4
  "description": "SDK for the Siglume Direct Request Payment SDRP payment protocol",
5
5
  "keywords": [
6
6
  "siglume",