medusa-hdfc-payment 0.0.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.
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleError = void 0;
4
+ const utils_1 = require("@medusajs/utils");
5
+ const handleError = (error) => {
6
+ const message = error.response?.data?.error_message ||
7
+ error.response?.data?.message ||
8
+ error.message ||
9
+ "HDFC API error";
10
+ const code = error.response?.status || 500;
11
+ const errorCode = error.response?.data?.error_code;
12
+ if (code === 401) {
13
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNAUTHORIZED, "Authentication failed with HDFC payment gateway");
14
+ }
15
+ if (code === 403) {
16
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, "Access forbidden. Please check your HDFC API credentials.");
17
+ }
18
+ if (code === 429) {
19
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Rate limit exceeded. Please try again later.");
20
+ }
21
+ if (code === 400 && error.response?.data?.errors) {
22
+ const validationErrors = Object.entries(error.response.data.errors)
23
+ .map(([field, msgs]) => `${field}: ${Array.isArray(msgs) ? msgs.join(", ") : msgs}`)
24
+ .join("; ");
25
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `HDFC validation failed: ${validationErrors}`);
26
+ }
27
+ // Map HDFC specific error codes to Medusa error types
28
+ if (errorCode) {
29
+ if (errorCode.includes("INSUFFICIENT") || errorCode.includes("BALANCE")) {
30
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Insufficient funds: ${message}`);
31
+ }
32
+ if (errorCode.includes("EXPIRED") || errorCode.includes("TIMEOUT")) {
33
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Payment expired: ${message}`);
34
+ }
35
+ if (errorCode.includes("DECLINED") || errorCode.includes("FAILED")) {
36
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Payment declined: ${message}`);
37
+ }
38
+ }
39
+ throw new utils_1.MedusaError(code === 404
40
+ ? utils_1.MedusaError.Types.NOT_FOUND
41
+ : code === 400
42
+ ? utils_1.MedusaError.Types.INVALID_DATA
43
+ : utils_1.MedusaError.Types.UNEXPECTED_STATE, `HDFC payment error: ${message}`);
44
+ };
45
+ exports.handleError = handleError;
46
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGFuZGxlLWVycm9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL3Byb3ZpZGVycy9oZGZjL2NsaWVudC9oYW5kbGUtZXJyb3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsMkNBQTZDO0FBSXRDLE1BQU0sV0FBVyxHQUFHLENBQUMsS0FBNEIsRUFBUyxFQUFFO0lBQ2pFLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxRQUFRLEVBQUUsSUFBSSxFQUFFLGFBQWE7UUFDbkMsS0FBSyxDQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUUsT0FBTztRQUM3QixLQUFLLENBQUMsT0FBTztRQUNiLGdCQUFnQixDQUFBO0lBQ2hDLE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxRQUFRLEVBQUUsTUFBTSxJQUFJLEdBQUcsQ0FBQTtJQUMxQyxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsUUFBUSxFQUFFLElBQUksRUFBRSxVQUFVLENBQUE7SUFFbEQsSUFBSSxJQUFJLEtBQUssR0FBRyxFQUFFLENBQUM7UUFDakIsTUFBTSxJQUFJLG1CQUFXLENBQ25CLG1CQUFXLENBQUMsS0FBSyxDQUFDLFlBQVksRUFDOUIsaURBQWlELENBQ2xELENBQUE7SUFDSCxDQUFDO0lBRUQsSUFBSSxJQUFJLEtBQUssR0FBRyxFQUFFLENBQUM7UUFDakIsTUFBTSxJQUFJLG1CQUFXLENBQ25CLG1CQUFXLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFDN0IsMkRBQTJELENBQzVELENBQUE7SUFDSCxDQUFDO0lBRUQsSUFBSSxJQUFJLEtBQUssR0FBRyxFQUFFLENBQUM7UUFDakIsTUFBTSxJQUFJLG1CQUFXLENBQ25CLG1CQUFXLENBQUMsS0FBSyxDQUFDLFlBQVksRUFDOUIsOENBQThDLENBQy9DLENBQUE7SUFDSCxDQUFDO0lBRUQsSUFBSSxJQUFJLEtBQUssR0FBRyxJQUFJLEtBQUssQ0FBQyxRQUFRLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDO1FBQ2pELE1BQU0sZ0JBQWdCLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUM7YUFDaEUsR0FBRyxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsS0FBSyxLQUFLLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO2FBQ25GLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUNiLE1BQU0sSUFBSSxtQkFBVyxDQUNuQixtQkFBVyxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQzlCLDJCQUEyQixnQkFBZ0IsRUFBRSxDQUM5QyxDQUFBO0lBQ0gsQ0FBQztJQUVELHNEQUFzRDtJQUN0RCxJQUFJLFNBQVMsRUFBRSxDQUFDO1FBQ2QsSUFBSSxTQUFTLENBQUMsUUFBUSxDQUFDLGNBQWMsQ0FBQyxJQUFJLFNBQVMsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztZQUN4RSxNQUFNLElBQUksbUJBQVcsQ0FDbkIsbUJBQVcsQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUM5Qix1QkFBdUIsT0FBTyxFQUFFLENBQ2pDLENBQUE7UUFDSCxDQUFDO1FBQ0QsSUFBSSxTQUFTLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxJQUFJLFNBQVMsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztZQUNuRSxNQUFNLElBQUksbUJBQVcsQ0FDbkIsbUJBQVcsQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUM5QixvQkFBb0IsT0FBTyxFQUFFLENBQzlCLENBQUE7UUFDSCxDQUFDO1FBQ0QsSUFBSSxTQUFTLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxJQUFJLFNBQVMsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztZQUNuRSxNQUFNLElBQUksbUJBQVcsQ0FDbkIsbUJBQVcsQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUM5QixxQkFBcUIsT0FBTyxFQUFFLENBQy9CLENBQUE7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVELE1BQU0sSUFBSSxtQkFBVyxDQUNuQixJQUFJLEtBQUssR0FBRztRQUNWLENBQUMsQ0FBQyxtQkFBVyxDQUFDLEtBQUssQ0FBQyxTQUFTO1FBQzdCLENBQUMsQ0FBQyxJQUFJLEtBQUssR0FBRztZQUNkLENBQUMsQ0FBQyxtQkFBVyxDQUFDLEtBQUssQ0FBQyxZQUFZO1lBQ2hDLENBQUMsQ0FBQyxtQkFBVyxDQUFDLEtBQUssQ0FBQyxnQkFBZ0IsRUFDdEMsdUJBQXVCLE9BQU8sRUFBRSxDQUNqQyxDQUFBO0FBQ0gsQ0FBQyxDQUFBO0FBckVZLFFBQUEsV0FBVyxlQXFFdkIifQ==
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const axios_1 = __importDefault(require("axios"));
7
+ const utils_1 = require("@medusajs/utils");
8
+ const handle_error_1 = require("./handle-error");
9
+ class HDFCClient {
10
+ constructor(options) {
11
+ this.isDisposed = false;
12
+ if (!options.merchant_id || !options.api_key || !options.secret_key) {
13
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "HDFC API credentials are required (merchant_id, api_key, secret_key)");
14
+ }
15
+ this.merchantId = options.merchant_id;
16
+ this.apiKey = options.api_key;
17
+ this.secretKey = options.secret_key;
18
+ this.environment = options.environment || "sandbox";
19
+ const baseURL = this.environment === "production"
20
+ ? "https://securepg.hdfcbank.com/api/v1"
21
+ : "https://securepg.hdfcbank.com/sandbox/api/v1";
22
+ this.axios = axios_1.default.create({
23
+ baseURL,
24
+ headers: {
25
+ "Content-Type": "application/json",
26
+ "Accept": "application/json",
27
+ },
28
+ timeout: 30000,
29
+ });
30
+ // Add authentication interceptor
31
+ this.axios.interceptors.request.use((config) => {
32
+ if (this.isDisposed) {
33
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Cannot use disposed HDFC client");
34
+ }
35
+ // Add authentication headers
36
+ config.headers["X-Merchant-Id"] = this.merchantId;
37
+ config.headers["X-API-Key"] = this.apiKey;
38
+ config.headers["Authorization"] = `Bearer ${this.secretKey}`;
39
+ return config;
40
+ });
41
+ // Add response interceptor for error handling
42
+ this.axios.interceptors.response.use((response) => response, async (error) => {
43
+ (0, handle_error_1.handleError)(error);
44
+ return Promise.reject(error);
45
+ });
46
+ }
47
+ dispose() {
48
+ this.isDisposed = true;
49
+ }
50
+ /**
51
+ * Initialize a payment session with HDFC
52
+ */
53
+ async initiate(data) {
54
+ try {
55
+ const response = await this.axios.post("/payments/initiate", {
56
+ merchant_id: this.merchantId,
57
+ order_id: data.order_id,
58
+ amount: data.amount,
59
+ currency: data.currency,
60
+ customer_email: data.customer_email,
61
+ customer_phone: data.customer_phone,
62
+ return_url: data.return_url,
63
+ cancel_url: data.cancel_url,
64
+ metadata: data.metadata,
65
+ });
66
+ return response.data;
67
+ }
68
+ catch (error) {
69
+ (0, handle_error_1.handleError)(error);
70
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Failed to initiate payment with HDFC");
71
+ }
72
+ }
73
+ /**
74
+ * Authorize a payment with HDFC
75
+ */
76
+ async authorize(data) {
77
+ try {
78
+ const response = await this.axios.post("/payments/authorize", {
79
+ merchant_id: this.merchantId,
80
+ order_id: data.order_id,
81
+ amount: data.amount,
82
+ currency: data.currency,
83
+ customer_email: data.customer_email,
84
+ customer_phone: data.customer_phone,
85
+ billing_address: data.billing_address,
86
+ return_url: data.return_url,
87
+ cancel_url: data.cancel_url,
88
+ metadata: data.metadata,
89
+ });
90
+ return response.data;
91
+ }
92
+ catch (error) {
93
+ (0, handle_error_1.handleError)(error);
94
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Failed to authorize payment with HDFC");
95
+ }
96
+ }
97
+ /**
98
+ * Capture an authorized payment
99
+ */
100
+ async capture(data) {
101
+ try {
102
+ const response = await this.axios.post(`/payments/${data.transaction_id}/capture`, {
103
+ merchant_id: this.merchantId,
104
+ amount: data.amount,
105
+ });
106
+ return response.data;
107
+ }
108
+ catch (error) {
109
+ (0, handle_error_1.handleError)(error);
110
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Failed to capture payment with HDFC");
111
+ }
112
+ }
113
+ /**
114
+ * Refund a captured payment
115
+ */
116
+ async refund(data) {
117
+ try {
118
+ const response = await this.axios.post(`/payments/${data.transaction_id}/refund`, {
119
+ merchant_id: this.merchantId,
120
+ amount: data.amount,
121
+ reason: data.reason,
122
+ });
123
+ return response.data;
124
+ }
125
+ catch (error) {
126
+ (0, handle_error_1.handleError)(error);
127
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Failed to refund payment with HDFC");
128
+ }
129
+ }
130
+ /**
131
+ * Get payment status
132
+ */
133
+ async getStatus(transactionId) {
134
+ try {
135
+ const response = await this.axios.get(`/payments/${transactionId}/status`, {
136
+ params: {
137
+ merchant_id: this.merchantId,
138
+ },
139
+ });
140
+ return response.data;
141
+ }
142
+ catch (error) {
143
+ (0, handle_error_1.handleError)(error);
144
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Failed to get payment status from HDFC");
145
+ }
146
+ }
147
+ /**
148
+ * Cancel a pending payment
149
+ */
150
+ async cancel(transactionId) {
151
+ try {
152
+ await this.axios.post(`/payments/${transactionId}/cancel`, {
153
+ merchant_id: this.merchantId,
154
+ });
155
+ }
156
+ catch (error) {
157
+ (0, handle_error_1.handleError)(error);
158
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Failed to cancel payment with HDFC");
159
+ }
160
+ }
161
+ }
162
+ exports.default = HDFCClient;
163
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvcHJvdmlkZXJzL2hkZmMvY2xpZW50L2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsa0RBQTRDO0FBQzVDLDJDQUE2QztBQUM3QyxpREFBNEM7QUFjNUMsTUFBcUIsVUFBVTtJQVE3QixZQUFZLE9BQTBCO1FBRjlCLGVBQVUsR0FBRyxLQUFLLENBQUE7UUFHeEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ3BFLE1BQU0sSUFBSSxtQkFBVyxDQUNuQixtQkFBVyxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQzlCLHNFQUFzRSxDQUN2RSxDQUFBO1FBQ0gsQ0FBQztRQUVELElBQUksQ0FBQyxVQUFVLEdBQUcsT0FBTyxDQUFDLFdBQVcsQ0FBQTtRQUNyQyxJQUFJLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUE7UUFDN0IsSUFBSSxDQUFDLFNBQVMsR0FBRyxPQUFPLENBQUMsVUFBVSxDQUFBO1FBQ25DLElBQUksQ0FBQyxXQUFXLEdBQUcsT0FBTyxDQUFDLFdBQVcsSUFBSSxTQUFTLENBQUE7UUFFbkQsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFdBQVcsS0FBSyxZQUFZO1lBQy9DLENBQUMsQ0FBQyxzQ0FBc0M7WUFDeEMsQ0FBQyxDQUFDLDhDQUE4QyxDQUFBO1FBRWxELElBQUksQ0FBQyxLQUFLLEdBQUcsZUFBSyxDQUFDLE1BQU0sQ0FBQztZQUN4QixPQUFPO1lBQ1AsT0FBTyxFQUFFO2dCQUNQLGNBQWMsRUFBRSxrQkFBa0I7Z0JBQ2xDLFFBQVEsRUFBRSxrQkFBa0I7YUFDN0I7WUFDRCxPQUFPLEVBQUUsS0FBSztTQUNmLENBQUMsQ0FBQTtRQUVGLGlDQUFpQztRQUNqQyxJQUFJLENBQUMsS0FB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
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ /**
3
+ * HDFC API Client Types
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvcHJvdmlkZXJzL2hkZmMvY2xpZW50L3R5cGVzL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7R0FFRyJ9
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const utils_1 = require("@medusajs/framework/utils");
7
+ const service_1 = __importDefault(require("./service"));
8
+ exports.default = (0, utils_1.ModuleProvider)(utils_1.Modules.PAYMENT, {
9
+ services: [service_1.default],
10
+ });
11
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvcHJvdmlkZXJzL2hkZmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxxREFBbUU7QUFDbkUsd0RBQWtEO0FBRWxELGtCQUFlLElBQUEsc0JBQWMsRUFBQyxlQUFPLENBQUMsT0FBTyxFQUFFO0lBQzdDLFFBQVEsRUFBRSxDQUFDLGlCQUEwQixDQUFDO0NBQ3ZDLENBQUMsQ0FBQSJ9
@@ -0,0 +1,394 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const utils_1 = require("@medusajs/utils");
7
+ const client_1 = __importDefault(require("./client"));
8
+ class HDFCPaymentProviderService extends utils_1.AbstractPaymentProvider {
9
+ constructor({ logger }, options) {
10
+ super({}, options);
11
+ this.logger_ = logger;
12
+ this.options_ = options;
13
+ this.client = new client_1.default({
14
+ merchant_id: options.merchant_id,
15
+ api_key: options.api_key,
16
+ secret_key: options.secret_key,
17
+ environment: options.environment || "sandbox",
18
+ });
19
+ }
20
+ /**
21
+ * Initialize a payment session
22
+ */
23
+ async initiatePayment(context) {
24
+ try {
25
+ const { order_id, amount, currency, customer, return_url, cancel_url } = context;
26
+ if (!order_id || !amount || !currency) {
27
+ return {
28
+ error: "Missing required fields: order_id, amount, currency",
29
+ };
30
+ }
31
+ const response = await this.client.initiate({
32
+ order_id,
33
+ amount: Math.round(amount),
34
+ currency,
35
+ customer_email: customer?.email,
36
+ customer_phone: customer?.phone,
37
+ return_url: return_url || this.options_.return_url,
38
+ cancel_url: cancel_url || this.options_.cancel_url,
39
+ metadata: {
40
+ order_id,
41
+ },
42
+ });
43
+ return {
44
+ data: {
45
+ payment_id: response.payment_id,
46
+ order_id: response.order_id,
47
+ payment_url: response.payment_url || response.redirect_url,
48
+ },
49
+ };
50
+ }
51
+ catch (error) {
52
+ this.logger_.error("HDFC initiate payment error:", error);
53
+ return {
54
+ error: error.message || "Failed to initiate payment",
55
+ };
56
+ }
57
+ }
58
+ /**
59
+ * Authorize a payment
60
+ */
61
+ async authorizePayment(paymentSessionData, context) {
62
+ try {
63
+ const { order_id, amount, currency, customer, billing_address } = context;
64
+ if (!order_id || !amount || !currency) {
65
+ return {
66
+ error: "Missing required fields: order_id, amount, currency",
67
+ };
68
+ }
69
+ const response = await this.client.authorize({
70
+ order_id,
71
+ amount: Math.round(amount),
72
+ currency,
73
+ customer_email: customer?.email,
74
+ customer_phone: customer?.phone,
75
+ billing_address,
76
+ return_url: this.options_.return_url,
77
+ cancel_url: this.options_.cancel_url,
78
+ metadata: {
79
+ order_id,
80
+ },
81
+ });
82
+ return {
83
+ status: (response.status === "authorized" ? "authorized" : "pending"),
84
+ data: {
85
+ transaction_id: response.transaction_id,
86
+ payment_id: response.payment_id,
87
+ order_id: response.order_id,
88
+ amount: response.amount,
89
+ currency: response.currency,
90
+ status: response.status,
91
+ payment_url: response.payment_url || response.redirect_url,
92
+ },
93
+ };
94
+ }
95
+ catch (error) {
96
+ this.logger_.error("HDFC authorize payment error:", error);
97
+ return {
98
+ error: error.message || "Failed to authorize payment",
99
+ };
100
+ }
101
+ }
102
+ /**
103
+ * Capture an authorized payment
104
+ */
105
+ async capturePayment(paymentSessionData) {
106
+ try {
107
+ const transactionId = paymentSessionData.transaction_id;
108
+ if (!transactionId) {
109
+ return {
110
+ error: "Missing transaction_id in payment session data",
111
+ };
112
+ }
113
+ const amount = paymentSessionData.amount;
114
+ const response = await this.client.capture({
115
+ transaction_id: transactionId,
116
+ amount: amount ? Math.round(amount) : undefined,
117
+ });
118
+ return {
119
+ status: "captured",
120
+ data: {
121
+ transaction_id: response.transaction_id,
122
+ payment_id: response.payment_id,
123
+ order_id: response.order_id,
124
+ amount: response.amount,
125
+ currency: response.currency,
126
+ status: response.status,
127
+ },
128
+ };
129
+ }
130
+ catch (error) {
131
+ this.logger_.error("HDFC capture payment error:", error);
132
+ return {
133
+ error: error.message || "Failed to capture payment",
134
+ };
135
+ }
136
+ }
137
+ /**
138
+ * Refund a payment
139
+ */
140
+ async refundPayment(paymentSessionData, refundAmount) {
141
+ try {
142
+ const transactionId = paymentSessionData.transaction_id;
143
+ if (!transactionId) {
144
+ return {
145
+ error: "Missing transaction_id in payment session data",
146
+ };
147
+ }
148
+ const response = await this.client.refund({
149
+ transaction_id: transactionId,
150
+ amount: Math.round(refundAmount),
151
+ reason: "Customer refund request",
152
+ });
153
+ return {
154
+ status: "captured",
155
+ data: {
156
+ transaction_id: response.transaction_id,
157
+ refund_id: response.refund_id,
158
+ amount: response.amount,
159
+ currency: response.currency,
160
+ status: response.status,
161
+ },
162
+ };
163
+ }
164
+ catch (error) {
165
+ this.logger_.error("HDFC refund payment error:", error);
166
+ return {
167
+ error: error.message || "Failed to refund payment",
168
+ };
169
+ }
170
+ }
171
+ /**
172
+ * Cancel a payment
173
+ */
174
+ async cancelPayment(paymentSessionData) {
175
+ try {
176
+ const transactionId = paymentSessionData.transaction_id;
177
+ if (!transactionId) {
178
+ return {
179
+ error: "Missing transaction_id in payment session data",
180
+ };
181
+ }
182
+ await this.client.cancel(transactionId);
183
+ return {
184
+ status: "canceled",
185
+ data: {
186
+ transaction_id: transactionId,
187
+ status: "cancelled",
188
+ },
189
+ };
190
+ }
191
+ catch (error) {
192
+ this.logger_.error("HDFC cancel payment error:", error);
193
+ return {
194
+ error: error.message || "Failed to cancel payment",
195
+ };
196
+ }
197
+ }
198
+ /**
199
+ * Get payment status
200
+ */
201
+ async getPaymentStatus(paymentSessionData) {
202
+ try {
203
+ const transactionId = paymentSessionData.transaction_id;
204
+ if (!transactionId) {
205
+ return "error";
206
+ }
207
+ const response = await this.client.getStatus(transactionId);
208
+ const status = response.status.toLowerCase();
209
+ if (status === "authorized" || status === "captured") {
210
+ return "authorized";
211
+ }
212
+ if (status === "pending" || status === "processing") {
213
+ return "pending";
214
+ }
215
+ if (status === "failed" || status === "error") {
216
+ return "error";
217
+ }
218
+ if (status === "cancelled" || status === "canceled") {
219
+ return "canceled";
220
+ }
221
+ return "requires_more";
222
+ }
223
+ catch (error) {
224
+ this.logger_.error("HDFC get payment status error:", error);
225
+ return "error";
226
+ }
227
+ }
228
+ /**
229
+ * Retrieve payment details
230
+ */
231
+ async retrievePayment(paymentSessionData) {
232
+ try {
233
+ const transactionId = paymentSessionData.transaction_id;
234
+ if (!transactionId) {
235
+ return {
236
+ error: "Missing transaction_id in payment session data",
237
+ };
238
+ }
239
+ const response = await this.client.getStatus(transactionId);
240
+ return {
241
+ status: (response.status === "authorized" || response.status === "captured"
242
+ ? "authorized"
243
+ : response.status === "pending" || response.status === "processing"
244
+ ? "pending"
245
+ : response.status === "failed" || response.status === "error"
246
+ ? "error"
247
+ : response.status === "cancelled" || response.status === "canceled"
248
+ ? "canceled"
249
+ : "requires_more"),
250
+ data: {
251
+ transaction_id: response.transaction_id,
252
+ payment_id: response.payment_id,
253
+ order_id: response.order_id,
254
+ amount: response.amount,
255
+ currency: response.currency,
256
+ status: response.status,
257
+ payment_method: response.payment_method,
258
+ card_last4: response.card_last4,
259
+ card_brand: response.card_brand,
260
+ },
261
+ };
262
+ }
263
+ catch (error) {
264
+ this.logger_.error("HDFC retrieve payment error:", error);
265
+ return {
266
+ error: error.message || "Failed to retrieve payment",
267
+ };
268
+ }
269
+ }
270
+ /**
271
+ * Update payment session
272
+ */
273
+ async updatePayment(context) {
274
+ try {
275
+ // For HDFC, updating payment typically means re-initiating
276
+ return await this.initiatePayment(context);
277
+ }
278
+ catch (error) {
279
+ this.logger_.error("HDFC update payment error:", error);
280
+ return {
281
+ error: error.message || "Failed to update payment",
282
+ };
283
+ }
284
+ }
285
+ /**
286
+ * Delete payment session
287
+ */
288
+ async deletePayment(paymentSessionData) {
289
+ try {
290
+ // Cancel the payment if it's still pending
291
+ return await this.cancelPayment(paymentSessionData);
292
+ }
293
+ catch (error) {
294
+ this.logger_.error("HDFC delete payment error:", error);
295
+ return {
296
+ error: error.message || "Failed to delete payment",
297
+ };
298
+ }
299
+ }
300
+ /**
301
+ * Get payment session data
302
+ */
303
+ async getPaymentData(paymentSessionData) {
304
+ try {
305
+ const transactionId = paymentSessionData.transaction_id;
306
+ if (!transactionId) {
307
+ return paymentSessionData;
308
+ }
309
+ const response = await this.client.getStatus(transactionId);
310
+ return {
311
+ ...paymentSessionData,
312
+ transaction_id: response.transaction_id,
313
+ payment_id: response.payment_id,
314
+ order_id: response.order_id,
315
+ amount: response.amount,
316
+ currency: response.currency,
317
+ status: response.status,
318
+ payment_method: response.payment_method,
319
+ card_last4: response.card_last4,
320
+ card_brand: response.card_brand,
321
+ };
322
+ }
323
+ catch (error) {
324
+ this.logger_.error("HDFC get payment data error:", error);
325
+ return paymentSessionData;
326
+ }
327
+ }
328
+ /**
329
+ * Handle webhook events from HDFC
330
+ */
331
+ async getWebhookActionAndData(payload) {
332
+ try {
333
+ const data = payload.data || {};
334
+ const eventType = (data.type || data.event_type || data.event || "unknown");
335
+ const sessionId = (data.session_id || data.payment_id || data.transaction_id);
336
+ const amount = data.amount;
337
+ // Map HDFC webhook events to Medusa actions
338
+ if (eventType.includes("payment.authorized") || eventType.includes("payment.captured")) {
339
+ if (!sessionId || amount === undefined) {
340
+ return {
341
+ action: "not_supported",
342
+ };
343
+ }
344
+ return {
345
+ action: "authorized",
346
+ data: {
347
+ session_id: sessionId,
348
+ amount: amount,
349
+ },
350
+ };
351
+ }
352
+ if (eventType.includes("payment.refunded")) {
353
+ if (!sessionId || amount === undefined) {
354
+ return {
355
+ action: "not_supported",
356
+ };
357
+ }
358
+ return {
359
+ action: "captured",
360
+ data: {
361
+ session_id: sessionId,
362
+ amount: amount,
363
+ },
364
+ };
365
+ }
366
+ if (eventType.includes("payment.failed") || eventType.includes("payment.error")) {
367
+ if (!sessionId) {
368
+ return {
369
+ action: "not_supported",
370
+ };
371
+ }
372
+ return {
373
+ action: "failed",
374
+ data: {
375
+ session_id: sessionId,
376
+ amount: amount || 0,
377
+ },
378
+ };
379
+ }
380
+ return {
381
+ action: "not_supported",
382
+ };
383
+ }
384
+ catch (error) {
385
+ this.logger_.error("HDFC webhook processing error:", error);
386
+ return {
387
+ action: "not_supported",
388
+ };
389
+ }
390
+ }
391
+ }
392
+ HDFCPaymentProviderService.identifier = "hdfc";
393
+ exports.default = HDFCPaymentProviderService;
394
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9wcm92aWRlcnMvaGRmYy9zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsMkNBQXNFO0FBWXRFLHNEQUFpQztBQU9qQyxNQUFNLDBCQUEyQixTQUFRLCtCQUF1QjtJQU85RCxZQUNFLEVBQUUsTUFBTSxFQUF3QixFQUNoQyxPQUE0QjtRQUU1QixLQUFLLENBQUMsRUFBRSxFQUFFLE9BQU8sQ0FBQyxDQUFBO1FBQ2xCLElBQUksQ0FBQyxPQUFPLEdBQUcsTUFBTSxDQUFBO1FBQ3JCLElBQUksQ0FBQyxRQUFRLEdBQUcsT0FBTyxDQUFBO1FBQ3ZCLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxnQkFBVSxDQUFDO1lBQzNCLFdBQVcsRUFBRSxPQUFPLENBQUMsV0FBVztZQUNoQyxPQUFPLEVBQUUsT0FBTyxDQUFDLE9BQU87WUFDeEIsVUFBVSxFQUFFLE9BQU8sQ0FBQyxVQUFVO1lBQzlCLFdBQVcsRUFBRSxPQUFPLENBQUMsV0FBVyxJQUFJLFNBQVM7U0FDOUMsQ0FBQyxDQUFBO0lBQ0osQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSyxDQUFDLGVBQWUsQ0FDbkIsT0FBZ0M7UUFFaEMsSUFBSSxDQUFDO1lBQ0gsTUFBTSxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLEdBQ3BFLE9BVUMsQ0FBQTtZQUVILElBQUksQ0FBQyxRQUFRLElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztnQkFDdEMsT0FBTztvQkFDTCxLQUFLLEVBQUUscURBQXFEO2lCQUM3RCxDQUFBO1lBQ0gsQ0FBQztZQUVELE1BQU0sUUFBUSxHQUFHLE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUM7Z0JBQzFDLFFBQVE7Z0JBQ1IsTUFBTSxFQUFFLElBQUks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
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ /**
3
+ * HDFC Payment Provider Types
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvcHJvdmlkZXJzL2hkZmMvdHlwZXMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOztHQUVHIn0=
package/README.md ADDED
@@ -0,0 +1,320 @@
1
+ # Medusa HDFC Payment Provider Plugin
2
+
3
+ <p align="center">
4
+ <strong>HDFC Payment Gateway Integration for Medusa v2 Stores</strong>
5
+ </p>
6
+
7
+ <p align="center">
8
+ <a href="https://www.npmjs.com/package/medusa-hdfc-payment">
9
+ <img src="https://img.shields.io/npm/v/medusa-hdfc-payment?color=blue&style=flat-square" alt="NPM Version">
10
+ </a>
11
+ <a href="https://www.npmjs.com/package/medusa-hdfc-payment">
12
+ <img src="https://img.shields.io/npm/dw/medusa-hdfc-payment?style=flat-square" alt="NPM Downloads">
13
+ </a>
14
+ <a href="https://github.com/your-org/medusa-hdfc-payment/blob/main/LICENSE">
15
+ <img src="https://img.shields.io/github/license/your-org/medusa-hdfc-payment?style=flat-square" alt="License">
16
+ </a>
17
+ </p>
18
+
19
+ <hr />
20
+
21
+ ## 🚀 Overview
22
+
23
+ The **Medusa HDFC Payment Provider Plugin** integrates [HDFC Bank's payment gateway](https://www.hdfcbank.com/) directly into your [Medusa](https://medusajs.com/) store.
24
+
25
+ Process payments securely through HDFC's payment gateway with support for authorization, capture, refunds, and payment status tracking—all seamlessly integrated with Medusa's checkout flow.
26
+
27
+ **Compatible with Medusa v2.0+**
28
+
29
+ ## ✨ Key Features
30
+
31
+ | Feature | Description |
32
+ | :--- | :--- |
33
+ | **💳 Payment Authorization** | Authorize payments securely through HDFC's payment gateway |
34
+ | **✅ Payment Capture** | Capture authorized payments to complete transactions |
35
+ | **↩️ Refund Support** | Process full or partial refunds for captured payments |
36
+ | **🚫 Payment Cancellation** | Cancel pending payments before completion |
37
+ | **📊 Status Tracking** | Real-time payment status tracking and updates |
38
+ | **🔐 Secure Integration** | Secure API authentication with merchant credentials |
39
+ | **🌍 Sandbox & Production** | Support for both sandbox and production environments |
40
+ | **📱 Webhook Support** | Handle payment webhooks for real-time status updates |
41
+
42
+ ## 📋 Prerequisites
43
+
44
+ Before you begin, ensure you have:
45
+
46
+ 1. A **[Medusa v2](https://docs.medusajs.com/)** server set up
47
+ 2. An **HDFC Bank merchant account** with payment gateway access
48
+ 3. **HDFC API credentials**:
49
+ - Merchant ID
50
+ - API Key
51
+ - Secret Key
52
+
53
+ ## 🛠️ Installation
54
+
55
+ Install the plugin using your preferred package manager:
56
+
57
+ ```bash
58
+ npm install medusa-hdfc-payment
59
+ # or
60
+ yarn add medusa-hdfc-payment
61
+ ```
62
+
63
+ ## ⚙️ Configuration
64
+
65
+ ### 1. Environment Variables
66
+
67
+ Add your HDFC credentials to your `.env` file.
68
+
69
+ > [!WARNING]
70
+ > **Security Note**: Never commit your actual API credentials to version control (git).
71
+
72
+ ```bash
73
+ HDFC_MERCHANT_ID="your_merchant_id"
74
+ HDFC_API_KEY="your_api_key"
75
+ HDFC_SECRET_KEY="your_secret_key"
76
+ HDFC_ENVIRONMENT="sandbox" # or "production"
77
+ HDFC_RETURN_URL="https://yourstore.com/payment/return"
78
+ HDFC_CANCEL_URL="https://yourstore.com/payment/cancel"
79
+ ```
80
+
81
+ ### 2. Medusa Config
82
+
83
+ Register the plugin in your `medusa-config.js` (or `medusa-config.ts`) file. Add it to the `modules` section for the payment provider.
84
+
85
+ ```javascript
86
+ module.exports = defineConfig({
87
+ // ... other config
88
+ modules: [
89
+ {
90
+ resolve: "@medusajs/medusa/payment",
91
+ options: {
92
+ providers: [
93
+ {
94
+ resolve: "medusa-hdfc-payment",
95
+ id: "hdfc",
96
+ options: {
97
+ merchant_id: process.env.HDFC_MERCHANT_ID,
98
+ api_key: process.env.HDFC_API_KEY,
99
+ secret_key: process.env.HDFC_SECRET_KEY,
100
+ environment: process.env.HDFC_ENVIRONMENT || "sandbox",
101
+ return_url: process.env.HDFC_RETURN_URL,
102
+ cancel_url: process.env.HDFC_CANCEL_URL,
103
+ },
104
+ },
105
+ ],
106
+ },
107
+ },
108
+ ],
109
+ });
110
+ ```
111
+
112
+ ### 3. TypeScript Configuration
113
+
114
+ If you're using TypeScript, ensure your `medusa-config.ts` is properly typed:
115
+
116
+ ```typescript
117
+ import { defineConfig } from "@medusajs/framework"
118
+
119
+ export default defineConfig({
120
+ // ... other config
121
+ modules: [
122
+ {
123
+ resolve: "@medusajs/medusa/payment",
124
+ options: {
125
+ providers: [
126
+ {
127
+ resolve: "medusa-hdfc-payment",
128
+ id: "hdfc",
129
+ options: {
130
+ merchant_id: process.env.HDFC_MERCHANT_ID!,
131
+ api_key: process.env.HDFC_API_KEY!,
132
+ secret_key: process.env.HDFC_SECRET_KEY!,
133
+ environment: (process.env.HDFC_ENVIRONMENT as "sandbox" | "production") || "sandbox",
134
+ return_url: process.env.HDFC_RETURN_URL,
135
+ cancel_url: process.env.HDFC_CANCEL_URL,
136
+ },
137
+ },
138
+ ],
139
+ },
140
+ },
141
+ ],
142
+ })
143
+ ```
144
+
145
+ ## 💻 Usage Guide
146
+
147
+ ### Enabling the Provider
148
+
149
+ 1. Log in to your **Medusa Admin**
150
+ 2. Go to **Settings** → **Regions**
151
+ 3. Select the region where you want to enable HDFC payments
152
+ 4. In the **Payment Providers** section, ensure `hdfc` is enabled
153
+ 5. Save changes
154
+
155
+ ### Payment Flow
156
+
157
+ The HDFC payment provider supports the standard Medusa payment flow:
158
+
159
+ 1. **Initiate Payment**: Customer selects HDFC as payment method during checkout
160
+ 2. **Authorize Payment**: Payment is authorized with HDFC gateway
161
+ 3. **Capture Payment**: After order confirmation, payment is captured
162
+ 4. **Refund**: Process refunds through the admin or API
163
+
164
+ ### Processing Payments
165
+
166
+ #### Authorization
167
+
168
+ When a customer selects HDFC as their payment method, the plugin will:
169
+ - Create a payment session with HDFC
170
+ - Redirect customer to HDFC payment page (if required)
171
+ - Authorize the payment amount
172
+
173
+ #### Capture
174
+
175
+ After order confirmation:
176
+ - The authorized payment is automatically captured
177
+ - Payment status is updated in Medusa
178
+ - Order is marked as paid
179
+
180
+ #### Refunds
181
+
182
+ To process a refund:
183
+ 1. Navigate to the order in Medusa Admin
184
+ 2. Go to the payment section
185
+ 3. Click "Refund" and specify the amount
186
+ 4. The refund will be processed through HDFC
187
+
188
+ ### Webhook Configuration
189
+
190
+ To receive real-time payment status updates, configure webhooks in your HDFC merchant dashboard:
191
+
192
+ 1. Log in to your HDFC merchant portal
193
+ 2. Navigate to Webhook Settings
194
+ 3. Add your webhook URL: `https://yourstore.com/webhooks/hdfc`
195
+ 4. Select events to receive:
196
+ - `payment.authorized`
197
+ - `payment.captured`
198
+ - `payment.refunded`
199
+ - `payment.failed`
200
+
201
+ The plugin will automatically process webhook events and update payment statuses accordingly.
202
+
203
+ ## 🐛 Troubleshooting
204
+
205
+ ### Payment Authorization Issues
206
+
207
+ #### "Authentication failed with HDFC payment gateway"
208
+ - Verify your `HDFC_MERCHANT_ID`, `HDFC_API_KEY`, and `HDFC_SECRET_KEY` are correct
209
+ - Ensure credentials match your environment (sandbox vs production)
210
+ - Check that your HDFC merchant account is active
211
+
212
+ #### "Missing required fields: order_id, amount, currency"
213
+ - Ensure the payment context includes all required fields
214
+ - Verify the order data is properly formatted
215
+ - Check Medusa logs for detailed error messages
216
+
217
+ ### Payment Capture Issues
218
+
219
+ #### "Missing transaction_id in payment session data"
220
+ - Ensure payment was successfully authorized before attempting capture
221
+ - Verify payment session data is properly stored
222
+ - Check that the transaction ID is returned from authorization
223
+
224
+ #### "Failed to capture payment with HDFC"
225
+ - Verify the payment is in an authorized state
226
+ - Check if the authorization has expired
227
+ - Ensure sufficient funds are available
228
+ - Review HDFC API logs for specific error codes
229
+
230
+ ### Refund Issues
231
+
232
+ #### "Payment declined: [error message]"
233
+ - Verify the payment was successfully captured before refunding
234
+ - Check refund amount doesn't exceed captured amount
235
+ - Ensure refund is within the allowed time window
236
+ - Review HDFC refund policies
237
+
238
+ ### Environment Issues
239
+
240
+ #### Sandbox vs Production
241
+ - **Sandbox**: Use for testing with test credentials
242
+ - **Production**: Use for live transactions with production credentials
243
+ - Ensure you're using the correct credentials for your selected environment
244
+ - API endpoints differ between environments
245
+
246
+ ### API Connection Issues
247
+
248
+ #### "Rate limit exceeded"
249
+ - HDFC API has rate limits per merchant
250
+ - Implement retry logic with exponential backoff
251
+ - Contact HDFC support to increase rate limits if needed
252
+
253
+ #### "Network timeout"
254
+ - Check your server's internet connectivity
255
+ - Verify HDFC API endpoints are accessible
256
+ - Increase timeout values if needed (default: 30 seconds)
257
+
258
+ ## 📚 API Reference
259
+
260
+ ### Payment Provider Methods
261
+
262
+ The plugin implements all required Medusa payment provider methods:
263
+
264
+ - `initiatePayment()` - Initialize payment session
265
+ - `authorizePayment()` - Authorize payment
266
+ - `capturePayment()` - Capture authorized payment
267
+ - `refundPayment()` - Process refund
268
+ - `cancelPayment()` - Cancel payment
269
+ - `getPaymentStatus()` - Get payment status
270
+ - `retrievePayment()` - Retrieve payment details
271
+ - `updatePayment()` - Update payment session
272
+ - `deletePayment()` - Delete payment session
273
+ - `getWebhookActionAndData()` - Process webhook events
274
+
275
+ ### Payment Status Values
276
+
277
+ The plugin returns standard Medusa payment statuses:
278
+
279
+ - `authorized` - Payment is authorized
280
+ - `pending` - Payment is pending
281
+ - `requires_more` - Additional action required
282
+ - `error` - Payment failed
283
+ - `canceled` - Payment cancelled
284
+
285
+ ## 🔒 Security Best Practices
286
+
287
+ 1. **Never commit credentials**: Always use environment variables
288
+ 2. **Use HTTPS**: Ensure all API calls are over HTTPS
289
+ 3. **Validate webhooks**: Verify webhook signatures from HDFC
290
+ 4. **Monitor transactions**: Regularly review payment logs
291
+ 5. **Keep credentials secure**: Rotate API keys periodically
292
+
293
+ ## 🤝 Contributing
294
+
295
+ Contributions are welcome! If you find a bug or want to add a feature:
296
+
297
+ 1. Fork the repository
298
+ 2. Create a feature branch (`git checkout -b feature/amazing-feature`)
299
+ 3. Commit your changes (`git commit -m 'Add some amazing feature'`)
300
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
301
+ 5. Open a Pull Request
302
+
303
+ ## 📄 License
304
+
305
+ This project is licensed under the [MIT License](LICENSE).
306
+
307
+ ## 📞 Support
308
+
309
+ For issues and questions:
310
+
311
+ - **Plugin Issues**: Open an issue on GitHub
312
+ - **HDFC API Support**: Contact HDFC merchant support
313
+ - **Medusa Support**: Visit [Medusa Discord](https://discord.gg/medusajs)
314
+
315
+ ---
316
+
317
+ <p align="center">
318
+ Built with ❤️ for the Medusa community
319
+ </p>
320
+
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "medusa-hdfc-payment",
3
+ "version": "0.0.1",
4
+ "description": "HDFC Payment Gateway Provider Plugin for MedusaJS 2",
5
+ "author": "",
6
+ "homepage": "",
7
+ "repository": "",
8
+ "license": "MIT",
9
+ "files": [
10
+ ".medusa/server"
11
+ ],
12
+ "main": ".medusa/server/src/providers/hdfc/index.js",
13
+ "exports": {
14
+ ".": "./.medusa/server/src/providers/hdfc/index.js",
15
+ "./package.json": "./package.json",
16
+ "./providers/*": "./.medusa/server/src/providers/*/index.js"
17
+ },
18
+ "keywords": [
19
+ "medusa",
20
+ "plugin",
21
+ "medusa-plugin",
22
+ "medusa-v2",
23
+ "medusa-plugin-payment",
24
+ "hdfc",
25
+ "payment-gateway"
26
+ ],
27
+ "scripts": {
28
+ "build": "medusa plugin:build",
29
+ "dev": "medusa plugin:develop",
30
+ "prepublishOnly": "medusa plugin:build"
31
+ },
32
+ "dependencies": {
33
+ "axios": "^1.6.0"
34
+ },
35
+ "devDependencies": {
36
+ "@medusajs/admin-sdk": "2.4.0",
37
+ "@medusajs/cli": "2.4.0",
38
+ "@medusajs/framework": "2.4.0",
39
+ "@medusajs/icons": "2.4.0",
40
+ "@medusajs/medusa": "2.4.0",
41
+ "@medusajs/test-utils": "2.4.0",
42
+ "@medusajs/types": "^2.12.3",
43
+ "@medusajs/ui": "4.0.4",
44
+ "@medusajs/utils": "2.4.0",
45
+ "@mikro-orm/cli": "6.4.3",
46
+ "@mikro-orm/core": "6.4.3",
47
+ "@mikro-orm/knex": "6.4.3",
48
+ "@mikro-orm/migrations": "6.4.3",
49
+ "@mikro-orm/postgresql": "6.4.3",
50
+ "@swc/core": "1.5.7",
51
+ "@types/node": "^20.0.0",
52
+ "awilix": "^8.0.1",
53
+ "pg": "^8.13.0",
54
+ "typescript": "^5.6.2"
55
+ },
56
+ "peerDependencies": {
57
+ "@medusajs/admin-sdk": "2.4.0",
58
+ "@medusajs/cli": "2.4.0",
59
+ "@medusajs/framework": "2.4.0",
60
+ "@medusajs/icons": "2.4.0",
61
+ "@medusajs/medusa": "2.4.0",
62
+ "@medusajs/test-utils": "2.4.0",
63
+ "@medusajs/ui": "4.0.3",
64
+ "@medusajs/utils": "2.4.0",
65
+ "@mikro-orm/cli": "6.4.3",
66
+ "@mikro-orm/core": "6.4.3",
67
+ "@mikro-orm/knex": "6.4.3",
68
+ "@mikro-orm/migrations": "6.4.3",
69
+ "@mikro-orm/postgresql": "6.4.3",
70
+ "awilix": "^8.0.1",
71
+ "pg": "^8.13.0"
72
+ },
73
+ "engines": {
74
+ "node": ">=20"
75
+ }
76
+ }