@duvdu-v1/duvdu 1.1.265 → 1.1.267

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.
@@ -39,7 +39,7 @@ interface PaymobOrder {
39
39
  interface PaymobOrderItem {
40
40
  name: string;
41
41
  description: string;
42
- amount_cents: number;
42
+ amount: number;
43
43
  quantity: number;
44
44
  }
45
45
  interface PaymobSourceData {
@@ -83,14 +83,9 @@ interface PaymobBillingData {
83
83
  floor: string;
84
84
  street: string;
85
85
  building: string;
86
- city: string;
86
+ city?: string;
87
87
  state: string;
88
88
  country: string;
89
- postal_code: string;
90
- }
91
- interface CreateOrderResult {
92
- orderId: number;
93
- token: string;
94
89
  }
95
90
  interface TransactionData {
96
91
  orderId: number;
@@ -138,28 +133,34 @@ interface OrderDetailsResult {
138
133
  merchant_order_id: string;
139
134
  }
140
135
  /**
141
- * Paymob Service Configuration
136
+ * Paymob Service Configuration for Flash Integration
142
137
  *
143
138
  * Required Keys:
144
- * - apiKey: Your Paymob API Key (used for authentication)
145
- * - integrationId: Your Paymob Integration ID (found in your Paymob dashboard)
146
- * - iframeId: Your Paymob Iframe ID (found in your Paymob dashboard)
147
- *
148
- * Note:
149
- * - Public Key: Used for client-side encryption (not needed for this service)
150
- * - Secret Key: Used for webhook signature verification (handled internally)
139
+ * - secretKey: Your Paymob Secret Key (for API authentication)
140
+ * - publicKey: Your Paymob Public Key (for client-side)
141
+ * - integrationId: Your Paymob Integration ID
142
+ * - hmacSecret: Your Paymob HMAC Secret (for webhook verification)
151
143
  */
152
144
  export declare class PaymobService {
153
- private readonly apiKey;
145
+ private readonly secretKey;
146
+ private readonly publicKey;
154
147
  private readonly integrationId;
155
- private readonly iframeId;
156
148
  private readonly baseUrl;
157
149
  private readonly hmacSecret;
158
150
  constructor();
159
- getAuthToken(): Promise<string>;
160
- createOrder(amount: number, currency?: string, items?: PaymobOrderItem[], merchant_order_id?: string): Promise<CreateOrderResult>;
161
- getPaymentKey(orderId: number, token: string, amount: number, billingData: PaymobBillingData): Promise<string>;
162
- createPaymentUrl(paymentKey: string): string;
151
+ /**
152
+ * Creates a payment intention using the Flash API
153
+ * @param amount The payment amount
154
+ * @param billingData The user data for billing
155
+ * @param items The order items
156
+ * @param currency The currency code (default: EGP)
157
+ * @param extras Custom metadata
158
+ * @returns The payment URL and client secret
159
+ */
160
+ createPaymentIntention(amount: number, billingData: PaymobBillingData, items: PaymobOrderItem[], currency?: string, extras?: Record<string, any>): Promise<{
161
+ paymentUrl: string;
162
+ clientSecret: string;
163
+ }>;
163
164
  /**
164
165
  * Creates a payment URL with user data and custom metadata
165
166
  * @param amount The payment amount
@@ -39,104 +39,74 @@ exports.PaymobService = void 0;
39
39
  const crypto = __importStar(require("crypto"));
40
40
  const axios_1 = __importDefault(require("axios"));
41
41
  /**
42
- * Paymob Service Configuration
42
+ * Paymob Service Configuration for Flash Integration
43
43
  *
44
44
  * Required Keys:
45
- * - apiKey: Your Paymob API Key (used for authentication)
46
- * - integrationId: Your Paymob Integration ID (found in your Paymob dashboard)
47
- * - iframeId: Your Paymob Iframe ID (found in your Paymob dashboard)
48
- *
49
- * Note:
50
- * - Public Key: Used for client-side encryption (not needed for this service)
51
- * - Secret Key: Used for webhook signature verification (handled internally)
45
+ * - secretKey: Your Paymob Secret Key (for API authentication)
46
+ * - publicKey: Your Paymob Public Key (for client-side)
47
+ * - integrationId: Your Paymob Integration ID
48
+ * - hmacSecret: Your Paymob HMAC Secret (for webhook verification)
52
49
  */
53
50
  class PaymobService {
54
51
  constructor() {
55
- this.apiKey = process.env.PAYMOB_API_KEY;
52
+ this.secretKey = process.env.PAYMOB_SECRET_KEY;
53
+ this.publicKey = process.env.PAYMOB_PUBLIC_KEY;
56
54
  this.integrationId = parseInt(process.env.PAYMOB_INTEGRATION_ID);
57
- this.iframeId = parseInt(process.env.PAYMOB_IFRAME_ID);
58
- this.baseUrl = process.env.PAYMOB_BASE_URL;
55
+ this.baseUrl = process.env.PAYMOB_BASE_URL || 'https://accept.paymob.com';
59
56
  this.hmacSecret = process.env.PAYMOB_HMAC_SECRET;
60
57
  console.log('PayMob configuration:', {
61
58
  integrationId: this.integrationId,
62
- iframeId: this.iframeId,
59
+ publicKey: this.publicKey,
63
60
  baseUrl: this.baseUrl,
64
61
  });
65
62
  }
66
- getAuthToken() {
67
- return __awaiter(this, void 0, void 0, function* () {
68
- try {
69
- const response = yield axios_1.default.post(`${this.baseUrl}/auth/tokens`, {
70
- api_key: this.apiKey,
71
- });
72
- return response.data.token;
73
- }
74
- catch (error) {
75
- const axiosError = error;
76
- throw new Error(`Failed to get Paymob auth token: ${axiosError.message}`);
77
- }
78
- });
79
- }
80
- createOrder(amount, currency = 'EGP', items = [], merchant_order_id) {
63
+ /**
64
+ * Creates a payment intention using the Flash API
65
+ * @param amount The payment amount
66
+ * @param billingData The user data for billing
67
+ * @param items The order items
68
+ * @param currency The currency code (default: EGP)
69
+ * @param extras Custom metadata
70
+ * @returns The payment URL and client secret
71
+ */
72
+ createPaymentIntention(amount, billingData, items, currency = 'EGP', extras) {
81
73
  var _a;
82
74
  return __awaiter(this, void 0, void 0, function* () {
83
75
  try {
84
- const authToken = yield this.getAuthToken();
85
- const orderData = {
86
- auth_token: authToken,
87
- delivery_needed: false,
88
- amount_cents: amount * 100,
76
+ const intentionData = {
77
+ amount,
89
78
  currency,
79
+ payment_methods: [this.integrationId, 'card'],
90
80
  items,
81
+ billing_data: billingData,
82
+ customer: {
83
+ first_name: billingData.first_name,
84
+ last_name: billingData.last_name,
85
+ email: billingData.email,
86
+ extras: extras || {},
87
+ },
88
+ extras: extras || {},
91
89
  };
92
- if (merchant_order_id) {
93
- orderData.merchant_order_id = merchant_order_id;
94
- }
95
- const response = yield axios_1.default.post(`${this.baseUrl}/ecommerce/orders`, orderData, {
90
+ const response = yield axios_1.default.post(`${this.baseUrl}/v1/intention/`, intentionData, {
96
91
  headers: {
92
+ 'Authorization': `Token ${this.secretKey}`,
97
93
  'Content-Type': 'application/json',
98
94
  },
99
95
  });
96
+ // Create the payment URL for Flash Checkout
97
+ const paymentUrl = `${this.baseUrl}/unifiedcheckout/?publicKey=${this.publicKey}&clientSecret=${response.data.client_secret}`;
100
98
  return {
101
- orderId: response.data.id,
102
- token: authToken,
103
- };
104
- }
105
- catch (error) {
106
- const axiosError = error;
107
- console.log('PayMob order error:', (_a = axiosError.response) === null || _a === void 0 ? void 0 : _a.data);
108
- throw new Error(`Failed to create Paymob order: ${axiosError.message}`);
109
- }
110
- });
111
- }
112
- getPaymentKey(orderId, token, amount, billingData) {
113
- return __awaiter(this, void 0, void 0, function* () {
114
- try {
115
- const paymentKeyRequest = {
116
- auth_token: token,
117
- amount_cents: amount * 100,
118
- expiration: 3600,
119
- order_id: orderId,
120
- billing_data: billingData,
121
- currency: 'EGP',
122
- integration_id: this.integrationId,
99
+ paymentUrl,
100
+ clientSecret: response.data.client_secret,
123
101
  };
124
- const response = yield axios_1.default.post(`${this.baseUrl}/acceptance/payment_keys`, paymentKeyRequest, {
125
- headers: {
126
- 'Content-Type': 'application/json',
127
- },
128
- });
129
- return response.data.token;
130
102
  }
131
103
  catch (error) {
132
104
  const axiosError = error;
133
- throw new Error(`Failed to get payment key: ${axiosError.message}`);
105
+ console.log('PayMob intention error:', (_a = axiosError.response) === null || _a === void 0 ? void 0 : _a.data);
106
+ throw new Error(`Failed to create Paymob payment intention: ${axiosError.message}`);
134
107
  }
135
108
  });
136
109
  }
137
- createPaymentUrl(paymentKey) {
138
- return `https://accept.paymob.com/api/acceptance/iframes/${this.iframeId}?payment_token=${paymentKey}`;
139
- }
140
110
  /**
141
111
  * Creates a payment URL with user data and custom metadata
142
112
  * @param amount The payment amount
@@ -147,9 +117,9 @@ class PaymobService {
147
117
  * @returns The payment URL and related data
148
118
  */
149
119
  createPaymentUrlWithUserData(amount, userId, contractId, userData, serviceType) {
120
+ var _a;
150
121
  return __awaiter(this, void 0, void 0, function* () {
151
- const authToken = yield this.getAuthToken();
152
- // Store custom data in merchant_order_id as JSON string
122
+ // Create metadata with custom data
153
123
  const customData = {
154
124
  contractId,
155
125
  userId,
@@ -157,23 +127,60 @@ class PaymobService {
157
127
  booking_id: 'BOOK_' + Date.now(),
158
128
  timestamp: new Date().toISOString(),
159
129
  };
160
- const order = yield this.createOrder(amount, 'EGP', [], JSON.stringify(customData));
161
- const paymentKey = yield this.getPaymentKey(order.orderId, authToken, amount, {
130
+ const extras = customData;
131
+ const billingData = {
162
132
  first_name: userData.firstName,
163
133
  last_name: userData.lastName,
164
134
  email: userData.email,
165
135
  phone_number: userData.phone,
166
136
  apartment: '123',
167
- floor: '123',
168
- street: '123',
137
+ floor: '1',
138
+ street: '123 Main St',
169
139
  building: '123',
170
- city: '123',
171
- state: '123',
172
- country: '123',
173
- postal_code: '123',
174
- });
175
- const paymentUrl = this.createPaymentUrl(paymentKey);
176
- return { paymentUrl };
140
+ state: 'Cairo',
141
+ country: 'EGY',
142
+ };
143
+ const items = [
144
+ {
145
+ name: `${serviceType} Payment`,
146
+ description: `Payment for contract ${contractId}`,
147
+ amount,
148
+ quantity: 1,
149
+ },
150
+ ];
151
+ // For Flash Integration, we need to create a modified intention request
152
+ // that includes merchant_order_id
153
+ const intentionData = {
154
+ amount,
155
+ currency: 'EGP',
156
+ payment_methods: [this.integrationId, 'card'],
157
+ items,
158
+ billing_data: billingData,
159
+ customer: {
160
+ first_name: billingData.first_name,
161
+ last_name: billingData.last_name,
162
+ email: billingData.email,
163
+ extras: extras || {},
164
+ },
165
+ extras: extras || {},
166
+ merchant_order_id: JSON.stringify(customData), // Store custom data here
167
+ };
168
+ try {
169
+ const response = yield axios_1.default.post(`${this.baseUrl}/v1/intention/`, intentionData, {
170
+ headers: {
171
+ 'Authorization': `Token ${this.secretKey}`,
172
+ 'Content-Type': 'application/json',
173
+ },
174
+ });
175
+ // Create the payment URL for Flash Checkout
176
+ const paymentUrl = `${this.baseUrl}/unifiedcheckout/?publicKey=${this.publicKey}&clientSecret=${response.data.client_secret}`;
177
+ return { paymentUrl };
178
+ }
179
+ catch (error) {
180
+ const axiosError = error;
181
+ console.log('PayMob intention error:', (_a = axiosError.response) === null || _a === void 0 ? void 0 : _a.data);
182
+ throw new Error(`Failed to create Paymob payment intention: ${axiosError.message}`);
183
+ }
177
184
  });
178
185
  }
179
186
  verifyPayment(hmac, data) {
@@ -183,7 +190,7 @@ class PaymobService {
183
190
  .map(([key, value]) => `${key}=${value}`)
184
191
  .join('');
185
192
  const calculatedHmac = crypto
186
- .createHmac('sha512', this.apiKey)
193
+ .createHmac('sha512', this.secretKey)
187
194
  .update(concatenatedString)
188
195
  .digest('hex');
189
196
  return calculatedHmac === hmac;
@@ -299,11 +306,10 @@ class PaymobService {
299
306
  getTransactionStatus(transactionId) {
300
307
  return __awaiter(this, void 0, void 0, function* () {
301
308
  try {
302
- const authToken = yield this.getAuthToken();
303
- const response = yield axios_1.default.get(`${this.baseUrl}/acceptance/transactions/${transactionId}`, {
309
+ const response = yield axios_1.default.get(`${this.baseUrl}/api/acceptance/transactions/${transactionId}`, {
304
310
  headers: {
305
311
  'Content-Type': 'application/json',
306
- Authorization: `Bearer ${authToken}`,
312
+ 'Authorization': `Token ${this.secretKey}`,
307
313
  },
308
314
  });
309
315
  return {
@@ -323,15 +329,29 @@ class PaymobService {
323
329
  * Get order details including metadata
324
330
  */
325
331
  getOrderDetails(orderId) {
332
+ var _a, _b, _c;
326
333
  return __awaiter(this, void 0, void 0, function* () {
327
334
  try {
328
- const authToken = yield this.getAuthToken();
329
- const response = yield axios_1.default.get(`${this.baseUrl}/ecommerce/orders/${orderId}`, {
330
- headers: {
331
- 'Content-Type': 'application/json',
332
- Authorization: `Bearer ${authToken}`,
333
- },
334
- });
335
+ // Try the Flash Integration API endpoint first
336
+ let response;
337
+ try {
338
+ response = yield axios_1.default.get(`${this.baseUrl}/v1/intention/orders/${orderId}`, {
339
+ headers: {
340
+ 'Content-Type': 'application/json',
341
+ 'Authorization': `Token ${this.secretKey}`,
342
+ },
343
+ });
344
+ }
345
+ catch (flashError) {
346
+ console.log('Flash API failed, trying legacy API...');
347
+ // Fallback to legacy API endpoint
348
+ response = yield axios_1.default.get(`${this.baseUrl}/api/ecommerce/orders/${orderId}`, {
349
+ headers: {
350
+ 'Content-Type': 'application/json',
351
+ 'Authorization': `Token ${this.secretKey}`,
352
+ },
353
+ });
354
+ }
335
355
  return {
336
356
  id: response.data.id,
337
357
  amount_cents: response.data.amount_cents,
@@ -343,6 +363,21 @@ class PaymobService {
343
363
  }
344
364
  catch (error) {
345
365
  const axiosError = error;
366
+ console.error('Order details error response:', (_a = axiosError.response) === null || _a === void 0 ? void 0 : _a.data);
367
+ console.error('Order details error status:', (_b = axiosError.response) === null || _b === void 0 ? void 0 : _b.status);
368
+ // If still failing, provide a fallback that returns minimal data
369
+ if (((_c = axiosError.response) === null || _c === void 0 ? void 0 : _c.status) === 401) {
370
+ console.log('Authentication failed, using fallback approach...');
371
+ // Return a minimal response that won't break the webhook
372
+ return {
373
+ id: orderId,
374
+ amount_cents: 0,
375
+ currency: 'EGP',
376
+ items: [],
377
+ created_at: new Date().toISOString(),
378
+ merchant_order_id: '', // Empty merchant_order_id will trigger fallback logic
379
+ };
380
+ }
346
381
  throw new Error(`Failed to get order details: ${axiosError.message}`);
347
382
  }
348
383
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@duvdu-v1/duvdu",
3
- "version": "1.1.265",
3
+ "version": "1.1.267",
4
4
  "main": "./build/index.js",
5
5
  "types": "./build/index.d.ts",
6
6
  "files": [