@genesis-tech/genesispay-seller 0.13.1 → 1.3.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.
Files changed (99) hide show
  1. package/CHANGELOG.md +206 -0
  2. package/README.md +670 -91
  3. package/dist/checkout-documents.d.ts +99 -0
  4. package/dist/checkout-documents.d.ts.map +1 -0
  5. package/dist/checkout-documents.js +155 -0
  6. package/dist/checkout-documents.js.map +1 -0
  7. package/dist/checkout-return.d.ts +41 -0
  8. package/dist/checkout-return.d.ts.map +1 -0
  9. package/dist/checkout-return.js +68 -0
  10. package/dist/checkout-return.js.map +1 -0
  11. package/dist/client.d.ts +318 -0
  12. package/dist/client.d.ts.map +1 -0
  13. package/dist/client.js +718 -0
  14. package/dist/client.js.map +1 -0
  15. package/dist/contract-mandates.d.ts +39 -0
  16. package/dist/contract-mandates.d.ts.map +1 -0
  17. package/dist/contract-mandates.js +98 -0
  18. package/dist/contract-mandates.js.map +1 -0
  19. package/dist/contract-usage.d.ts +29 -0
  20. package/dist/contract-usage.d.ts.map +1 -0
  21. package/dist/contract-usage.js +92 -0
  22. package/dist/contract-usage.js.map +1 -0
  23. package/dist/customers.d.ts +41 -0
  24. package/dist/customers.d.ts.map +1 -0
  25. package/dist/customers.js +76 -0
  26. package/dist/customers.js.map +1 -0
  27. package/dist/entitlements.d.ts +19 -0
  28. package/dist/entitlements.d.ts.map +1 -0
  29. package/dist/entitlements.js +30 -0
  30. package/dist/entitlements.js.map +1 -0
  31. package/dist/errors.d.ts +129 -0
  32. package/dist/errors.d.ts.map +1 -0
  33. package/dist/errors.js +273 -0
  34. package/dist/errors.js.map +1 -0
  35. package/dist/fulfillment-attempts.d.ts +29 -0
  36. package/dist/fulfillment-attempts.d.ts.map +1 -0
  37. package/dist/fulfillment-attempts.js +71 -0
  38. package/dist/fulfillment-attempts.js.map +1 -0
  39. package/dist/fulfillment.d.ts +152 -0
  40. package/dist/fulfillment.d.ts.map +1 -0
  41. package/dist/fulfillment.js +810 -0
  42. package/dist/fulfillment.js.map +1 -0
  43. package/dist/genesispay-settlement.d.ts +32 -0
  44. package/dist/genesispay-settlement.d.ts.map +1 -0
  45. package/dist/genesispay-settlement.js +500 -0
  46. package/dist/genesispay-settlement.js.map +1 -0
  47. package/dist/index.d.ts +22 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +21 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/invoices.d.ts +111 -0
  52. package/dist/invoices.d.ts.map +1 -0
  53. package/dist/invoices.js +192 -0
  54. package/dist/invoices.js.map +1 -0
  55. package/dist/item-tax.d.ts +15 -0
  56. package/dist/item-tax.d.ts.map +1 -0
  57. package/dist/item-tax.js +19 -0
  58. package/dist/item-tax.js.map +1 -0
  59. package/dist/mandate-gate.d.ts +54 -0
  60. package/dist/mandate-gate.d.ts.map +1 -0
  61. package/dist/mandate-gate.js +183 -0
  62. package/dist/mandate-gate.js.map +1 -0
  63. package/dist/mandates.d.ts +189 -0
  64. package/dist/mandates.d.ts.map +1 -0
  65. package/dist/mandates.js +234 -0
  66. package/dist/mandates.js.map +1 -0
  67. package/dist/networks.d.ts +10 -0
  68. package/dist/networks.d.ts.map +1 -0
  69. package/dist/networks.js +23 -0
  70. package/dist/networks.js.map +1 -0
  71. package/dist/payment-gate.d.ts +98 -0
  72. package/dist/payment-gate.d.ts.map +1 -0
  73. package/dist/payment-gate.js +370 -0
  74. package/dist/payment-gate.js.map +1 -0
  75. package/dist/plans.d.ts +68 -0
  76. package/dist/plans.d.ts.map +1 -0
  77. package/dist/plans.js +127 -0
  78. package/dist/plans.js.map +1 -0
  79. package/dist/products.d.ts +170 -0
  80. package/dist/products.d.ts.map +1 -0
  81. package/dist/products.js +1317 -0
  82. package/dist/products.js.map +1 -0
  83. package/dist/resource.d.ts +47 -0
  84. package/dist/resource.d.ts.map +1 -0
  85. package/dist/resource.js +71 -0
  86. package/dist/resource.js.map +1 -0
  87. package/dist/strict-response.d.ts +21 -0
  88. package/dist/strict-response.d.ts.map +1 -0
  89. package/dist/strict-response.js +68 -0
  90. package/dist/strict-response.js.map +1 -0
  91. package/dist/usdc-amount.d.ts +7 -0
  92. package/dist/usdc-amount.d.ts.map +1 -0
  93. package/dist/usdc-amount.js +21 -0
  94. package/dist/usdc-amount.js.map +1 -0
  95. package/dist/webhooks.d.ts +352 -0
  96. package/dist/webhooks.d.ts.map +1 -0
  97. package/dist/webhooks.js +244 -0
  98. package/dist/webhooks.js.map +1 -0
  99. package/package.json +4 -3
