@siglume/direct-request-payment 0.4.17 → 0.4.19
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 +40 -0
- package/README.md +60 -4
- package/bin/siglume-sdrp.mjs +267 -0
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/docs/announcement-ja.md +5 -3
- package/docs/api-reference.md +34 -1
- package/docs/merchant-quickstart.md +19 -2
- package/docs/payment-lifecycle.md +85 -0
- package/docs/pricing.md +6 -6
- package/docs/quickstart-10-minutes.md +145 -0
- package/docs/troubleshooting.md +70 -0
- package/examples/express-checkout.ts +14 -0
- package/examples/hosted-checkout-python/.env.example +5 -0
- package/examples/hosted-checkout-python/README.md +21 -0
- package/examples/hosted-checkout-python/app.py +124 -0
- package/examples/hosted-checkout-python/order_store.py +42 -0
- package/examples/hosted-checkout-python/pyproject.toml +9 -0
- package/examples/hosted-checkout-typescript/.env.example +5 -0
- package/examples/hosted-checkout-typescript/README.md +21 -0
- package/examples/hosted-checkout-typescript/package.json +20 -0
- package/examples/hosted-checkout-typescript/src/order-store.ts +52 -0
- package/examples/hosted-checkout-typescript/src/server.ts +139 -0
- package/examples/hosted-checkout-typescript/tsconfig.json +13 -0
- package/package.json +12 -1
- package/templates/express/README.md +22 -0
- package/templates/express/siglume-order-store.example.ts +53 -0
- package/templates/express/siglume-sdrp-routes.ts +157 -0
- package/templates/fastapi/README.md +22 -0
- package/templates/fastapi/siglume_order_store_example.py +54 -0
- package/templates/fastapi/siglume_sdrp_routes.py +107 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,45 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.19 - 2026-06-20
|
|
4
|
+
|
|
5
|
+
Make the 10-minute integration path a real product-integration path instead of
|
|
6
|
+
a separate demo.
|
|
7
|
+
|
|
8
|
+
- Added npm and PyPI CLI bins `siglume-sdrp` and `siglume-check`.
|
|
9
|
+
- Added `siglume-check readiness` to validate merchant token, merchant key,
|
|
10
|
+
HTTPS origin/webhook configuration, Standard-band probe amount, merchant
|
|
11
|
+
account/billing readiness, and Hosted Checkout availability through an unpaid
|
|
12
|
+
checkout-session probe.
|
|
13
|
+
- Added `siglume-sdrp init express` for npm and `siglume-sdrp init fastapi` for
|
|
14
|
+
npm/PyPI to copy framework-specific checkout/webhook route files into an
|
|
15
|
+
existing product.
|
|
16
|
+
- Added Express and FastAPI integration templates with order-store adapter
|
|
17
|
+
interfaces so teams can wire SDRP into their real order database instead of
|
|
18
|
+
starting from an isolated sample app.
|
|
19
|
+
- Reframed the 10-minute guide around existing-product integration and moved
|
|
20
|
+
the readiness check before any coding.
|
|
21
|
+
|
|
22
|
+
## 0.4.18 - 2026-06-19
|
|
23
|
+
|
|
24
|
+
Developer-onboarding cleanup for the v0.4.17 public review.
|
|
25
|
+
|
|
26
|
+
- Added a scoped 10-minute first-test guide for one Standard Payment Hosted
|
|
27
|
+
Checkout flow, with explicit prerequisites and non-goals.
|
|
28
|
+
- Added payment lifecycle and troubleshooting docs covering Hosted Checkout
|
|
29
|
+
readiness, webhook failure handling, retries, support references, and refund
|
|
30
|
+
escalation boundaries.
|
|
31
|
+
- Added README glossary and use-case fit tables so merchant / provider /
|
|
32
|
+
publisher / payee wording and 10-minute claims are less ambiguous.
|
|
33
|
+
- Added minimal Hosted Checkout TypeScript and Python starter directories with
|
|
34
|
+
`.env.example`, seeded test order, checkout start route, and webhook handler.
|
|
35
|
+
- Replaced "Stripe Checkout equivalent" wording with Siglume wallet hosted
|
|
36
|
+
checkout wording in public docs and SDK comments.
|
|
37
|
+
- Exported Python `TypedDict` response names for Hosted Checkout, Micro / Nano
|
|
38
|
+
summaries, settlement batches, webhook verification, and confirmation
|
|
39
|
+
classification.
|
|
40
|
+
- Marked the existing Express checkout example as demo-only and not
|
|
41
|
+
production-safe.
|
|
42
|
+
|
|
3
43
|
## 0.4.17 - 2026-06-19
|
|
4
44
|
|
|
5
45
|
Public-surface cleanup for the v0.4.15 external review.
|
package/README.md
CHANGED
|
@@ -56,7 +56,7 @@ buyer**.
|
|
|
56
56
|
redirect them to the returned `checkout_url`. They sign into Siglume (passkey
|
|
57
57
|
or email code — the login *is* the wallet), review the amount, approve once,
|
|
58
58
|
and pay from their own wallet, then return to your `success_url`. This is the
|
|
59
|
-
|
|
59
|
+
Siglume wallet hosted checkout path.
|
|
60
60
|
|
|
61
61
|
2. **AI agent / agent-to-agent (AtoA) → direct API / tools.** An autonomous
|
|
62
62
|
buyer agent pays through `DirectRequestPaymentClient` (your app holds the
|
|
@@ -78,6 +78,53 @@ Honest framing: the part that integrates quickly is the **merchant plumbing**
|
|
|
78
78
|
shopper to have — or create — a Siglume wallet and pay from it; it is not a
|
|
79
79
|
card-style "instant" checkout for first-time buyers.
|
|
80
80
|
|
|
81
|
+
## Fast Path
|
|
82
|
+
|
|
83
|
+
Use [10-Minute Product Integration](./docs/quickstart-10-minutes.md) to add
|
|
84
|
+
Hosted Checkout routes to an existing Express or FastAPI product. The path is
|
|
85
|
+
CLI-first:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
npm install @siglume/direct-request-payment
|
|
89
|
+
npx siglume-check readiness
|
|
90
|
+
npx siglume-sdrp init express --target src/siglume
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
or:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
pip install siglume-direct-request-payment
|
|
97
|
+
siglume-sdrp init fastapi --target app/siglume
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The readiness command checks account, billing, origin, webhook, and Hosted
|
|
101
|
+
Checkout availability before you write checkout code.
|
|
102
|
+
|
|
103
|
+
Before implementation, confirm Hosted Checkout readiness in
|
|
104
|
+
[Troubleshooting](./docs/troubleshooting.md#hosted-checkout-readiness). For
|
|
105
|
+
state handling, read [Payment lifecycle](./docs/payment-lifecycle.md) before
|
|
106
|
+
fulfilling orders.
|
|
107
|
+
|
|
108
|
+
## Who Is Who
|
|
109
|
+
|
|
110
|
+
| Term | Meaning for public integrations |
|
|
111
|
+
| --- | --- |
|
|
112
|
+
| Buyer | The Siglume wallet user who pays. The merchant SDK does not log this user in. |
|
|
113
|
+
| Merchant | The external product or store that starts checkout, owns the order, and verifies webhooks. |
|
|
114
|
+
| Provider | The revenue recipient in Micro / Nano statements. In a simple EC integration this is usually the same business as the merchant. |
|
|
115
|
+
| Publisher / listing owner | Marketplace-facing owner of a listing or capability. Most Hosted Checkout merchants do not need to handle this term directly. |
|
|
116
|
+
| Payee | Internal settlement-grouping language. Public integration guides avoid this term unless a statement API field includes it. |
|
|
117
|
+
|
|
118
|
+
## Use-Case Fit
|
|
119
|
+
|
|
120
|
+
| Use case | Recommended path | 10-minute integration path? | Production work still required |
|
|
121
|
+
| --- | --- | --- | --- |
|
|
122
|
+
| EC one-time Standard payment | Hosted Checkout | Yes, with `siglume-check readiness` and `siglume-sdrp init` | Refund/support process and monitoring |
|
|
123
|
+
| Game consumables | Hosted Checkout or agent/API | Conditional | Idempotent entitlement grants, disconnect recovery, Micro / Nano unsettled-risk handling |
|
|
124
|
+
| Paid API / AtoA | Direct API or Siglume marketplace tool | Conditional | Request idempotency, buyer auth context, reconciliation |
|
|
125
|
+
| SaaS subscription | Recurring challenge plus raw API | No | Renewal, cancellation, failed renewal, plan-change lifecycle |
|
|
126
|
+
| Scheduled autopay | Recurring challenge plus schedule token | No | Scheduler, token custody, budget failure handling |
|
|
127
|
+
|
|
81
128
|
## Hosted Checkout (Human Web Shoppers)
|
|
82
129
|
|
|
83
130
|
**Beta / server rollout:** Hosted Checkout is rolling out account by account.
|
|
@@ -86,6 +133,8 @@ case `createCheckoutSession(...)` / `getCheckoutSession(...)` raises
|
|
|
86
133
|
`HostedCheckoutNotAvailableError` instead of exposing the raw rollout 404/409.
|
|
87
134
|
Keep the signed `direct_payment.confirmed` webhook as the durable signal, and
|
|
88
135
|
inspect its settlement machine fields before marking any order paid.
|
|
136
|
+
Check readiness before you build the flow; see
|
|
137
|
+
[Hosted Checkout readiness](./docs/troubleshooting.md#hosted-checkout-readiness).
|
|
89
138
|
|
|
90
139
|
Hosted Checkout is a Siglume-hosted page that turns a "Pay with Siglume" button
|
|
91
140
|
into a completed wallet payment, then returns the shopper to your store. It
|
|
@@ -286,8 +335,8 @@ the flat amounts differ.
|
|
|
286
335
|
| Public one-time payment amount | Applied automatically | What you select | Fee | Settlement |
|
|
287
336
|
| --- | --- | --- | --- | --- |
|
|
288
337
|
| JPY 501+ / USD 3.01+ | 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 |
|
|
289
|
-
| JPY 50-500 / USD 0.31-3.00 | Micro Payment | Applied automatically by amount | JPY 2 / USD 0.01 per SDRP Tx |
|
|
290
|
-
| JPY 1-49 / USD 0.01-0.30 | Nano Payment | Applied automatically by amount | JPY 0.2 / USD 0.001 per SDRP Tx |
|
|
338
|
+
| JPY 50-500 / USD 0.31-3.00 | Micro Payment | Applied automatically by amount | JPY 2 / USD 0.01 per SDRP Tx | Closes weekly, or earlier when provider gross reaches JPY 10,000 / USD 100.00. See [Settlement schedule](./docs/pricing.md#settlement-schedule). |
|
|
339
|
+
| JPY 1-49 / USD 0.01-0.30 | Nano Payment | Applied automatically by amount | JPY 0.2 / USD 0.001 per SDRP Tx | Closes monthly, or earlier when provider gross reaches JPY 10,000 / USD 100.00. See [Settlement schedule](./docs/pricing.md#settlement-schedule). |
|
|
291
340
|
|
|
292
341
|
In this table, `Tx` means one accepted SDRP payment, not an on-chain settlement
|
|
293
342
|
transaction.
|
|
@@ -641,7 +690,9 @@ an order paid from the event type alone.
|
|
|
641
690
|
- Do not treat Direct Request Payment as stored value, prepaid points, escrow, or
|
|
642
691
|
a platform balance.
|
|
643
692
|
|
|
644
|
-
Read [docs/security.md](./docs/security.md) before going live.
|
|
693
|
+
Read [docs/security.md](./docs/security.md) before going live. Use
|
|
694
|
+
[docs/troubleshooting.md](./docs/troubleshooting.md) for operational error
|
|
695
|
+
handling and support escalation.
|
|
645
696
|
|
|
646
697
|
## Go-Live Checklist
|
|
647
698
|
|
|
@@ -670,12 +721,17 @@ Read [docs/security.md](./docs/security.md) before going live.
|
|
|
670
721
|
## Documentation
|
|
671
722
|
|
|
672
723
|
- [Merchant quickstart](./docs/merchant-quickstart.md)
|
|
724
|
+
- [10-minute product integration](./docs/quickstart-10-minutes.md)
|
|
725
|
+
- [Payment lifecycle](./docs/payment-lifecycle.md)
|
|
726
|
+
- [Troubleshooting](./docs/troubleshooting.md)
|
|
673
727
|
- [API reference](./docs/api-reference.md)
|
|
674
728
|
- [Pricing](./docs/pricing.md)
|
|
675
729
|
- [Micro / Nano statements and notices](./docs/metered-statements.md)
|
|
676
730
|
- [Security guide](./docs/security.md)
|
|
677
731
|
- [Merchant setup example](./examples/setup-merchant.ts)
|
|
678
732
|
- [Express checkout example](./examples/express-checkout.ts)
|
|
733
|
+
- [Hosted Checkout TypeScript starter](./examples/hosted-checkout-typescript)
|
|
734
|
+
- [Hosted Checkout Python starter](./examples/hosted-checkout-python)
|
|
679
735
|
- [Japanese launch announcement draft](./docs/announcement-ja.md)
|
|
680
736
|
- [Changelog](./CHANGELOG.md)
|
|
681
737
|
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
import { mkdir, readFile, readdir, stat, writeFile } from "node:fs/promises";
|
|
5
|
+
import { dirname, join, resolve } from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
DirectRequestPaymentMerchantClient,
|
|
10
|
+
HostedCheckoutNotAvailableError,
|
|
11
|
+
SiglumeApiError,
|
|
12
|
+
} from "../dist/index.js";
|
|
13
|
+
|
|
14
|
+
const rootDir = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
15
|
+
|
|
16
|
+
main().catch((error) => {
|
|
17
|
+
console.error(`siglume-sdrp: ${error instanceof Error ? error.message : String(error)}`);
|
|
18
|
+
process.exitCode = 1;
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
async function main() {
|
|
22
|
+
loadDotEnv();
|
|
23
|
+
const [command = "help", ...args] = process.argv.slice(2);
|
|
24
|
+
if (command === "help" || command === "--help" || command === "-h") {
|
|
25
|
+
printHelp();
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (command === "readiness" || command === "doctor") {
|
|
29
|
+
await readiness(parseArgs(args));
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (command === "init") {
|
|
33
|
+
await init(args);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
throw new Error(`Unknown command: ${command}`);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function printHelp() {
|
|
40
|
+
console.log(`Siglume SDRP integration CLI
|
|
41
|
+
|
|
42
|
+
Usage:
|
|
43
|
+
siglume-check readiness --merchant <key> --origin <https://shop.example> --webhook-url <https://api.example/siglume/webhook>
|
|
44
|
+
siglume-sdrp init express --target src/siglume
|
|
45
|
+
siglume-sdrp init fastapi --target app/siglume
|
|
46
|
+
|
|
47
|
+
Readiness options:
|
|
48
|
+
--merchant <key> Merchant key. Defaults to SIGLUME_DIRECT_PAYMENT_MERCHANT.
|
|
49
|
+
--origin <origin> Public shop origin. Defaults to SHOP_PUBLIC_ORIGIN.
|
|
50
|
+
--webhook-url <url> Public webhook URL. Defaults to SHOP_WEBHOOK_URL.
|
|
51
|
+
--currency <JPY|USD> Probe currency. Defaults to SIGLUME_DIRECT_PAYMENT_TEST_CURRENCY or JPY.
|
|
52
|
+
--amount-minor <amount> Standard-band probe amount. Defaults to 501 for JPY, 301 for USD.
|
|
53
|
+
--base-url <url> Siglume API base URL. Defaults to SIGLUME_API_BASE or production.
|
|
54
|
+
--no-api Validate local config only; do not call Siglume.
|
|
55
|
+
--no-probe Call getMerchant only; do not create an unpaid checkout session.
|
|
56
|
+
--json Print machine-readable JSON.
|
|
57
|
+
`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function parseArgs(args) {
|
|
61
|
+
const out = { api: true, probe: true, json: false };
|
|
62
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
63
|
+
const arg = args[i];
|
|
64
|
+
if (arg === "--no-api") {
|
|
65
|
+
out.api = false;
|
|
66
|
+
} else if (arg === "--no-probe") {
|
|
67
|
+
out.probe = false;
|
|
68
|
+
} else if (arg === "--json") {
|
|
69
|
+
out.json = true;
|
|
70
|
+
} else if (arg === "--force") {
|
|
71
|
+
out.force = true;
|
|
72
|
+
} else if (arg.startsWith("--")) {
|
|
73
|
+
const key = arg.slice(2).replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
74
|
+
const value = args[i + 1];
|
|
75
|
+
if (!value || value.startsWith("--")) {
|
|
76
|
+
throw new Error(`${arg} requires a value.`);
|
|
77
|
+
}
|
|
78
|
+
out[key] = value;
|
|
79
|
+
i += 1;
|
|
80
|
+
} else {
|
|
81
|
+
throw new Error(`Unexpected argument: ${arg}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async function readiness(options) {
|
|
88
|
+
const checks = [];
|
|
89
|
+
const merchant = options.merchant || process.env.SIGLUME_DIRECT_PAYMENT_MERCHANT || "";
|
|
90
|
+
const origin = options.origin || process.env.SHOP_PUBLIC_ORIGIN || "";
|
|
91
|
+
const webhookUrl = options.webhookUrl || process.env.SHOP_WEBHOOK_URL || "";
|
|
92
|
+
const token = process.env.SIGLUME_MERCHANT_AUTH_TOKEN || process.env.SIGLUME_AUTH_TOKEN || "";
|
|
93
|
+
const currency = normalizeCurrency(options.currency || process.env.SIGLUME_DIRECT_PAYMENT_TEST_CURRENCY || "JPY");
|
|
94
|
+
const amountMinor = Number(options.amountMinor || process.env.SIGLUME_DIRECT_PAYMENT_TEST_AMOUNT_MINOR || (currency === "USD" ? 301 : 501));
|
|
95
|
+
|
|
96
|
+
check(checks, "merchant_key", Boolean(merchant), "Set SIGLUME_DIRECT_PAYMENT_MERCHANT or pass --merchant.");
|
|
97
|
+
check(checks, "merchant_token", Boolean(token) && !token.startsWith("cli_"), "Set SIGLUME_MERCHANT_AUTH_TOKEN to a merchant Siglume bearer token, not a cli_ key.");
|
|
98
|
+
check(checks, "shop_origin", isHttpsOrigin(origin), "Set SHOP_PUBLIC_ORIGIN to an https origin, for example https://www.example.com.");
|
|
99
|
+
check(checks, "webhook_url", isHttpsUrl(webhookUrl), "Set SHOP_WEBHOOK_URL to a public https webhook URL.");
|
|
100
|
+
check(checks, "standard_probe_amount", isStandardAmount(currency, amountMinor), "Use a Standard-band probe amount: JPY 501+ or USD 301+ minor units.");
|
|
101
|
+
|
|
102
|
+
if (options.api && !hasFailures(checks)) {
|
|
103
|
+
const merchantClient = new DirectRequestPaymentMerchantClient({
|
|
104
|
+
auth_token: token,
|
|
105
|
+
base_url: options.baseUrl || process.env.SIGLUME_API_BASE,
|
|
106
|
+
});
|
|
107
|
+
try {
|
|
108
|
+
const merchantResponse = await merchantClient.getMerchant(merchant);
|
|
109
|
+
const account = merchantResponse.merchant_account || {};
|
|
110
|
+
check(checks, "merchant_exists", Boolean(account.merchant), "Run merchant setup before checkout.");
|
|
111
|
+
check(checks, "billing_mandate", Boolean(account.billing_mandate_id) || activeLike(account.billing_status), "Complete the merchant billing mandate wallet approval.");
|
|
112
|
+
warnIf(checks, "merchant_status", account.status && !activeLike(account.status), `Merchant status is ${account.status}; confirm it is allowed to accept payments.`);
|
|
113
|
+
warnIf(checks, "billing_status", account.billing_status && !activeLike(account.billing_status), `Billing status is ${account.billing_status}; confirm it is active before accepting payments.`);
|
|
114
|
+
} catch (error) {
|
|
115
|
+
check(checks, "merchant_api", false, apiErrorMessage(error, "Could not read the merchant account."));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (options.probe && !hasFailures(checks)) {
|
|
119
|
+
try {
|
|
120
|
+
const session = await merchantClient.createCheckoutSession({
|
|
121
|
+
merchant,
|
|
122
|
+
amount_minor: amountMinor,
|
|
123
|
+
currency,
|
|
124
|
+
nonce: `sdrp-readiness-${Date.now()}`,
|
|
125
|
+
success_url: `${origin}/siglume-readiness/success`,
|
|
126
|
+
cancel_url: `${origin}/siglume-readiness/cancel`,
|
|
127
|
+
metadata: { source: "siglume-sdrp-readiness" },
|
|
128
|
+
});
|
|
129
|
+
check(checks, "hosted_checkout", Boolean(session.checkout_url && session.challenge_hash), "Hosted Checkout did not return a checkout_url.");
|
|
130
|
+
} catch (error) {
|
|
131
|
+
const message = error instanceof HostedCheckoutNotAvailableError
|
|
132
|
+
? "Hosted Checkout is not enabled for this merchant account. Ask Siglume to enable it before coding the human checkout path."
|
|
133
|
+
: apiErrorMessage(error, "Hosted Checkout probe failed. Check checkout_allowed_origins, currency, amount, and billing mandate.");
|
|
134
|
+
check(checks, "hosted_checkout", false, message);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const ok = !hasFailures(checks);
|
|
140
|
+
if (options.json) {
|
|
141
|
+
console.log(JSON.stringify({ ok, checks }, null, 2));
|
|
142
|
+
} else {
|
|
143
|
+
for (const item of checks) {
|
|
144
|
+
const mark = item.status === "pass" ? "OK" : item.status === "warn" ? "WARN" : "FAIL";
|
|
145
|
+
console.log(`${mark} ${item.name}: ${item.message}`);
|
|
146
|
+
}
|
|
147
|
+
console.log(ok ? "Ready for 10-minute SDRP integration." : "Not ready. Fix the FAIL items before coding checkout.");
|
|
148
|
+
}
|
|
149
|
+
if (!ok) {
|
|
150
|
+
process.exitCode = 1;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async function init(args) {
|
|
155
|
+
const framework = args[0];
|
|
156
|
+
const parsed = parseArgs(args.slice(1));
|
|
157
|
+
const target = parsed.target;
|
|
158
|
+
if (!["express", "fastapi"].includes(framework)) {
|
|
159
|
+
throw new Error("init requires framework: express or fastapi.");
|
|
160
|
+
}
|
|
161
|
+
if (!target) {
|
|
162
|
+
throw new Error("init requires --target <directory>.");
|
|
163
|
+
}
|
|
164
|
+
const from = join(rootDir, "templates", framework);
|
|
165
|
+
const to = resolve(process.cwd(), target);
|
|
166
|
+
await copyDir(from, to, Boolean(parsed.force));
|
|
167
|
+
console.log(`Copied ${framework} SDRP integration files to ${to}`);
|
|
168
|
+
console.log("Wire the exported router into your app, then run siglume-check readiness before opening checkout.");
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
async function copyDir(from, to, force) {
|
|
172
|
+
await mkdir(to, { recursive: true });
|
|
173
|
+
for (const entry of await readdir(from)) {
|
|
174
|
+
const src = join(from, entry);
|
|
175
|
+
const dst = join(to, entry);
|
|
176
|
+
const info = await stat(src);
|
|
177
|
+
if (info.isDirectory()) {
|
|
178
|
+
await copyDir(src, dst, force);
|
|
179
|
+
} else {
|
|
180
|
+
if (!force && await exists(dst)) {
|
|
181
|
+
throw new Error(`${dst} already exists. Re-run with --force to overwrite.`);
|
|
182
|
+
}
|
|
183
|
+
await mkdir(dirname(dst), { recursive: true });
|
|
184
|
+
await writeFile(dst, await readFile(src));
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
async function exists(path) {
|
|
190
|
+
try {
|
|
191
|
+
await stat(path);
|
|
192
|
+
return true;
|
|
193
|
+
} catch {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function loadDotEnv() {
|
|
199
|
+
try {
|
|
200
|
+
const text = readFileSync(resolve(process.cwd(), ".env"), "utf8");
|
|
201
|
+
for (const line of text.split(/\r?\n/)) {
|
|
202
|
+
const trimmed = line.trim();
|
|
203
|
+
if (!trimmed || trimmed.startsWith("#") || !trimmed.includes("=")) continue;
|
|
204
|
+
const [key, ...rest] = trimmed.split("=");
|
|
205
|
+
if (key && !process.env[key]) {
|
|
206
|
+
process.env[key] = rest.join("=").replace(/^["']|["']$/g, "");
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
} catch {
|
|
210
|
+
// .env is optional.
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function check(checks, name, passed, message) {
|
|
215
|
+
checks.push({ name, status: passed ? "pass" : "fail", message: passed ? "ready" : message });
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function warnIf(checks, name, condition, message) {
|
|
219
|
+
if (condition) {
|
|
220
|
+
checks.push({ name, status: "warn", message });
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function hasFailures(checks) {
|
|
225
|
+
return checks.some((item) => item.status === "fail");
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function isHttpsOrigin(value) {
|
|
229
|
+
try {
|
|
230
|
+
const url = new URL(value);
|
|
231
|
+
return url.protocol === "https:" && url.origin === value.replace(/\/$/, "");
|
|
232
|
+
} catch {
|
|
233
|
+
return false;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function isHttpsUrl(value) {
|
|
238
|
+
try {
|
|
239
|
+
const url = new URL(value);
|
|
240
|
+
return url.protocol === "https:";
|
|
241
|
+
} catch {
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function normalizeCurrency(value) {
|
|
247
|
+
const currency = String(value || "").toUpperCase();
|
|
248
|
+
if (currency !== "JPY" && currency !== "USD") {
|
|
249
|
+
throw new Error("--currency must be JPY or USD.");
|
|
250
|
+
}
|
|
251
|
+
return currency;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function isStandardAmount(currency, amountMinor) {
|
|
255
|
+
return Number.isSafeInteger(amountMinor) && amountMinor >= (currency === "USD" ? 301 : 501);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function activeLike(value) {
|
|
259
|
+
return /^(active|ready|current|ok|enabled|paid|complete|completed)$/i.test(String(value || ""));
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function apiErrorMessage(error, fallback) {
|
|
263
|
+
if (error instanceof SiglumeApiError) {
|
|
264
|
+
return `${fallback} ${error.code} (${error.status}).`;
|
|
265
|
+
}
|
|
266
|
+
return fallback;
|
|
267
|
+
}
|
package/dist/index.cjs
CHANGED
|
@@ -83,7 +83,7 @@ var DIRECT_REQUEST_PAYMENT_RECEIPT_KIND = "sdrp_direct_payment";
|
|
|
83
83
|
var DIRECT_REQUEST_PAYMENT_ALLOWANCE_RECEIPT_KIND = "sdrp_direct_payment_allowance";
|
|
84
84
|
var DIRECT_REQUEST_PAYMENT_REFERENCE_TYPE = "sdrp_direct_payment_requirement";
|
|
85
85
|
var DEFAULT_WEBHOOK_TOLERANCE_SECONDS = 300;
|
|
86
|
-
var DIRECT_REQUEST_PAYMENT_SDK_VERSION = "0.4.
|
|
86
|
+
var DIRECT_REQUEST_PAYMENT_SDK_VERSION = "0.4.19";
|
|
87
87
|
var DIRECT_REQUEST_PAYMENT_STANDARD_SETTLED_STATUS = "settled";
|
|
88
88
|
var DIRECT_REQUEST_PAYMENT_METERED_ACCEPTED_STATUS = "pending_settlement";
|
|
89
89
|
var DIRECT_REQUEST_PAYMENT_STANDARD_FINALITY = "per_payment_onchain";
|
|
@@ -327,8 +327,8 @@ var DirectRequestPaymentMerchantClient = class {
|
|
|
327
327
|
return this.request("POST", "/sdrp/direct-payments/merchants", payload);
|
|
328
328
|
}
|
|
329
329
|
/**
|
|
330
|
-
* Create a Hosted Checkout session
|
|
331
|
-
*
|
|
330
|
+
* Create a Hosted Checkout session for human web shoppers. Siglume authors
|
|
331
|
+
* the challenge server-side, persists a single-use
|
|
332
332
|
* expiring session, and returns a `checkout_url`. Redirect the shopper there;
|
|
333
333
|
* they log into Siglume, approve, and pay from their own wallet, then return
|
|
334
334
|
* to your `success_url`. Fulfill on the `direct_payment.confirmed` webhook
|