paymongo-cli 1.4.4 → 1.4.7

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.
Files changed (155) hide show
  1. package/.github/copilot-instructions.md +95 -95
  2. package/CHANGELOG.md +85 -1
  3. package/LICENSE +20 -20
  4. package/dist/.tsbuildinfo +1 -1
  5. package/dist/commands/config.js +30 -15
  6. package/dist/commands/dev/logs.js +3 -3
  7. package/dist/commands/dev/status.js +2 -2
  8. package/dist/commands/dev/stop.js +3 -3
  9. package/dist/commands/dev.js +9 -8
  10. package/dist/commands/env.js +6 -6
  11. package/dist/commands/generate/templates/checkout-page/index.js +520 -520
  12. package/dist/commands/generate/templates/payment-intent/javascript.js +68 -68
  13. package/dist/commands/generate/templates/payment-intent/typescript.js +92 -92
  14. package/dist/commands/generate/templates/webhook-handler/javascript.js +192 -147
  15. package/dist/commands/generate/templates/webhook-handler/typescript.js +147 -117
  16. package/dist/commands/generate.js +43 -37
  17. package/dist/commands/init.js +25 -8
  18. package/dist/commands/login.js +56 -19
  19. package/dist/commands/payments.js +9 -8
  20. package/dist/commands/team/index.js +11 -9
  21. package/dist/commands/trigger.js +58 -18
  22. package/dist/commands/webhooks.js +8 -7
  23. package/dist/index.js +9 -2
  24. package/dist/services/analytics/service.js +24 -19
  25. package/dist/services/api/client.js +16 -16
  26. package/dist/services/config/manager.js +6 -8
  27. package/dist/services/dev/process-manager.js +30 -32
  28. package/dist/services/dev/server.js +45 -39
  29. package/dist/services/team/service.js +4 -1
  30. package/dist/types/schemas.js +38 -9
  31. package/dist/utils/bulk.js +36 -4
  32. package/dist/utils/constants.js +11 -1
  33. package/dist/utils/errors.js +6 -0
  34. package/dist/utils/validator.js +10 -9
  35. package/dist/utils/webhook-store.js +18 -15
  36. package/eslint.config.ts +70 -70
  37. package/package.json +2 -2
  38. package/coverage/base.css +0 -224
  39. package/coverage/block-navigation.js +0 -87
  40. package/coverage/favicon.png +0 -0
  41. package/coverage/index.html +0 -281
  42. package/coverage/lcov-report/base.css +0 -224
  43. package/coverage/lcov-report/block-navigation.js +0 -87
  44. package/coverage/lcov-report/favicon.png +0 -0
  45. package/coverage/lcov-report/index.html +0 -281
  46. package/coverage/lcov-report/prettify.css +0 -1
  47. package/coverage/lcov-report/prettify.js +0 -2
  48. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  49. package/coverage/lcov-report/sorter.js +0 -210
  50. package/coverage/lcov.info +0 -5053
  51. package/coverage/prettify.css +0 -1
  52. package/coverage/prettify.js +0 -2
  53. package/coverage/sort-arrow-sprite.png +0 -0
  54. package/coverage/sorter.js +0 -210
  55. package/dist/commands/config.d.ts +0 -21
  56. package/dist/commands/config.d.ts.map +0 -1
  57. package/dist/commands/config.js.map +0 -1
  58. package/dist/commands/dev.d.ts +0 -16
  59. package/dist/commands/dev.d.ts.map +0 -1
  60. package/dist/commands/dev.js.map +0 -1
  61. package/dist/commands/env.d.ts +0 -4
  62. package/dist/commands/env.d.ts.map +0 -1
  63. package/dist/commands/env.js.map +0 -1
  64. package/dist/commands/init.d.ts +0 -15
  65. package/dist/commands/init.d.ts.map +0 -1
  66. package/dist/commands/init.js.map +0 -1
  67. package/dist/commands/login.d.ts +0 -20
  68. package/dist/commands/login.d.ts.map +0 -1
  69. package/dist/commands/login.js.map +0 -1
  70. package/dist/commands/payments.d.ts +0 -41
  71. package/dist/commands/payments.d.ts.map +0 -1
  72. package/dist/commands/payments.js.map +0 -1
  73. package/dist/commands/team/index.d.ts +0 -4
  74. package/dist/commands/team/index.d.ts.map +0 -1
  75. package/dist/commands/team/index.js.map +0 -1
  76. package/dist/commands/trigger.d.ts +0 -4
  77. package/dist/commands/trigger.d.ts.map +0 -1
  78. package/dist/commands/trigger.js.map +0 -1
  79. package/dist/commands/webhooks.d.ts +0 -23
  80. package/dist/commands/webhooks.d.ts.map +0 -1
  81. package/dist/commands/webhooks.js.map +0 -1
  82. package/dist/index.d.ts +0 -3
  83. package/dist/index.d.ts.map +0 -1
  84. package/dist/index.js.map +0 -1
  85. package/dist/services/analytics/service.d.ts +0 -35
  86. package/dist/services/analytics/service.d.ts.map +0 -1
  87. package/dist/services/analytics/service.js.map +0 -1
  88. package/dist/services/api/client.d.ts +0 -26
  89. package/dist/services/api/client.d.ts.map +0 -1
  90. package/dist/services/api/client.js.map +0 -1
  91. package/dist/services/api/rate-limiter.d.ts +0 -64
  92. package/dist/services/api/rate-limiter.d.ts.map +0 -1
  93. package/dist/services/api/rate-limiter.js.map +0 -1
  94. package/dist/services/api/undici-client.d.ts +0 -39
  95. package/dist/services/api/undici-client.d.ts.map +0 -1
  96. package/dist/services/api/undici-client.js +0 -288
  97. package/dist/services/api/undici-client.js.map +0 -1
  98. package/dist/services/config/manager.d.ts +0 -16
  99. package/dist/services/config/manager.d.ts.map +0 -1
  100. package/dist/services/config/manager.js.map +0 -1
  101. package/dist/services/dev/process-manager.d.ts +0 -50
  102. package/dist/services/dev/process-manager.d.ts.map +0 -1
  103. package/dist/services/dev/process-manager.js.map +0 -1
  104. package/dist/services/github/auth.d.ts +0 -15
  105. package/dist/services/github/auth.d.ts.map +0 -1
  106. package/dist/services/github/auth.js +0 -79
  107. package/dist/services/github/auth.js.map +0 -1
  108. package/dist/services/github/client.d.ts +0 -95
  109. package/dist/services/github/client.d.ts.map +0 -1
  110. package/dist/services/github/client.js +0 -130
  111. package/dist/services/github/client.js.map +0 -1
  112. package/dist/services/github/sync.d.ts +0 -26
  113. package/dist/services/github/sync.d.ts.map +0 -1
  114. package/dist/services/github/sync.js +0 -203
  115. package/dist/services/github/sync.js.map +0 -1
  116. package/dist/services/payments/simulator.d.ts +0 -28
  117. package/dist/services/payments/simulator.d.ts.map +0 -1
  118. package/dist/services/payments/simulator.js.map +0 -1
  119. package/dist/services/team/service.d.ts +0 -44
  120. package/dist/services/team/service.d.ts.map +0 -1
  121. package/dist/services/team/service.js.map +0 -1
  122. package/dist/services/web/server.d.ts +0 -31
  123. package/dist/services/web/server.d.ts.map +0 -1
  124. package/dist/services/web/server.js +0 -206
  125. package/dist/services/web/server.js.map +0 -1
  126. package/dist/types/paymongo.d.ts +0 -204
  127. package/dist/types/paymongo.d.ts.map +0 -1
  128. package/dist/types/paymongo.js.map +0 -1
  129. package/dist/types/schemas.d.ts +0 -80
  130. package/dist/types/schemas.d.ts.map +0 -1
  131. package/dist/types/schemas.js.map +0 -1
  132. package/dist/utils/bulk.d.ts +0 -62
  133. package/dist/utils/bulk.d.ts.map +0 -1
  134. package/dist/utils/bulk.js.map +0 -1
  135. package/dist/utils/cache.d.ts +0 -22
  136. package/dist/utils/cache.d.ts.map +0 -1
  137. package/dist/utils/cache.js.map +0 -1
  138. package/dist/utils/constants.d.ts +0 -32
  139. package/dist/utils/constants.d.ts.map +0 -1
  140. package/dist/utils/constants.js.map +0 -1
  141. package/dist/utils/errors.d.ts +0 -34
  142. package/dist/utils/errors.d.ts.map +0 -1
  143. package/dist/utils/errors.js.map +0 -1
  144. package/dist/utils/logger.d.ts +0 -20
  145. package/dist/utils/logger.d.ts.map +0 -1
  146. package/dist/utils/logger.js.map +0 -1
  147. package/dist/utils/spinner.d.ts +0 -17
  148. package/dist/utils/spinner.d.ts.map +0 -1
  149. package/dist/utils/spinner.js.map +0 -1
  150. package/dist/utils/validator.d.ts +0 -10
  151. package/dist/utils/validator.d.ts.map +0 -1
  152. package/dist/utils/validator.js.map +0 -1
  153. package/dist/utils/webhook-store.d.ts +0 -22
  154. package/dist/utils/webhook-store.d.ts.map +0 -1
  155. package/dist/utils/webhook-store.js.map +0 -1
