@siglume/direct-request-payment 0.3.5 → 0.4.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/CHANGELOG.md +75 -0
- package/README.md +142 -31
- package/dist/index.cjs +64 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +51 -1
- package/dist/index.d.ts +51 -1
- package/dist/index.js +64 -2
- package/dist/index.js.map +1 -1
- package/docs/announcement-ja.md +43 -6
- package/docs/api-reference.md +129 -3
- package/docs/merchant-quickstart.md +141 -6
- package/docs/pricing.md +98 -15
- package/docs/security.md +27 -5
- package/examples/express-checkout.ts +4 -2
- package/examples/setup-merchant.ts +9 -1
- package/package.json +8 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,80 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.0 - 2026-06-18
|
|
4
|
+
|
|
5
|
+
Hosted Checkout for human web shoppers ("Pay with Siglume"). The two buyer
|
|
6
|
+
systems are now both first-class: AI agents pay through the API/tools (unchanged)
|
|
7
|
+
and humans pay through a Siglume-hosted checkout page.
|
|
8
|
+
|
|
9
|
+
- **`DirectRequestPaymentMerchantClient.createCheckoutSession(...)`** (TS + Py):
|
|
10
|
+
create a single-use, expiring Hosted Checkout session. Siglume authors the
|
|
11
|
+
challenge server-side and returns a `checkout_url`; redirect the shopper there.
|
|
12
|
+
The shopper logs into Siglume, approves, and pays from their own Siglume wallet
|
|
13
|
+
(JPYC / USDC), then returns to your `success_url`. Fulfill on the existing
|
|
14
|
+
`direct_payment.confirmed` webhook — the source of truth — exactly as with the
|
|
15
|
+
agent flow. The merchant SDK still does not authenticate the buyer.
|
|
16
|
+
- **`getCheckoutSession(session_id)`** (TS + Py): read a session's status
|
|
17
|
+
(`open` / `authenticated` / `paid` / `expired` / `cancelled` / `failed`).
|
|
18
|
+
- **`checkout_allowed_origins`** added to `setupMerchant` / `setupCheckout`: a
|
|
19
|
+
return-URL origin allowlist (open-redirect defense). `success_url` /
|
|
20
|
+
`cancel_url` must be on a registered origin; the `webhook_callback_url` origin
|
|
21
|
+
is auto-allowed.
|
|
22
|
+
- Docs: documented the **two buyer systems** (human Web = Hosted Checkout; AI
|
|
23
|
+
agent / AtoA = direct API / tools), the AtoA **prerequisite** that the buyer
|
|
24
|
+
agent is pre-connected to Siglume (MCP/OAuth, or a custom app holding the
|
|
25
|
+
buyer's Siglume JWT), and the merchant / Siglume / buyer **boundaries** —
|
|
26
|
+
including that the buyer needs a Siglume wallet and this is **not** a card
|
|
27
|
+
payment.
|
|
28
|
+
|
|
29
|
+
No wire-format changes to existing challenges, requirements, or webhooks; 0.3.x
|
|
30
|
+
clients interoperate unchanged. Hosted Checkout is gated server-side and is a
|
|
31
|
+
purely additive surface.
|
|
32
|
+
|
|
33
|
+
## 0.3.6 - 2026-06-18
|
|
34
|
+
|
|
35
|
+
Documentation and public-surface cleanup release. No wire-format or API changes;
|
|
36
|
+
challenges and clients from 0.3.x interoperate unchanged.
|
|
37
|
+
|
|
38
|
+
- Documented the Micro / Nano **settlement schedule** in the README and the
|
|
39
|
+
pricing guide: Micro settles weekly, Nano settles monthly, with the closing
|
|
40
|
+
period, timezone, revenue-recognition point, retry / carry-over, and
|
|
41
|
+
rejected / no-charge behavior spelled out. The exact close time, default
|
|
42
|
+
timezone, and settlement lag are marked platform-managed — the platform
|
|
43
|
+
response is the source of truth.
|
|
44
|
+
- Clarified that Micro / Nano provider revenue stays unsettled until the weekly /
|
|
45
|
+
monthly on-chain settlement succeeds, that failed settlements are retried and
|
|
46
|
+
may go past due, and that Siglume does not advance, guarantee, or insure unpaid
|
|
47
|
+
amounts.
|
|
48
|
+
- Reframed the docs as a standalone SDRP payment SDK. Internal implementation
|
|
49
|
+
language was removed from the public surface: the legacy `external_402` mode
|
|
50
|
+
value and the `free` Launch-tier key are now isolated in a single
|
|
51
|
+
"Compatibility Notes" section, and internal batch / ledger terms were dropped.
|
|
52
|
+
- Hardened the examples: they no longer print returned secrets (`setup.env`) and
|
|
53
|
+
no longer return raw `error.message` to the client.
|
|
54
|
+
- Removed `external-402` from the npm / PyPI keywords; added `sdrp`,
|
|
55
|
+
`direct-request-payment`, `micropayments`, `metered-billing`, `jpyc`, `usdc`.
|
|
56
|
+
- Hardened `.gitignore` (`.env`, `.env.*`, `.npmrc`, `.pypirc`, `.venv/`,
|
|
57
|
+
`coverage/`) and removed a developer-specific path from `RELEASING.md`.
|
|
58
|
+
|
|
59
|
+
## 0.3.5 - 2026-06-18
|
|
60
|
+
|
|
61
|
+
- Docs: protocol-first README framing for the SDRP Direct Request Payment SDK.
|
|
62
|
+
|
|
63
|
+
## 0.3.4 - 2026-06-18
|
|
64
|
+
|
|
65
|
+
- Docs: clarified the SDRP pricing structure — a Standard plan is selected, and
|
|
66
|
+
Micro / Nano are applied automatically by amount — across the README and
|
|
67
|
+
pricing guide.
|
|
68
|
+
|
|
69
|
+
## 0.3.3 - 2026-06-18
|
|
70
|
+
|
|
71
|
+
- Docs: SDRP direct-payment framing across the README, API reference, merchant
|
|
72
|
+
quickstart, pricing, and security guides.
|
|
73
|
+
|
|
74
|
+
## 0.3.2 - 2026-06-18
|
|
75
|
+
|
|
76
|
+
- Docs: documented the SDRP Micro / Nano amount-band boundaries.
|
|
77
|
+
|
|
3
78
|
## 0.3.1 - 2026-06-12
|
|
4
79
|
|
|
5
80
|
- Docs: scheduled autopay (`cadence: "daily"`) is documented as an approval
|
package/README.md
CHANGED
|
@@ -5,24 +5,15 @@
|
|
|
5
5
|
|
|
6
6
|
## Protocol Overview
|
|
7
7
|
|
|
8
|
-
Siglume Direct Request Payment is
|
|
9
|
-
want to accept Siglume wallet payments. The merchant fixes the order,
|
|
10
|
-
and currency on its server; the buyer pays with a Siglume wallet;
|
|
11
|
-
applies the correct pricing and settlement path from the payment amount
|
|
12
|
-
execution conditions.
|
|
13
|
-
|
|
14
|
-
During merchant setup, only the **Standard Payment plan** is selected. Micro
|
|
15
|
-
Payment and Nano Payment are not separate choices for the merchant or buyer.
|
|
16
|
-
They are applied automatically by amount.
|
|
8
|
+
Siglume Direct Request Payment (SDRP) is a wallet payment protocol for products
|
|
9
|
+
that want to accept Siglume wallet payments. The merchant fixes the order,
|
|
10
|
+
amount, and currency on its server; the buyer pays with a Siglume wallet;
|
|
11
|
+
Siglume applies the correct pricing and settlement path from the payment amount.
|
|
17
12
|
|
|
18
13
|
Use this package when an external EC site, booking service, membership service,
|
|
19
14
|
or paid API wants to accept Siglume wallet payments without taking custody of
|
|
20
|
-
customer funds.
|
|
21
|
-
|
|
22
|
-
Micro Payment or Nano Payment.
|
|
23
|
-
|
|
24
|
-
The current platform payload still uses the internal mode name `external_402`;
|
|
25
|
-
this SDK sets that value for you when creating a payment requirement.
|
|
15
|
+
customer funds. The SDK creates and verifies one-time and recurring wallet
|
|
16
|
+
payments; it does not hold customer funds or wallets.
|
|
26
17
|
|
|
27
18
|
Payment requirement creation must run in the authenticated buyer's Siglume
|
|
28
19
|
context. Your merchant server must not use a merchant secret or API key to
|
|
@@ -34,7 +25,114 @@ token for setup. `DirectRequestPaymentClient` requires the buyer's Siglume
|
|
|
34
25
|
bearer token for payment requirements. Do not use a Developer Portal `cli_` API
|
|
35
26
|
key with this package.
|
|
36
27
|
|
|
37
|
-
|
|
28
|
+
## Two Kinds of Buyer
|
|
29
|
+
|
|
30
|
+
SDRP serves two kinds of buyer, and you integrate each differently. In both
|
|
31
|
+
cases the buyer pays from a **Siglume wallet** (JPYC for JPY, USDC for USD) — it
|
|
32
|
+
is **not** a card payment — and your **merchant SDK never authenticates the
|
|
33
|
+
buyer**.
|
|
34
|
+
|
|
35
|
+
1. **Human web shopper → Hosted Checkout.** When a person clicks "Pay with
|
|
36
|
+
Siglume" on your site, call
|
|
37
|
+
[`createCheckoutSession(...)`](#hosted-checkout-human-web-shoppers) and
|
|
38
|
+
redirect them to the returned `checkout_url`. They sign into Siglume (passkey
|
|
39
|
+
or email code — the login *is* the wallet), review the amount, approve once,
|
|
40
|
+
and pay from their own wallet, then return to your `success_url`. This is the
|
|
41
|
+
Stripe-Checkout-equivalent path.
|
|
42
|
+
|
|
43
|
+
2. **AI agent / agent-to-agent (AtoA) → direct API / tools.** An autonomous
|
|
44
|
+
buyer agent pays through `DirectRequestPaymentClient` (your app holds the
|
|
45
|
+
buyer's Siglume JWT) or through the Siglume marketplace tool
|
|
46
|
+
`market_confirm_direct_payment_and_execute` (MCP).
|
|
47
|
+
|
|
48
|
+
**Prerequisite (important):** agent payment assumes the buyer agent is
|
|
49
|
+
**already connected to Siglume before the payment**. An AI client
|
|
50
|
+
(Claude / ChatGPT / Cursor, …) connects through the **Siglume MCP server
|
|
51
|
+
(OAuth authorization, with a consent screen)**; a custom app holds the
|
|
52
|
+
buyer's **Siglume bearer token (JWT)**. Either way a Siglume authentication
|
|
53
|
+
context must be established before paying — the merchant SDK does not log the
|
|
54
|
+
buyer in. Unattended runs are bounded by Siglume's **approval gates / spending
|
|
55
|
+
budgets** (per-run / daily / monthly auto-pay budgets, or Works approval), not
|
|
56
|
+
by the merchant.
|
|
57
|
+
|
|
58
|
+
Honest framing: the part that integrates quickly is the **merchant plumbing**
|
|
59
|
+
(challenge or checkout session + webhook). Human web payment still requires the
|
|
60
|
+
shopper to have — or create — a Siglume wallet and pay from it; it is not a
|
|
61
|
+
card-style "instant" checkout for first-time buyers.
|
|
62
|
+
|
|
63
|
+
## Hosted Checkout (Human Web Shoppers)
|
|
64
|
+
|
|
65
|
+
Hosted Checkout is a Siglume-hosted page that turns a "Pay with Siglume" button
|
|
66
|
+
into a completed wallet payment, then returns the shopper to your store. It
|
|
67
|
+
orchestrates the same rails as the agent flow — there is no new money movement
|
|
68
|
+
and the merchant fulfills on the same `direct_payment.confirmed` webhook.
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import { DirectRequestPaymentMerchantClient } from "@siglume/direct-request-payment";
|
|
72
|
+
|
|
73
|
+
const merchant = new DirectRequestPaymentMerchantClient({ auth_token: process.env.SIGLUME_MERCHANT_AUTH_TOKEN });
|
|
74
|
+
|
|
75
|
+
// 1. Register the return-URL origins once (open-redirect defense). The origin of
|
|
76
|
+
// your webhook_callback_url is auto-allowed in addition to these.
|
|
77
|
+
await merchant.setupMerchant({
|
|
78
|
+
merchant: "your_merchant_key",
|
|
79
|
+
webhook_callback_url: "https://api.your-shop.com/webhooks/siglume",
|
|
80
|
+
checkout_allowed_origins: ["https://www.your-shop.com"],
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// 2. Per order: create a session and redirect the shopper to checkout_url.
|
|
84
|
+
const session = await merchant.createCheckoutSession({
|
|
85
|
+
merchant: "your_merchant_key",
|
|
86
|
+
amount_minor: 500, // server-fixed; the browser cannot change it
|
|
87
|
+
currency: "JPY",
|
|
88
|
+
nonce: order.id, // unique per order
|
|
89
|
+
success_url: "https://www.your-shop.com/thanks",
|
|
90
|
+
cancel_url: "https://www.your-shop.com/cart",
|
|
91
|
+
metadata: { order_id: order.id },
|
|
92
|
+
});
|
|
93
|
+
redirect(session.checkout_url); // -> https://siglume.com/pay/<session_id>
|
|
94
|
+
|
|
95
|
+
// 3. Fulfill when the signed direct_payment.confirmed webhook arrives (the
|
|
96
|
+
// source of truth). Poll merchant.getCheckoutSession(session.session_id) if
|
|
97
|
+
// you also want to show status in your own UI.
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Siglume fixes the amount, currency, challenge, and return URLs **server-side** at
|
|
101
|
+
session creation, so the browser cannot tamper with the price or the redirect
|
|
102
|
+
target. The shopper's Siglume credentials are never shared with your store.
|
|
103
|
+
|
|
104
|
+
**Who does what.**
|
|
105
|
+
|
|
106
|
+
- **Merchant** — confirms the order; signs the challenge (agent flow) or creates
|
|
107
|
+
a checkout session (web flow); verifies the webhook signature; fulfills
|
|
108
|
+
idempotently. Never sees the buyer's Siglume credentials.
|
|
109
|
+
- **Siglume** — provides the wallet and login, executes the wallet payment,
|
|
110
|
+
applies the fee, settles on-chain, and routes Micro / Nano automatically by
|
|
111
|
+
amount band.
|
|
112
|
+
- **Buyer** — needs a Siglume wallet funded in **JPYC / USDC**. **Not a card
|
|
113
|
+
payment.**
|
|
114
|
+
|
|
115
|
+
## Amount-Based Pricing and Settlement
|
|
116
|
+
|
|
117
|
+
Pricing has one structure: you choose a **Standard Payment** plan once during
|
|
118
|
+
setup, and after that the applied fee and the settlement timing follow the
|
|
119
|
+
**payment amount** automatically. There is nothing else to choose.
|
|
120
|
+
|
|
121
|
+
- **Standard Payment** — most payments. Your selected plan's percentage fee,
|
|
122
|
+
settled on-chain immediately after each payment confirms.
|
|
123
|
+
- **Micro Payment** — small payments, applied automatically by amount. A flat
|
|
124
|
+
per-transaction protocol fee, **settled weekly**.
|
|
125
|
+
- **Nano Payment** — very small payments, applied automatically by amount. A
|
|
126
|
+
flat per-usage protocol fee, **settled monthly**.
|
|
127
|
+
|
|
128
|
+
Micro Payment and Nano Payment are not separate products you opt into; they are
|
|
129
|
+
amount bands Siglume applies on your behalf. Your integration code is the same
|
|
130
|
+
regardless of which band a payment falls into. The full fee table and the exact
|
|
131
|
+
weekly / monthly settlement schedule are in [docs/pricing.md](./docs/pricing.md).
|
|
132
|
+
Provider revenue in the Micro and Nano bands is not settled revenue until the
|
|
133
|
+
weekly or monthly on-chain settlement succeeds. Siglume keeps outstanding failed
|
|
134
|
+
settlements for retry under the published policy, but does not advance or
|
|
135
|
+
guarantee provider revenue before settlement succeeds.
|
|
38
136
|
|
|
39
137
|
## What This SDK Covers
|
|
40
138
|
|
|
@@ -78,15 +176,15 @@ amounts differ.
|
|
|
78
176
|
|
|
79
177
|
| Payment amount | Applied automatically | What you select | Fee | Settlement |
|
|
80
178
|
| --- | --- | --- | --- | --- |
|
|
81
|
-
| 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. |
|
|
82
|
-
| JPY 50-500 / about USD 0.30-3.00 | Micro Payment |
|
|
83
|
-
| Under JPY 1 to JPY 49 / under USD 0.01 to about USD 0.30 | Nano Payment |
|
|
179
|
+
| 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 |
|
|
180
|
+
| JPY 50-500 / about USD 0.30-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) |
|
|
181
|
+
| Under JPY 1 to JPY 49 / under USD 0.01 to about 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) |
|
|
84
182
|
|
|
85
183
|
A merchant billing mandate is required before accepting payments, even on the
|
|
86
|
-
Launch plan.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
184
|
+
Launch plan. `fee_bps` returned on a payment requirement is the authoritative
|
|
185
|
+
fee rate for that payment in the merchant's settlement currency. The full fee
|
|
186
|
+
table and the weekly / monthly settlement schedule live in
|
|
187
|
+
[docs/pricing.md](./docs/pricing.md).
|
|
90
188
|
|
|
91
189
|
## Merchant Setup: One SDK Call
|
|
92
190
|
|
|
@@ -110,12 +208,12 @@ const setup = await merchant.setupCheckout({
|
|
|
110
208
|
max_amount_minor: 100000,
|
|
111
209
|
});
|
|
112
210
|
|
|
113
|
-
|
|
114
|
-
//
|
|
115
|
-
//
|
|
116
|
-
//
|
|
117
|
-
//
|
|
118
|
-
|
|
211
|
+
// setup.env holds the merchant key plus the challenge and webhook secrets:
|
|
212
|
+
// SIGLUME_DIRECT_PAYMENT_MERCHANT (not secret)
|
|
213
|
+
// SIGLUME_DIRECT_PAYMENT_CHALLENGE_SECRET (secret)
|
|
214
|
+
// SIGLUME_WEBHOOK_SECRET (secret)
|
|
215
|
+
// Write these to your server-side secret store. Do NOT log the secret values.
|
|
216
|
+
console.log(`Configured merchant: ${setup.env.SIGLUME_DIRECT_PAYMENT_MERCHANT}`);
|
|
119
217
|
```
|
|
120
218
|
|
|
121
219
|
```py
|
|
@@ -136,7 +234,9 @@ setup = merchant.setup_checkout(
|
|
|
136
234
|
max_amount_minor=100000,
|
|
137
235
|
)
|
|
138
236
|
|
|
139
|
-
|
|
237
|
+
# setup["env"] holds the merchant key plus the challenge and webhook secrets.
|
|
238
|
+
# Persist them to your server-side secret store; do not log the secret values.
|
|
239
|
+
print("Configured merchant:", setup["env"]["SIGLUME_DIRECT_PAYMENT_MERCHANT"])
|
|
140
240
|
```
|
|
141
241
|
|
|
142
242
|
Store returned secrets on the merchant server. `challenge_secret` and
|
|
@@ -289,7 +389,8 @@ const recurring = await createDirectRequestPaymentRecurringChallenge({
|
|
|
289
389
|
// POST /v1/sdrp/direct-payments/subscriptions
|
|
290
390
|
// { merchant, amount_minor, currency, cadence: "monthly", challenge }
|
|
291
391
|
// For scheduled autopay, the buyer instead creates a scheduled auto-pay
|
|
292
|
-
// authorization
|
|
392
|
+
// authorization and hands you the schedule_token; your scheduler triggers
|
|
393
|
+
// each occurrence with that token.
|
|
293
394
|
```
|
|
294
395
|
|
|
295
396
|
```py
|
|
@@ -383,6 +484,16 @@ Read [docs/security.md](./docs/security.md) before going live.
|
|
|
383
484
|
- Fulfill orders only from verified webhook data, with idempotency.
|
|
384
485
|
- Treat `fee_bps` returned by Siglume as the runtime fee source of truth.
|
|
385
486
|
|
|
487
|
+
## Compatibility Notes
|
|
488
|
+
|
|
489
|
+
- The Direct Request Payment HTTP endpoints live under
|
|
490
|
+
`/v1/sdrp/direct-payments/...`; the SDK targets them for you.
|
|
491
|
+
- For wire compatibility the platform still tags these payments with the legacy
|
|
492
|
+
mode value `external_402`, and the merchant registry may still expose the
|
|
493
|
+
legacy billing-plan key `free` for the Launch tier. The SDK sets and reads
|
|
494
|
+
these values for you — treat them as compatibility identifiers, not public
|
|
495
|
+
product names.
|
|
496
|
+
|
|
386
497
|
## Documentation
|
|
387
498
|
|
|
388
499
|
- [Merchant quickstart](./docs/merchant-quickstart.md)
|
package/dist/index.cjs
CHANGED
|
@@ -125,7 +125,7 @@ var DirectRequestPaymentClient = class {
|
|
|
125
125
|
this.auth_token = authToken;
|
|
126
126
|
this.base_url = (options.base_url ?? envValue("SIGLUME_API_BASE") ?? DEFAULT_SIGLUME_API_BASE).replace(/\/+$/, "");
|
|
127
127
|
this.timeout_ms = Math.max(1, Math.trunc(options.timeout_ms ?? 15e3));
|
|
128
|
-
this.user_agent = options.user_agent ?? "@siglume/direct-request-payment/0.
|
|
128
|
+
this.user_agent = options.user_agent ?? "@siglume/direct-request-payment/0.4.0";
|
|
129
129
|
this.fetch_impl = fetchImpl;
|
|
130
130
|
}
|
|
131
131
|
async createPaymentRequirement(input) {
|
|
@@ -230,7 +230,7 @@ var DirectRequestPaymentMerchantClient = class {
|
|
|
230
230
|
this.auth_token = authToken;
|
|
231
231
|
this.base_url = (options.base_url ?? envValue("SIGLUME_API_BASE") ?? DEFAULT_SIGLUME_API_BASE).replace(/\/+$/, "");
|
|
232
232
|
this.timeout_ms = Math.max(1, Math.trunc(options.timeout_ms ?? 15e3));
|
|
233
|
-
this.user_agent = options.user_agent ?? "@siglume/direct-request-payment/0.
|
|
233
|
+
this.user_agent = options.user_agent ?? "@siglume/direct-request-payment/0.4.0";
|
|
234
234
|
this.fetch_impl = fetchImpl;
|
|
235
235
|
}
|
|
236
236
|
async setupMerchant(input) {
|
|
@@ -254,8 +254,47 @@ var DirectRequestPaymentMerchantClient = class {
|
|
|
254
254
|
if (input.max_amount_minor !== void 0) {
|
|
255
255
|
payload.max_amount_minor = positiveInteger(input.max_amount_minor, "max_amount_minor");
|
|
256
256
|
}
|
|
257
|
+
if (input.checkout_allowed_origins !== void 0) {
|
|
258
|
+
payload.checkout_allowed_origins = normalizeOriginList(input.checkout_allowed_origins);
|
|
259
|
+
}
|
|
257
260
|
return this.request("POST", "/sdrp/direct-payments/merchants", payload);
|
|
258
261
|
}
|
|
262
|
+
/**
|
|
263
|
+
* Create a Hosted Checkout session (Stripe-Checkout-equivalent for human web
|
|
264
|
+
* shoppers). Siglume authors the challenge server-side, persists a single-use
|
|
265
|
+
* expiring session, and returns a `checkout_url`. Redirect the shopper there;
|
|
266
|
+
* they log into Siglume, approve, and pay from their own wallet, then return
|
|
267
|
+
* to your `success_url`. Fulfill on the `direct_payment.confirmed` webhook
|
|
268
|
+
* (the source of truth), exactly as with the agent flow.
|
|
269
|
+
*
|
|
270
|
+
* `success_url`/`cancel_url` must be on an origin you registered via
|
|
271
|
+
* `checkout_allowed_origins` (or your `webhook_callback_url` origin).
|
|
272
|
+
*/
|
|
273
|
+
async createCheckoutSession(input) {
|
|
274
|
+
const payload = {
|
|
275
|
+
merchant: normalizeSelfServiceMerchant(input.merchant),
|
|
276
|
+
amount_minor: positiveInteger(input.amount_minor, "amount_minor"),
|
|
277
|
+
currency: normalizeCurrency(input.currency),
|
|
278
|
+
nonce: requireNonEmpty(input.nonce, "nonce"),
|
|
279
|
+
success_url: requireNonEmpty(input.success_url, "success_url"),
|
|
280
|
+
cancel_url: requireNonEmpty(input.cancel_url, "cancel_url")
|
|
281
|
+
};
|
|
282
|
+
if (input.metadata !== void 0) {
|
|
283
|
+
payload.metadata = cloneJsonObject(input.metadata, "metadata");
|
|
284
|
+
}
|
|
285
|
+
return this.request(
|
|
286
|
+
"POST",
|
|
287
|
+
"/sdrp/direct-payments/checkout-sessions",
|
|
288
|
+
payload
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
/** Read a Hosted Checkout session's status (open / authenticated / paid / expired / cancelled / failed). */
|
|
292
|
+
async getCheckoutSession(session_id) {
|
|
293
|
+
return this.request(
|
|
294
|
+
"GET",
|
|
295
|
+
`/sdrp/direct-payments/checkout-sessions/${encodeURIComponent(requireNonEmpty(session_id, "session_id"))}`
|
|
296
|
+
);
|
|
297
|
+
}
|
|
259
298
|
async getMerchant(merchant) {
|
|
260
299
|
return this.request(
|
|
261
300
|
"GET",
|
|
@@ -624,6 +663,29 @@ function normalizeAllowedCurrencies(value) {
|
|
|
624
663
|
function defaultTokenForCurrency(currency) {
|
|
625
664
|
return currency === "JPY" ? "JPYC" : "USDC";
|
|
626
665
|
}
|
|
666
|
+
function normalizeOriginList(value) {
|
|
667
|
+
if (!Array.isArray(value)) {
|
|
668
|
+
throw new SiglumeDirectRequestPaymentError("checkout_allowed_origins must be an array of origin URLs.");
|
|
669
|
+
}
|
|
670
|
+
const seen = /* @__PURE__ */ new Set();
|
|
671
|
+
const origins = [];
|
|
672
|
+
for (const item of value) {
|
|
673
|
+
let url;
|
|
674
|
+
try {
|
|
675
|
+
url = new URL(requireNonEmpty(String(item), "checkout_allowed_origins entry"));
|
|
676
|
+
} catch {
|
|
677
|
+
throw new SiglumeDirectRequestPaymentError(
|
|
678
|
+
"each checkout_allowed_origins entry must be an absolute origin such as https://shop.example.com."
|
|
679
|
+
);
|
|
680
|
+
}
|
|
681
|
+
const origin = `${url.protocol.toLowerCase()}//${url.host.toLowerCase()}`;
|
|
682
|
+
if (!seen.has(origin)) {
|
|
683
|
+
seen.add(origin);
|
|
684
|
+
origins.push(origin);
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
return origins;
|
|
688
|
+
}
|
|
627
689
|
function positiveInteger(value, name) {
|
|
628
690
|
const parsed = Number(value);
|
|
629
691
|
if (!Number.isSafeInteger(parsed) || parsed <= 0) {
|