@nvwa-app/sdk-functions 6.1.0 → 6.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.
- package/dist/index.d.mts +16 -1
- package/dist/index.d.ts +16 -1
- package/dist/index.js +73 -2
- package/dist/index.mjs +68 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -57,6 +57,21 @@ interface GetOrderResult {
|
|
|
57
57
|
currency: string;
|
|
58
58
|
raw: Record<string, unknown>;
|
|
59
59
|
}
|
|
60
|
+
declare const PAYMENT_SUCCESS_NOTIFY_SIGNATURE_HEADER = "X-Payment-Gateway-Signature";
|
|
61
|
+
interface PaymentSuccessNotifyPayload {
|
|
62
|
+
platformOrderId: string;
|
|
63
|
+
bizOrderId: string;
|
|
64
|
+
status: "succeeded";
|
|
65
|
+
amount: number;
|
|
66
|
+
currency: string;
|
|
67
|
+
providerId: string;
|
|
68
|
+
providerOrderId?: string;
|
|
69
|
+
timestamp: string;
|
|
70
|
+
paidAt: string;
|
|
71
|
+
}
|
|
72
|
+
declare function verifySuccessNotifySignature(rawBody: string, signature: string | null | undefined, secret: string): Promise<boolean>;
|
|
73
|
+
declare function parseSuccessNotifyPayload(rawBody: string): PaymentSuccessNotifyPayload;
|
|
74
|
+
declare function verifyAndParseSuccessNotifyRequest(request: Request, secret: string): Promise<PaymentSuccessNotifyPayload>;
|
|
60
75
|
interface PaymentGatewayClient {
|
|
61
76
|
createOrder(params: CreateOrderParams): Promise<CreateOrderResult>;
|
|
62
77
|
getOrder(platformOrderId: string): Promise<GetOrderResult>;
|
|
@@ -92,4 +107,4 @@ interface CapabilityExecuteResponse<Data = unknown> {
|
|
|
92
107
|
*/
|
|
93
108
|
declare function executeCapability<Result = unknown>(capabilityName: string, param?: unknown, options?: ExecuteCapabilityOptions): Promise<Result | undefined>;
|
|
94
109
|
|
|
95
|
-
export { type AuthUser, type CapabilityExecuteResponse, type CreateOrderParams, type CreateOrderResult, type ExecuteCapabilityOptions, type GetAvailableProvidersOptions, type GetOrderResult, type PaymentGatewayClient, type PaymentGatewayClientOptions, type PaymentPlatform, createPaymentClient, executeCapability, filterProvidersByPlatform, getAvailableProviders, getConfiguredProviders, getDb, getPayment, getRequestUser, providerSupportedPlatforms };
|
|
110
|
+
export { type AuthUser, type CapabilityExecuteResponse, type CreateOrderParams, type CreateOrderResult, type ExecuteCapabilityOptions, type GetAvailableProvidersOptions, type GetOrderResult, PAYMENT_SUCCESS_NOTIFY_SIGNATURE_HEADER, type PaymentGatewayClient, type PaymentGatewayClientOptions, type PaymentPlatform, type PaymentSuccessNotifyPayload, createPaymentClient, executeCapability, filterProvidersByPlatform, getAvailableProviders, getConfiguredProviders, getDb, getPayment, getRequestUser, parseSuccessNotifyPayload, providerSupportedPlatforms, verifyAndParseSuccessNotifyRequest, verifySuccessNotifySignature };
|
package/dist/index.d.ts
CHANGED
|
@@ -57,6 +57,21 @@ interface GetOrderResult {
|
|
|
57
57
|
currency: string;
|
|
58
58
|
raw: Record<string, unknown>;
|
|
59
59
|
}
|
|
60
|
+
declare const PAYMENT_SUCCESS_NOTIFY_SIGNATURE_HEADER = "X-Payment-Gateway-Signature";
|
|
61
|
+
interface PaymentSuccessNotifyPayload {
|
|
62
|
+
platformOrderId: string;
|
|
63
|
+
bizOrderId: string;
|
|
64
|
+
status: "succeeded";
|
|
65
|
+
amount: number;
|
|
66
|
+
currency: string;
|
|
67
|
+
providerId: string;
|
|
68
|
+
providerOrderId?: string;
|
|
69
|
+
timestamp: string;
|
|
70
|
+
paidAt: string;
|
|
71
|
+
}
|
|
72
|
+
declare function verifySuccessNotifySignature(rawBody: string, signature: string | null | undefined, secret: string): Promise<boolean>;
|
|
73
|
+
declare function parseSuccessNotifyPayload(rawBody: string): PaymentSuccessNotifyPayload;
|
|
74
|
+
declare function verifyAndParseSuccessNotifyRequest(request: Request, secret: string): Promise<PaymentSuccessNotifyPayload>;
|
|
60
75
|
interface PaymentGatewayClient {
|
|
61
76
|
createOrder(params: CreateOrderParams): Promise<CreateOrderResult>;
|
|
62
77
|
getOrder(platformOrderId: string): Promise<GetOrderResult>;
|
|
@@ -92,4 +107,4 @@ interface CapabilityExecuteResponse<Data = unknown> {
|
|
|
92
107
|
*/
|
|
93
108
|
declare function executeCapability<Result = unknown>(capabilityName: string, param?: unknown, options?: ExecuteCapabilityOptions): Promise<Result | undefined>;
|
|
94
109
|
|
|
95
|
-
export { type AuthUser, type CapabilityExecuteResponse, type CreateOrderParams, type CreateOrderResult, type ExecuteCapabilityOptions, type GetAvailableProvidersOptions, type GetOrderResult, type PaymentGatewayClient, type PaymentGatewayClientOptions, type PaymentPlatform, createPaymentClient, executeCapability, filterProvidersByPlatform, getAvailableProviders, getConfiguredProviders, getDb, getPayment, getRequestUser, providerSupportedPlatforms };
|
|
110
|
+
export { type AuthUser, type CapabilityExecuteResponse, type CreateOrderParams, type CreateOrderResult, type ExecuteCapabilityOptions, type GetAvailableProvidersOptions, type GetOrderResult, PAYMENT_SUCCESS_NOTIFY_SIGNATURE_HEADER, type PaymentGatewayClient, type PaymentGatewayClientOptions, type PaymentPlatform, type PaymentSuccessNotifyPayload, createPaymentClient, executeCapability, filterProvidersByPlatform, getAvailableProviders, getConfiguredProviders, getDb, getPayment, getRequestUser, parseSuccessNotifyPayload, providerSupportedPlatforms, verifyAndParseSuccessNotifyRequest, verifySuccessNotifySignature };
|
package/dist/index.js
CHANGED
|
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
PAYMENT_SUCCESS_NOTIFY_SIGNATURE_HEADER: () => PAYMENT_SUCCESS_NOTIFY_SIGNATURE_HEADER,
|
|
33
34
|
createPaymentClient: () => createPaymentClient,
|
|
34
35
|
executeCapability: () => executeCapability,
|
|
35
36
|
filterProvidersByPlatform: () => filterProvidersByPlatform,
|
|
@@ -38,7 +39,10 @@ __export(index_exports, {
|
|
|
38
39
|
getDb: () => getDb,
|
|
39
40
|
getPayment: () => getPayment,
|
|
40
41
|
getRequestUser: () => getRequestUser,
|
|
41
|
-
|
|
42
|
+
parseSuccessNotifyPayload: () => parseSuccessNotifyPayload,
|
|
43
|
+
providerSupportedPlatforms: () => providerSupportedPlatforms,
|
|
44
|
+
verifyAndParseSuccessNotifyRequest: () => verifyAndParseSuccessNotifyRequest,
|
|
45
|
+
verifySuccessNotifySignature: () => verifySuccessNotifySignature
|
|
42
46
|
});
|
|
43
47
|
module.exports = __toCommonJS(index_exports);
|
|
44
48
|
|
|
@@ -103,6 +107,69 @@ var PROVIDER_SUPPORTED_PLATFORMS = {
|
|
|
103
107
|
"alipay-miniprogram": ["alipay-miniprogram"],
|
|
104
108
|
"stripe": ["web"]
|
|
105
109
|
};
|
|
110
|
+
var PAYMENT_SUCCESS_NOTIFY_SIGNATURE_HEADER = "X-Payment-Gateway-Signature";
|
|
111
|
+
function decodeBase64ToBytes(input) {
|
|
112
|
+
try {
|
|
113
|
+
return Uint8Array.from(atob(input), (char) => char.charCodeAt(0));
|
|
114
|
+
} catch {
|
|
115
|
+
throw new Error("Invalid base64 signature");
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function isPaymentSuccessNotifyPayload(value) {
|
|
119
|
+
if (!value || typeof value !== "object") return false;
|
|
120
|
+
const payload = value;
|
|
121
|
+
return typeof payload.platformOrderId === "string" && payload.platformOrderId.length > 0 && typeof payload.bizOrderId === "string" && payload.bizOrderId.length > 0 && payload.status === "succeeded" && typeof payload.amount === "number" && Number.isFinite(payload.amount) && typeof payload.currency === "string" && payload.currency.length > 0 && typeof payload.providerId === "string" && payload.providerId.length > 0 && typeof payload.timestamp === "string" && payload.timestamp.length > 0 && typeof payload.paidAt === "string" && payload.paidAt.length > 0 && (payload.providerOrderId == null || typeof payload.providerOrderId === "string");
|
|
122
|
+
}
|
|
123
|
+
async function signHmacSha256Bytes(message, secret) {
|
|
124
|
+
const key = await crypto.subtle.importKey(
|
|
125
|
+
"raw",
|
|
126
|
+
new TextEncoder().encode(secret),
|
|
127
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
128
|
+
false,
|
|
129
|
+
["sign"]
|
|
130
|
+
);
|
|
131
|
+
const signature = await crypto.subtle.sign(
|
|
132
|
+
"HMAC",
|
|
133
|
+
key,
|
|
134
|
+
new TextEncoder().encode(message)
|
|
135
|
+
);
|
|
136
|
+
return new Uint8Array(signature);
|
|
137
|
+
}
|
|
138
|
+
function timingSafeEqualBytes(a, b) {
|
|
139
|
+
if (a.length !== b.length) return false;
|
|
140
|
+
let diff = 0;
|
|
141
|
+
for (let i = 0; i < a.length; i += 1) {
|
|
142
|
+
diff |= a[i] ^ b[i];
|
|
143
|
+
}
|
|
144
|
+
return diff === 0;
|
|
145
|
+
}
|
|
146
|
+
async function verifySuccessNotifySignature(rawBody, signature, secret) {
|
|
147
|
+
if (!signature || !secret) return false;
|
|
148
|
+
const expected = await signHmacSha256Bytes(rawBody, secret);
|
|
149
|
+
const actual = decodeBase64ToBytes(signature);
|
|
150
|
+
return timingSafeEqualBytes(expected, actual);
|
|
151
|
+
}
|
|
152
|
+
function parseSuccessNotifyPayload(rawBody) {
|
|
153
|
+
let parsed;
|
|
154
|
+
try {
|
|
155
|
+
parsed = JSON.parse(rawBody);
|
|
156
|
+
} catch {
|
|
157
|
+
throw new Error("Invalid success notify JSON body");
|
|
158
|
+
}
|
|
159
|
+
if (!isPaymentSuccessNotifyPayload(parsed)) {
|
|
160
|
+
throw new Error("Invalid success notify payload");
|
|
161
|
+
}
|
|
162
|
+
return parsed;
|
|
163
|
+
}
|
|
164
|
+
async function verifyAndParseSuccessNotifyRequest(request, secret) {
|
|
165
|
+
const rawBody = await request.text();
|
|
166
|
+
const signature = request.headers.get(PAYMENT_SUCCESS_NOTIFY_SIGNATURE_HEADER);
|
|
167
|
+
const verified = await verifySuccessNotifySignature(rawBody, signature, secret);
|
|
168
|
+
if (!verified) {
|
|
169
|
+
throw new Error("Invalid payment notify signature");
|
|
170
|
+
}
|
|
171
|
+
return parseSuccessNotifyPayload(rawBody);
|
|
172
|
+
}
|
|
106
173
|
function resolveBaseUrl(explicit) {
|
|
107
174
|
const url = explicit ?? getEnv("PAYMENT_GATEWAY_URL");
|
|
108
175
|
if (!url) throw new Error("PAYMENT_GATEWAY_URL is not set; payment gateway client requires it");
|
|
@@ -303,6 +370,7 @@ ${projectCode}`;
|
|
|
303
370
|
}
|
|
304
371
|
// Annotate the CommonJS export names for ESM import in node:
|
|
305
372
|
0 && (module.exports = {
|
|
373
|
+
PAYMENT_SUCCESS_NOTIFY_SIGNATURE_HEADER,
|
|
306
374
|
createPaymentClient,
|
|
307
375
|
executeCapability,
|
|
308
376
|
filterProvidersByPlatform,
|
|
@@ -311,5 +379,8 @@ ${projectCode}`;
|
|
|
311
379
|
getDb,
|
|
312
380
|
getPayment,
|
|
313
381
|
getRequestUser,
|
|
314
|
-
|
|
382
|
+
parseSuccessNotifyPayload,
|
|
383
|
+
providerSupportedPlatforms,
|
|
384
|
+
verifyAndParseSuccessNotifyRequest,
|
|
385
|
+
verifySuccessNotifySignature
|
|
315
386
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -59,6 +59,69 @@ var PROVIDER_SUPPORTED_PLATFORMS = {
|
|
|
59
59
|
"alipay-miniprogram": ["alipay-miniprogram"],
|
|
60
60
|
"stripe": ["web"]
|
|
61
61
|
};
|
|
62
|
+
var PAYMENT_SUCCESS_NOTIFY_SIGNATURE_HEADER = "X-Payment-Gateway-Signature";
|
|
63
|
+
function decodeBase64ToBytes(input) {
|
|
64
|
+
try {
|
|
65
|
+
return Uint8Array.from(atob(input), (char) => char.charCodeAt(0));
|
|
66
|
+
} catch {
|
|
67
|
+
throw new Error("Invalid base64 signature");
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function isPaymentSuccessNotifyPayload(value) {
|
|
71
|
+
if (!value || typeof value !== "object") return false;
|
|
72
|
+
const payload = value;
|
|
73
|
+
return typeof payload.platformOrderId === "string" && payload.platformOrderId.length > 0 && typeof payload.bizOrderId === "string" && payload.bizOrderId.length > 0 && payload.status === "succeeded" && typeof payload.amount === "number" && Number.isFinite(payload.amount) && typeof payload.currency === "string" && payload.currency.length > 0 && typeof payload.providerId === "string" && payload.providerId.length > 0 && typeof payload.timestamp === "string" && payload.timestamp.length > 0 && typeof payload.paidAt === "string" && payload.paidAt.length > 0 && (payload.providerOrderId == null || typeof payload.providerOrderId === "string");
|
|
74
|
+
}
|
|
75
|
+
async function signHmacSha256Bytes(message, secret) {
|
|
76
|
+
const key = await crypto.subtle.importKey(
|
|
77
|
+
"raw",
|
|
78
|
+
new TextEncoder().encode(secret),
|
|
79
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
80
|
+
false,
|
|
81
|
+
["sign"]
|
|
82
|
+
);
|
|
83
|
+
const signature = await crypto.subtle.sign(
|
|
84
|
+
"HMAC",
|
|
85
|
+
key,
|
|
86
|
+
new TextEncoder().encode(message)
|
|
87
|
+
);
|
|
88
|
+
return new Uint8Array(signature);
|
|
89
|
+
}
|
|
90
|
+
function timingSafeEqualBytes(a, b) {
|
|
91
|
+
if (a.length !== b.length) return false;
|
|
92
|
+
let diff = 0;
|
|
93
|
+
for (let i = 0; i < a.length; i += 1) {
|
|
94
|
+
diff |= a[i] ^ b[i];
|
|
95
|
+
}
|
|
96
|
+
return diff === 0;
|
|
97
|
+
}
|
|
98
|
+
async function verifySuccessNotifySignature(rawBody, signature, secret) {
|
|
99
|
+
if (!signature || !secret) return false;
|
|
100
|
+
const expected = await signHmacSha256Bytes(rawBody, secret);
|
|
101
|
+
const actual = decodeBase64ToBytes(signature);
|
|
102
|
+
return timingSafeEqualBytes(expected, actual);
|
|
103
|
+
}
|
|
104
|
+
function parseSuccessNotifyPayload(rawBody) {
|
|
105
|
+
let parsed;
|
|
106
|
+
try {
|
|
107
|
+
parsed = JSON.parse(rawBody);
|
|
108
|
+
} catch {
|
|
109
|
+
throw new Error("Invalid success notify JSON body");
|
|
110
|
+
}
|
|
111
|
+
if (!isPaymentSuccessNotifyPayload(parsed)) {
|
|
112
|
+
throw new Error("Invalid success notify payload");
|
|
113
|
+
}
|
|
114
|
+
return parsed;
|
|
115
|
+
}
|
|
116
|
+
async function verifyAndParseSuccessNotifyRequest(request, secret) {
|
|
117
|
+
const rawBody = await request.text();
|
|
118
|
+
const signature = request.headers.get(PAYMENT_SUCCESS_NOTIFY_SIGNATURE_HEADER);
|
|
119
|
+
const verified = await verifySuccessNotifySignature(rawBody, signature, secret);
|
|
120
|
+
if (!verified) {
|
|
121
|
+
throw new Error("Invalid payment notify signature");
|
|
122
|
+
}
|
|
123
|
+
return parseSuccessNotifyPayload(rawBody);
|
|
124
|
+
}
|
|
62
125
|
function resolveBaseUrl(explicit) {
|
|
63
126
|
const url = explicit ?? getEnv("PAYMENT_GATEWAY_URL");
|
|
64
127
|
if (!url) throw new Error("PAYMENT_GATEWAY_URL is not set; payment gateway client requires it");
|
|
@@ -258,6 +321,7 @@ ${projectCode}`;
|
|
|
258
321
|
return responseBody.data;
|
|
259
322
|
}
|
|
260
323
|
export {
|
|
324
|
+
PAYMENT_SUCCESS_NOTIFY_SIGNATURE_HEADER,
|
|
261
325
|
createPaymentClient,
|
|
262
326
|
executeCapability,
|
|
263
327
|
filterProvidersByPlatform,
|
|
@@ -266,5 +330,8 @@ export {
|
|
|
266
330
|
getDb,
|
|
267
331
|
getPayment,
|
|
268
332
|
getRequestUser,
|
|
269
|
-
|
|
333
|
+
parseSuccessNotifyPayload,
|
|
334
|
+
providerSupportedPlatforms,
|
|
335
|
+
verifyAndParseSuccessNotifyRequest,
|
|
336
|
+
verifySuccessNotifySignature
|
|
270
337
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nvwa-app/sdk-functions",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.3.0",
|
|
4
4
|
"description": "NVWA Edge Functions SDK: db, payment gateway, auth, provider list. Use in Deno: import from 'npm:@nvwa-app/sdk-functions'.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|