@siglume/direct-request-payment 0.4.6 → 0.4.8
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 +20 -0
- package/README.md +55 -46
- package/dist/index.cjs +116 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +48 -2
- package/dist/index.d.ts +48 -2
- package/dist/index.js +116 -1
- package/dist/index.js.map +1 -1
- package/docs/announcement-ja.md +2 -2
- package/docs/api-reference.md +40 -15
- package/docs/merchant-quickstart.md +76 -64
- package/docs/pricing.md +14 -10
- package/examples/express-checkout.ts +32 -22
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.8 - 2026-06-19
|
|
4
|
+
|
|
5
|
+
Webhook sample hardening release.
|
|
6
|
+
|
|
7
|
+
- Added TypeScript and Python confirmation classifiers for Standard settled
|
|
8
|
+
payments, Micro / Nano accepted usage, and Micro / Nano settled batches.
|
|
9
|
+
- Updated public webhook samples to require finality, settlement status, and
|
|
10
|
+
non-empty settlement identifiers before fulfilling or reconciling.
|
|
11
|
+
- Routed unknown Micro / Nano challenge hashes and malformed settlement batch
|
|
12
|
+
confirmations to manual review in copy-paste samples.
|
|
13
|
+
|
|
14
|
+
## 0.4.7 - 2026-06-19
|
|
15
|
+
|
|
16
|
+
Documentation-only patch release.
|
|
17
|
+
|
|
18
|
+
- Clarified that SDRP merchant setup and billing mandate terms assume acceptance
|
|
19
|
+
of automatic Micro / Nano delayed aggregated settlement for low-price bands.
|
|
20
|
+
- Replaced merchant-specific override wording with the operational rule that
|
|
21
|
+
products requiring immediate settlement should be priced in the Standard band.
|
|
22
|
+
|
|
3
23
|
## 0.4.6 - 2026-06-19
|
|
4
24
|
|
|
5
25
|
Patch release for the external webhook-state re-review.
|
package/README.md
CHANGED
|
@@ -103,10 +103,10 @@ const session = await merchant.createCheckoutSession({
|
|
|
103
103
|
});
|
|
104
104
|
redirect(session.checkout_url); // -> https://siglume.com/pay/<session_id>
|
|
105
105
|
|
|
106
|
-
// 3. Handle the signed direct_payment.confirmed webhook.
|
|
107
|
-
//
|
|
108
|
-
//
|
|
109
|
-
// until the later
|
|
106
|
+
// 3. Handle the signed direct_payment.confirmed webhook. Use
|
|
107
|
+
// classifyDirectPaymentConfirmation(event). Fulfill Standard only for
|
|
108
|
+
// standard_settled; treat metered_usage_accepted as fulfilled-unsettled
|
|
109
|
+
// until the later metered_batch_settled event arrives.
|
|
110
110
|
// Poll merchant.getCheckoutSession(session.session_id) if you also want to
|
|
111
111
|
// show status in your own UI.
|
|
112
112
|
```
|
|
@@ -138,10 +138,10 @@ session = merchant.create_checkout_session(
|
|
|
138
138
|
)
|
|
139
139
|
redirect(session["checkout_url"]) # -> https://siglume.com/pay/<session_id>
|
|
140
140
|
|
|
141
|
-
# 3. Handle the signed direct_payment.confirmed webhook.
|
|
142
|
-
#
|
|
143
|
-
#
|
|
144
|
-
# until the later
|
|
141
|
+
# 3. Handle the signed direct_payment.confirmed webhook. Use
|
|
142
|
+
# classify_direct_payment_confirmation(event). Fulfill Standard only for
|
|
143
|
+
# standard_settled; treat metered_usage_accepted as fulfilled-unsettled
|
|
144
|
+
# until the later metered_batch_settled event arrives.
|
|
145
145
|
# Poll merchant.get_checkout_session(session["session_id"]) if you also want
|
|
146
146
|
# to show status in your own UI.
|
|
147
147
|
```
|
|
@@ -193,10 +193,12 @@ weekly / monthly settlement schedule are in [docs/pricing.md](./docs/pricing.md)
|
|
|
193
193
|
Provider revenue in the Micro and Nano bands is not settled revenue until the
|
|
194
194
|
weekly or monthly on-chain settlement succeeds. Siglume keeps outstanding failed
|
|
195
195
|
settlements for retry under the published policy, but does not advance or
|
|
196
|
-
guarantee provider revenue before settlement succeeds.
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
before
|
|
196
|
+
guarantee provider revenue before settlement succeeds. Merchant setup and the
|
|
197
|
+
billing mandate terms assume the merchant accepts this Micro / Nano delayed
|
|
198
|
+
aggregated settlement model whenever they offer amounts in these bands. If a
|
|
199
|
+
product cannot fulfill before provider revenue is settled, keep the price in the
|
|
200
|
+
Standard band; in practice, do not offer JPY 500-and-under or USD 3-and-under
|
|
201
|
+
items for that product.
|
|
200
202
|
Micro / Nano budget checks reserve spending capacity only; they do not lock,
|
|
201
203
|
escrow, or guarantee the buyer's wallet balance, allowance, or settlement funds.
|
|
202
204
|
Sub-minor-unit Nano fees are accumulated with decimal precision and rounded only
|
|
@@ -260,16 +262,19 @@ amounts differ.
|
|
|
260
262
|
| Under JPY 50 / up to 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) |
|
|
261
263
|
|
|
262
264
|
A merchant billing mandate is required before accepting payments, even on the
|
|
263
|
-
Launch plan. The current public API
|
|
264
|
-
JPY 500-and-under / USD 3-and-under
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
is
|
|
271
|
-
|
|
272
|
-
|
|
265
|
+
Launch plan. The current public API chooses the payment band from
|
|
266
|
+
`amount_minor`; JPY 500-and-under / USD 3-and-under payments are routed to
|
|
267
|
+
Micro / Nano delayed aggregated settlement. Accepting the SDRP merchant terms
|
|
268
|
+
means accepting automatic Micro / Nano delayed aggregated settlement for those
|
|
269
|
+
low-price bands. If immediate on-chain settlement is a hard requirement, price
|
|
270
|
+
the item in the Standard band; in practice, do not offer JPY 500-and-under or
|
|
271
|
+
USD 3-and-under items for that product. Public Direct Payment / Hosted Checkout
|
|
272
|
+
`amount_minor` is a positive integer in minor currency units, so public one-time
|
|
273
|
+
Nano amounts start at JPY 1 or USD 0.01. For Standard Payment, `fee_bps`
|
|
274
|
+
returned on a payment requirement is the authoritative fee rate for that payment
|
|
275
|
+
in the merchant's settlement currency. For Micro / Nano, the statement APIs
|
|
276
|
+
expose `protocol_fee_minor`, `gross_buyer_debit_minor`, `buyer_debit_minor`, and
|
|
277
|
+
`rounding_delta_minor`.
|
|
273
278
|
The full fee table and the weekly / monthly settlement schedule live in
|
|
274
279
|
[docs/pricing.md](./docs/pricing.md). Statement APIs for "how much was used,
|
|
275
280
|
when will it close, when can it debit, and what is settled" are documented in
|
|
@@ -520,7 +525,10 @@ the payload. Create a marketplace webhook subscription with
|
|
|
520
525
|
signing secret once.
|
|
521
526
|
|
|
522
527
|
```ts
|
|
523
|
-
import {
|
|
528
|
+
import {
|
|
529
|
+
classifyDirectPaymentConfirmation,
|
|
530
|
+
verifyDirectRequestPaymentWebhook,
|
|
531
|
+
} from "@siglume/direct-request-payment";
|
|
524
532
|
|
|
525
533
|
const { event } = await verifyDirectRequestPaymentWebhook(
|
|
526
534
|
process.env.SIGLUME_WEBHOOK_SECRET!,
|
|
@@ -529,18 +537,16 @@ const { event } = await verifyDirectRequestPaymentWebhook(
|
|
|
529
537
|
);
|
|
530
538
|
|
|
531
539
|
if (event.type === "direct_payment.confirmed") {
|
|
532
|
-
|
|
540
|
+
const confirmation = classifyDirectPaymentConfirmation(event);
|
|
541
|
+
if (confirmation.kind === "metered_batch_settled") {
|
|
533
542
|
// Reconcile settled Micro / Nano batches by settlement_batch_id /
|
|
534
543
|
// usage_event_digest; these events do not carry an order challenge hash.
|
|
535
|
-
} else if (
|
|
536
|
-
event.data.pricing_band === "standard" &&
|
|
537
|
-
event.data.finality === "per_payment_onchain" &&
|
|
538
|
-
event.data.settlement_status === "settled"
|
|
539
|
-
) {
|
|
544
|
+
} else if (confirmation.kind === "standard_settled") {
|
|
540
545
|
// Mark the order paid once if event.data.challenge_hash/order mapping matches.
|
|
541
|
-
} else if (
|
|
542
|
-
// Mark fulfilled-but-unsettled
|
|
543
|
-
|
|
546
|
+
} else if (confirmation.kind === "metered_usage_accepted") {
|
|
547
|
+
// Mark fulfilled-but-unsettled after matching confirmation.challenge_hash.
|
|
548
|
+
} else {
|
|
549
|
+
// Route confirmation.reason to manual review. Do not mark paid or fulfilled.
|
|
544
550
|
}
|
|
545
551
|
}
|
|
546
552
|
```
|
|
@@ -548,7 +554,10 @@ if (event.type === "direct_payment.confirmed") {
|
|
|
548
554
|
```py
|
|
549
555
|
import os
|
|
550
556
|
|
|
551
|
-
from siglume_direct_request_payment import
|
|
557
|
+
from siglume_direct_request_payment import (
|
|
558
|
+
classify_direct_payment_confirmation,
|
|
559
|
+
verify_direct_request_payment_webhook,
|
|
560
|
+
)
|
|
552
561
|
|
|
553
562
|
verified = verify_direct_request_payment_webhook(
|
|
554
563
|
os.environ["SIGLUME_WEBHOOK_SECRET"],
|
|
@@ -557,30 +566,30 @@ verified = verify_direct_request_payment_webhook(
|
|
|
557
566
|
)
|
|
558
567
|
|
|
559
568
|
if verified["event"]["type"] == "direct_payment.confirmed":
|
|
560
|
-
|
|
561
|
-
if
|
|
569
|
+
confirmation = classify_direct_payment_confirmation(verified["event"])
|
|
570
|
+
if confirmation["kind"] == "metered_batch_settled":
|
|
562
571
|
# Reconcile settled Micro / Nano batches by settlement_batch_id /
|
|
563
572
|
# usage_event_digest; these events do not carry an order challenge hash.
|
|
564
573
|
pass
|
|
565
|
-
elif
|
|
566
|
-
data.get("pricing_band") == "standard"
|
|
567
|
-
and data.get("finality") == "per_payment_onchain"
|
|
568
|
-
and data.get("settlement_status") == "settled"
|
|
569
|
-
):
|
|
574
|
+
elif confirmation["kind"] == "standard_settled":
|
|
570
575
|
# Mark the order paid once if event.data.challenge_hash/order mapping matches.
|
|
571
576
|
pass
|
|
572
|
-
elif
|
|
573
|
-
# Mark fulfilled-but-unsettled
|
|
574
|
-
|
|
577
|
+
elif confirmation["kind"] == "metered_usage_accepted":
|
|
578
|
+
# Mark fulfilled-but-unsettled after matching confirmation["challenge_hash"].
|
|
579
|
+
pass
|
|
580
|
+
else:
|
|
581
|
+
# Route confirmation["reason"] to manual review. Do not mark paid or fulfilled.
|
|
575
582
|
pass
|
|
576
583
|
```
|
|
577
584
|
|
|
578
585
|
New `direct_payment.confirmed` payloads include `pricing_band`,
|
|
579
586
|
`settlement_cadence`, `finality`, `protocol_fee_minor`, `settlement_status`,
|
|
580
587
|
`settlement_batch_id`, `chain_receipt_id`, `usage_event_digest`, `settled_at`,
|
|
581
|
-
and when available `request_hash_v2`. Use
|
|
582
|
-
|
|
583
|
-
|
|
588
|
+
and when available `request_hash_v2`. Use
|
|
589
|
+
`classifyDirectPaymentConfirmation(event)` /
|
|
590
|
+
`classify_direct_payment_confirmation(event)` or the same machine-field checks
|
|
591
|
+
instead of inferring settlement semantics from the event name alone. Do not mark
|
|
592
|
+
an order paid from the event type alone.
|
|
584
593
|
|
|
585
594
|
## Security Rules
|
|
586
595
|
|
package/dist/index.cjs
CHANGED
|
@@ -34,11 +34,15 @@ __export(src_exports, {
|
|
|
34
34
|
DEFAULT_WEBHOOK_TOLERANCE_SECONDS: () => DEFAULT_WEBHOOK_TOLERANCE_SECONDS,
|
|
35
35
|
DIRECT_REQUEST_PAYMENT_ALLOWANCE_RECEIPT_KIND: () => DIRECT_REQUEST_PAYMENT_ALLOWANCE_RECEIPT_KIND,
|
|
36
36
|
DIRECT_REQUEST_PAYMENT_CHALLENGE_SCHEME: () => DIRECT_REQUEST_PAYMENT_CHALLENGE_SCHEME,
|
|
37
|
+
DIRECT_REQUEST_PAYMENT_METERED_ACCEPTED_STATUS: () => DIRECT_REQUEST_PAYMENT_METERED_ACCEPTED_STATUS,
|
|
38
|
+
DIRECT_REQUEST_PAYMENT_METERED_FINALITY: () => DIRECT_REQUEST_PAYMENT_METERED_FINALITY,
|
|
37
39
|
DIRECT_REQUEST_PAYMENT_MODE: () => DIRECT_REQUEST_PAYMENT_MODE,
|
|
38
40
|
DIRECT_REQUEST_PAYMENT_RECEIPT_KIND: () => DIRECT_REQUEST_PAYMENT_RECEIPT_KIND,
|
|
39
41
|
DIRECT_REQUEST_PAYMENT_RECURRING_CHALLENGE_SCHEME: () => DIRECT_REQUEST_PAYMENT_RECURRING_CHALLENGE_SCHEME,
|
|
40
42
|
DIRECT_REQUEST_PAYMENT_REFERENCE_TYPE: () => DIRECT_REQUEST_PAYMENT_REFERENCE_TYPE,
|
|
41
43
|
DIRECT_REQUEST_PAYMENT_SDK_VERSION: () => DIRECT_REQUEST_PAYMENT_SDK_VERSION,
|
|
44
|
+
DIRECT_REQUEST_PAYMENT_STANDARD_FINALITY: () => DIRECT_REQUEST_PAYMENT_STANDARD_FINALITY,
|
|
45
|
+
DIRECT_REQUEST_PAYMENT_STANDARD_SETTLED_STATUS: () => DIRECT_REQUEST_PAYMENT_STANDARD_SETTLED_STATUS,
|
|
42
46
|
DirectRequestPaymentClient: () => DirectRequestPaymentClient,
|
|
43
47
|
DirectRequestPaymentMerchantClient: () => DirectRequestPaymentMerchantClient,
|
|
44
48
|
HostedCheckoutNotAvailableError: () => HostedCheckoutNotAvailableError,
|
|
@@ -50,6 +54,7 @@ __export(src_exports, {
|
|
|
50
54
|
buildPaymentExecutionPayload: () => buildPaymentExecutionPayload,
|
|
51
55
|
buildPreparedTransactionExecutionPayload: () => buildPreparedTransactionExecutionPayload,
|
|
52
56
|
buildWebhookSignatureHeader: () => buildWebhookSignatureHeader,
|
|
57
|
+
classifyDirectPaymentConfirmation: () => classifyDirectPaymentConfirmation,
|
|
53
58
|
computeWebhookSignature: () => computeWebhookSignature,
|
|
54
59
|
createDirectRequestPaymentChallenge: () => createDirectRequestPaymentChallenge,
|
|
55
60
|
createDirectRequestPaymentChallengeSignature: () => createDirectRequestPaymentChallengeSignature,
|
|
@@ -78,7 +83,11 @@ var DIRECT_REQUEST_PAYMENT_RECEIPT_KIND = "sdrp_direct_payment";
|
|
|
78
83
|
var DIRECT_REQUEST_PAYMENT_ALLOWANCE_RECEIPT_KIND = "sdrp_direct_payment_allowance";
|
|
79
84
|
var DIRECT_REQUEST_PAYMENT_REFERENCE_TYPE = "sdrp_direct_payment_requirement";
|
|
80
85
|
var DEFAULT_WEBHOOK_TOLERANCE_SECONDS = 300;
|
|
81
|
-
var DIRECT_REQUEST_PAYMENT_SDK_VERSION = "0.4.
|
|
86
|
+
var DIRECT_REQUEST_PAYMENT_SDK_VERSION = "0.4.8";
|
|
87
|
+
var DIRECT_REQUEST_PAYMENT_STANDARD_SETTLED_STATUS = "settled";
|
|
88
|
+
var DIRECT_REQUEST_PAYMENT_METERED_ACCEPTED_STATUS = "pending_settlement";
|
|
89
|
+
var DIRECT_REQUEST_PAYMENT_STANDARD_FINALITY = "per_payment_onchain";
|
|
90
|
+
var DIRECT_REQUEST_PAYMENT_METERED_FINALITY = "aggregated_onchain_settlement";
|
|
82
91
|
var DIRECT_REQUEST_PAYMENT_CONFIRMED_WEBHOOK_MODES = /* @__PURE__ */ new Set([DIRECT_REQUEST_PAYMENT_MODE, "metered_settlement_batch"]);
|
|
83
92
|
var SiglumeDirectRequestPaymentError = class extends Error {
|
|
84
93
|
constructor(message) {
|
|
@@ -671,6 +680,112 @@ function parseDirectRequestPaymentWebhookEvent(payload) {
|
|
|
671
680
|
}
|
|
672
681
|
return parsed;
|
|
673
682
|
}
|
|
683
|
+
function classifyDirectPaymentConfirmation(event) {
|
|
684
|
+
const data = event.data;
|
|
685
|
+
const requirementId = stringOrNull(data.requirement_id) ?? stringOrNull(data.direct_payment_requirement_id);
|
|
686
|
+
const challengeHash = stringOrNull(data.challenge_hash);
|
|
687
|
+
const pricingBand = stringOrNull(data.pricing_band);
|
|
688
|
+
const finality = stringOrNull(data.finality);
|
|
689
|
+
const settlementStatus = stringOrNull(data.settlement_status);
|
|
690
|
+
if (event.type !== "direct_payment.confirmed") {
|
|
691
|
+
return {
|
|
692
|
+
kind: "unknown",
|
|
693
|
+
event,
|
|
694
|
+
data,
|
|
695
|
+
reason: "not_direct_payment_confirmed",
|
|
696
|
+
requirement_id: requirementId,
|
|
697
|
+
settlement_batch_id: stringOrNull(data.settlement_batch_id),
|
|
698
|
+
pricing_band: pricingBand,
|
|
699
|
+
settlement_status: settlementStatus,
|
|
700
|
+
finality
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
if (data.mode === "metered_settlement_batch") {
|
|
704
|
+
const settlementBatchId = stringOrNull(data.settlement_batch_id);
|
|
705
|
+
const chainReceiptId = stringOrNull(data.chain_receipt_id);
|
|
706
|
+
const usageEventDigest = stringOrNull(data.usage_event_digest);
|
|
707
|
+
if (settlementStatus === DIRECT_REQUEST_PAYMENT_STANDARD_SETTLED_STATUS && settlementBatchId && chainReceiptId && usageEventDigest) {
|
|
708
|
+
return {
|
|
709
|
+
kind: "metered_batch_settled",
|
|
710
|
+
event,
|
|
711
|
+
data,
|
|
712
|
+
settlement_batch_id: settlementBatchId,
|
|
713
|
+
chain_receipt_id: chainReceiptId,
|
|
714
|
+
usage_event_digest: usageEventDigest,
|
|
715
|
+
settled_at: stringOrNull(data.settled_at)
|
|
716
|
+
};
|
|
717
|
+
}
|
|
718
|
+
return {
|
|
719
|
+
kind: "unknown",
|
|
720
|
+
event,
|
|
721
|
+
data,
|
|
722
|
+
reason: "invalid_metered_settlement_confirmation",
|
|
723
|
+
requirement_id: requirementId,
|
|
724
|
+
settlement_batch_id: settlementBatchId,
|
|
725
|
+
pricing_band: pricingBand,
|
|
726
|
+
settlement_status: settlementStatus,
|
|
727
|
+
finality
|
|
728
|
+
};
|
|
729
|
+
}
|
|
730
|
+
if (pricingBand === "standard") {
|
|
731
|
+
const chainReceiptId = stringOrNull(data.chain_receipt_id);
|
|
732
|
+
if (finality === DIRECT_REQUEST_PAYMENT_STANDARD_FINALITY && settlementStatus === DIRECT_REQUEST_PAYMENT_STANDARD_SETTLED_STATUS && requirementId && challengeHash && chainReceiptId) {
|
|
733
|
+
return {
|
|
734
|
+
kind: "standard_settled",
|
|
735
|
+
event,
|
|
736
|
+
data,
|
|
737
|
+
requirement_id: requirementId,
|
|
738
|
+
challenge_hash: challengeHash,
|
|
739
|
+
chain_receipt_id: chainReceiptId,
|
|
740
|
+
request_hash_v2: stringOrNull(data.request_hash_v2)
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
return {
|
|
744
|
+
kind: "unknown",
|
|
745
|
+
event,
|
|
746
|
+
data,
|
|
747
|
+
reason: "missing_standard_settlement_fields",
|
|
748
|
+
requirement_id: requirementId,
|
|
749
|
+
pricing_band: pricingBand,
|
|
750
|
+
settlement_status: settlementStatus,
|
|
751
|
+
finality
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
if (pricingBand === "micro" || pricingBand === "nano") {
|
|
755
|
+
if (finality === DIRECT_REQUEST_PAYMENT_METERED_FINALITY && settlementStatus === DIRECT_REQUEST_PAYMENT_METERED_ACCEPTED_STATUS && requirementId && challengeHash) {
|
|
756
|
+
return {
|
|
757
|
+
kind: "metered_usage_accepted",
|
|
758
|
+
event,
|
|
759
|
+
data,
|
|
760
|
+
pricing_band: pricingBand,
|
|
761
|
+
requirement_id: requirementId,
|
|
762
|
+
challenge_hash: challengeHash,
|
|
763
|
+
request_hash_v2: stringOrNull(data.request_hash_v2)
|
|
764
|
+
};
|
|
765
|
+
}
|
|
766
|
+
return {
|
|
767
|
+
kind: "unknown",
|
|
768
|
+
event,
|
|
769
|
+
data,
|
|
770
|
+
reason: "missing_metered_usage_fields",
|
|
771
|
+
requirement_id: requirementId,
|
|
772
|
+
pricing_band: pricingBand,
|
|
773
|
+
settlement_status: settlementStatus,
|
|
774
|
+
finality
|
|
775
|
+
};
|
|
776
|
+
}
|
|
777
|
+
return {
|
|
778
|
+
kind: "unknown",
|
|
779
|
+
event,
|
|
780
|
+
data,
|
|
781
|
+
reason: "unknown_confirmation_shape",
|
|
782
|
+
requirement_id: requirementId,
|
|
783
|
+
settlement_batch_id: stringOrNull(data.settlement_batch_id),
|
|
784
|
+
pricing_band: pricingBand,
|
|
785
|
+
settlement_status: settlementStatus,
|
|
786
|
+
finality
|
|
787
|
+
};
|
|
788
|
+
}
|
|
674
789
|
async function verifyDirectRequestPaymentWebhook(signing_secret, body, signature_header, options = {}) {
|
|
675
790
|
const verification = await verifyWebhookSignature(signing_secret, body, signature_header, options);
|
|
676
791
|
const text = new TextDecoder().decode(bodyBytes(body));
|