@siglume/direct-request-payment 0.1.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/LICENSE +21 -0
- package/README.md +237 -0
- package/dist/index.cjs +555 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +235 -0
- package/dist/index.d.ts +235 -0
- package/dist/index.js +524 -0
- package/dist/index.js.map +1 -0
- package/docs/api-reference.md +116 -0
- package/docs/merchant-quickstart.md +255 -0
- package/docs/pricing.md +56 -0
- package/docs/security.md +85 -0
- package/examples/express-checkout.ts +105 -0
- package/package.json +57 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Siglume Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# @siglume/direct-request-payment
|
|
2
|
+
|
|
3
|
+
Merchant SDK for Siglume Direct Request Payment checkout integrations.
|
|
4
|
+
|
|
5
|
+
Use this package when an external EC site, booking service, membership service,
|
|
6
|
+
or paid API wants to accept Siglume wallet payments without taking custody of
|
|
7
|
+
customer funds.
|
|
8
|
+
|
|
9
|
+
This SDK is intentionally separate from `@siglume/api-sdk`:
|
|
10
|
+
|
|
11
|
+
- `@siglume/api-sdk` is for publishing agent-facing APIs to the Siglume API Store.
|
|
12
|
+
- `@siglume/direct-request-payment` is for external merchants integrating
|
|
13
|
+
Siglume Direct Request Payment into their own checkout.
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @siglume/direct-request-payment
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install siglume-direct-request-payment
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Node.js 18 or later is required for the TypeScript SDK. Python 3.11 or later is
|
|
26
|
+
required for the Python SDK.
|
|
27
|
+
|
|
28
|
+
## Current Platform Contract
|
|
29
|
+
|
|
30
|
+
The public product name is **Siglume Direct Request Payment**. The current
|
|
31
|
+
platform payload still uses the internal mode name `external_402`; this SDK sets
|
|
32
|
+
that value for you when creating a payment requirement.
|
|
33
|
+
|
|
34
|
+
Payment requirement creation must run in the authenticated buyer's Siglume
|
|
35
|
+
context. Your merchant server must not use a merchant secret or API key to
|
|
36
|
+
charge a customer wallet. The merchant server creates the signed challenge; the
|
|
37
|
+
buyer-facing Siglume payment flow creates and pays the requirement.
|
|
38
|
+
|
|
39
|
+
`DirectRequestPaymentClient` requires the buyer's Siglume bearer token. Do not
|
|
40
|
+
use a Developer Portal `cli_` API key with this package.
|
|
41
|
+
|
|
42
|
+
## Trial Pricing
|
|
43
|
+
|
|
44
|
+
Siglume Direct Request Payment is currently offered with trial-phase merchant
|
|
45
|
+
pricing designed for small EC sites, booking services, membership services, paid
|
|
46
|
+
APIs, and agent-to-agent payment experiments.
|
|
47
|
+
|
|
48
|
+
| Plan | Monthly fee | Payment fee |
|
|
49
|
+
| --- | ---: | ---: |
|
|
50
|
+
| Launch | JPY 0 | 0% through 100 payments/month, then 1.8% |
|
|
51
|
+
| Starter | JPY 980 | 1.0% |
|
|
52
|
+
| Growth | JPY 2,980 | 0.7% |
|
|
53
|
+
| Pro | JPY 9,800 | 0.5% |
|
|
54
|
+
|
|
55
|
+
The minimum fee is JPY 3 for each fee-bearing payment, including Launch-plan
|
|
56
|
+
payments after the included monthly allowance. A merchant billing mandate is
|
|
57
|
+
required before accepting payments, even on the Launch plan. The API and merchant
|
|
58
|
+
registry may still expose the internal plan key `free` for this tier. See
|
|
59
|
+
[docs/pricing.md](./docs/pricing.md) for details.
|
|
60
|
+
|
|
61
|
+
Per-payment fees are deducted at payment settlement time, so the merchant
|
|
62
|
+
receives the net amount. Monthly base fees are collected through the merchant
|
|
63
|
+
billing mandate. The listed public pricing is JPY-denominated; USD/USDC merchant
|
|
64
|
+
billing requires separately agreed terms.
|
|
65
|
+
|
|
66
|
+
## Merchant Server: Create a Challenge
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import { createDirectRequestPaymentChallenge } from "@siglume/direct-request-payment";
|
|
70
|
+
|
|
71
|
+
const challenge = await createDirectRequestPaymentChallenge({
|
|
72
|
+
merchant: "example_merchant",
|
|
73
|
+
amount_minor: 1200,
|
|
74
|
+
currency: "JPY",
|
|
75
|
+
secret: process.env.SIGLUME_DIRECT_PAYMENT_CHALLENGE_SECRET!,
|
|
76
|
+
nonce: "order_123-attempt_1",
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Return only challenge.challenge to the buyer-facing checkout.
|
|
80
|
+
// Never return the challenge secret to the browser.
|
|
81
|
+
console.log(challenge.challenge);
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
```py
|
|
85
|
+
import os
|
|
86
|
+
|
|
87
|
+
from siglume_direct_request_payment import create_direct_request_payment_challenge
|
|
88
|
+
|
|
89
|
+
challenge = create_direct_request_payment_challenge(
|
|
90
|
+
merchant="example_merchant",
|
|
91
|
+
amount_minor=1200,
|
|
92
|
+
currency="JPY",
|
|
93
|
+
secret=os.environ["SIGLUME_DIRECT_PAYMENT_CHALLENGE_SECRET"],
|
|
94
|
+
nonce="order_123-attempt_1",
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
print(challenge["challenge"])
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The signed challenge binds:
|
|
101
|
+
|
|
102
|
+
- merchant key
|
|
103
|
+
- amount in minor units
|
|
104
|
+
- currency
|
|
105
|
+
- nonce
|
|
106
|
+
|
|
107
|
+
Changing any of those values invalidates the challenge.
|
|
108
|
+
The nonce must not contain `:` because the current platform challenge format is
|
|
109
|
+
`scheme:nonce:signature`.
|
|
110
|
+
|
|
111
|
+
## Buyer Payment Flow
|
|
112
|
+
|
|
113
|
+
Use `DirectRequestPaymentClient` only with the authenticated buyer's Siglume
|
|
114
|
+
bearer token. `SIGLUME_AUTH_TOKEN` may be used in server-side payment-confirmation
|
|
115
|
+
helpers; `SIGLUME_API_KEY` and Developer Portal `cli_` keys are not accepted.
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
import { DirectRequestPaymentClient } from "@siglume/direct-request-payment";
|
|
119
|
+
|
|
120
|
+
const siglume = new DirectRequestPaymentClient({
|
|
121
|
+
auth_token: buyerSiglumeBearerToken,
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
const requirement = await siglume.createPaymentRequirement({
|
|
125
|
+
merchant: "example_merchant",
|
|
126
|
+
amount_minor: 1200,
|
|
127
|
+
currency: "JPY",
|
|
128
|
+
challenge: challengeFromMerchantServer,
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
if (requirement.approve_transaction_request) {
|
|
132
|
+
await siglume.executeAllowanceTransaction(requirement, { await_finality: true });
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const payment = await siglume.executePaymentTransaction(requirement, {
|
|
136
|
+
await_finality: true,
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
const receiptId = String(payment.receipt?.receipt_id ?? "");
|
|
140
|
+
const verified = await siglume.verifyPaymentRequirement(requirement.requirement_id, {
|
|
141
|
+
receipt_id: receiptId,
|
|
142
|
+
await_finality: false,
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
console.log(verified.status);
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
```py
|
|
149
|
+
from siglume_direct_request_payment import DirectRequestPaymentClient
|
|
150
|
+
|
|
151
|
+
siglume = DirectRequestPaymentClient(auth_token=buyer_siglume_bearer_token)
|
|
152
|
+
|
|
153
|
+
requirement = siglume.create_payment_requirement(
|
|
154
|
+
merchant="example_merchant",
|
|
155
|
+
amount_minor=1200,
|
|
156
|
+
currency="JPY",
|
|
157
|
+
challenge=challenge_from_merchant_server,
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
if requirement.get("approve_transaction_request"):
|
|
161
|
+
siglume.execute_allowance_transaction(requirement, await_finality=True)
|
|
162
|
+
|
|
163
|
+
payment = siglume.execute_payment_transaction(requirement, await_finality=True)
|
|
164
|
+
receipt_id = str((payment.get("receipt") or {}).get("receipt_id") or "")
|
|
165
|
+
|
|
166
|
+
verified = siglume.verify_payment_requirement(
|
|
167
|
+
requirement["requirement_id"],
|
|
168
|
+
receipt_id=receipt_id,
|
|
169
|
+
await_finality=False,
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
print(verified["status"])
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Webhooks
|
|
176
|
+
|
|
177
|
+
Your merchant system should treat Siglume webhooks as the durable delivery
|
|
178
|
+
signal. Always verify the signature against the raw request body before trusting
|
|
179
|
+
the payload. Create a marketplace webhook subscription with
|
|
180
|
+
`POST /v1/market/webhooks/subscriptions`; the response returns the `whsec_`
|
|
181
|
+
signing secret once.
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
import { verifyDirectRequestPaymentWebhook } from "@siglume/direct-request-payment";
|
|
185
|
+
|
|
186
|
+
const { event } = await verifyDirectRequestPaymentWebhook(
|
|
187
|
+
process.env.SIGLUME_WEBHOOK_SECRET!,
|
|
188
|
+
rawRequestBody,
|
|
189
|
+
request.headers["siglume-signature"],
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
if (event.type === "direct_payment.confirmed") {
|
|
193
|
+
// Mark the order paid if event.data.challenge_hash/order mapping matches.
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
```py
|
|
198
|
+
import os
|
|
199
|
+
|
|
200
|
+
from siglume_direct_request_payment import verify_direct_request_payment_webhook
|
|
201
|
+
|
|
202
|
+
verified = verify_direct_request_payment_webhook(
|
|
203
|
+
os.environ["SIGLUME_WEBHOOK_SECRET"],
|
|
204
|
+
raw_request_body,
|
|
205
|
+
siglume_signature_header,
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
if verified["event"]["type"] == "direct_payment.confirmed":
|
|
209
|
+
# Mark the order paid if event.data.challenge_hash/order mapping matches.
|
|
210
|
+
pass
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Security Rules
|
|
214
|
+
|
|
215
|
+
- Keep the challenge secret on the merchant server only.
|
|
216
|
+
- Keep merchant order amount and currency server-authored.
|
|
217
|
+
- Use one nonce per order payment attempt.
|
|
218
|
+
- Store `challenge_hash` with the order and reject mismatches.
|
|
219
|
+
- Make order fulfillment idempotent by `requirement_id` and order id.
|
|
220
|
+
- Verify webhook signatures against the raw body.
|
|
221
|
+
- Do not use a merchant token to charge a customer wallet.
|
|
222
|
+
- Do not treat Direct Request Payment as stored value, prepaid points, escrow, or
|
|
223
|
+
a platform balance.
|
|
224
|
+
|
|
225
|
+
Read [docs/security.md](./docs/security.md) before going live.
|
|
226
|
+
|
|
227
|
+
## Documentation
|
|
228
|
+
|
|
229
|
+
- [Merchant quickstart](./docs/merchant-quickstart.md)
|
|
230
|
+
- [API reference](./docs/api-reference.md)
|
|
231
|
+
- [Pricing](./docs/pricing.md)
|
|
232
|
+
- [Security guide](./docs/security.md)
|
|
233
|
+
- [Express checkout example](./examples/express-checkout.ts)
|
|
234
|
+
|
|
235
|
+
## License
|
|
236
|
+
|
|
237
|
+
MIT
|