@mohasinac/payment-razorpay 0.1.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.cjs ADDED
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ RazorpayProvider: () => RazorpayProvider,
34
+ paiseToRupees: () => paiseToRupees,
35
+ rupeesToPaise: () => rupeesToPaise,
36
+ verifyPaymentSignature: () => verifyPaymentSignature
37
+ });
38
+ module.exports = __toCommonJS(index_exports);
39
+ var import_razorpay = __toESM(require("razorpay"), 1);
40
+ var import_crypto = require("crypto");
41
+ var RazorpayProvider = class {
42
+ constructor(config) {
43
+ this.razorpay = new import_razorpay.default({
44
+ key_id: config.keyId,
45
+ key_secret: config.keySecret
46
+ });
47
+ this.webhookSecret = config.webhookSecret;
48
+ }
49
+ async createOrder(amount, currency = "INR", metadata) {
50
+ var _a;
51
+ const order = await this.razorpay.orders.create({
52
+ amount,
53
+ currency,
54
+ notes: metadata
55
+ });
56
+ return {
57
+ id: String(order.id),
58
+ amount: Number(order.amount),
59
+ currency: String(order.currency),
60
+ status: "created",
61
+ receipt: (_a = order.receipt) != null ? _a : void 0,
62
+ metadata,
63
+ createdAt: new Date(Number(order.created_at) * 1e3).toISOString()
64
+ };
65
+ }
66
+ /**
67
+ * Verify Razorpay webhook signature (HMAC-SHA256 over raw body).
68
+ * Requires webhookSecret to be set in the constructor.
69
+ */
70
+ verifyWebhook(payload, signature) {
71
+ if (!this.webhookSecret) return false;
72
+ const expected = (0, import_crypto.createHmac)("sha256", this.webhookSecret).update(payload).digest("hex");
73
+ if (signature.length !== 64 || expected.length !== 64) return false;
74
+ return (0, import_crypto.timingSafeEqual)(
75
+ Buffer.from(expected, "hex"),
76
+ Buffer.from(signature, "hex")
77
+ );
78
+ }
79
+ async capturePayment(paymentId) {
80
+ var _a;
81
+ const payment = await this.razorpay.payments.fetch(paymentId);
82
+ return {
83
+ id: String(payment.id),
84
+ orderId: String((_a = payment.order_id) != null ? _a : ""),
85
+ amount: Number(payment.amount),
86
+ currency: String(payment.currency),
87
+ status: payment.status === "captured" ? "captured" : "failed",
88
+ capturedAt: (/* @__PURE__ */ new Date()).toISOString()
89
+ };
90
+ }
91
+ async refund(paymentId, amount) {
92
+ const refundData = {};
93
+ if (amount !== void 0) refundData.amount = amount;
94
+ const result = await this.razorpay.payments.refund(
95
+ paymentId,
96
+ refundData
97
+ );
98
+ return {
99
+ id: String(result.id),
100
+ paymentId,
101
+ amount: Number(result.amount),
102
+ currency: String(result.currency),
103
+ status: result.status === "processed" ? "processed" : "pending",
104
+ createdAt: new Date(Number(result.created_at) * 1e3).toISOString()
105
+ };
106
+ }
107
+ async getOrder(orderId) {
108
+ var _a;
109
+ const order = await this.razorpay.orders.fetch(orderId);
110
+ return {
111
+ id: String(order.id),
112
+ amount: Number(order.amount),
113
+ currency: String(order.currency),
114
+ status: "created",
115
+ receipt: (_a = order.receipt) != null ? _a : void 0,
116
+ createdAt: new Date(Number(order.created_at) * 1e3).toISOString()
117
+ };
118
+ }
119
+ };
120
+ function rupeesToPaise(rupees) {
121
+ return Math.round(rupees * 100);
122
+ }
123
+ function paiseToRupees(paise) {
124
+ return paise / 100;
125
+ }
126
+ function verifyPaymentSignature(params, keySecret) {
127
+ if (!keySecret) return false;
128
+ const expected = (0, import_crypto.createHmac)("sha256", keySecret).update(`${params.razorpay_order_id}|${params.razorpay_payment_id}`).digest("hex");
129
+ if (params.razorpay_signature.length !== 64) return false;
130
+ return (0, import_crypto.timingSafeEqual)(
131
+ Buffer.from(expected, "hex"),
132
+ Buffer.from(params.razorpay_signature, "hex")
133
+ );
134
+ }
135
+ // Annotate the CommonJS export names for ESM import in node:
136
+ 0 && (module.exports = {
137
+ RazorpayProvider,
138
+ paiseToRupees,
139
+ rupeesToPaise,
140
+ verifyPaymentSignature
141
+ });
@@ -0,0 +1,58 @@
1
+ import { IPaymentProvider, PaymentOrder, PaymentCapture, Refund } from '@mohasinac/contracts';
2
+
3
+ /**
4
+ * @mohasinac/payment-razorpay — Razorpay IPaymentProvider implementation
5
+ *
6
+ * Implements the @mohasinac/contracts IPaymentProvider interface.
7
+ * Accepts credentials via constructor — no Firestore or DB dependency.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * import { RazorpayProvider } from "@mohasinac/payment-razorpay";
12
+ * import { registerProviders } from "@mohasinac/contracts";
13
+ *
14
+ * registerProviders({
15
+ * payment: new RazorpayProvider({
16
+ * keyId: process.env.RAZORPAY_KEY_ID!,
17
+ * keySecret: process.env.RAZORPAY_KEY_SECRET!,
18
+ * webhookSecret: process.env.RAZORPAY_WEBHOOK_SECRET,
19
+ * }),
20
+ * });
21
+ * ```
22
+ */
23
+
24
+ interface RazorpayConfig {
25
+ keyId: string;
26
+ keySecret: string;
27
+ webhookSecret?: string;
28
+ }
29
+ declare class RazorpayProvider implements IPaymentProvider {
30
+ private readonly razorpay;
31
+ private readonly webhookSecret?;
32
+ constructor(config: RazorpayConfig);
33
+ createOrder(amount: number, currency?: string, metadata?: Record<string, unknown>): Promise<PaymentOrder>;
34
+ /**
35
+ * Verify Razorpay webhook signature (HMAC-SHA256 over raw body).
36
+ * Requires webhookSecret to be set in the constructor.
37
+ */
38
+ verifyWebhook(payload: string, signature: string): boolean;
39
+ capturePayment(paymentId: string): Promise<PaymentCapture>;
40
+ refund(paymentId: string, amount?: number): Promise<Refund>;
41
+ getOrder(orderId: string): Promise<PaymentOrder>;
42
+ }
43
+ /** Convert rupees (float) → paise (integer) for Razorpay amount field */
44
+ declare function rupeesToPaise(rupees: number): number;
45
+ /** Convert paise (integer) → rupees (float) */
46
+ declare function paiseToRupees(paise: number): number;
47
+ interface RazorpayPaymentResult {
48
+ razorpay_order_id: string;
49
+ razorpay_payment_id: string;
50
+ razorpay_signature: string;
51
+ }
52
+ /**
53
+ * Verify Razorpay payment signature.
54
+ * Uses HMAC-SHA256 over `{orderId}|{paymentId}` with the key secret.
55
+ */
56
+ declare function verifyPaymentSignature(params: RazorpayPaymentResult, keySecret: string): boolean;
57
+
58
+ export { type RazorpayConfig, type RazorpayPaymentResult, RazorpayProvider, paiseToRupees, rupeesToPaise, verifyPaymentSignature };
@@ -0,0 +1,58 @@
1
+ import { IPaymentProvider, PaymentOrder, PaymentCapture, Refund } from '@mohasinac/contracts';
2
+
3
+ /**
4
+ * @mohasinac/payment-razorpay — Razorpay IPaymentProvider implementation
5
+ *
6
+ * Implements the @mohasinac/contracts IPaymentProvider interface.
7
+ * Accepts credentials via constructor — no Firestore or DB dependency.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * import { RazorpayProvider } from "@mohasinac/payment-razorpay";
12
+ * import { registerProviders } from "@mohasinac/contracts";
13
+ *
14
+ * registerProviders({
15
+ * payment: new RazorpayProvider({
16
+ * keyId: process.env.RAZORPAY_KEY_ID!,
17
+ * keySecret: process.env.RAZORPAY_KEY_SECRET!,
18
+ * webhookSecret: process.env.RAZORPAY_WEBHOOK_SECRET,
19
+ * }),
20
+ * });
21
+ * ```
22
+ */
23
+
24
+ interface RazorpayConfig {
25
+ keyId: string;
26
+ keySecret: string;
27
+ webhookSecret?: string;
28
+ }
29
+ declare class RazorpayProvider implements IPaymentProvider {
30
+ private readonly razorpay;
31
+ private readonly webhookSecret?;
32
+ constructor(config: RazorpayConfig);
33
+ createOrder(amount: number, currency?: string, metadata?: Record<string, unknown>): Promise<PaymentOrder>;
34
+ /**
35
+ * Verify Razorpay webhook signature (HMAC-SHA256 over raw body).
36
+ * Requires webhookSecret to be set in the constructor.
37
+ */
38
+ verifyWebhook(payload: string, signature: string): boolean;
39
+ capturePayment(paymentId: string): Promise<PaymentCapture>;
40
+ refund(paymentId: string, amount?: number): Promise<Refund>;
41
+ getOrder(orderId: string): Promise<PaymentOrder>;
42
+ }
43
+ /** Convert rupees (float) → paise (integer) for Razorpay amount field */
44
+ declare function rupeesToPaise(rupees: number): number;
45
+ /** Convert paise (integer) → rupees (float) */
46
+ declare function paiseToRupees(paise: number): number;
47
+ interface RazorpayPaymentResult {
48
+ razorpay_order_id: string;
49
+ razorpay_payment_id: string;
50
+ razorpay_signature: string;
51
+ }
52
+ /**
53
+ * Verify Razorpay payment signature.
54
+ * Uses HMAC-SHA256 over `{orderId}|{paymentId}` with the key secret.
55
+ */
56
+ declare function verifyPaymentSignature(params: RazorpayPaymentResult, keySecret: string): boolean;
57
+
58
+ export { type RazorpayConfig, type RazorpayPaymentResult, RazorpayProvider, paiseToRupees, rupeesToPaise, verifyPaymentSignature };
package/dist/index.js ADDED
@@ -0,0 +1,103 @@
1
+ // src/index.ts
2
+ import Razorpay from "razorpay";
3
+ import { createHmac, timingSafeEqual } from "crypto";
4
+ var RazorpayProvider = class {
5
+ constructor(config) {
6
+ this.razorpay = new Razorpay({
7
+ key_id: config.keyId,
8
+ key_secret: config.keySecret
9
+ });
10
+ this.webhookSecret = config.webhookSecret;
11
+ }
12
+ async createOrder(amount, currency = "INR", metadata) {
13
+ var _a;
14
+ const order = await this.razorpay.orders.create({
15
+ amount,
16
+ currency,
17
+ notes: metadata
18
+ });
19
+ return {
20
+ id: String(order.id),
21
+ amount: Number(order.amount),
22
+ currency: String(order.currency),
23
+ status: "created",
24
+ receipt: (_a = order.receipt) != null ? _a : void 0,
25
+ metadata,
26
+ createdAt: new Date(Number(order.created_at) * 1e3).toISOString()
27
+ };
28
+ }
29
+ /**
30
+ * Verify Razorpay webhook signature (HMAC-SHA256 over raw body).
31
+ * Requires webhookSecret to be set in the constructor.
32
+ */
33
+ verifyWebhook(payload, signature) {
34
+ if (!this.webhookSecret) return false;
35
+ const expected = createHmac("sha256", this.webhookSecret).update(payload).digest("hex");
36
+ if (signature.length !== 64 || expected.length !== 64) return false;
37
+ return timingSafeEqual(
38
+ Buffer.from(expected, "hex"),
39
+ Buffer.from(signature, "hex")
40
+ );
41
+ }
42
+ async capturePayment(paymentId) {
43
+ var _a;
44
+ const payment = await this.razorpay.payments.fetch(paymentId);
45
+ return {
46
+ id: String(payment.id),
47
+ orderId: String((_a = payment.order_id) != null ? _a : ""),
48
+ amount: Number(payment.amount),
49
+ currency: String(payment.currency),
50
+ status: payment.status === "captured" ? "captured" : "failed",
51
+ capturedAt: (/* @__PURE__ */ new Date()).toISOString()
52
+ };
53
+ }
54
+ async refund(paymentId, amount) {
55
+ const refundData = {};
56
+ if (amount !== void 0) refundData.amount = amount;
57
+ const result = await this.razorpay.payments.refund(
58
+ paymentId,
59
+ refundData
60
+ );
61
+ return {
62
+ id: String(result.id),
63
+ paymentId,
64
+ amount: Number(result.amount),
65
+ currency: String(result.currency),
66
+ status: result.status === "processed" ? "processed" : "pending",
67
+ createdAt: new Date(Number(result.created_at) * 1e3).toISOString()
68
+ };
69
+ }
70
+ async getOrder(orderId) {
71
+ var _a;
72
+ const order = await this.razorpay.orders.fetch(orderId);
73
+ return {
74
+ id: String(order.id),
75
+ amount: Number(order.amount),
76
+ currency: String(order.currency),
77
+ status: "created",
78
+ receipt: (_a = order.receipt) != null ? _a : void 0,
79
+ createdAt: new Date(Number(order.created_at) * 1e3).toISOString()
80
+ };
81
+ }
82
+ };
83
+ function rupeesToPaise(rupees) {
84
+ return Math.round(rupees * 100);
85
+ }
86
+ function paiseToRupees(paise) {
87
+ return paise / 100;
88
+ }
89
+ function verifyPaymentSignature(params, keySecret) {
90
+ if (!keySecret) return false;
91
+ const expected = createHmac("sha256", keySecret).update(`${params.razorpay_order_id}|${params.razorpay_payment_id}`).digest("hex");
92
+ if (params.razorpay_signature.length !== 64) return false;
93
+ return timingSafeEqual(
94
+ Buffer.from(expected, "hex"),
95
+ Buffer.from(params.razorpay_signature, "hex")
96
+ );
97
+ }
98
+ export {
99
+ RazorpayProvider,
100
+ paiseToRupees,
101
+ rupeesToPaise,
102
+ verifyPaymentSignature
103
+ };
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@mohasinac/payment-razorpay",
3
+ "version": "0.1.0",
4
+ "private": false,
5
+ "publishConfig": { "access": "public" },
6
+ "type": "module",
7
+ "main": "./dist/index.cjs",
8
+ "module": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js",
14
+ "require": "./dist/index.cjs"
15
+ }
16
+ },
17
+ "files": ["dist"],
18
+ "scripts": {
19
+ "build": "tsup src/index.ts --format esm,cjs --dts",
20
+ "dev": "tsup --watch",
21
+ "typecheck": "tsc --noEmit"
22
+ },
23
+ "dependencies": {
24
+ "@mohasinac/contracts": "^1.1.0",
25
+ "@mohasinac/errors": "^1.1.0"
26
+ },
27
+ "peerDependencies": {
28
+ "razorpay": ">=2.9.0"
29
+ },
30
+ "devDependencies": {
31
+ "razorpay": "^2.9.6",
32
+ "tsup": "^8.5.0",
33
+ "typescript": "^5.9.3"
34
+ }
35
+ }