@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 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
- providerSupportedPlatforms: () => providerSupportedPlatforms
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
- providerSupportedPlatforms
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
- providerSupportedPlatforms
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.1.0",
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",