@genesis-tech/genesispay-seller 0.12.0 → 0.13.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/CHANGELOG.md +45 -0
- package/README.md +89 -10
- package/package.json +1 -1
- package/dist/client.d.ts +0 -283
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js +0 -575
- package/dist/client.js.map +0 -1
- package/dist/customers.d.ts +0 -41
- package/dist/customers.d.ts.map +0 -1
- package/dist/customers.js +0 -76
- package/dist/customers.js.map +0 -1
- package/dist/entitlements.d.ts +0 -19
- package/dist/entitlements.d.ts.map +0 -1
- package/dist/entitlements.js +0 -30
- package/dist/entitlements.js.map +0 -1
- package/dist/errors.d.ts +0 -63
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js +0 -162
- package/dist/errors.js.map +0 -1
- package/dist/genesispay-settlement.d.ts +0 -30
- package/dist/genesispay-settlement.d.ts.map +0 -1
- package/dist/genesispay-settlement.js +0 -103
- package/dist/genesispay-settlement.js.map +0 -1
- package/dist/index.d.ts +0 -15
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -13
- package/dist/index.js.map +0 -1
- package/dist/invoices.d.ts +0 -80
- package/dist/invoices.d.ts.map +0 -1
- package/dist/invoices.js +0 -133
- package/dist/invoices.js.map +0 -1
- package/dist/mandate-gate.d.ts +0 -49
- package/dist/mandate-gate.d.ts.map +0 -1
- package/dist/mandate-gate.js +0 -109
- package/dist/mandate-gate.js.map +0 -1
- package/dist/mandates.d.ts +0 -172
- package/dist/mandates.d.ts.map +0 -1
- package/dist/mandates.js +0 -213
- package/dist/mandates.js.map +0 -1
- package/dist/networks.d.ts +0 -10
- package/dist/networks.d.ts.map +0 -1
- package/dist/networks.js +0 -22
- package/dist/networks.js.map +0 -1
- package/dist/payment-gate.d.ts +0 -67
- package/dist/payment-gate.d.ts.map +0 -1
- package/dist/payment-gate.js +0 -106
- package/dist/payment-gate.js.map +0 -1
- package/dist/plans.d.ts +0 -68
- package/dist/plans.d.ts.map +0 -1
- package/dist/plans.js +0 -127
- package/dist/plans.js.map +0 -1
- package/dist/products.d.ts +0 -146
- package/dist/products.d.ts.map +0 -1
- package/dist/products.js +0 -295
- package/dist/products.js.map +0 -1
- package/dist/resource.d.ts +0 -47
- package/dist/resource.d.ts.map +0 -1
- package/dist/resource.js +0 -71
- package/dist/resource.js.map +0 -1
- package/dist/usdc-amount.d.ts +0 -7
- package/dist/usdc-amount.d.ts.map +0 -1
- package/dist/usdc-amount.js +0 -21
- package/dist/usdc-amount.js.map +0 -1
- package/dist/webhooks.d.ts +0 -277
- package/dist/webhooks.d.ts.map +0 -1
- package/dist/webhooks.js +0 -224
- package/dist/webhooks.js.map +0 -1
package/dist/webhooks.js
DELETED
|
@@ -1,224 +0,0 @@
|
|
|
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
|
-
/**
|
|
13
|
-
* Every event type this SDK version knows. Mirrors the server's
|
|
14
|
-
* `WebhookEventType` (`src/features/sellers/webhooks.ts`) — the drift alarm is
|
|
15
|
-
* `src/features/sellers/webhook-signature-contract.test.ts`, which fails when
|
|
16
|
-
* the server grows a type this list does not have.
|
|
17
|
-
*
|
|
18
|
-
* Exported as a runtime array (not only as a type) so a handler can ask
|
|
19
|
-
* `isKnownGenesisPayEventType(event.type)` before it decides what to do.
|
|
20
|
-
*/
|
|
21
|
-
export const GENESISPAY_EVENT_TYPES = [
|
|
22
|
-
"payment.confirmed",
|
|
23
|
-
"link.paid",
|
|
24
|
-
"product.purchased",
|
|
25
|
-
"agent_payment.pending_approval",
|
|
26
|
-
"agent_payment.settled",
|
|
27
|
-
"mandate.active",
|
|
28
|
-
"mandate.charged",
|
|
29
|
-
"mandate.charge_failed",
|
|
30
|
-
"mandate.revoked",
|
|
31
|
-
"subscription.renewed",
|
|
32
|
-
"subscription.past_due",
|
|
33
|
-
];
|
|
34
|
-
/** True when `type` is an event type this SDK version knows about. */
|
|
35
|
-
export function isKnownGenesisPayEventType(type) {
|
|
36
|
-
return GENESISPAY_EVENT_TYPES.includes(type);
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Thrown for every rejection path: malformed/missing header, missing `t`/`v1`,
|
|
40
|
-
* timestamp outside the tolerance window, signature mismatch, non-JSON body.
|
|
41
|
-
* Messages never contain the secret or the expected signature.
|
|
42
|
-
*/
|
|
43
|
-
export class GenesisPaySignatureVerificationError extends Error {
|
|
44
|
-
constructor(message) {
|
|
45
|
-
super(message);
|
|
46
|
-
this.name = "GenesisPaySignatureVerificationError";
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
const DEFAULT_TOLERANCE_SECONDS = 300;
|
|
50
|
-
const SIGNATURE_HEADER_NAME = "GENESISPAY-SIGNATURE";
|
|
51
|
-
const textEncoder = new TextEncoder();
|
|
52
|
-
const textDecoder = new TextDecoder("utf-8", { fatal: false });
|
|
53
|
-
/**
|
|
54
|
-
* Parses `t=…,v1=…` tolerantly: any order, surrounding whitespace, and
|
|
55
|
-
* repeated `v1=` values (secret rotation — one match is enough).
|
|
56
|
-
*/
|
|
57
|
-
function parseSignatureHeader(header) {
|
|
58
|
-
let timestampRaw;
|
|
59
|
-
const signatures = [];
|
|
60
|
-
for (const rawPart of header.split(",")) {
|
|
61
|
-
const part = rawPart.trim();
|
|
62
|
-
if (part.length === 0)
|
|
63
|
-
continue;
|
|
64
|
-
const separator = part.indexOf("=");
|
|
65
|
-
if (separator <= 0) {
|
|
66
|
-
throw new GenesisPaySignatureVerificationError(`Malformed ${SIGNATURE_HEADER_NAME} header: expected comma-separated key=value pairs.`);
|
|
67
|
-
}
|
|
68
|
-
const key = part.slice(0, separator).trim();
|
|
69
|
-
const value = part.slice(separator + 1).trim();
|
|
70
|
-
if (key === "t") {
|
|
71
|
-
// A second `t=` would make the signed payload ambiguous.
|
|
72
|
-
if (timestampRaw !== undefined) {
|
|
73
|
-
throw new GenesisPaySignatureVerificationError(`Malformed ${SIGNATURE_HEADER_NAME} header: duplicate "t" value.`);
|
|
74
|
-
}
|
|
75
|
-
timestampRaw = value;
|
|
76
|
-
}
|
|
77
|
-
else if (key === "v1") {
|
|
78
|
-
if (value.length > 0)
|
|
79
|
-
signatures.push(value);
|
|
80
|
-
}
|
|
81
|
-
// Unknown keys (future scheme versions) are ignored on purpose.
|
|
82
|
-
}
|
|
83
|
-
if (timestampRaw === undefined || timestampRaw.length === 0) {
|
|
84
|
-
throw new GenesisPaySignatureVerificationError(`Missing "t" in ${SIGNATURE_HEADER_NAME} header.`);
|
|
85
|
-
}
|
|
86
|
-
if (!/^\d+$/.test(timestampRaw)) {
|
|
87
|
-
throw new GenesisPaySignatureVerificationError(`Invalid "t" in ${SIGNATURE_HEADER_NAME} header: expected unix seconds.`);
|
|
88
|
-
}
|
|
89
|
-
const timestampSeconds = Number(timestampRaw);
|
|
90
|
-
if (!Number.isSafeInteger(timestampSeconds)) {
|
|
91
|
-
throw new GenesisPaySignatureVerificationError(`Invalid "t" in ${SIGNATURE_HEADER_NAME} header: expected unix seconds.`);
|
|
92
|
-
}
|
|
93
|
-
if (signatures.length === 0) {
|
|
94
|
-
throw new GenesisPaySignatureVerificationError(`Missing "v1" in ${SIGNATURE_HEADER_NAME} header.`);
|
|
95
|
-
}
|
|
96
|
-
return { timestampSeconds, signatures };
|
|
97
|
-
}
|
|
98
|
-
function getSubtleCrypto() {
|
|
99
|
-
const subtle = globalThis.crypto?.subtle;
|
|
100
|
-
if (!subtle) {
|
|
101
|
-
throw new GenesisPaySignatureVerificationError("WebCrypto (globalThis.crypto.subtle) is unavailable in this runtime; webhook verification requires it.");
|
|
102
|
-
}
|
|
103
|
-
return subtle;
|
|
104
|
-
}
|
|
105
|
-
async function computeExpectedSignature(secret, signedPayload) {
|
|
106
|
-
const subtle = getSubtleCrypto();
|
|
107
|
-
const key = await subtle.importKey("raw", textEncoder.encode(secret), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
|
|
108
|
-
const signature = await subtle.sign("HMAC", key, textEncoder.encode(signedPayload));
|
|
109
|
-
return toHex(new Uint8Array(signature));
|
|
110
|
-
}
|
|
111
|
-
function toHex(bytes) {
|
|
112
|
-
let hex = "";
|
|
113
|
-
for (const byte of bytes) {
|
|
114
|
-
hex += byte.toString(16).padStart(2, "0");
|
|
115
|
-
}
|
|
116
|
-
return hex;
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Constant-time string comparison. Length is checked first (lengths are not
|
|
120
|
-
* secret), then every byte is folded into an XOR accumulator — no early return
|
|
121
|
-
* and no `===` on the hex strings, so timing does not leak the position of the
|
|
122
|
-
* first differing byte.
|
|
123
|
-
*/
|
|
124
|
-
function timingSafeEqualStrings(a, b) {
|
|
125
|
-
if (a.length !== b.length)
|
|
126
|
-
return false;
|
|
127
|
-
let diff = 0;
|
|
128
|
-
for (let i = 0; i < a.length; i += 1) {
|
|
129
|
-
diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
|
|
130
|
-
}
|
|
131
|
-
return diff === 0;
|
|
132
|
-
}
|
|
133
|
-
function decodeRawBody(rawBody) {
|
|
134
|
-
if (typeof rawBody === "string")
|
|
135
|
-
return rawBody;
|
|
136
|
-
return textDecoder.decode(rawBody);
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Verifies a GenesisPay webhook delivery and returns the parsed event.
|
|
140
|
-
*
|
|
141
|
-
* Pass the **raw** request body exactly as received — never a re-serialized
|
|
142
|
-
* `JSON.parse` + `JSON.stringify` round trip, which changes the bytes and
|
|
143
|
-
* invalidates the signature. Parsing happens only after verification succeeds.
|
|
144
|
-
*
|
|
145
|
-
* An event type this SDK version does not know is **not** a failure: the
|
|
146
|
-
* delivery is verified and returned unchanged, so a server that adds a new
|
|
147
|
-
* event type can never turn a customer's webhook route into a 400. Only the
|
|
148
|
-
* signature and the envelope (`id`, `type`, `createdAt`, object `data`) can
|
|
149
|
-
* reject a delivery. Widen to `GenesisPayAnyEvent` and use
|
|
150
|
-
* `isKnownGenesisPayEventType()` if you want to handle that case explicitly.
|
|
151
|
-
*
|
|
152
|
-
* @throws {GenesisPaySignatureVerificationError} on any verification failure.
|
|
153
|
-
*
|
|
154
|
-
* @example
|
|
155
|
-
* ```ts
|
|
156
|
-
* const event = await constructEvent(
|
|
157
|
-
* await request.text(),
|
|
158
|
-
* request.headers.get("genesispay-signature") ?? "",
|
|
159
|
-
* process.env.GENESISPAY_WEBHOOK_SECRET!,
|
|
160
|
-
* );
|
|
161
|
-
* if (event.type === "payment.confirmed") {
|
|
162
|
-
* fulfil(event.data.link.clientReferenceId, event.data.attempt.txHash);
|
|
163
|
-
* }
|
|
164
|
-
* ```
|
|
165
|
-
*/
|
|
166
|
-
export async function constructEvent(rawBody, signatureHeader, secret, opts = {}) {
|
|
167
|
-
if (typeof signatureHeader !== "string" || signatureHeader.trim().length === 0) {
|
|
168
|
-
throw new GenesisPaySignatureVerificationError(`Missing ${SIGNATURE_HEADER_NAME} header.`);
|
|
169
|
-
}
|
|
170
|
-
if (typeof secret !== "string" || secret.length === 0) {
|
|
171
|
-
throw new GenesisPaySignatureVerificationError("Missing webhook signing secret.");
|
|
172
|
-
}
|
|
173
|
-
const toleranceSeconds = opts.toleranceSeconds ?? DEFAULT_TOLERANCE_SECONDS;
|
|
174
|
-
if (!Number.isFinite(toleranceSeconds) || toleranceSeconds < 0) {
|
|
175
|
-
throw new GenesisPaySignatureVerificationError("Invalid toleranceSeconds: expected a non-negative number.");
|
|
176
|
-
}
|
|
177
|
-
const { timestampSeconds, signatures } = parseSignatureHeader(signatureHeader);
|
|
178
|
-
const nowMs = opts.nowMs ?? Date.now();
|
|
179
|
-
const nowSeconds = Math.floor(nowMs / 1_000);
|
|
180
|
-
const skewSeconds = Math.abs(nowSeconds - timestampSeconds);
|
|
181
|
-
if (skewSeconds > toleranceSeconds) {
|
|
182
|
-
// Rejects future timestamps too — a clock-skewed or replayed delivery.
|
|
183
|
-
throw new GenesisPaySignatureVerificationError(`Webhook timestamp is outside the tolerance window of ${toleranceSeconds}s (off by ${skewSeconds}s).`);
|
|
184
|
-
}
|
|
185
|
-
const body = decodeRawBody(rawBody);
|
|
186
|
-
const expected = await computeExpectedSignature(secret, `${timestampSeconds}.${body}`);
|
|
187
|
-
let matched = false;
|
|
188
|
-
for (const candidate of signatures) {
|
|
189
|
-
// No early break: every candidate is compared so the work does not depend
|
|
190
|
-
// on which one matches.
|
|
191
|
-
matched = timingSafeEqualStrings(expected, candidate.toLowerCase()) || matched;
|
|
192
|
-
}
|
|
193
|
-
if (!matched) {
|
|
194
|
-
throw new GenesisPaySignatureVerificationError("Webhook signature mismatch: the payload does not match the signing secret.");
|
|
195
|
-
}
|
|
196
|
-
let parsed;
|
|
197
|
-
try {
|
|
198
|
-
parsed = JSON.parse(body);
|
|
199
|
-
}
|
|
200
|
-
catch {
|
|
201
|
-
throw new GenesisPaySignatureVerificationError("Webhook body is not valid JSON.");
|
|
202
|
-
}
|
|
203
|
-
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
204
|
-
throw new GenesisPaySignatureVerificationError("Webhook body is not a JSON object.");
|
|
205
|
-
}
|
|
206
|
-
// The envelope is asserted rather than cast. `id` in particular is the
|
|
207
|
-
// documented idempotency key — it is stable across delivery retries, so an
|
|
208
|
-
// integrator deduping on it would silently process a payment twice if it
|
|
209
|
-
// arrived as undefined. A signed body that does not carry the envelope means
|
|
210
|
-
// the sender is not the GenesisPay we know, so failing here is correct.
|
|
211
|
-
const envelope = parsed;
|
|
212
|
-
for (const field of ["id", "type", "createdAt"]) {
|
|
213
|
-
if (typeof envelope[field] !== "string" || envelope[field] === "") {
|
|
214
|
-
throw new GenesisPaySignatureVerificationError(`Webhook body is missing a string "${field}" field.`);
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
if (typeof envelope.data !== "object" ||
|
|
218
|
-
envelope.data === null ||
|
|
219
|
-
Array.isArray(envelope.data)) {
|
|
220
|
-
throw new GenesisPaySignatureVerificationError('Webhook body is missing an object "data" field.');
|
|
221
|
-
}
|
|
222
|
-
return parsed;
|
|
223
|
-
}
|
|
224
|
-
//# sourceMappingURL=webhooks.js.map
|
package/dist/webhooks.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../src/webhooks.ts"],"names":[],"mappings":"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"}
|