orvex-pay 1.1.0 → 1.2.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 OrvexPay
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -49,7 +49,26 @@ Currently, this SDK supports the `invoices` resource.
49
49
  Creates a new payment invoice and returns an `InvoiceResponse` containing the `payUrl`.
50
50
 
51
51
  ### `orvex.invoices.retrieve(invoiceId)`
52
- Gets the status of an existing invoice using its `invoiceId`.
52
+ Gets the status of an existing invoice using its `invoiceId`.
53
+
54
+ ## Webhook Security
55
+
56
+ To ensure that a webhook was actually sent by OrvexPay, you should verify the signature.
57
+
58
+ ```typescript
59
+ import { OrvexClient } from 'orvex-pay';
60
+
61
+ // Use the raw body of the request
62
+ const isValid = OrvexClient.webhooks.verifySignature(
63
+ req.rawBody,
64
+ req.headers['x-orvex-signature'],
65
+ process.env.ORVEX_WEBHOOK_SECRET
66
+ );
67
+
68
+ if (isValid) {
69
+ // Process the payment event
70
+ }
71
+ ```
53
72
 
54
73
  ---
55
74
 
package/dist/index.d.mts CHANGED
@@ -27,6 +27,7 @@ interface InvoiceResponse {
27
27
  payAmount: number;
28
28
  payCurrency: string;
29
29
  priceAmountInUsd?: number;
30
+ amountReceived?: number;
30
31
  payAddress: string;
31
32
  status: string;
32
33
  createdAt: string;
@@ -43,6 +44,7 @@ interface OrvexApiClientOptions {
43
44
  declare class InvoicesResource {
44
45
  private client;
45
46
  constructor(client: AxiosInstance);
47
+ private handleError;
46
48
  /**
47
49
  * Creates a new payment invoice.
48
50
  * @param params
@@ -51,16 +53,38 @@ declare class InvoicesResource {
51
53
  create(params: CreateInvoiceRequest): Promise<InvoiceResponse>;
52
54
  /**
53
55
  * Retrieves an invoice by its invoiceId.
54
- * @param id The invoice ID returned by the initial API call
56
+ * @param invoiceId The invoice ID returned by the initial API call
55
57
  * @returns
56
58
  */
57
59
  retrieve(invoiceId: string): Promise<InvoiceResponse>;
58
60
  }
59
61
 
62
+ declare class Webhooks {
63
+ /**
64
+ * Verifies the signature of an incoming webhook from OrvexPay.
65
+ *
66
+ * @param payload Raw string body of the webhook request.
67
+ * @param signature The signature from the 'x-orvex-signature' header.
68
+ * @param secret Your webhook secret from the Merchant Dashboard.
69
+ * @returns boolean
70
+ */
71
+ static verifySignature(payload: string, signature: string, secret: string): boolean;
72
+ }
73
+
60
74
  declare class OrvexClient {
61
75
  invoices: InvoicesResource;
76
+ webhooks: typeof Webhooks;
62
77
  private readonly client;
63
78
  constructor(options: OrvexApiClientOptions);
64
79
  }
65
80
 
66
- export { type CreateInvoiceRequest, type InvoiceResponse, InvoicesResource, type OrvexApiClientOptions, OrvexClient };
81
+ declare class OrvexError extends Error {
82
+ readonly statusCode?: number;
83
+ readonly responseData?: any;
84
+ constructor(message: string, statusCode?: number, responseData?: any);
85
+ }
86
+ declare class OrvexSignatureError extends OrvexError {
87
+ constructor(message: string);
88
+ }
89
+
90
+ export { type CreateInvoiceRequest, type InvoiceResponse, InvoicesResource, type OrvexApiClientOptions, OrvexClient, OrvexError, OrvexSignatureError, Webhooks, OrvexClient as default };
package/dist/index.d.ts CHANGED
@@ -27,6 +27,7 @@ interface InvoiceResponse {
27
27
  payAmount: number;
28
28
  payCurrency: string;
29
29
  priceAmountInUsd?: number;
30
+ amountReceived?: number;
30
31
  payAddress: string;
31
32
  status: string;
32
33
  createdAt: string;
@@ -43,6 +44,7 @@ interface OrvexApiClientOptions {
43
44
  declare class InvoicesResource {
44
45
  private client;
45
46
  constructor(client: AxiosInstance);
47
+ private handleError;
46
48
  /**
47
49
  * Creates a new payment invoice.
48
50
  * @param params
@@ -51,16 +53,38 @@ declare class InvoicesResource {
51
53
  create(params: CreateInvoiceRequest): Promise<InvoiceResponse>;
52
54
  /**
53
55
  * Retrieves an invoice by its invoiceId.
54
- * @param id The invoice ID returned by the initial API call
56
+ * @param invoiceId The invoice ID returned by the initial API call
55
57
  * @returns
56
58
  */
57
59
  retrieve(invoiceId: string): Promise<InvoiceResponse>;
58
60
  }
59
61
 
62
+ declare class Webhooks {
63
+ /**
64
+ * Verifies the signature of an incoming webhook from OrvexPay.
65
+ *
66
+ * @param payload Raw string body of the webhook request.
67
+ * @param signature The signature from the 'x-orvex-signature' header.
68
+ * @param secret Your webhook secret from the Merchant Dashboard.
69
+ * @returns boolean
70
+ */
71
+ static verifySignature(payload: string, signature: string, secret: string): boolean;
72
+ }
73
+
60
74
  declare class OrvexClient {
61
75
  invoices: InvoicesResource;
76
+ webhooks: typeof Webhooks;
62
77
  private readonly client;
63
78
  constructor(options: OrvexApiClientOptions);
64
79
  }
65
80
 
66
- export { type CreateInvoiceRequest, type InvoiceResponse, InvoicesResource, type OrvexApiClientOptions, OrvexClient };
81
+ declare class OrvexError extends Error {
82
+ readonly statusCode?: number;
83
+ readonly responseData?: any;
84
+ constructor(message: string, statusCode?: number, responseData?: any);
85
+ }
86
+ declare class OrvexSignatureError extends OrvexError {
87
+ constructor(message: string);
88
+ }
89
+
90
+ export { type CreateInvoiceRequest, type InvoiceResponse, InvoicesResource, type OrvexApiClientOptions, OrvexClient, OrvexError, OrvexSignatureError, Webhooks, OrvexClient as default };
package/dist/index.js CHANGED
@@ -31,19 +31,54 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
33
  InvoicesResource: () => InvoicesResource,
34
- OrvexClient: () => OrvexClient
34
+ OrvexClient: () => OrvexClient,
35
+ OrvexError: () => OrvexError,
36
+ OrvexSignatureError: () => OrvexSignatureError,
37
+ Webhooks: () => Webhooks,
38
+ default: () => index_default
35
39
  });
36
40
  module.exports = __toCommonJS(index_exports);
37
41
 
38
42
  // src/client.ts
39
43
  var import_axios = __toESM(require("axios"));
40
44
 
45
+ // src/errors.ts
46
+ var OrvexError = class _OrvexError extends Error {
47
+ statusCode;
48
+ responseData;
49
+ constructor(message, statusCode, responseData) {
50
+ super(message);
51
+ this.name = "OrvexError";
52
+ this.statusCode = statusCode;
53
+ this.responseData = responseData;
54
+ if (Error.captureStackTrace) {
55
+ Error.captureStackTrace(this, _OrvexError);
56
+ }
57
+ }
58
+ };
59
+ var OrvexSignatureError = class extends OrvexError {
60
+ constructor(message) {
61
+ super(message, 401);
62
+ this.name = "OrvexSignatureError";
63
+ }
64
+ };
65
+
41
66
  // src/resources/invoices.ts
42
67
  var InvoicesResource = class {
43
68
  client;
44
69
  constructor(client) {
45
70
  this.client = client;
46
71
  }
72
+ handleError(error) {
73
+ if (error.response && error.response.data) {
74
+ throw new OrvexError(
75
+ error.response.data.message || "OrvexPay API Error",
76
+ error.response.status,
77
+ error.response.data
78
+ );
79
+ }
80
+ throw error;
81
+ }
47
82
  /**
48
83
  * Creates a new payment invoice.
49
84
  * @param params
@@ -54,15 +89,12 @@ var InvoicesResource = class {
54
89
  const response = await this.client.post("/api/invoice", params);
55
90
  return response.data;
56
91
  } catch (error) {
57
- if (error.response && error.response.data) {
58
- throw new Error(`OrvexPay API Error: ${JSON.stringify(error.response.data)}`);
59
- }
60
- throw error;
92
+ this.handleError(error);
61
93
  }
62
94
  }
63
95
  /**
64
96
  * Retrieves an invoice by its invoiceId.
65
- * @param id The invoice ID returned by the initial API call
97
+ * @param invoiceId The invoice ID returned by the initial API call
66
98
  * @returns
67
99
  */
68
100
  async retrieve(invoiceId) {
@@ -70,21 +102,44 @@ var InvoicesResource = class {
70
102
  const response = await this.client.get(`/api/invoice/${invoiceId}`);
71
103
  return response.data;
72
104
  } catch (error) {
73
- if (error.response && error.response.data) {
74
- throw new Error(`OrvexPay API Error: ${JSON.stringify(error.response.data)}`);
75
- }
76
- throw error;
105
+ this.handleError(error);
77
106
  }
78
107
  }
79
108
  };
80
109
 
110
+ // src/webhooks.ts
111
+ var crypto = __toESM(require("crypto"));
112
+ var Webhooks = class {
113
+ /**
114
+ * Verifies the signature of an incoming webhook from OrvexPay.
115
+ *
116
+ * @param payload Raw string body of the webhook request.
117
+ * @param signature The signature from the 'x-orvex-signature' header.
118
+ * @param secret Your webhook secret from the Merchant Dashboard.
119
+ * @returns boolean
120
+ */
121
+ static verifySignature(payload, signature, secret) {
122
+ if (!signature || !secret) {
123
+ throw new OrvexSignatureError("Missing signature or webhook secret.");
124
+ }
125
+ const expectedSignature = crypto.createHmac("sha256", secret).update(payload).digest("hex");
126
+ const signatureBuffer = Buffer.from(signature);
127
+ const expectedBuffer = Buffer.from(expectedSignature);
128
+ if (signatureBuffer.length !== expectedBuffer.length || !crypto.timingSafeEqual(signatureBuffer, expectedBuffer)) {
129
+ throw new OrvexSignatureError("Invalid webhook signature.");
130
+ }
131
+ return true;
132
+ }
133
+ };
134
+
81
135
  // src/client.ts
82
136
  var OrvexClient = class {
83
137
  invoices;
138
+ webhooks = Webhooks;
84
139
  client;
85
140
  constructor(options) {
86
141
  if (!options.apiKey) {
87
- throw new Error("OrvexPay: apiKey is required to initialize the client.");
142
+ throw new OrvexError("OrvexPay: apiKey is required to initialize the client.");
88
143
  }
89
144
  this.client = import_axios.default.create({
90
145
  baseURL: options.baseURL ? options.baseURL.replace(/\/$/, "") : "https://api.orvexpay.com",
@@ -97,8 +152,14 @@ var OrvexClient = class {
97
152
  this.invoices = new InvoicesResource(this.client);
98
153
  }
99
154
  };
155
+
156
+ // src/index.ts
157
+ var index_default = OrvexClient;
100
158
  // Annotate the CommonJS export names for ESM import in node:
101
159
  0 && (module.exports = {
102
160
  InvoicesResource,
103
- OrvexClient
161
+ OrvexClient,
162
+ OrvexError,
163
+ OrvexSignatureError,
164
+ Webhooks
104
165
  });
package/dist/index.mjs CHANGED
@@ -1,12 +1,43 @@
1
1
  // src/client.ts
2
2
  import axios from "axios";
3
3
 
4
+ // src/errors.ts
5
+ var OrvexError = class _OrvexError extends Error {
6
+ statusCode;
7
+ responseData;
8
+ constructor(message, statusCode, responseData) {
9
+ super(message);
10
+ this.name = "OrvexError";
11
+ this.statusCode = statusCode;
12
+ this.responseData = responseData;
13
+ if (Error.captureStackTrace) {
14
+ Error.captureStackTrace(this, _OrvexError);
15
+ }
16
+ }
17
+ };
18
+ var OrvexSignatureError = class extends OrvexError {
19
+ constructor(message) {
20
+ super(message, 401);
21
+ this.name = "OrvexSignatureError";
22
+ }
23
+ };
24
+
4
25
  // src/resources/invoices.ts
5
26
  var InvoicesResource = class {
6
27
  client;
7
28
  constructor(client) {
8
29
  this.client = client;
9
30
  }
31
+ handleError(error) {
32
+ if (error.response && error.response.data) {
33
+ throw new OrvexError(
34
+ error.response.data.message || "OrvexPay API Error",
35
+ error.response.status,
36
+ error.response.data
37
+ );
38
+ }
39
+ throw error;
40
+ }
10
41
  /**
11
42
  * Creates a new payment invoice.
12
43
  * @param params
@@ -17,15 +48,12 @@ var InvoicesResource = class {
17
48
  const response = await this.client.post("/api/invoice", params);
18
49
  return response.data;
19
50
  } catch (error) {
20
- if (error.response && error.response.data) {
21
- throw new Error(`OrvexPay API Error: ${JSON.stringify(error.response.data)}`);
22
- }
23
- throw error;
51
+ this.handleError(error);
24
52
  }
25
53
  }
26
54
  /**
27
55
  * Retrieves an invoice by its invoiceId.
28
- * @param id The invoice ID returned by the initial API call
56
+ * @param invoiceId The invoice ID returned by the initial API call
29
57
  * @returns
30
58
  */
31
59
  async retrieve(invoiceId) {
@@ -33,21 +61,44 @@ var InvoicesResource = class {
33
61
  const response = await this.client.get(`/api/invoice/${invoiceId}`);
34
62
  return response.data;
35
63
  } catch (error) {
36
- if (error.response && error.response.data) {
37
- throw new Error(`OrvexPay API Error: ${JSON.stringify(error.response.data)}`);
38
- }
39
- throw error;
64
+ this.handleError(error);
40
65
  }
41
66
  }
42
67
  };
43
68
 
69
+ // src/webhooks.ts
70
+ import * as crypto from "crypto";
71
+ var Webhooks = class {
72
+ /**
73
+ * Verifies the signature of an incoming webhook from OrvexPay.
74
+ *
75
+ * @param payload Raw string body of the webhook request.
76
+ * @param signature The signature from the 'x-orvex-signature' header.
77
+ * @param secret Your webhook secret from the Merchant Dashboard.
78
+ * @returns boolean
79
+ */
80
+ static verifySignature(payload, signature, secret) {
81
+ if (!signature || !secret) {
82
+ throw new OrvexSignatureError("Missing signature or webhook secret.");
83
+ }
84
+ const expectedSignature = crypto.createHmac("sha256", secret).update(payload).digest("hex");
85
+ const signatureBuffer = Buffer.from(signature);
86
+ const expectedBuffer = Buffer.from(expectedSignature);
87
+ if (signatureBuffer.length !== expectedBuffer.length || !crypto.timingSafeEqual(signatureBuffer, expectedBuffer)) {
88
+ throw new OrvexSignatureError("Invalid webhook signature.");
89
+ }
90
+ return true;
91
+ }
92
+ };
93
+
44
94
  // src/client.ts
45
95
  var OrvexClient = class {
46
96
  invoices;
97
+ webhooks = Webhooks;
47
98
  client;
48
99
  constructor(options) {
49
100
  if (!options.apiKey) {
50
- throw new Error("OrvexPay: apiKey is required to initialize the client.");
101
+ throw new OrvexError("OrvexPay: apiKey is required to initialize the client.");
51
102
  }
52
103
  this.client = axios.create({
53
104
  baseURL: options.baseURL ? options.baseURL.replace(/\/$/, "") : "https://api.orvexpay.com",
@@ -60,7 +111,14 @@ var OrvexClient = class {
60
111
  this.invoices = new InvoicesResource(this.client);
61
112
  }
62
113
  };
114
+
115
+ // src/index.ts
116
+ var index_default = OrvexClient;
63
117
  export {
64
118
  InvoicesResource,
65
- OrvexClient
119
+ OrvexClient,
120
+ OrvexError,
121
+ OrvexSignatureError,
122
+ Webhooks,
123
+ index_default as default
66
124
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orvex-pay",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "description": "Official Node.js SDK for the OrvexPay API",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
package/src/client.ts CHANGED
@@ -1,14 +1,17 @@
1
1
  import axios, { AxiosInstance } from 'axios';
2
2
  import { OrvexApiClientOptions } from './types';
3
3
  import { InvoicesResource } from './resources/invoices';
4
+ import { Webhooks } from './webhooks';
5
+ import { OrvexError } from './errors';
4
6
 
5
7
  export class OrvexClient {
6
8
  public invoices: InvoicesResource;
9
+ public webhooks = Webhooks;
7
10
  private readonly client: AxiosInstance;
8
11
 
9
12
  constructor(options: OrvexApiClientOptions) {
10
13
  if (!options.apiKey) {
11
- throw new Error('OrvexPay: apiKey is required to initialize the client.');
14
+ throw new OrvexError('OrvexPay: apiKey is required to initialize the client.');
12
15
  }
13
16
 
14
17
  this.client = axios.create({
package/src/errors.ts ADDED
@@ -0,0 +1,23 @@
1
+ export class OrvexError extends Error {
2
+ public readonly statusCode?: number;
3
+ public readonly responseData?: any;
4
+
5
+ constructor(message: string, statusCode?: number, responseData?: any) {
6
+ super(message);
7
+ this.name = 'OrvexError';
8
+ this.statusCode = statusCode;
9
+ this.responseData = responseData;
10
+
11
+ // Ensure stack trace is correctly captured in Node.js
12
+ if (Error.captureStackTrace) {
13
+ Error.captureStackTrace(this, OrvexError);
14
+ }
15
+ }
16
+ }
17
+
18
+ export class OrvexSignatureError extends OrvexError {
19
+ constructor(message: string) {
20
+ super(message, 401);
21
+ this.name = 'OrvexSignatureError';
22
+ }
23
+ }
package/src/index.ts CHANGED
@@ -1,3 +1,8 @@
1
+ import { OrvexClient } from './client';
1
2
  export * from './client';
2
3
  export * from './types';
4
+ export * from './errors';
5
+ export * from './webhooks';
3
6
  export * from './resources/invoices';
7
+
8
+ export default OrvexClient;
@@ -1,5 +1,6 @@
1
1
  import { AxiosInstance } from 'axios';
2
2
  import { CreateInvoiceRequest, InvoiceResponse } from '../types';
3
+ import { OrvexError } from '../errors';
3
4
 
4
5
  export class InvoicesResource {
5
6
  private client: AxiosInstance;
@@ -8,6 +9,17 @@ export class InvoicesResource {
8
9
  this.client = client;
9
10
  }
10
11
 
12
+ private handleError(error: any): never {
13
+ if (error.response && error.response.data) {
14
+ throw new OrvexError(
15
+ error.response.data.message || 'OrvexPay API Error',
16
+ error.response.status,
17
+ error.response.data
18
+ );
19
+ }
20
+ throw error;
21
+ }
22
+
11
23
  /**
12
24
  * Creates a new payment invoice.
13
25
  * @param params
@@ -18,16 +30,13 @@ export class InvoicesResource {
18
30
  const response = await this.client.post<InvoiceResponse>('/api/invoice', params);
19
31
  return response.data;
20
32
  } catch (error: any) {
21
- if (error.response && error.response.data) {
22
- throw new Error(`OrvexPay API Error: ${JSON.stringify(error.response.data)}`);
23
- }
24
- throw error;
33
+ this.handleError(error);
25
34
  }
26
35
  }
27
36
 
28
37
  /**
29
38
  * Retrieves an invoice by its invoiceId.
30
- * @param id The invoice ID returned by the initial API call
39
+ * @param invoiceId The invoice ID returned by the initial API call
31
40
  * @returns
32
41
  */
33
42
  async retrieve(invoiceId: string): Promise<InvoiceResponse> {
@@ -35,10 +44,7 @@ export class InvoicesResource {
35
44
  const response = await this.client.get<InvoiceResponse>(`/api/invoice/${invoiceId}`);
36
45
  return response.data;
37
46
  } catch (error: any) {
38
- if (error.response && error.response.data) {
39
- throw new Error(`OrvexPay API Error: ${JSON.stringify(error.response.data)}`);
40
- }
41
- throw error;
47
+ this.handleError(error);
42
48
  }
43
49
  }
44
50
  }
package/src/types.ts CHANGED
@@ -26,6 +26,7 @@ export interface InvoiceResponse {
26
26
  payAmount: number;
27
27
  payCurrency: string;
28
28
  priceAmountInUsd?: number;
29
+ amountReceived?: number;
29
30
  payAddress: string;
30
31
  status: string;
31
32
  createdAt: string;
@@ -0,0 +1,32 @@
1
+ import * as crypto from 'crypto';
2
+ import { OrvexSignatureError } from './errors';
3
+
4
+ export class Webhooks {
5
+ /**
6
+ * Verifies the signature of an incoming webhook from OrvexPay.
7
+ *
8
+ * @param payload Raw string body of the webhook request.
9
+ * @param signature The signature from the 'x-orvex-signature' header.
10
+ * @param secret Your webhook secret from the Merchant Dashboard.
11
+ * @returns boolean
12
+ */
13
+ static verifySignature(payload: string, signature: string, secret: string): boolean {
14
+ if (!signature || !secret) {
15
+ throw new OrvexSignatureError('Missing signature or webhook secret.');
16
+ }
17
+
18
+ const expectedSignature = crypto
19
+ .createHmac('sha256', secret)
20
+ .update(payload)
21
+ .digest('hex');
22
+
23
+ const signatureBuffer = Buffer.from(signature);
24
+ const expectedBuffer = Buffer.from(expectedSignature);
25
+
26
+ if (signatureBuffer.length !== expectedBuffer.length || !crypto.timingSafeEqual(signatureBuffer, expectedBuffer)) {
27
+ throw new OrvexSignatureError('Invalid webhook signature.');
28
+ }
29
+
30
+ return true;
31
+ }
32
+ }