@siglume/direct-request-payment 0.3.0 → 0.3.1

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
@@ -1,73 +1,73 @@
1
- # Pricing
2
-
3
- This page documents the trial-phase merchant pricing for Siglume Direct Request
4
- Payment as of 2026-06-11. Pricing can change by agreement or future product
5
- release; the Siglume platform response is the source of truth for per-payment
6
- fee data returned at runtime.
7
-
8
- ## Settlement Currencies
9
-
10
- Siglume Direct Request Payment launches in the US and Japan, and both settlement
11
- currencies are first-class:
12
-
13
- - **JPY**, settled on-chain in **JPYC**
14
- - **USD**, settled on-chain in **USDC**
15
-
16
- A merchant settles in a single currency, chosen at onboarding. The settlement fee
17
- percentage (the payment fee column below) is identical in both currencies. Only
18
- the flat amounts — the monthly base fee and the per-payment minimum fee — are
19
- quoted per currency.
20
-
21
- ## Trial Plans
22
-
23
- | Plan | Monthly fee (JPY) | Monthly fee (USD) | Payment fee | Intended starting point |
24
- | --- | ---: | ---: | ---: | --- |
25
- | Launch | JPY 0 | USD 0 | 1.8% | Proofs of concept and low-volume trials |
26
- | Starter | JPY 980 | USD 6.00 | 1.0% | Early production checkout trials |
27
- | Growth | JPY 2,980 | USD 18.00 | 0.7% | Growing EC, booking, membership, and API services |
28
- | Pro | JPY 9,800 | USD 60.00 | 0.5% | Higher-volume merchant integrations |
29
-
30
- Every payment is fee-bearing at the plan rate. The minimum fee is JPY 30
31
- (USD merchants: USD 0.20) per payment. The minimum covers the worst-case
32
- per-payment settlement cost (an on-chain signature plus network gas), so small
33
- payments are never processed at a loss; on larger payments the percentage rate
34
- applies instead.
35
-
36
- USD pricing is the JPY tier converted at roughly 160 JPY/USD and rounded to
37
- clean price points that keep the same 1:3:10 tier ratio.
38
-
39
- If no paid plan is selected during merchant setup, the merchant account uses the
40
- Launch plan. A merchant billing mandate is still required before accepting
41
- payments so Siglume can collect the monthly base fee automatically.
42
-
43
- The current Siglume API and merchant registry may still expose the internal
44
- `billing_plan` value `free` for the Launch tier. Treat `free` as an internal
45
- compatibility key, not the public plan name. (Until 2026-06-12 the Launch plan
46
- included a free monthly allowance of 100 payments; that allowance has been
47
- retired — the platform `fee_bps` response is always the source of truth.)
48
-
49
- Per-payment fees are collected during payment settlement through the
50
- DirectPaymentHub split. The merchant receives the net amount after that fee.
51
- Monthly base fees are collected separately through the merchant billing mandate.
52
-
53
- The same fee schedule applies in JPY and USD. The Siglume platform returns
54
- `fee_bps` in the merchant's settlement currency on every payment requirement, so
55
- the SDK never has to know which currency table to read — it just trusts the
56
- value Siglume returns.
57
-
58
- ## SDK Behavior
59
-
60
- The SDK does not calculate merchant invoices or enforce plan limits locally.
61
- Instead, it exposes billing-related values returned by Siglume, including
62
- `fee_bps` on a payment requirement. This keeps merchant billing centralized in
63
- the Siglume platform and avoids stale client-side pricing logic.
64
-
65
- ## Supported Use Cases
66
-
67
- The trial pricing is intended for:
68
-
69
- - Small EC checkout
70
- - Booking and reservation services
71
- - Membership services
72
- - Paid API access
73
- - Agent-to-agent payment experiments
1
+ # Pricing
2
+
3
+ This page documents the trial-phase merchant pricing for Siglume Direct Request
4
+ Payment as of 2026-06-12. Pricing can change by agreement or future product
5
+ release; the Siglume platform response is the source of truth for per-payment
6
+ fee data returned at runtime.
7
+
8
+ ## Settlement Currencies
9
+
10
+ Siglume Direct Request Payment launches in the US and Japan, and both settlement
11
+ currencies are first-class:
12
+
13
+ - **JPY**, settled on-chain in **JPYC**
14
+ - **USD**, settled on-chain in **USDC**
15
+
16
+ A merchant settles in a single currency, chosen at onboarding. The settlement fee
17
+ percentage (the payment fee column below) is identical in both currencies. Only
18
+ the flat amounts — the monthly base fee and the per-payment minimum fee — are
19
+ quoted per currency.
20
+
21
+ ## Trial Plans
22
+
23
+ | Plan | Monthly fee (JPY) | Monthly fee (USD) | Payment fee | Intended starting point |
24
+ | --- | ---: | ---: | ---: | --- |
25
+ | Launch | JPY 0 | USD 0 | 1.8% | Proofs of concept and low-volume trials |
26
+ | Starter | JPY 980 | USD 6.00 | 1.0% | Early production checkout trials |
27
+ | Growth | JPY 2,980 | USD 18.00 | 0.7% | Growing EC, booking, membership, and API services |
28
+ | Pro | JPY 9,800 | USD 60.00 | 0.5% | Higher-volume merchant integrations |
29
+
30
+ Every payment is fee-bearing at the plan rate. The minimum fee is JPY 30
31
+ (USD merchants: USD 0.20) per payment. The minimum covers the worst-case
32
+ per-payment settlement cost (an on-chain signature plus network gas), so small
33
+ payments are never processed at a loss; on larger payments the percentage rate
34
+ applies instead.
35
+
36
+ USD pricing is the JPY tier converted at roughly 160 JPY/USD and rounded to
37
+ clean price points that keep the same 1:3:10 tier ratio.
38
+
39
+ If no paid plan is selected during merchant setup, the merchant account uses the
40
+ Launch plan. A merchant billing mandate is still required before accepting
41
+ payments so Siglume can collect the monthly base fee automatically.
42
+
43
+ The current Siglume API and merchant registry may still expose the internal
44
+ `billing_plan` value `free` for the Launch tier. Treat `free` as an internal
45
+ compatibility key, not the public plan name. (Until 2026-06-12 the Launch plan
46
+ included a free monthly allowance of 100 payments; that allowance has been
47
+ retired — the platform `fee_bps` response is always the source of truth.)
48
+
49
+ Per-payment fees are collected during payment settlement through the
50
+ DirectPaymentHub split. The merchant receives the net amount after that fee.
51
+ Monthly base fees are collected separately through the merchant billing mandate.
52
+
53
+ The same fee schedule applies in JPY and USD. The Siglume platform returns
54
+ `fee_bps` in the merchant's settlement currency on every payment requirement, so
55
+ the SDK never has to know which currency table to read — it just trusts the
56
+ value Siglume returns.
57
+
58
+ ## SDK Behavior
59
+
60
+ The SDK does not calculate merchant invoices or enforce plan limits locally.
61
+ Instead, it exposes billing-related values returned by Siglume, including
62
+ `fee_bps` on a payment requirement. This keeps merchant billing centralized in
63
+ the Siglume platform and avoids stale client-side pricing logic.
64
+
65
+ ## Supported Use Cases
66
+
67
+ The trial pricing is intended for:
68
+
69
+ - Small EC checkout
70
+ - Booking and reservation services
71
+ - Membership services
72
+ - Paid API access
73
+ - Agent-to-agent payment experiments
package/docs/security.md CHANGED
@@ -1,99 +1,110 @@
1
- # Security Guide
2
-
3
- Direct Request Payment is a wallet payment rail. Treat it like payment
4
- infrastructure, not like a generic API call.
5
-
6
- ## Do Not Expose Secrets
7
-
8
- These values must stay server-side:
9
-
10
- - `SIGLUME_DIRECT_PAYMENT_CHALLENGE_SECRET`
11
- - `SIGLUME_WEBHOOK_SECRET`
12
- - any merchant administrative credentials
13
-
14
- The buyer-facing browser may receive the signed `challenge` string, but never
15
- the secret that produced it.
16
-
17
- ## Keep JWT Roles Separate
18
-
19
- Use the merchant's Siglume JWT only for setup actions such as `setupCheckout`,
20
- challenge secret rotation, billing mandate preparation, and webhook subscription
21
- creation.
22
-
23
- Use the buyer's Siglume JWT only when creating and paying a payment requirement.
24
- A merchant JWT or Developer Portal `cli_` key must not be used to charge a
25
- customer wallet.
26
-
27
- ## Bind the Order Server-Side
28
-
29
- The HMAC challenge covers:
30
-
31
- ```text
32
- merchant:amount_minor:currency:nonce
33
- ```
34
-
35
- Use a nonce derived from a durable order payment attempt, for example
36
- `order_123-attempt_1`. The nonce must not contain `:` because the platform
37
- challenge is encoded as `scheme:nonce:signature`. Store the returned
38
- `challenge_hash` on the order. When a
39
- webhook arrives, look up the order by `challenge_hash`.
40
-
41
- ## Do Not Trust Browser Amounts
42
-
43
- The merchant server owns:
44
-
45
- - SKU or plan
46
- - amount in minor units
47
- - currency
48
- - nonce
49
-
50
- If a browser says the order total is 1200 JPY, treat that as display state only.
51
- Re-read the order server-side before generating the challenge.
52
-
53
- ## Webhook Verification
54
-
55
- Verify the `Siglume-Signature` header using the raw request body. Do not parse
56
- and re-stringify JSON before verification.
57
-
58
- The SDK expects the Siglume signature format:
59
-
60
- ```text
61
- t=<unix timestamp>,v1=<hex hmac sha256>
62
- ```
63
-
64
- The signed payload is:
65
-
66
- ```text
67
- <timestamp>.<raw body>
68
- ```
69
-
70
- The default tolerance is 300 seconds.
71
-
72
- Use verified webhook data as the durable completion signal. Browser redirects,
73
- client-side callbacks, or local transaction responses can improve UX, but they
74
- should not be the only source used to fulfill an order.
75
-
76
- ## Idempotency
77
-
78
- Fulfill exactly once per order. Store at least:
79
-
80
- - order id
81
- - challenge hash
82
- - Siglume requirement id
83
- - on-chain receipt id or transaction hash if present
84
- - fulfillment state
85
-
86
- Duplicate webhook deliveries and manual redelivery can occur. A duplicate
87
- webhook with the same requirement id must not ship the order twice.
88
-
89
- ## What Direct Request Payment Is Not
90
-
91
- Direct Request Payment is not:
92
-
93
- - stored value
94
- - prepaid points
95
- - escrow
96
- - a platform balance
97
- - a card payment fallback
98
-
99
- It is a one-request wallet payment gate backed by an on-chain receipt.
1
+ # Security Guide
2
+
3
+ Direct Request Payment is a wallet payment rail. Treat it like payment
4
+ infrastructure, not like a generic API call.
5
+
6
+ ## Do Not Expose Secrets
7
+
8
+ These values must stay server-side:
9
+
10
+ - `SIGLUME_DIRECT_PAYMENT_CHALLENGE_SECRET`
11
+ - `SIGLUME_WEBHOOK_SECRET`
12
+ - any merchant administrative credentials
13
+
14
+ The buyer-facing browser may receive the signed `challenge` string, but never
15
+ the secret that produced it.
16
+
17
+ ## Keep JWT Roles Separate
18
+
19
+ Use the merchant's Siglume JWT only for setup actions such as `setupCheckout`,
20
+ challenge secret rotation, billing mandate preparation, and webhook subscription
21
+ creation.
22
+
23
+ Use the buyer's Siglume JWT only when creating and paying a payment requirement.
24
+ A merchant JWT or Developer Portal `cli_` key must not be used to charge a
25
+ customer wallet.
26
+
27
+ ## Bind the Order Server-Side
28
+
29
+ The HMAC challenge covers:
30
+
31
+ ```text
32
+ merchant:amount_minor:currency:nonce
33
+ ```
34
+
35
+ Use a nonce derived from a durable order payment attempt, for example
36
+ `order_123-attempt_1`. The nonce must not contain `:` because the platform
37
+ challenge is encoded as `scheme:nonce:signature`. Store the returned
38
+ `challenge_hash` on the order. When a
39
+ webhook arrives, look up the order by `challenge_hash`.
40
+
41
+ Recurring approvals use a different challenge scheme and HMAC material:
42
+
43
+ ```text
44
+ merchant:amount_minor:currency:cadence:nonce
45
+ ```
46
+
47
+ `cadence="monthly"` is for subscriptions. `cadence="daily"` is the scheduled
48
+ autopay approval tag; it does not itself limit occurrences to once per day.
49
+ Scheduled autopay execution is bounded by the buyer-approved per-run, daily, and
50
+ monthly auto-pay budget.
51
+
52
+ ## Do Not Trust Browser Amounts
53
+
54
+ The merchant server owns:
55
+
56
+ - SKU or plan
57
+ - amount in minor units
58
+ - currency
59
+ - nonce
60
+
61
+ If a browser says the order total is 1200 JPY, treat that as display state only.
62
+ Re-read the order server-side before generating the challenge.
63
+
64
+ ## Webhook Verification
65
+
66
+ Verify the `Siglume-Signature` header using the raw request body. Do not parse
67
+ and re-stringify JSON before verification.
68
+
69
+ The SDK expects the Siglume signature format:
70
+
71
+ ```text
72
+ t=<unix timestamp>,v1=<hex hmac sha256>
73
+ ```
74
+
75
+ The signed payload is:
76
+
77
+ ```text
78
+ <timestamp>.<raw body>
79
+ ```
80
+
81
+ The default tolerance is 300 seconds.
82
+
83
+ Use verified webhook data as the durable completion signal. Browser redirects,
84
+ client-side callbacks, or local transaction responses can improve UX, but they
85
+ should not be the only source used to fulfill an order.
86
+
87
+ ## Idempotency
88
+
89
+ Fulfill exactly once per order. Store at least:
90
+
91
+ - order id
92
+ - challenge hash
93
+ - Siglume requirement id
94
+ - on-chain receipt id or transaction hash if present
95
+ - fulfillment state
96
+
97
+ Duplicate webhook deliveries and manual redelivery can occur. A duplicate
98
+ webhook with the same requirement id must not ship the order twice.
99
+
100
+ ## What Direct Request Payment Is Not
101
+
102
+ Direct Request Payment is not:
103
+
104
+ - stored value
105
+ - prepaid points
106
+ - escrow
107
+ - a platform balance
108
+ - a card payment fallback
109
+
110
+ It is a one-request wallet payment gate backed by an on-chain receipt.
@@ -1,106 +1,106 @@
1
- import express from "express";
2
- import {
3
- createDirectRequestPaymentChallenge,
4
- DirectRequestPaymentClient,
5
- verifyDirectRequestPaymentWebhook,
6
- } from "@siglume/direct-request-payment";
7
-
8
- const app = express();
9
- const port = Number(process.env.PORT || 3000);
10
- const merchantKey = process.env.SIGLUME_DIRECT_PAYMENT_MERCHANT || "example_merchant";
11
-
12
- // Use JSON for normal routes. Use raw body only on the webhook route.
13
- app.use((req, res, next) => {
14
- if (req.path === "/siglume/webhook") {
15
- next();
16
- return;
17
- }
18
- express.json()(req, res, next);
19
- });
20
-
21
- const orders = new Map<string, any>();
22
-
23
- const asyncRoute =
24
- (handler: express.RequestHandler): express.RequestHandler =>
25
- (req, res, next) => {
26
- Promise.resolve(handler(req, res, next)).catch(next);
27
- };
28
-
29
- app.post("/checkout/siglume/start", asyncRoute(async (req, res) => {
30
- const orderId = String(req.body.order_id || "");
31
- const order = orders.get(orderId);
32
- if (!order) {
33
- res.status(404).json({ error: "order_not_found" });
34
- return;
35
- }
36
-
37
- order.payment_attempt = Number(order.payment_attempt || 0) + 1;
38
- const challenge = await createDirectRequestPaymentChallenge({
39
- merchant: merchantKey,
40
- amount_minor: order.amount_minor,
41
- currency: order.currency,
42
- secret: process.env.SIGLUME_DIRECT_PAYMENT_CHALLENGE_SECRET!,
43
- nonce: `${order.id}-attempt_${order.payment_attempt}`,
44
- });
45
-
46
- order.siglume_challenge_hash = challenge.challenge_hash;
47
- order.siglume_payment_status = "pending";
48
-
49
- res.json({
50
- order_id: order.id,
51
- amount_minor: order.amount_minor,
52
- currency: order.currency,
53
- siglume_challenge: challenge.challenge,
54
- });
55
- }));
56
-
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
- app.post("/siglume/webhook", express.raw({ type: "application/json" }), asyncRoute(async (req, res) => {
82
- const header = String(req.headers["siglume-signature"] || "");
83
- const { event } = await verifyDirectRequestPaymentWebhook(
84
- process.env.SIGLUME_WEBHOOK_SECRET!,
85
- req.body,
86
- header,
87
- );
88
-
89
- if (event.type === "direct_payment.confirmed") {
90
- const challengeHash = String(event.data.challenge_hash || "");
91
- const order = [...orders.values()].find((item) => item.siglume_challenge_hash === challengeHash);
92
- if (order) {
93
- order.siglume_payment_status = "paid";
94
- order.siglume_requirement_id = event.data.requirement_id || event.data.direct_payment_requirement_id;
95
- }
96
- }
97
-
98
- res.status(204).send();
99
- }));
100
-
101
- app.use((error: unknown, _req: express.Request, res: express.Response, _next: express.NextFunction) => {
102
- const message = error instanceof Error ? error.message : "internal_error";
103
- res.status(500).json({ error: message });
104
- });
105
-
106
- app.listen(port);
1
+ import express from "express";
2
+ import {
3
+ createDirectRequestPaymentChallenge,
4
+ DirectRequestPaymentClient,
5
+ verifyDirectRequestPaymentWebhook,
6
+ } from "@siglume/direct-request-payment";
7
+
8
+ const app = express();
9
+ const port = Number(process.env.PORT || 3000);
10
+ const merchantKey = process.env.SIGLUME_DIRECT_PAYMENT_MERCHANT || "example_merchant";
11
+
12
+ // Use JSON for normal routes. Use raw body only on the webhook route.
13
+ app.use((req, res, next) => {
14
+ if (req.path === "/siglume/webhook") {
15
+ next();
16
+ return;
17
+ }
18
+ express.json()(req, res, next);
19
+ });
20
+
21
+ const orders = new Map<string, any>();
22
+
23
+ const asyncRoute =
24
+ (handler: express.RequestHandler): express.RequestHandler =>
25
+ (req, res, next) => {
26
+ Promise.resolve(handler(req, res, next)).catch(next);
27
+ };
28
+
29
+ app.post("/checkout/siglume/start", asyncRoute(async (req, res) => {
30
+ const orderId = String(req.body.order_id || "");
31
+ const order = orders.get(orderId);
32
+ if (!order) {
33
+ res.status(404).json({ error: "order_not_found" });
34
+ return;
35
+ }
36
+
37
+ order.payment_attempt = Number(order.payment_attempt || 0) + 1;
38
+ const challenge = await createDirectRequestPaymentChallenge({
39
+ merchant: merchantKey,
40
+ amount_minor: order.amount_minor,
41
+ currency: order.currency,
42
+ secret: process.env.SIGLUME_DIRECT_PAYMENT_CHALLENGE_SECRET!,
43
+ nonce: `${order.id}-attempt_${order.payment_attempt}`,
44
+ });
45
+
46
+ order.siglume_challenge_hash = challenge.challenge_hash;
47
+ order.siglume_payment_status = "pending";
48
+
49
+ res.json({
50
+ order_id: order.id,
51
+ amount_minor: order.amount_minor,
52
+ currency: order.currency,
53
+ siglume_challenge: challenge.challenge,
54
+ });
55
+ }));
56
+
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
+ app.post("/siglume/webhook", express.raw({ type: "application/json" }), asyncRoute(async (req, res) => {
82
+ const header = String(req.headers["siglume-signature"] || "");
83
+ const { event } = await verifyDirectRequestPaymentWebhook(
84
+ process.env.SIGLUME_WEBHOOK_SECRET!,
85
+ req.body,
86
+ header,
87
+ );
88
+
89
+ if (event.type === "direct_payment.confirmed") {
90
+ const challengeHash = String(event.data.challenge_hash || "");
91
+ const order = [...orders.values()].find((item) => item.siglume_challenge_hash === challengeHash);
92
+ if (order) {
93
+ order.siglume_payment_status = "paid";
94
+ order.siglume_requirement_id = event.data.requirement_id || event.data.direct_payment_requirement_id;
95
+ }
96
+ }
97
+
98
+ res.status(204).send();
99
+ }));
100
+
101
+ app.use((error: unknown, _req: express.Request, res: express.Response, _next: express.NextFunction) => {
102
+ const message = error instanceof Error ? error.message : "internal_error";
103
+ res.status(500).json({ error: message });
104
+ });
105
+
106
+ app.listen(port);
@@ -1,17 +1,17 @@
1
- import { DirectRequestPaymentMerchantClient } from "@siglume/direct-request-payment";
2
-
3
- const merchant = new DirectRequestPaymentMerchantClient({
4
- auth_token: process.env.SIGLUME_MERCHANT_AUTH_TOKEN,
5
- });
6
-
7
- const setup = await merchant.setupCheckout({
8
- merchant: process.env.SIGLUME_DIRECT_PAYMENT_MERCHANT || "example_merchant",
9
- display_name: process.env.SIGLUME_DIRECT_PAYMENT_DISPLAY_NAME || "Example Merchant",
10
- billing_plan: process.env.SIGLUME_DIRECT_PAYMENT_PLAN || "launch",
11
- billing_currency: process.env.SIGLUME_DIRECT_PAYMENT_BILLING_CURRENCY || "JPY",
12
- webhook_callback_url: process.env.SIGLUME_DIRECT_PAYMENT_WEBHOOK_URL,
13
- max_amount_minor: Number(process.env.SIGLUME_DIRECT_PAYMENT_BILLING_CAP_MINOR || 100000),
14
- create_webhook_subscription: Boolean(process.env.SIGLUME_DIRECT_PAYMENT_WEBHOOK_URL),
15
- });
16
-
17
- console.log(JSON.stringify(setup, null, 2));
1
+ import { DirectRequestPaymentMerchantClient } from "@siglume/direct-request-payment";
2
+
3
+ const merchant = new DirectRequestPaymentMerchantClient({
4
+ auth_token: process.env.SIGLUME_MERCHANT_AUTH_TOKEN,
5
+ });
6
+
7
+ const setup = await merchant.setupCheckout({
8
+ merchant: process.env.SIGLUME_DIRECT_PAYMENT_MERCHANT || "example_merchant",
9
+ display_name: process.env.SIGLUME_DIRECT_PAYMENT_DISPLAY_NAME || "Example Merchant",
10
+ billing_plan: process.env.SIGLUME_DIRECT_PAYMENT_PLAN || "launch",
11
+ billing_currency: process.env.SIGLUME_DIRECT_PAYMENT_BILLING_CURRENCY || "JPY",
12
+ webhook_callback_url: process.env.SIGLUME_DIRECT_PAYMENT_WEBHOOK_URL,
13
+ max_amount_minor: Number(process.env.SIGLUME_DIRECT_PAYMENT_BILLING_CAP_MINOR || 100000),
14
+ create_webhook_subscription: Boolean(process.env.SIGLUME_DIRECT_PAYMENT_WEBHOOK_URL),
15
+ });
16
+
17
+ console.log(JSON.stringify(setup, null, 2));