@@ -0,0 +1,352 @@
1
+ import { GENESISPAY_API_VERSION, type ExpectedDeliveryContract, type NetworkContract, type FeeCollectionStatus } from "./fulfillment.js";
2
+ /**
3
+ * Every event type this SDK version knows. Mirrors the server's
4
+ * `WebhookEventType` (`src/features/sellers/webhooks.ts`) — the drift alarm is
5
+ * `src/features/sellers/webhook-signature-contract.test.ts`, which fails when
6
+ * the server grows a type this list does not have.
7
+ *
8
+ * Exported as a runtime array (not only as a type) so a handler can ask
9
+ * `isKnownGenesisPayEventType(event.type)` before it decides what to do.
10
+ */
11
+ export declare const GENESISPAY_EVENT_TYPES: readonly ["payment.confirmed", "payment.fulfilled", "link.paid", "product.purchased", "agent_payment.pending_approval", "agent_payment.settled", "mandate.active", "mandate.charged", "mandate.charge_failed", "mandate.revoked", "subscription.renewed", "subscription.past_due"];
12
+ /** Union of the event types this SDK version knows. */
13
+ export type GenesisPayEventType = (typeof GENESISPAY_EVENT_TYPES)[number];
14
+ /** True when `type` is an event type this SDK version knows about. */
15
+ export declare function isKnownGenesisPayEventType(type: string): type is GenesisPayEventType;
16
+ /** Shared envelope; `type`/`data` are pinned per event by the union below. */
17
+ type GenesisPayEventEnvelope<TType extends string, TData> = {
18
+ /** Stable across delivery retries — the idempotency key to dedupe on. */
19
+ id: string;
20
+ type: TType;
21
+ createdAt: string;
22
+ data: TData;
23
+ };
24
+ /**
25
+ * `data` of `payment.confirmed` / `link.paid`. Mirrors the server's
26
+ * `PaymentWebhookEventPayload`; amounts stay strings (minor units are `bigint`
27
+ * on the server and would lose precision as a JSON number).
28
+ */
29
+ export type GenesisPayPaymentEventData = {
30
+ link: {
31
+ publicId: string;
32
+ title: string;
33
+ /**
34
+ * The currency `amount` is denominated in. Read it before you book the
35
+ * money: a EURC link settles in euros, and nothing else in this payload
36
+ * says so.
37
+ *
38
+ * **Optional on purpose, unlike every other field here.** The payload is
39
+ * not re-validated at runtime — `constructEvent` checks the signature and
40
+ * the envelope, then hands the body over — and a delivery enqueued before
41
+ * this field existed is stored and *retried* verbatim, so it can still
42
+ * arrive without one. There is no safe default to fill in: guessing
43
+ * `"USDC"` on a euro payment is the exact confusion this field was added to
44
+ * remove. Treat an absent asset as "cannot book this yet" — ack the
45
+ * delivery, alert, resolve the link through `checkout.retrieve`.
46
+ */
47
+ asset?: "USDC" | "EURC";
48
+ /**
49
+ * Decimal amount in `asset` — euros on a EURC link, dollars on a USDC one.
50
+ * A delivery that predates this field omits it, but unlike `asset` it has a
51
+ * safe fallback: `amount ?? amountUsdc`, which always carried the identical
52
+ * value. That is why this one is typed as present and `asset` is not.
53
+ *
54
+ * The two are emitted by the same code path, so a delivery missing one is
55
+ * missing the other and the `asset` guard fires first — the fallback is
56
+ * belt-and-braces, not the main line of defence. Keep them emitted together
57
+ * if you ever change that path.
58
+ */
59
+ amount: string;
60
+ amountUsdcMinor: string;
61
+ /**
62
+ * @deprecated Same value as `amount`. The name is wrong on a EURC link —
63
+ * it carries euros there — which is why `amount` replaced it. Still sent on
64
+ * every delivery; removed no earlier than 1.0.
65
+ */
66
+ amountUsdc: string;
67
+ linkType: "single" | "reusable";
68
+ /** Correlation data set at link creation, echoed verbatim. */
69
+ metadata: Record<string, string> | null;
70
+ clientReferenceId: string | null;
71
+ };
72
+ attempt: {
73
+ id: string;
74
+ /** `null` for simulated payments — there is no transaction to link to. */
75
+ txHash: string | null;
76
+ /**
77
+ * The chain `txHash` is on. Today every settlement reports `8453`/`84532`
78
+ * (Base mainnet/Sepolia) — but do **not** hard-code that as the whole set.
79
+ * Match the chain you expect and treat anything else as unrecognized rather
80
+ * than as test money; a bare `chainId !== 8453` test inverts on the first
81
+ * chain that is added.
82
+ *
83
+ * Read it *with* the hash and never separately: the same hash string
84
+ * resolves to nothing on the wrong chain, and a testnet settlement is
85
+ * otherwise indistinguishable from a mainnet one.
86
+ *
87
+ * It sits here rather than on `link` because the two can differ: a
88
+ * settlement broadcast by a provider lands on the chain that provider uses,
89
+ * which is not necessarily the chain the link was created for.
90
+ *
91
+ * `null` when there is no hash to resolve, or the provider named no chain.
92
+ * Optional — a delivery enqueued before this field existed is retried
93
+ * verbatim and arrives without it. **Do not default it.** Note the polarity
94
+ * trap: `undefined !== 8453` is true, so the natural `if (chainId !== 8453)`
95
+ * check reads a *missing* chain as testnet, and the mirror check reads it as
96
+ * mainnet. Branch on presence first.
97
+ */
98
+ chainId?: number | null;
99
+ payerWallet: string | null;
100
+ createdAt: string;
101
+ confirmedAt: string | null;
102
+ /**
103
+ * `true` when no funds moved — a test-mode `simulate-payment` attempt.
104
+ * `false` for a real settlement, including on testnet and in provider
105
+ * sandboxes: this is the fabricated-payment axis, not the environment axis.
106
+ */
107
+ simulated: boolean;
108
+ /**
109
+ * The gross the link is priced at, in minor units of `link.asset` (=
110
+ * `link.amountUsdcMinor`). Additive with the fee triplet below; older
111
+ * deliveries enqueued before these fields existed arrive without them, so
112
+ * treat them as optional and do not default `feeCollected` (MR-804).
113
+ */
114
+ amountMinor?: string;
115
+ /** Platform fee snapshot in minor units of `link.asset`. */
116
+ feeMinor?: string;
117
+ /**
118
+ * `amountMinor − feeMinor` — what the seller nets IF the fee is collected
119
+ * on-chain. Do not book it unconditionally: the seller's actual on-chain
120
+ * credit is `feeCollected ? netMinor : amountMinor`. A record-only leg
121
+ * (`feeCollected: false`) credited the seller the full `amountMinor` — the
122
+ * fee is a receivable that did not move at settlement.
123
+ */
124
+ netMinor?: string;
125
+ /**
126
+ * Whether the fee actually moved to the treasury on-chain. `false` on a
127
+ * record-only leg (single-auth checkout, agent, EUR, or a pending
128
+ * receivable) is correct, not a bug. Do not infer it from the presence of
129
+ * `feeTxHash` alone; read this flag — it is the switch for what the seller
130
+ * was credited: `feeCollected ? netMinor : amountMinor`.
131
+ */
132
+ feeCollected?: boolean;
133
+ /** The fee leg's tx hash; `null` unless the fee was collected on-chain. */
134
+ feeTxHash?: string | null;
135
+ };
136
+ occurredAt: string;
137
+ };
138
+ /** `data` of the mandate/subscription events; mirrors `buildMandateWebhookPayload`. */
139
+ export type GenesisPayMandateEventData = {
140
+ /** Present for contract events. `mandate` is a projection-time snapshot, not the historical event state. */
141
+ protocol?: "contract_mandate_v1";
142
+ mandateStateContext?: {
143
+ kind: "projection_snapshot";
144
+ observedAt: string;
145
+ };
146
+ /** Immutable chain event facts; occurredAt is its block timestamp. Deliveries may be out of order. */
147
+ contractEvent?: {
148
+ kind: "activation" | "revocation" | "subscription_charge" | "per_use_charge";
149
+ chainId: number;
150
+ executor: string;
151
+ transactionHash: string;
152
+ blockHash: string;
153
+ blockNumber: string;
154
+ logIndex: number;
155
+ logicalEventIdentity: string;
156
+ sequence: string | null;
157
+ grossMinor: string;
158
+ sellerMinor: string;
159
+ feeMinor: string;
160
+ nextEligibleAt: string | null;
161
+ };
162
+ mandate: {
163
+ id: string;
164
+ kind: string;
165
+ status: string;
166
+ payerWallet: string;
167
+ /**
168
+ * Which plan the subscription belongs to — without it a `mandate.active`
169
+ * handler knows *that* someone subscribed but not *to what*. `null` for
170
+ * mandates proposed directly rather than through a plan checkout. Like
171
+ * every field here it mirrors the current server payload and is not
172
+ * re-validated at runtime, so read it as `?? null` if you also accept
173
+ * deliveries from a deployment that predates the field.
174
+ */
175
+ subscriptionPlanId: string | null;
176
+ asset: string;
177
+ allowanceMinor: string;
178
+ capPerChargeMinor: string;
179
+ spentMinor: string;
180
+ amountPerPeriodMinor: string | null;
181
+ periodDays: number | null;
182
+ nextChargeAt: string | null;
183
+ };
184
+ charge: {
185
+ id: string;
186
+ kind: string;
187
+ amountMinor: string;
188
+ status: string;
189
+ txHash: string | null;
190
+ /**
191
+ * The platform fee in minor units of the mandate's `asset` (MR-104). The
192
+ * seller receives `amountMinor − feeMinor` once the fee is collected.
193
+ *
194
+ * Optional like every field added after launch: `webhook_deliveries` rows
195
+ * are replayed verbatim, so a delivery enqueued before this field existed
196
+ * arrives without it. Read it as `?? null`.
197
+ */
198
+ feeMinor?: string;
199
+ /**
200
+ * Whether the fee was collected on-chain (MR-1008/MR-1009). `true` only
201
+ * when the fee leg's transfer confirmed; `false` on every record-only leg
202
+ * (a deployment not collecting on the mandate leg, or a still-pending
203
+ * receivable) — and that `false` is the honest state, not an error. Do NOT
204
+ * default a missing value to `false`: absent means the delivery predates the
205
+ * field, not that nothing was collected.
206
+ */
207
+ feeCollected?: boolean;
208
+ /** The fee leg's tx hash; `null` unless the fee was collected on-chain. */
209
+ feeTxHash?: string | null;
210
+ resourceUrl: string | null;
211
+ failureReason: string | null;
212
+ } | null;
213
+ occurredAt: string;
214
+ };
215
+ export type GenesisPayPaymentEvent = GenesisPayEventEnvelope<"payment.confirmed" | "link.paid", GenesisPayPaymentEventData>;
216
+ /** Signed snapshot only. Fresh fulfillment.verify is required before credit. */
217
+ export type GenesisPayFulfillmentEventData = {
218
+ schema: "genesispay.fulfillment-evidence";
219
+ version: typeof GENESISPAY_API_VERSION;
220
+ authorityVersion: typeof GENESISPAY_API_VERSION;
221
+ sellerId: string;
222
+ attemptId: string;
223
+ linkId: string;
224
+ clientReferenceId: string | null;
225
+ entitlementId: string | null;
226
+ entitlement: {
227
+ expiresAt: string;
228
+ revokedAt: string | null;
229
+ valid: boolean;
230
+ } | null;
231
+ paymentChannel: "checkout" | "x402" | "bank_transfer";
232
+ simulation: {
233
+ simulated: false;
234
+ };
235
+ status: "confirmed";
236
+ confirmedAt: string;
237
+ transactionHash: `0x${string}`;
238
+ network: NetworkContract;
239
+ settlement: {
240
+ strategy: "dual" | "atomic";
241
+ grossAmountMinor: string;
242
+ sellerAmountMinor: string;
243
+ destination: `0x${string}`;
244
+ feeTerms: {
245
+ type: "record_only" | "payer_authorized";
246
+ amountMinor: string;
247
+ treasuryAddress: `0x${string}` | null;
248
+ };
249
+ feeCollection: {
250
+ status: FeeCollectionStatus;
251
+ amountMinor: string | null;
252
+ treasuryAddress: `0x${string}` | null;
253
+ transactionHash: `0x${string}` | null;
254
+ collectedAt: string | null;
255
+ };
256
+ };
257
+ product: {
258
+ contractVersion: typeof GENESISPAY_API_VERSION;
259
+ productId: string;
260
+ sku: string | null;
261
+ delivery: ExpectedDeliveryContract;
262
+ } | null;
263
+ };
264
+ export type GenesisPayFulfillmentEvent = GenesisPayEventEnvelope<"payment.fulfilled", GenesisPayFulfillmentEventData> & {
265
+ apiVersion: typeof GENESISPAY_API_VERSION;
266
+ livemode: boolean;
267
+ };
268
+ export type GenesisPayMandateEvent = GenesisPayEventEnvelope<"mandate.active" | "mandate.charged" | "mandate.charge_failed" | "mandate.revoked" | "subscription.renewed" | "subscription.past_due", GenesisPayMandateEventData>;
269
+ /**
270
+ * Agent-payment events are reserved on the server but have no emitter yet, so
271
+ * their payload is deliberately left open rather than invented here.
272
+ */
273
+ export type GenesisPayAgentPaymentEvent = GenesisPayEventEnvelope<"agent_payment.pending_approval" | "agent_payment.settled", Record<string, unknown>>;
274
+ /**
275
+ * An event type this SDK version does not know — a newer server talking to an
276
+ * older SDK. It is a *valid* event: `constructEvent` verifies and returns it
277
+ * like any other (see `GenesisPayAnyEvent`), it never throws on the type.
278
+ */
279
+ export type GenesisPayUnknownEvent = GenesisPayEventEnvelope<string, Record<string, unknown>>;
280
+ /**
281
+ * Verified webhook delivery, discriminated on `type`:
282
+ *
283
+ * ```ts
284
+ * if (event.type === "payment.confirmed") {
285
+ * event.data.attempt.txHash; // typed, no cast
286
+ * }
287
+ * ```
288
+ *
289
+ * **Why this union has no `{ type: string & {} }` member.** TypeScript only
290
+ * narrows on a discriminant whose type is a literal in *every* constituent: add
291
+ * one member with a plain `string` type and `event.type === "payment.confirmed"`
292
+ * stops narrowing `data` for all the others too — the exact regression R1 sets
293
+ * out to fix. Forward compatibility therefore lives at runtime (an unknown type
294
+ * is verified and returned, never rejected) plus in `GenesisPayAnyEvent` /
295
+ * `GenesisPayUnknownEvent` for handlers that want to model the open world:
296
+ *
297
+ * ```ts
298
+ * const any: GenesisPayAnyEvent = event; // widens, no cast needed
299
+ * if (!isKnownGenesisPayEventType(any.type)) return new Response("ok"); // ack & ignore
300
+ * ```
301
+ */
302
+ export type GenesisPayEvent = GenesisPayFulfillmentEvent | GenesisPayPaymentEvent | GenesisPayMandateEvent | GenesisPayAgentPaymentEvent;
303
+ /**
304
+ * Open-world view of a delivery: every known event widens to it, and it is the
305
+ * honest type for an event whose `type` this SDK version does not know.
306
+ */
307
+ export type GenesisPayAnyEvent = GenesisPayEvent | GenesisPayUnknownEvent;
308
+ /**
309
+ * Thrown for every rejection path: malformed/missing header, missing `t`/`v1`,
310
+ * timestamp outside the tolerance window, signature mismatch, non-JSON body.
311
+ * Messages never contain the secret or the expected signature.
312
+ */
313
+ export declare class GenesisPaySignatureVerificationError extends Error {
314
+ constructor(message: string);
315
+ }
316
+ export type ConstructEventOptions = {
317
+ /** Replay window in seconds, applied in both directions. Default 300. */
318
+ toleranceSeconds?: number;
319
+ /** Injectable clock (epoch milliseconds); defaults to `Date.now()`. */
320
+ nowMs?: number;
321
+ };
322
+ /**
323
+ * Verifies a GenesisPay webhook delivery and returns the parsed event.
324
+ *
325
+ * Pass the **raw** request body exactly as received — never a re-serialized
326
+ * `JSON.parse` + `JSON.stringify` round trip, which changes the bytes and
327
+ * invalidates the signature. Parsing happens only after verification succeeds.
328
+ *
329
+ * An event type this SDK version does not know is **not** a failure: the
330
+ * delivery is verified and returned unchanged, so a server that adds a new
331
+ * event type can never turn a customer's webhook route into a 400. Only the
332
+ * signature and the envelope (`id`, `type`, `createdAt`, object `data`) can
333
+ * reject a delivery. Widen to `GenesisPayAnyEvent` and use
334
+ * `isKnownGenesisPayEventType()` if you want to handle that case explicitly.
335
+ *
336
+ * @throws {GenesisPaySignatureVerificationError} on any verification failure.
337
+ *
338
+ * @example
339
+ * ```ts
340
+ * const event = await constructEvent(
341
+ * await request.text(),
342
+ * request.headers.get("genesispay-signature") ?? "",
343
+ * process.env.GENESISPAY_WEBHOOK_SECRET!,
344
+ * );
345
+ * if (event.type === "payment.confirmed") {
346
+ * fulfil(event.data.link.clientReferenceId, event.data.attempt.txHash);
347
+ * }
348
+ * ```
349
+ */
350
+ export declare function constructEvent(rawBody: string | Uint8Array, signatureHeader: string, secret: string, opts?: ConstructEventOptions): Promise<GenesisPayEvent>;
351
+ export {};
352
+ //# sourceMappingURL=webhooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../src/webhooks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,244 @@
1
+ // Webhook signature verification for GenesisPay deliveries.
2
+ //
3
+ // The server signs every delivery in `src/features/sellers/webhooks.ts`:
4
+ //
5
+ // GENESISPAY-SIGNATURE: t=<unix-seconds>,v1=<hex>
6
+ // v1 = HMAC_SHA256(secret, `${t}.${rawBody}`)
7
+ //
8
+ // Deliberately implemented on WebCrypto (`globalThis.crypto.subtle`) rather
9
+ // than `node:crypto` so the SDK also runs on Edge runtimes, Cloudflare Workers
10
+ // and Bun. That is why `constructEvent` is async — a conscious deviation from
11
+ // Stripe's synchronous `constructEvent`.
12
+ import { assertFulfillmentEventEvidence, GENESISPAY_API_VERSION } from "./fulfillment.js";
13
+ /**
14
+ * Every event type this SDK version knows. Mirrors the server's
15
+ * `WebhookEventType` (`src/features/sellers/webhooks.ts`) — the drift alarm is
16
+ * `src/features/sellers/webhook-signature-contract.test.ts`, which fails when
17
+ * the server grows a type this list does not have.
18
+ *
19
+ * Exported as a runtime array (not only as a type) so a handler can ask
20
+ * `isKnownGenesisPayEventType(event.type)` before it decides what to do.
21
+ */
22
+ export const GENESISPAY_EVENT_TYPES = [
23
+ "payment.confirmed",
24
+ "payment.fulfilled",
25
+ "link.paid",
26
+ "product.purchased",
27
+ "agent_payment.pending_approval",
28
+ "agent_payment.settled",
29
+ "mandate.active",
30
+ "mandate.charged",
31
+ "mandate.charge_failed",
32
+ "mandate.revoked",
33
+ "subscription.renewed",
34
+ "subscription.past_due",
35
+ ];
36
+ /** True when `type` is an event type this SDK version knows about. */
37
+ export function isKnownGenesisPayEventType(type) {
38
+ return GENESISPAY_EVENT_TYPES.includes(type);
39
+ }
40
+ /**
41
+ * Thrown for every rejection path: malformed/missing header, missing `t`/`v1`,
42
+ * timestamp outside the tolerance window, signature mismatch, non-JSON body.
43
+ * Messages never contain the secret or the expected signature.
44
+ */
45
+ export class GenesisPaySignatureVerificationError extends Error {
46
+ constructor(message) {
47
+ super(message);
48
+ this.name = "GenesisPaySignatureVerificationError";
49
+ }
50
+ }
51
+ const DEFAULT_TOLERANCE_SECONDS = 300;
52
+ const SIGNATURE_HEADER_NAME = "GENESISPAY-SIGNATURE";
53
+ const textEncoder = new TextEncoder();
54
+ const textDecoder = new TextDecoder("utf-8", { fatal: false });
55
+ /**
56
+ * Parses `t=…,v1=…` tolerantly: any order, surrounding whitespace, and
57
+ * repeated `v1=` values (secret rotation — one match is enough).
58
+ */
59
+ function parseSignatureHeader(header) {
60
+ let timestampRaw;
61
+ const signatures = [];
62
+ for (const rawPart of header.split(",")) {
63
+ const part = rawPart.trim();
64
+ if (part.length === 0)
65
+ continue;
66
+ const separator = part.indexOf("=");
67
+ if (separator <= 0) {
68
+ throw new GenesisPaySignatureVerificationError(`Malformed ${SIGNATURE_HEADER_NAME} header: expected comma-separated key=value pairs.`);
69
+ }
70
+ const key = part.slice(0, separator).trim();
71
+ const value = part.slice(separator + 1).trim();
72
+ if (key === "t") {
73
+ // A second `t=` would make the signed payload ambiguous.
74
+ if (timestampRaw !== undefined) {
75
+ throw new GenesisPaySignatureVerificationError(`Malformed ${SIGNATURE_HEADER_NAME} header: duplicate "t" value.`);
76
+ }
77
+ timestampRaw = value;
78
+ }
79
+ else if (key === "v1") {
80
+ if (value.length > 0)
81
+ signatures.push(value);
82
+ }
83
+ // Unknown keys (future scheme versions) are ignored on purpose.
84
+ }
85
+ if (timestampRaw === undefined || timestampRaw.length === 0) {
86
+ throw new GenesisPaySignatureVerificationError(`Missing "t" in ${SIGNATURE_HEADER_NAME} header.`);
87
+ }
88
+ if (!/^\d+$/.test(timestampRaw)) {
89
+ throw new GenesisPaySignatureVerificationError(`Invalid "t" in ${SIGNATURE_HEADER_NAME} header: expected unix seconds.`);
90
+ }
91
+ const timestampSeconds = Number(timestampRaw);
92
+ if (!Number.isSafeInteger(timestampSeconds)) {
93
+ throw new GenesisPaySignatureVerificationError(`Invalid "t" in ${SIGNATURE_HEADER_NAME} header: expected unix seconds.`);
94
+ }
95
+ if (signatures.length === 0) {
96
+ throw new GenesisPaySignatureVerificationError(`Missing "v1" in ${SIGNATURE_HEADER_NAME} header.`);
97
+ }
98
+ return { timestampSeconds, signatures };
99
+ }
100
+ function getSubtleCrypto() {
101
+ const subtle = globalThis.crypto?.subtle;
102
+ if (!subtle) {
103
+ throw new GenesisPaySignatureVerificationError("WebCrypto (globalThis.crypto.subtle) is unavailable in this runtime; webhook verification requires it.");
104
+ }
105
+ return subtle;
106
+ }
107
+ async function computeExpectedSignature(secret, signedPayload) {
108
+ const subtle = getSubtleCrypto();
109
+ const key = await subtle.importKey("raw", textEncoder.encode(secret), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
110
+ const signature = await subtle.sign("HMAC", key, textEncoder.encode(signedPayload));
111
+ return toHex(new Uint8Array(signature));
112
+ }
113
+ function toHex(bytes) {
114
+ let hex = "";
115
+ for (const byte of bytes) {
116
+ hex += byte.toString(16).padStart(2, "0");
117
+ }
118
+ return hex;
119
+ }
120
+ /**
121
+ * Constant-time string comparison. Length is checked first (lengths are not
122
+ * secret), then every byte is folded into an XOR accumulator — no early return
123
+ * and no `===` on the hex strings, so timing does not leak the position of the
124
+ * first differing byte.
125
+ */
126
+ function timingSafeEqualStrings(a, b) {
127
+ if (a.length !== b.length)
128
+ return false;
129
+ let diff = 0;
130
+ for (let i = 0; i < a.length; i += 1) {
131
+ diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
132
+ }
133
+ return diff === 0;
134
+ }
135
+ function decodeRawBody(rawBody) {
136
+ if (typeof rawBody === "string")
137
+ return rawBody;
138
+ return textDecoder.decode(rawBody);
139
+ }
140
+ /**
141
+ * Verifies a GenesisPay webhook delivery and returns the parsed event.
142
+ *
143
+ * Pass the **raw** request body exactly as received — never a re-serialized
144
+ * `JSON.parse` + `JSON.stringify` round trip, which changes the bytes and
145
+ * invalidates the signature. Parsing happens only after verification succeeds.
146
+ *
147
+ * An event type this SDK version does not know is **not** a failure: the
148
+ * delivery is verified and returned unchanged, so a server that adds a new
149
+ * event type can never turn a customer's webhook route into a 400. Only the
150
+ * signature and the envelope (`id`, `type`, `createdAt`, object `data`) can
151
+ * reject a delivery. Widen to `GenesisPayAnyEvent` and use
152
+ * `isKnownGenesisPayEventType()` if you want to handle that case explicitly.
153
+ *
154
+ * @throws {GenesisPaySignatureVerificationError} on any verification failure.
155
+ *
156
+ * @example
157
+ * ```ts
158
+ * const event = await constructEvent(
159
+ * await request.text(),
160
+ * request.headers.get("genesispay-signature") ?? "",
161
+ * process.env.GENESISPAY_WEBHOOK_SECRET!,
162
+ * );
163
+ * if (event.type === "payment.confirmed") {
164
+ * fulfil(event.data.link.clientReferenceId, event.data.attempt.txHash);
165
+ * }
166
+ * ```
167
+ */
168
+ export async function constructEvent(rawBody, signatureHeader, secret, opts = {}) {
169
+ if (typeof signatureHeader !== "string" || signatureHeader.trim().length === 0) {
170
+ throw new GenesisPaySignatureVerificationError(`Missing ${SIGNATURE_HEADER_NAME} header.`);
171
+ }
172
+ if (typeof secret !== "string" || secret.length === 0) {
173
+ throw new GenesisPaySignatureVerificationError("Missing webhook signing secret.");
174
+ }
175
+ const toleranceSeconds = opts.toleranceSeconds ?? DEFAULT_TOLERANCE_SECONDS;
176
+ if (!Number.isFinite(toleranceSeconds) || toleranceSeconds < 0) {
177
+ throw new GenesisPaySignatureVerificationError("Invalid toleranceSeconds: expected a non-negative number.");
178
+ }
179
+ const { timestampSeconds, signatures } = parseSignatureHeader(signatureHeader);
180
+ const nowMs = opts.nowMs ?? Date.now();
181
+ const nowSeconds = Math.floor(nowMs / 1_000);
182
+ const skewSeconds = Math.abs(nowSeconds - timestampSeconds);
183
+ if (skewSeconds > toleranceSeconds) {
184
+ // Rejects future timestamps too — a clock-skewed or replayed delivery.
185
+ throw new GenesisPaySignatureVerificationError(`Webhook timestamp is outside the tolerance window of ${toleranceSeconds}s (off by ${skewSeconds}s).`);
186
+ }
187
+ const body = decodeRawBody(rawBody);
188
+ const expected = await computeExpectedSignature(secret, `${timestampSeconds}.${body}`);
189
+ let matched = false;
190
+ for (const candidate of signatures) {
191
+ // No early break: every candidate is compared so the work does not depend
192
+ // on which one matches.
193
+ matched = timingSafeEqualStrings(expected, candidate.toLowerCase()) || matched;
194
+ }
195
+ if (!matched) {
196
+ throw new GenesisPaySignatureVerificationError("Webhook signature mismatch: the payload does not match the signing secret.");
197
+ }
198
+ let parsed;
199
+ try {
200
+ parsed = JSON.parse(body);
201
+ }
202
+ catch {
203
+ throw new GenesisPaySignatureVerificationError("Webhook body is not valid JSON.");
204
+ }
205
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
206
+ throw new GenesisPaySignatureVerificationError("Webhook body is not a JSON object.");
207
+ }
208
+ // The envelope is asserted rather than cast. `id` in particular is the
209
+ // documented idempotency key — it is stable across delivery retries, so an
210
+ // integrator deduping on it would silently process a payment twice if it
211
+ // arrived as undefined. A signed body that does not carry the envelope means
212
+ // the sender is not the GenesisPay we know, so failing here is correct.
213
+ const envelope = parsed;
214
+ for (const field of ["id", "type", "createdAt"]) {
215
+ if (typeof envelope[field] !== "string" || envelope[field] === "") {
216
+ throw new GenesisPaySignatureVerificationError(`Webhook body is missing a string "${field}" field.`);
217
+ }
218
+ }
219
+ if (typeof envelope.data !== "object" ||
220
+ envelope.data === null ||
221
+ Array.isArray(envelope.data)) {
222
+ throw new GenesisPaySignatureVerificationError('Webhook body is missing an object "data" field.');
223
+ }
224
+ if (envelope.type === "payment.fulfilled") {
225
+ const fulfilled = parsed;
226
+ const data = envelope.data;
227
+ if (fulfilled.apiVersion !== GENESISPAY_API_VERSION || typeof fulfilled.livemode !== "boolean" ||
228
+ !(data.clientReferenceId === null || typeof data.clientReferenceId === "string")) {
229
+ throw new GenesisPaySignatureVerificationError("Invalid payment.fulfilled envelope.");
230
+ }
231
+ try {
232
+ assertFulfillmentEventEvidence(data);
233
+ }
234
+ catch {
235
+ throw new GenesisPaySignatureVerificationError("Invalid payment.fulfilled evidence snapshot.");
236
+ }
237
+ const network = data.network;
238
+ if (fulfilled.livemode !== (network.mode === "live")) {
239
+ throw new GenesisPaySignatureVerificationError("Inconsistent payment.fulfilled livemode.");
240
+ }
241
+ }
242
+ return parsed;
243
+ }
244
+ //# sourceMappingURL=webhooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../src/webhooks.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@genesis-tech/genesispay-seller",
3
- "version": "0.13.1",
4
- "description": "Framework-agnostic x402 payment gate for sellers, powered by GenesisPay.",
3
+ "version": "1.3.0",
4
+ "description": "Seller SDK for strict GenesisPay fulfilment verification, checkout, and x402 gates.",
5
5
  "license": "MIT",
6
6
  "author": "GenesisTech",
7
7
  "homepage": "https://github.com/GenesisTechAT/genesispay-js/tree/main/packages/seller-sdk#readme",
@@ -46,10 +46,11 @@
46
46
  ],
47
47
  "scripts": {
48
48
  "build": "tsc -b",
49
+ "prepack": "npm run build -- --force",
49
50
  "typecheck": "tsc --noEmit"
50
51
  },
51
52
  "dependencies": {
52
- "@genesis-tech/genesispay-protocol": "^0.3.0",
53
+ "@genesis-tech/genesispay-protocol": "^0.5.0",
53
54
  "viem": "^2.48.11"
54
55
  },
55
56
  "devDependencies": {