@@ -1,165 +1,210 @@
1
1
  function generateEventHandlers(events) {
2
2
  return events
3
- .map((event) => `
4
- case '${event}':
5
- console.log('Processing ${event} event:', data);
6
- // Add your ${event} handling logic here
3
+ .map((event) => `
4
+ case '${event}':
5
+ console.log('Processing ${event} event:', data);
6
+ // Add your ${event} handling logic here
7
7
  break;`)
8
8
  .join('');
9
9
  }
10
10
  export function expressTemplate(events) {
11
11
  const eventHandlers = generateEventHandlers(events);
12
- return `const express = require('express');
13
- const crypto = require('crypto');
14
-
15
- const app = express();
16
- app.use(express.json());
17
-
18
- // Webhook secret from PayMongo dashboard
19
- const WEBHOOK_SECRET = process.env.PAYMONGO_WEBHOOK_SECRET;
20
-
21
- function verifySignature(payload, signature, secret) {
22
- const expectedSignature = crypto
23
- .createHmac('sha256', secret)
24
- .update(payload, 'utf8')
25
- .digest('hex');
26
-
27
- return signature === \`sha256=\${expectedSignature}\`;
28
- }
29
-
30
- app.post('/webhooks/paymongo', (req, res) => {
31
- try {
32
- const signature = req.headers['paymongo-signature'];
33
- const payload = JSON.stringify(req.body);
34
-
35
- // Verify webhook signature (optional but recommended)
36
- if (WEBHOOK_SECRET && !verifySignature(payload, signature, WEBHOOK_SECRET)) {
37
- console.log('Invalid signature');
38
- return res.status(400).json({ error: 'Invalid signature' });
39
- }
40
-
41
- const { data } = req.body;
42
- const eventType = data.attributes.type;
43
-
44
- switch (eventType) {${eventHandlers}
45
- default:
46
- console.log('Unhandled event type:', eventType);
47
- }
48
-
49
- res.json({ received: true });
50
- } catch (error) {
51
- console.error('Webhook processing error:', error);
52
- res.status(500).json({ error: 'Internal server error' });
53
- }
54
- });
55
-
56
- const PORT = process.env.PORT || 3000;
57
- app.listen(PORT, () => {
58
- console.log(\`Webhook server running on port \${PORT}\`);
12
+ return `const express = require('express');
13
+ const crypto = require('crypto');
14
+
15
+ const app = express();
16
+ app.use(express.json());
17
+
18
+ // Webhook secret from PayMongo dashboard
19
+ const WEBHOOK_SECRET = process.env.PAYMONGO_WEBHOOK_SECRET;
20
+
21
+ function verifySignature(payload, signatureHeader, secret) {
22
+ if (!signatureHeader) {
23
+ return false;
24
+ }
25
+
26
+ const parts = signatureHeader.split(',');
27
+ const timestamp = parts.find((part) => part.startsWith('t='))?.split('=')[1];
28
+ const signature = parts.find((part) => part.startsWith('te='))?.split('=')[1];
29
+
30
+ if (!timestamp || !signature) {
31
+ return false;
32
+ }
33
+
34
+ const expectedSignature = crypto
35
+ .createHmac('sha256', secret)
36
+ .update(timestamp + '.' + payload, 'utf8')
37
+ .digest('hex');
38
+
39
+ return crypto.timingSafeEqual(
40
+ Buffer.from(signature, 'hex'),
41
+ Buffer.from(expectedSignature, 'hex')
42
+ );
43
+ }
44
+
45
+ app.post('/webhooks/paymongo', (req, res) => {
46
+ try {
47
+ const signature = req.headers['paymongo-signature'];
48
+ const payload = JSON.stringify(req.body);
49
+
50
+ // Verify webhook signature (optional but recommended)
51
+ if (WEBHOOK_SECRET && !verifySignature(payload, signature, WEBHOOK_SECRET)) {
52
+ console.log('Invalid signature');
53
+ return res.status(400).json({ error: 'Invalid signature' });
54
+ }
55
+
56
+ const { data } = req.body;
57
+ const eventType = data.attributes.type;
58
+
59
+ switch (eventType) {${eventHandlers}
60
+ default:
61
+ console.log('Unhandled event type:', eventType);
62
+ }
63
+
64
+ res.json({ received: true });
65
+ } catch (error) {
66
+ console.error('Webhook processing error:', error);
67
+ res.status(500).json({ error: 'Internal server error' });
68
+ }
69
+ });
70
+
71
+ const PORT = process.env.PORT || 3000;
72
+ app.listen(PORT, () => {
73
+ console.log(\`Webhook server running on port \${PORT}\`);
59
74
  });`;
60
75
  }
61
76
  export function fastifyTemplate(events) {
62
77
  const eventHandlers = generateEventHandlers(events);
63
- return `const fastify = require('fastify')({ logger: true });
64
- const crypto = require('crypto');
65
-
66
- // Webhook secret from PayMongo dashboard
67
- const WEBHOOK_SECRET = process.env.PAYMONGO_WEBHOOK_SECRET;
68
-
69
- function verifySignature(payload, signature, secret) {
70
- const expectedSignature = crypto
71
- .createHmac('sha256', secret)
72
- .update(payload, 'utf8')
73
- .digest('hex');
74
-
75
- return signature === \`sha256=\${expectedSignature}\`;
76
- }
77
-
78
- fastify.post('/webhooks/paymongo', async (request, reply) => {
79
- try {
80
- const signature = request.headers['paymongo-signature'];
81
- const payload = JSON.stringify(request.body);
82
-
83
- // Verify webhook signature (optional but recommended)
84
- if (WEBHOOK_SECRET && !verifySignature(payload, signature, WEBHOOK_SECRET)) {
85
- console.log('Invalid signature');
86
- return reply.code(400).send({ error: 'Invalid signature' });
87
- }
88
-
89
- const { data } = request.body;
90
- const eventType = data.attributes.type;
91
-
92
- switch (eventType) {${eventHandlers}
93
- default:
94
- console.log('Unhandled event type:', eventType);
95
- }
96
-
97
- return { received: true };
98
- } catch (error) {
99
- console.error('Webhook processing error:', error);
100
- return reply.code(500).send({ error: 'Internal server error' });
101
- }
102
- });
103
-
104
- const start = async () => {
105
- try {
106
- await fastify.listen({ port: process.env.PORT || 3000 });
107
- } catch (err) {
108
- fastify.log.error(err);
109
- process.exit(1);
110
- }
111
- };
112
-
78
+ return `const fastify = require('fastify')({ logger: true });
79
+ const crypto = require('crypto');
80
+
81
+ // Webhook secret from PayMongo dashboard
82
+ const WEBHOOK_SECRET = process.env.PAYMONGO_WEBHOOK_SECRET;
83
+
84
+ function verifySignature(payload, signatureHeader, secret) {
85
+ if (!signatureHeader) {
86
+ return false;
87
+ }
88
+
89
+ const parts = signatureHeader.split(',');
90
+ const timestamp = parts.find((part) => part.startsWith('t='))?.split('=')[1];
91
+ const signature = parts.find((part) => part.startsWith('te='))?.split('=')[1];
92
+
93
+ if (!timestamp || !signature) {
94
+ return false;
95
+ }
96
+
97
+ const expectedSignature = crypto
98
+ .createHmac('sha256', secret)
99
+ .update(timestamp + '.' + payload, 'utf8')
100
+ .digest('hex');
101
+
102
+ return crypto.timingSafeEqual(
103
+ Buffer.from(signature, 'hex'),
104
+ Buffer.from(expectedSignature, 'hex')
105
+ );
106
+ }
107
+
108
+ fastify.post('/webhooks/paymongo', async (request, reply) => {
109
+ try {
110
+ const signature = request.headers['paymongo-signature'];
111
+ const payload = JSON.stringify(request.body);
112
+
113
+ // Verify webhook signature (optional but recommended)
114
+ if (WEBHOOK_SECRET && !verifySignature(payload, signature, WEBHOOK_SECRET)) {
115
+ console.log('Invalid signature');
116
+ return reply.code(400).send({ error: 'Invalid signature' });
117
+ }
118
+
119
+ const { data } = request.body;
120
+ const eventType = data.attributes.type;
121
+
122
+ switch (eventType) {${eventHandlers}
123
+ default:
124
+ console.log('Unhandled event type:', eventType);
125
+ }
126
+
127
+ return { received: true };
128
+ } catch (error) {
129
+ console.error('Webhook processing error:', error);
130
+ return reply.code(500).send({ error: 'Internal server error' });
131
+ }
132
+ });
133
+
134
+ const start = async () => {
135
+ try {
136
+ await fastify.listen({ port: process.env.PORT || 3000 });
137
+ } catch (err) {
138
+ fastify.log.error(err);
139
+ process.exit(1);
140
+ }
141
+ };
142
+
113
143
  start();`;
114
144
  }
115
145
  export function genericTemplate(events) {
116
146
  const eventHandlers = generateEventHandlers(events);
117
- return `// Simple webhook handler for ${events.join(', ')}
118
-
119
- const crypto = require('crypto');
120
-
121
- // Webhook secret from PayMongo dashboard
122
- const WEBHOOK_SECRET = process.env.PAYMONGO_WEBHOOK_SECRET;
123
-
124
- function verifySignature(payload, signature, secret) {
125
- const expectedSignature = crypto
126
- .createHmac('sha256', secret)
127
- .update(payload, 'utf8')
128
- .digest('hex');
129
-
130
- return signature === \`sha256=\${expectedSignature}\`;
131
- }
132
-
133
- function handleWebhook(request, response) {
134
- try {
135
- const signature = request.headers['paymongo-signature'];
136
- const payload = JSON.stringify(request.body);
137
-
138
- // Verify webhook signature (optional but recommended)
139
- if (WEBHOOK_SECRET && !verifySignature(payload, signature, WEBHOOK_SECRET)) {
140
- console.log('Invalid signature');
141
- response.writeHead(400, { 'Content-Type': 'application/json' });
142
- response.end(JSON.stringify({ error: 'Invalid signature' }));
143
- return;
144
- }
145
-
146
- const { data } = request.body;
147
- const eventType = data.attributes.type;
148
-
149
- switch (eventType) {${eventHandlers}
150
- default:
151
- console.log('Unhandled event type:', eventType);
152
- }
153
-
154
- response.writeHead(200, { 'Content-Type': 'application/json' });
155
- response.end(JSON.stringify({ received: true }));
156
- } catch (error) {
157
- console.error('Webhook processing error:', error);
158
- response.writeHead(500, { 'Content-Type': 'application/json' });
159
- response.end(JSON.stringify({ error: 'Internal server error' }));
160
- }
161
- }
162
-
147
+ return `// Simple webhook handler for ${events.join(', ')}
148
+
149
+ const crypto = require('crypto');
150
+
151
+ // Webhook secret from PayMongo dashboard
152
+ const WEBHOOK_SECRET = process.env.PAYMONGO_WEBHOOK_SECRET;
153
+
154
+ function verifySignature(payload, signatureHeader, secret) {
155
+ if (!signatureHeader) {
156
+ return false;
157
+ }
158
+
159
+ const parts = signatureHeader.split(',');
160
+ const timestamp = parts.find((part) => part.startsWith('t='))?.split('=')[1];
161
+ const signature = parts.find((part) => part.startsWith('te='))?.split('=')[1];
162
+
163
+ if (!timestamp || !signature) {
164
+ return false;
165
+ }
166
+
167
+ const expectedSignature = crypto
168
+ .createHmac('sha256', secret)
169
+ .update(timestamp + '.' + payload, 'utf8')
170
+ .digest('hex');
171
+
172
+ return crypto.timingSafeEqual(
173
+ Buffer.from(signature, 'hex'),
174
+ Buffer.from(expectedSignature, 'hex')
175
+ );
176
+ }
177
+
178
+ function handleWebhook(request, response) {
179
+ try {
180
+ const signature = request.headers['paymongo-signature'];
181
+ const payload = JSON.stringify(request.body);
182
+
183
+ // Verify webhook signature (optional but recommended)
184
+ if (WEBHOOK_SECRET && !verifySignature(payload, signature, WEBHOOK_SECRET)) {
185
+ console.log('Invalid signature');
186
+ response.writeHead(400, { 'Content-Type': 'application/json' });
187
+ response.end(JSON.stringify({ error: 'Invalid signature' }));
188
+ return;
189
+ }
190
+
191
+ const { data } = request.body;
192
+ const eventType = data.attributes.type;
193
+
194
+ switch (eventType) {${eventHandlers}
195
+ default:
196
+ console.log('Unhandled event type:', eventType);
197
+ }
198
+
199
+ response.writeHead(200, { 'Content-Type': 'application/json' });
200
+ response.end(JSON.stringify({ received: true }));
201
+ } catch (error) {
202
+ console.error('Webhook processing error:', error);
203
+ response.writeHead(500, { 'Content-Type': 'application/json' });
204
+ response.end(JSON.stringify({ error: 'Internal server error' }));
205
+ }
206
+ }
207
+
163
208
  module.exports = { handleWebhook };`;
164
209
  }
165
210
  export function getWebhookHandlerTemplate(events, framework) {
@@ -1,131 +1,161 @@
1
1
  function generateEventHandlers(events) {
2
2
  return events
3
- .map((event) => `
4
- case '${event}':
5
- console.log('Processing ${event} event:', data);
6
- // Add your ${event} handling logic here
3
+ .map((event) => `
4
+ case '${event}':
5
+ console.log('Processing ${event} event:', data);
6
+ // Add your ${event} handling logic here
7
7
  break;`)
8
8
  .join('');
9
9
  }
10
10
  export function expressTemplate(events) {
11
11
  const eventHandlers = generateEventHandlers(events);
12
- return `import express, { Request, Response } from 'express';
13
- import crypto from 'crypto';
14
-
15
- const app = express();
16
- app.use(express.json());
17
-
18
- // Webhook secret from PayMongo dashboard
19
- const WEBHOOK_SECRET = process.env.PAYMONGO_WEBHOOK_SECRET;
20
-
21
- interface PayMongoWebhookPayload {
22
- data: {
23
- id: string;
24
- type: string;
25
- attributes: {
26
- type: string;
27
- livemode: boolean;
28
- created_at: number;
29
- updated_at: number;
30
- data: any;
31
- };
32
- };
33
- }
34
-
35
- function verifySignature(payload: string, signature: string, secret: string): boolean {
36
- const expectedSignature = crypto
37
- .createHmac('sha256', secret)
38
- .update(payload, 'utf8')
39
- .digest('hex');
40
-
41
- return signature === \`sha256=\${expectedSignature}\`;
42
- }
43
-
44
- app.post('/webhooks/paymongo', (req: Request, res: Response) => {
45
- try {
46
- const signature = req.headers['paymongo-signature'] as string;
47
- const payload = JSON.stringify(req.body);
48
-
49
- // Verify webhook signature (optional but recommended)
50
- if (WEBHOOK_SECRET && !verifySignature(payload, signature, WEBHOOK_SECRET)) {
51
- console.log('Invalid signature');
52
- return res.status(400).json({ error: 'Invalid signature' });
53
- }
54
-
55
- const { data }: PayMongoWebhookPayload = req.body;
56
- const eventType = data.attributes.type;
57
-
58
- switch (eventType) {${eventHandlers}
59
- default:
60
- console.log('Unhandled event type:', eventType);
61
- }
62
-
63
- res.json({ received: true });
64
- } catch (error) {
65
- console.error('Webhook processing error:', error);
66
- res.status(500).json({ error: 'Internal server error' });
67
- }
68
- });
69
-
70
- const PORT = process.env.PORT || 3000;
71
- app.listen(PORT, () => {
72
- console.log(\`Webhook server running on port \${PORT}\`);
12
+ return `import express, { Request, Response } from 'express';
13
+ import crypto from 'crypto';
14
+
15
+ const app = express();
16
+ app.use(express.json());
17
+
18
+ // Webhook secret from PayMongo dashboard
19
+ const WEBHOOK_SECRET = process.env.PAYMONGO_WEBHOOK_SECRET;
20
+
21
+ interface PayMongoWebhookPayload {
22
+ data: {
23
+ id: string;
24
+ type: string;
25
+ attributes: {
26
+ type: string;
27
+ livemode: boolean;
28
+ created_at: number;
29
+ updated_at: number;
30
+ data: any;
31
+ };
32
+ };
33
+ }
34
+
35
+ function verifySignature(payload: string, signatureHeader: string, secret: string): boolean {
36
+ if (!signatureHeader) {
37
+ return false;
38
+ }
39
+
40
+ const parts = signatureHeader.split(',');
41
+ const timestamp = parts.find((part) => part.startsWith('t='))?.split('=')[1];
42
+ const signature = parts.find((part) => part.startsWith('te='))?.split('=')[1];
43
+
44
+ if (!timestamp || !signature) {
45
+ return false;
46
+ }
47
+
48
+ const expectedSignature = crypto
49
+ .createHmac('sha256', secret)
50
+ .update(timestamp + '.' + payload, 'utf8')
51
+ .digest('hex');
52
+
53
+ return crypto.timingSafeEqual(
54
+ Buffer.from(signature, 'hex'),
55
+ Buffer.from(expectedSignature, 'hex')
56
+ );
57
+ }
58
+
59
+ app.post('/webhooks/paymongo', (req: Request, res: Response) => {
60
+ try {
61
+ const signature = req.headers['paymongo-signature'] as string;
62
+ const payload = JSON.stringify(req.body);
63
+
64
+ // Verify webhook signature (optional but recommended)
65
+ if (WEBHOOK_SECRET && !verifySignature(payload, signature, WEBHOOK_SECRET)) {
66
+ console.log('Invalid signature');
67
+ return res.status(400).json({ error: 'Invalid signature' });
68
+ }
69
+
70
+ const { data }: PayMongoWebhookPayload = req.body;
71
+ const eventType = data.attributes.type;
72
+
73
+ switch (eventType) {${eventHandlers}
74
+ default:
75
+ console.log('Unhandled event type:', eventType);
76
+ }
77
+
78
+ res.json({ received: true });
79
+ } catch (error) {
80
+ console.error('Webhook processing error:', error);
81
+ res.status(500).json({ error: 'Internal server error' });
82
+ }
83
+ });
84
+
85
+ const PORT = process.env.PORT || 3000;
86
+ app.listen(PORT, () => {
87
+ console.log(\`Webhook server running on port \${PORT}\`);
73
88
  });`;
74
89
  }
75
90
  export function genericTemplate(events) {
76
91
  const eventHandlers = generateEventHandlers(events);
77
- return `// TypeScript webhook handler for ${events.join(', ')}
78
-
79
- import crypto from 'crypto';
80
-
81
- const WEBHOOK_SECRET = process.env.PAYMONGO_WEBHOOK_SECRET;
82
-
83
- interface PayMongoWebhookPayload {
84
- data: {
85
- id: string;
86
- type: string;
87
- attributes: {
88
- type: string;
89
- livemode: boolean;
90
- created_at: number;
91
- updated_at: number;
92
- data: any;
93
- };
94
- };
95
- }
96
-
97
- function verifySignature(payload: string, signature: string, secret: string): boolean {
98
- const expectedSignature = crypto
99
- .createHmac('sha256', secret)
100
- .update(payload, 'utf8')
101
- .digest('hex');
102
-
103
- return signature === \`sha256=\${expectedSignature}\`;
104
- }
105
-
106
- export function handleWebhook(body: PayMongoWebhookPayload, signature?: string): { received: boolean } {
107
- try {
108
- const payload = JSON.stringify(body);
109
-
110
- // Verify webhook signature (optional but recommended)
111
- if (WEBHOOK_SECRET && signature && !verifySignature(payload, signature, WEBHOOK_SECRET)) {
112
- console.log('Invalid signature');
113
- throw new Error('Invalid signature');
114
- }
115
-
116
- const { data } = body;
117
- const eventType = data.attributes.type;
118
-
119
- switch (eventType) {${eventHandlers}
120
- default:
121
- console.log('Unhandled event type:', eventType);
122
- }
123
-
124
- return { received: true };
125
- } catch (error) {
126
- console.error('Webhook processing error:', error);
127
- throw error;
128
- }
92
+ return `// TypeScript webhook handler for ${events.join(', ')}
93
+
94
+ import crypto from 'crypto';
95
+
96
+ const WEBHOOK_SECRET = process.env.PAYMONGO_WEBHOOK_SECRET;
97
+
98
+ interface PayMongoWebhookPayload {
99
+ data: {
100
+ id: string;
101
+ type: string;
102
+ attributes: {
103
+ type: string;
104
+ livemode: boolean;
105
+ created_at: number;
106
+ updated_at: number;
107
+ data: any;
108
+ };
109
+ };
110
+ }
111
+
112
+ function verifySignature(payload: string, signatureHeader: string, secret: string): boolean {
113
+ if (!signatureHeader) {
114
+ return false;
115
+ }
116
+
117
+ const parts = signatureHeader.split(',');
118
+ const timestamp = parts.find((part) => part.startsWith('t='))?.split('=')[1];
119
+ const signature = parts.find((part) => part.startsWith('te='))?.split('=')[1];
120
+
121
+ if (!timestamp || !signature) {
122
+ return false;
123
+ }
124
+
125
+ const expectedSignature = crypto
126
+ .createHmac('sha256', secret)
127
+ .update(timestamp + '.' + payload, 'utf8')
128
+ .digest('hex');
129
+
130
+ return crypto.timingSafeEqual(
131
+ Buffer.from(signature, 'hex'),
132
+ Buffer.from(expectedSignature, 'hex')
133
+ );
134
+ }
135
+
136
+ export function handleWebhook(body: PayMongoWebhookPayload, signature?: string): { received: boolean } {
137
+ try {
138
+ const payload = JSON.stringify(body);
139
+
140
+ // Verify webhook signature (optional but recommended)
141
+ if (WEBHOOK_SECRET && signature && !verifySignature(payload, signature, WEBHOOK_SECRET)) {
142
+ console.log('Invalid signature');
143
+ throw new Error('Invalid signature');
144
+ }
145
+
146
+ const { data } = body;
147
+ const eventType = data.attributes.type;
148
+
149
+ switch (eventType) {${eventHandlers}
150
+ default:
151
+ console.log('Unhandled event type:', eventType);
152
+ }
153
+
154
+ return { received: true };
155
+ } catch (error) {
156
+ console.error('Webhook processing error:', error);
157
+ throw error;
158
+ }
129
159
  }`;
130
160
  }
131
161
  export function getWebhookHandlerTemplate(events, framework) {