paymongo-cli 1.4.4 → 1.4.6

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 (142) hide show
  1. package/.github/copilot-instructions.md +95 -95
  2. package/CHANGELOG.md +27 -0
  3. package/LICENSE +20 -20
  4. package/dist/.tsbuildinfo +1 -1
  5. package/dist/commands/config.js +14 -0
  6. package/dist/commands/dev.js +2 -1
  7. package/dist/commands/generate/templates/checkout-page/index.js +520 -520
  8. package/dist/commands/generate/templates/payment-intent/javascript.js +68 -68
  9. package/dist/commands/generate/templates/payment-intent/typescript.js +92 -92
  10. package/dist/commands/generate/templates/webhook-handler/javascript.js +192 -147
  11. package/dist/commands/generate/templates/webhook-handler/typescript.js +147 -117
  12. package/dist/commands/generate.js +43 -37
  13. package/dist/commands/init.js +22 -5
  14. package/dist/commands/login.js +53 -16
  15. package/dist/commands/team/index.js +4 -3
  16. package/dist/commands/trigger.js +40 -2
  17. package/dist/commands/webhooks.js +1 -1
  18. package/dist/services/analytics/service.js +5 -1
  19. package/dist/services/api/client.js +1 -1
  20. package/dist/services/config/manager.js +6 -8
  21. package/dist/services/team/service.js +4 -1
  22. package/dist/types/schemas.js +38 -9
  23. package/eslint.config.ts +70 -70
  24. package/package.json +2 -2
  25. package/coverage/base.css +0 -224
  26. package/coverage/block-navigation.js +0 -87
  27. package/coverage/favicon.png +0 -0
  28. package/coverage/index.html +0 -281
  29. package/coverage/lcov-report/base.css +0 -224
  30. package/coverage/lcov-report/block-navigation.js +0 -87
  31. package/coverage/lcov-report/favicon.png +0 -0
  32. package/coverage/lcov-report/index.html +0 -281
  33. package/coverage/lcov-report/prettify.css +0 -1
  34. package/coverage/lcov-report/prettify.js +0 -2
  35. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  36. package/coverage/lcov-report/sorter.js +0 -210
  37. package/coverage/lcov.info +0 -5053
  38. package/coverage/prettify.css +0 -1
  39. package/coverage/prettify.js +0 -2
  40. package/coverage/sort-arrow-sprite.png +0 -0
  41. package/coverage/sorter.js +0 -210
  42. package/dist/commands/config.d.ts +0 -21
  43. package/dist/commands/config.d.ts.map +0 -1
  44. package/dist/commands/config.js.map +0 -1
  45. package/dist/commands/dev.d.ts +0 -16
  46. package/dist/commands/dev.d.ts.map +0 -1
  47. package/dist/commands/dev.js.map +0 -1
  48. package/dist/commands/env.d.ts +0 -4
  49. package/dist/commands/env.d.ts.map +0 -1
  50. package/dist/commands/env.js.map +0 -1
  51. package/dist/commands/init.d.ts +0 -15
  52. package/dist/commands/init.d.ts.map +0 -1
  53. package/dist/commands/init.js.map +0 -1
  54. package/dist/commands/login.d.ts +0 -20
  55. package/dist/commands/login.d.ts.map +0 -1
  56. package/dist/commands/login.js.map +0 -1
  57. package/dist/commands/payments.d.ts +0 -41
  58. package/dist/commands/payments.d.ts.map +0 -1
  59. package/dist/commands/payments.js.map +0 -1
  60. package/dist/commands/team/index.d.ts +0 -4
  61. package/dist/commands/team/index.d.ts.map +0 -1
  62. package/dist/commands/team/index.js.map +0 -1
  63. package/dist/commands/trigger.d.ts +0 -4
  64. package/dist/commands/trigger.d.ts.map +0 -1
  65. package/dist/commands/trigger.js.map +0 -1
  66. package/dist/commands/webhooks.d.ts +0 -23
  67. package/dist/commands/webhooks.d.ts.map +0 -1
  68. package/dist/commands/webhooks.js.map +0 -1
  69. package/dist/index.d.ts +0 -3
  70. package/dist/index.d.ts.map +0 -1
  71. package/dist/index.js.map +0 -1
  72. package/dist/services/analytics/service.d.ts +0 -35
  73. package/dist/services/analytics/service.d.ts.map +0 -1
  74. package/dist/services/analytics/service.js.map +0 -1
  75. package/dist/services/api/client.d.ts +0 -26
  76. package/dist/services/api/client.d.ts.map +0 -1
  77. package/dist/services/api/client.js.map +0 -1
  78. package/dist/services/api/rate-limiter.d.ts +0 -64
  79. package/dist/services/api/rate-limiter.d.ts.map +0 -1
  80. package/dist/services/api/rate-limiter.js.map +0 -1
  81. package/dist/services/api/undici-client.d.ts +0 -39
  82. package/dist/services/api/undici-client.d.ts.map +0 -1
  83. package/dist/services/api/undici-client.js +0 -288
  84. package/dist/services/api/undici-client.js.map +0 -1
  85. package/dist/services/config/manager.d.ts +0 -16
  86. package/dist/services/config/manager.d.ts.map +0 -1
  87. package/dist/services/config/manager.js.map +0 -1
  88. package/dist/services/dev/process-manager.d.ts +0 -50
  89. package/dist/services/dev/process-manager.d.ts.map +0 -1
  90. package/dist/services/dev/process-manager.js.map +0 -1
  91. package/dist/services/github/auth.d.ts +0 -15
  92. package/dist/services/github/auth.d.ts.map +0 -1
  93. package/dist/services/github/auth.js +0 -79
  94. package/dist/services/github/auth.js.map +0 -1
  95. package/dist/services/github/client.d.ts +0 -95
  96. package/dist/services/github/client.d.ts.map +0 -1
  97. package/dist/services/github/client.js +0 -130
  98. package/dist/services/github/client.js.map +0 -1
  99. package/dist/services/github/sync.d.ts +0 -26
  100. package/dist/services/github/sync.d.ts.map +0 -1
  101. package/dist/services/github/sync.js +0 -203
  102. package/dist/services/github/sync.js.map +0 -1
  103. package/dist/services/payments/simulator.d.ts +0 -28
  104. package/dist/services/payments/simulator.d.ts.map +0 -1
  105. package/dist/services/payments/simulator.js.map +0 -1
  106. package/dist/services/team/service.d.ts +0 -44
  107. package/dist/services/team/service.d.ts.map +0 -1
  108. package/dist/services/team/service.js.map +0 -1
  109. package/dist/services/web/server.d.ts +0 -31
  110. package/dist/services/web/server.d.ts.map +0 -1
  111. package/dist/services/web/server.js +0 -206
  112. package/dist/services/web/server.js.map +0 -1
  113. package/dist/types/paymongo.d.ts +0 -204
  114. package/dist/types/paymongo.d.ts.map +0 -1
  115. package/dist/types/paymongo.js.map +0 -1
  116. package/dist/types/schemas.d.ts +0 -80
  117. package/dist/types/schemas.d.ts.map +0 -1
  118. package/dist/types/schemas.js.map +0 -1
  119. package/dist/utils/bulk.d.ts +0 -62
  120. package/dist/utils/bulk.d.ts.map +0 -1
  121. package/dist/utils/bulk.js.map +0 -1
  122. package/dist/utils/cache.d.ts +0 -22
  123. package/dist/utils/cache.d.ts.map +0 -1
  124. package/dist/utils/cache.js.map +0 -1
  125. package/dist/utils/constants.d.ts +0 -32
  126. package/dist/utils/constants.d.ts.map +0 -1
  127. package/dist/utils/constants.js.map +0 -1
  128. package/dist/utils/errors.d.ts +0 -34
  129. package/dist/utils/errors.d.ts.map +0 -1
  130. package/dist/utils/errors.js.map +0 -1
  131. package/dist/utils/logger.d.ts +0 -20
  132. package/dist/utils/logger.d.ts.map +0 -1
  133. package/dist/utils/logger.js.map +0 -1
  134. package/dist/utils/spinner.d.ts +0 -17
  135. package/dist/utils/spinner.d.ts.map +0 -1
  136. package/dist/utils/spinner.js.map +0 -1
  137. package/dist/utils/validator.d.ts +0 -10
  138. package/dist/utils/validator.d.ts.map +0 -1
  139. package/dist/utils/validator.js.map +0 -1
  140. package/dist/utils/webhook-store.d.ts +0 -22
  141. package/dist/utils/webhook-store.d.ts.map +0 -1
  142. 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) {