@easypayment/medusa-paypal 0.6.2 → 0.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.medusa/server/src/admin/index.js +12 -15
- package/.medusa/server/src/admin/index.mjs +12 -15
- package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.d.ts.map +1 -1
- package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.js.map +1 -1
- package/.medusa/server/src/api/store/paypal/capture-order/route.d.ts.map +1 -1
- package/.medusa/server/src/api/store/paypal/capture-order/route.js +1 -11
- package/.medusa/server/src/api/store/paypal/capture-order/route.js.map +1 -1
- package/.medusa/server/src/api/store/paypal/create-order/route.d.ts.map +1 -1
- package/.medusa/server/src/api/store/paypal/create-order/route.js +0 -9
- package/.medusa/server/src/api/store/paypal/create-order/route.js.map +1 -1
- package/.medusa/server/src/api/store/paypal/webhook/route.d.ts.map +1 -1
- package/.medusa/server/src/api/store/paypal/webhook/route.js +162 -115
- package/.medusa/server/src/api/store/paypal/webhook/route.js.map +1 -1
- package/.medusa/server/src/api/store/paypal-complete/route.d.ts.map +1 -1
- package/.medusa/server/src/api/store/paypal-complete/route.js +0 -6
- package/.medusa/server/src/api/store/paypal-complete/route.js.map +1 -1
- package/.medusa/server/src/jobs/paypal-webhook-retry.d.ts.map +1 -1
- package/.medusa/server/src/jobs/paypal-webhook-retry.js +97 -43
- package/.medusa/server/src/jobs/paypal-webhook-retry.js.map +1 -1
- package/.medusa/server/src/modules/paypal/migrations/20270201000000_add_webhook_dead_letter.d.ts +6 -0
- package/.medusa/server/src/modules/paypal/migrations/20270201000000_add_webhook_dead_letter.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/migrations/20270201000000_add_webhook_dead_letter.js +20 -0
- package/.medusa/server/src/modules/paypal/migrations/20270201000000_add_webhook_dead_letter.js.map +1 -0
- package/.medusa/server/src/modules/paypal/payment-provider/service.d.ts.map +1 -1
- package/.medusa/server/src/modules/paypal/payment-provider/service.js +0 -42
- package/.medusa/server/src/modules/paypal/payment-provider/service.js.map +1 -1
- package/.medusa/server/src/modules/paypal/service.d.ts +0 -8
- package/.medusa/server/src/modules/paypal/service.d.ts.map +1 -1
- package/.medusa/server/src/modules/paypal/service.js +6 -114
- package/.medusa/server/src/modules/paypal/service.js.map +1 -1
- package/.medusa/server/src/modules/paypal/types/config.d.ts +0 -2
- package/.medusa/server/src/modules/paypal/types/config.d.ts.map +1 -1
- package/.medusa/server/src/modules/paypal/types/config.js +0 -9
- package/.medusa/server/src/modules/paypal/types/config.js.map +1 -1
- package/.medusa/server/src/modules/paypal/webhook-processor.d.ts +21 -17
- package/.medusa/server/src/modules/paypal/webhook-processor.d.ts.map +1 -1
- package/.medusa/server/src/modules/paypal/webhook-processor.js +195 -99
- package/.medusa/server/src/modules/paypal/webhook-processor.js.map +1 -1
- package/README.md +156 -159
- package/package.json +1 -1
- package/src/admin/routes/settings/paypal/_components/Tabs.tsx +48 -52
- package/src/admin/routes/settings/paypal/paypal-settings/page.tsx +0 -23
- package/src/api/store/payment-collections/[id]/payment-sessions/route.ts +56 -65
- package/src/api/store/paypal/capture-order/route.ts +266 -276
- package/src/api/store/paypal/create-order/route.ts +0 -9
- package/src/api/store/paypal/webhook/route.ts +325 -246
- package/src/api/store/paypal-complete/route.ts +69 -75
- package/src/jobs/paypal-webhook-retry.ts +149 -85
- package/src/modules/paypal/migrations/20270201000000_add_webhook_dead_letter.ts +17 -0
- package/src/modules/paypal/payment-provider/service.ts +1079 -1121
- package/src/modules/paypal/service.ts +6 -127
- package/src/modules/paypal/types/config.ts +33 -47
- package/src/modules/paypal/webhook-processor.ts +377 -215
- package/.medusa/server/src/api/admin/paypal/rotate-credentials/route.d.ts +0 -3
- package/.medusa/server/src/api/admin/paypal/rotate-credentials/route.d.ts.map +0 -1
- package/.medusa/server/src/api/admin/paypal/rotate-credentials/route.js +0 -9
- package/.medusa/server/src/api/admin/paypal/rotate-credentials/route.js.map +0 -1
- package/.medusa/server/src/jobs/paypal-reconcile.d.ts +0 -7
- package/.medusa/server/src/jobs/paypal-reconcile.d.ts.map +0 -1
- package/.medusa/server/src/jobs/paypal-reconcile.js +0 -109
- package/.medusa/server/src/jobs/paypal-reconcile.js.map +0 -1
- package/.medusa/server/src/modules/paypal/utils/crypto.d.ts +0 -4
- package/.medusa/server/src/modules/paypal/utils/crypto.d.ts.map +0 -1
- package/.medusa/server/src/modules/paypal/utils/crypto.js +0 -47
- package/.medusa/server/src/modules/paypal/utils/crypto.js.map +0 -1
- package/src/api/admin/paypal/rotate-credentials/route.ts +0 -8
- package/src/jobs/paypal-reconcile.ts +0 -113
- package/src/modules/paypal/utils/crypto.ts +0 -51
|
@@ -3,54 +3,77 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.POST = POST;
|
|
4
4
|
const webhook_processor_1 = require("../../../../modules/paypal/webhook-processor");
|
|
5
5
|
const REPLAY_WINDOW_MINUTES = (() => {
|
|
6
|
-
const
|
|
7
|
-
return Number.isFinite(
|
|
6
|
+
const v = Number(process.env.PAYPAL_WEBHOOK_REPLAY_WINDOW_MINUTES);
|
|
7
|
+
return Number.isFinite(v) && v > 0 ? v : 60;
|
|
8
8
|
})();
|
|
9
9
|
function getHeader(headers, name) {
|
|
10
10
|
const direct = headers[name];
|
|
11
|
-
if (Array.isArray(direct))
|
|
11
|
+
if (Array.isArray(direct))
|
|
12
12
|
return direct[0];
|
|
13
|
-
|
|
14
|
-
if (typeof direct === "string") {
|
|
13
|
+
if (typeof direct === "string")
|
|
15
14
|
return direct;
|
|
15
|
+
const lower = name.toLowerCase();
|
|
16
|
+
const key = Object.keys(headers).find((h) => h.toLowerCase() === lower);
|
|
17
|
+
if (!key)
|
|
18
|
+
return undefined;
|
|
19
|
+
const val = headers[key];
|
|
20
|
+
return Array.isArray(val) ? val[0] : val;
|
|
21
|
+
}
|
|
22
|
+
function validateRequest(req) {
|
|
23
|
+
const payload = (req.body || {});
|
|
24
|
+
const eventId = String(payload?.id || payload?.event_id || "").trim();
|
|
25
|
+
const eventType = String(payload?.event_type || payload?.eventType || "").trim();
|
|
26
|
+
if (!eventId || !eventType) {
|
|
27
|
+
return { ok: false, status: 400, message: "Missing required fields: id and event_type" };
|
|
16
28
|
}
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
29
|
+
const transmissionTimeHeader = getHeader(req.headers, "paypal-transmission-time");
|
|
30
|
+
if (!transmissionTimeHeader) {
|
|
31
|
+
return {
|
|
32
|
+
ok: false,
|
|
33
|
+
status: 400,
|
|
34
|
+
message: "Missing required header: paypal-transmission-time",
|
|
35
|
+
};
|
|
22
36
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
37
|
+
const transmissionMs = Date.parse(transmissionTimeHeader);
|
|
38
|
+
if (!Number.isFinite(transmissionMs)) {
|
|
39
|
+
return {
|
|
40
|
+
ok: false,
|
|
41
|
+
status: 400,
|
|
42
|
+
message: "Invalid paypal-transmission-time header value",
|
|
43
|
+
};
|
|
29
44
|
}
|
|
30
|
-
const
|
|
31
|
-
if (
|
|
32
|
-
|
|
45
|
+
const ageMs = Math.abs(Date.now() - transmissionMs);
|
|
46
|
+
if (ageMs > REPLAY_WINDOW_MINUTES * 60 * 1000) {
|
|
47
|
+
return {
|
|
48
|
+
ok: false,
|
|
49
|
+
status: 400,
|
|
50
|
+
message: `Webhook rejected: outside ${REPLAY_WINDOW_MINUTES}-minute replay window`,
|
|
51
|
+
};
|
|
33
52
|
}
|
|
34
|
-
|
|
35
|
-
|
|
53
|
+
return {
|
|
54
|
+
ok: true,
|
|
55
|
+
eventId,
|
|
56
|
+
eventType,
|
|
57
|
+
transmissionId: getHeader(req.headers, "paypal-transmission-id") || null,
|
|
58
|
+
transmissionTime: new Date(transmissionMs),
|
|
59
|
+
};
|
|
36
60
|
}
|
|
37
61
|
function resolveWebhookId(environment, settings) {
|
|
38
62
|
const ids = (settings?.webhook_ids || {});
|
|
39
|
-
const legacyLive = settings?.webhook_id_live;
|
|
40
|
-
const legacySandbox = settings?.webhook_id_sandbox;
|
|
41
63
|
if (environment === "live") {
|
|
42
|
-
return ids.live ||
|
|
64
|
+
return (ids.live ||
|
|
65
|
+
settings?.webhook_id_live ||
|
|
66
|
+
process.env.PAYPAL_WEBHOOK_ID_LIVE);
|
|
43
67
|
}
|
|
44
|
-
return ids.sandbox ||
|
|
68
|
+
return (ids.sandbox ||
|
|
69
|
+
settings?.webhook_id_sandbox ||
|
|
70
|
+
process.env.PAYPAL_WEBHOOK_ID_SANDBOX);
|
|
45
71
|
}
|
|
46
72
|
async function verifyWebhookSignature(paypal, environment, body, headers) {
|
|
47
|
-
if (isReplay(headers)) {
|
|
48
|
-
throw new Error("PayPal webhook replay protection triggered");
|
|
49
|
-
}
|
|
50
73
|
const settings = await paypal.getSettings().catch(() => ({ data: {} }));
|
|
51
74
|
const webhookId = resolveWebhookId(environment, settings?.data || {});
|
|
52
75
|
if (!webhookId) {
|
|
53
|
-
throw new Error(`
|
|
76
|
+
throw new Error(`PayPal webhook ID not configured for environment "${environment}". Set PAYPAL_WEBHOOK_ID_${environment.toUpperCase()} or configure it in admin settings.`);
|
|
54
77
|
}
|
|
55
78
|
const base = environment === "live"
|
|
56
79
|
? "https://api-m.paypal.com"
|
|
@@ -65,15 +88,11 @@ async function verifyWebhookSignature(paypal, environment, body, headers) {
|
|
|
65
88
|
webhook_id: webhookId,
|
|
66
89
|
webhook_event: body,
|
|
67
90
|
};
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
verifyPayload.transmission_time,
|
|
74
|
-
];
|
|
75
|
-
if (requiredHeaders.some((value) => !value)) {
|
|
76
|
-
throw new Error("Missing required PayPal webhook signature headers");
|
|
91
|
+
const missing = Object.entries(verifyPayload)
|
|
92
|
+
.filter(([k, v]) => k !== "webhook_id" && k !== "webhook_event" && !v)
|
|
93
|
+
.map(([k]) => k);
|
|
94
|
+
if (missing.length > 0) {
|
|
95
|
+
throw new Error(`Missing required PayPal webhook headers: ${missing.join(", ")}`);
|
|
77
96
|
}
|
|
78
97
|
const resp = await fetch(`${base}/v1/notifications/verify-webhook-signature`, {
|
|
79
98
|
method: "POST",
|
|
@@ -84,34 +103,53 @@ async function verifyWebhookSignature(paypal, environment, body, headers) {
|
|
|
84
103
|
body: JSON.stringify(verifyPayload),
|
|
85
104
|
});
|
|
86
105
|
const json = await resp.json().catch(() => ({}));
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
throw new Error(`PayPal
|
|
106
|
+
const debugId = resp.headers.get("paypal-debug-id") || json?.debug_id;
|
|
107
|
+
if (!resp.ok) {
|
|
108
|
+
throw new Error(`PayPal signature verification API error (${resp.status}): ${JSON.stringify(json)}` +
|
|
109
|
+
(debugId ? ` debug_id=${debugId}` : ""));
|
|
110
|
+
}
|
|
111
|
+
if (json?.verification_status !== "VERIFIED") {
|
|
112
|
+
throw new Error(`PayPal webhook signature not verified. Status: ${json?.verification_status}` +
|
|
113
|
+
(debugId ? ` debug_id=${debugId}` : ""));
|
|
90
114
|
}
|
|
91
115
|
}
|
|
92
116
|
async function POST(req, res) {
|
|
93
117
|
const paypal = req.scope.resolve("paypal_onboarding");
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
transmission_id: transmissionId,
|
|
110
|
-
});
|
|
111
|
-
if ((existingByTransmission || []).length > 0) {
|
|
118
|
+
const validation = validateRequest(req);
|
|
119
|
+
if (!validation.ok) {
|
|
120
|
+
console.warn("[PayPal] webhook: validation failed:", validation.message);
|
|
121
|
+
return res.status(validation.status).json({ message: validation.message });
|
|
122
|
+
}
|
|
123
|
+
const { eventId, eventType, transmissionId, transmissionTime } = validation;
|
|
124
|
+
const payload = (req.body || {});
|
|
125
|
+
if (transmissionId) {
|
|
126
|
+
try {
|
|
127
|
+
const existing = await paypal.listPayPalWebhookEvents({ transmission_id: transmissionId });
|
|
128
|
+
if ((existing || []).length > 0) {
|
|
129
|
+
console.info("[PayPal] webhook: duplicate transmission_id", {
|
|
130
|
+
transmissionId,
|
|
131
|
+
eventId,
|
|
132
|
+
});
|
|
112
133
|
return res.json({ ok: true, duplicate: true });
|
|
113
134
|
}
|
|
114
135
|
}
|
|
136
|
+
catch (e) {
|
|
137
|
+
console.warn("[PayPal] webhook: transmission_id dedup check failed:", e?.message);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
try {
|
|
141
|
+
const creds = await paypal.getActiveCredentials();
|
|
142
|
+
await verifyWebhookSignature(paypal, creds.environment, payload, req.headers);
|
|
143
|
+
}
|
|
144
|
+
catch (e) {
|
|
145
|
+
console.error("[PayPal] webhook: signature verification failed:", e?.message);
|
|
146
|
+
return res
|
|
147
|
+
.status(401)
|
|
148
|
+
.json({ message: e?.message || "Webhook signature verification failed" });
|
|
149
|
+
}
|
|
150
|
+
const eventVersion = (0, webhook_processor_1.normalizeEventVersion)(payload);
|
|
151
|
+
let recordId = null;
|
|
152
|
+
try {
|
|
115
153
|
const recordResult = await paypal.createWebhookEventRecord({
|
|
116
154
|
event_id: eventId,
|
|
117
155
|
event_type: eventType,
|
|
@@ -123,81 +161,90 @@ async function POST(req, res) {
|
|
|
123
161
|
attempt_count: 1,
|
|
124
162
|
});
|
|
125
163
|
if (!recordResult.created) {
|
|
164
|
+
console.info("[PayPal] webhook: duplicate event_id", { eventId, eventType });
|
|
126
165
|
return res.json({ ok: true, duplicate: true });
|
|
127
166
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}
|
|
140
|
-
return res.json({ ok: true, ignored: true });
|
|
141
|
-
}
|
|
142
|
-
const processed = await (0, webhook_processor_1.processPayPalWebhookEvent)(req.scope, {
|
|
143
|
-
eventType,
|
|
144
|
-
payload,
|
|
167
|
+
recordId = recordResult.event?.id ?? null;
|
|
168
|
+
}
|
|
169
|
+
catch (e) {
|
|
170
|
+
console.error("[PayPal] webhook: failed to create DB record:", e?.message);
|
|
171
|
+
return res.status(500).json({ message: "Failed to record webhook event" });
|
|
172
|
+
}
|
|
173
|
+
if (!(0, webhook_processor_1.isAllowedEventType)(eventType)) {
|
|
174
|
+
console.info("[PayPal] webhook: unsupported event type, ignoring", { eventType });
|
|
175
|
+
await paypal.recordAuditEvent("webhook_unsupported_event", {
|
|
176
|
+
event_id: eventId,
|
|
177
|
+
event_type: eventType,
|
|
145
178
|
});
|
|
146
|
-
if (
|
|
147
|
-
await paypal
|
|
148
|
-
|
|
179
|
+
if (recordId) {
|
|
180
|
+
await paypal
|
|
181
|
+
.updateWebhookEventRecord({
|
|
182
|
+
id: recordId,
|
|
183
|
+
status: "ignored",
|
|
184
|
+
processed_at: new Date(),
|
|
185
|
+
})
|
|
186
|
+
.catch(() => { });
|
|
187
|
+
}
|
|
188
|
+
return res.json({ ok: true, ignored: true });
|
|
189
|
+
}
|
|
190
|
+
try {
|
|
191
|
+
const processed = await (0, webhook_processor_1.processPayPalWebhookEvent)(req.scope, { eventType, payload });
|
|
192
|
+
if (recordId) {
|
|
193
|
+
await paypal
|
|
194
|
+
.updateWebhookEventRecord({
|
|
195
|
+
id: recordId,
|
|
149
196
|
status: "processed",
|
|
150
197
|
processed_at: new Date(),
|
|
151
198
|
resource_id: processed.refundId || processed.captureId || processed.orderId || null,
|
|
152
|
-
})
|
|
199
|
+
})
|
|
200
|
+
.catch(() => { });
|
|
153
201
|
}
|
|
154
|
-
console.info("[PayPal] webhook", {
|
|
202
|
+
console.info("[PayPal] webhook: processed", {
|
|
155
203
|
event_id: eventId,
|
|
156
204
|
event_type: eventType,
|
|
157
205
|
order_id: processed.orderId,
|
|
158
206
|
capture_id: processed.captureId,
|
|
159
207
|
refund_id: processed.refundId,
|
|
160
208
|
cart_id: processed.cartId,
|
|
209
|
+
session_updated: processed.sessionUpdated,
|
|
161
210
|
});
|
|
162
|
-
|
|
163
|
-
await paypal.recordMetric("webhook_success");
|
|
164
|
-
}
|
|
165
|
-
catch {
|
|
166
|
-
// ignore metrics failures
|
|
167
|
-
}
|
|
211
|
+
await paypal.recordMetric("webhook_success").catch(() => { });
|
|
168
212
|
return res.json({ ok: true });
|
|
169
213
|
}
|
|
170
214
|
catch (e) {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
await paypal.recordAuditEvent("webhook_failed", {
|
|
190
|
-
event_id: payload?.id || payload?.event_id,
|
|
191
|
-
event_type: payload?.event_type || payload?.eventType,
|
|
192
|
-
message: e?.message || String(e),
|
|
193
|
-
});
|
|
194
|
-
await paypal.recordMetric("webhook_failed");
|
|
215
|
+
console.error("[PayPal] webhook: processing failed", {
|
|
216
|
+
event_id: eventId,
|
|
217
|
+
event_type: eventType,
|
|
218
|
+
error: e?.message,
|
|
219
|
+
});
|
|
220
|
+
const retryable = (0, webhook_processor_1.isRetryableError)(e);
|
|
221
|
+
const nextStatus = retryable ? "failed" : "dead_letter";
|
|
222
|
+
if (recordId) {
|
|
223
|
+
await paypal
|
|
224
|
+
.updateWebhookEventRecord({
|
|
225
|
+
id: recordId,
|
|
226
|
+
status: nextStatus,
|
|
227
|
+
attempt_count: 1,
|
|
228
|
+
next_retry_at: retryable ? (0, webhook_processor_1.computeNextRetryAt)(1) : null,
|
|
229
|
+
last_error: e?.message || String(e),
|
|
230
|
+
})
|
|
231
|
+
.catch(() => { });
|
|
195
232
|
}
|
|
196
|
-
|
|
197
|
-
|
|
233
|
+
await paypal
|
|
234
|
+
.recordAuditEvent("webhook_processing_failed", {
|
|
235
|
+
event_id: eventId,
|
|
236
|
+
event_type: eventType,
|
|
237
|
+
retryable,
|
|
238
|
+
message: e?.message || String(e),
|
|
239
|
+
})
|
|
240
|
+
.catch(() => { });
|
|
241
|
+
await paypal.recordMetric("webhook_failed").catch(() => { });
|
|
242
|
+
if (!retryable) {
|
|
243
|
+
return res.status(200).json({ ok: false, message: e?.message });
|
|
198
244
|
}
|
|
199
|
-
|
|
200
|
-
|
|
245
|
+
return res
|
|
246
|
+
.status(500)
|
|
247
|
+
.json({ message: e?.message || "PayPal webhook processing error" });
|
|
201
248
|
}
|
|
202
249
|
}
|
|
203
250
|
//# sourceMappingURL=route.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../../../../src/api/store/paypal/webhook/route.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../../../../src/api/store/paypal/webhook/route.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../src/api/store/paypal-complete/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAK7E,wBAAsB,IAAI,CAAC,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../src/api/store/paypal-complete/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAK7E,wBAAsB,IAAI,CAAC,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE,cAAc,2BAgEjE"}
|
|
@@ -8,7 +8,6 @@ async function POST(req, res) {
|
|
|
8
8
|
return res.status(400).json({ error: "cart_id is required" });
|
|
9
9
|
}
|
|
10
10
|
try {
|
|
11
|
-
// Step 1 — read paymentAction from DB settings (same pattern as capture-order)
|
|
12
11
|
const paypal = req.scope.resolve("paypal_onboarding");
|
|
13
12
|
const settings = await paypal.getSettings().catch(() => ({}));
|
|
14
13
|
const settingsData = settings && typeof settings === "object" && "data" in settings
|
|
@@ -18,11 +17,8 @@ async function POST(req, res) {
|
|
|
18
17
|
const paymentAction = typeof additionalSettings.paymentAction === "string"
|
|
19
18
|
? additionalSettings.paymentAction
|
|
20
19
|
: "capture";
|
|
21
|
-
// "authorize" mode → session status = "authorized"
|
|
22
|
-
// "capture" mode → session status = "captured"
|
|
23
20
|
const sessionStatus = paymentAction === "authorize" ? "authorized" : "captured";
|
|
24
21
|
const timestampKey = paymentAction === "authorize" ? "authorized_at" : "captured_at";
|
|
25
|
-
// Step 2 — find the PayPal session for this cart
|
|
26
22
|
const query = req.scope.resolve("query");
|
|
27
23
|
const { data: carts } = await query.graph({
|
|
28
24
|
entity: "cart",
|
|
@@ -44,7 +40,6 @@ async function POST(req, res) {
|
|
|
44
40
|
if (!session) {
|
|
45
41
|
return res.status(400).json({ error: "No PayPal payment session found for cart" });
|
|
46
42
|
}
|
|
47
|
-
// Step 3 — update session with correct status + amount
|
|
48
43
|
const paymentModule = req.scope.resolve(utils_1.Modules.PAYMENT);
|
|
49
44
|
await paymentModule.updatePaymentSession({
|
|
50
45
|
id: session.id,
|
|
@@ -53,7 +48,6 @@ async function POST(req, res) {
|
|
|
53
48
|
amount: session.amount,
|
|
54
49
|
currency_code: session.currency_code,
|
|
55
50
|
});
|
|
56
|
-
console.log(`[paypal-complete] session ${sessionStatus}:`, session.id);
|
|
57
51
|
return res.json({ success: true, session_id: session.id });
|
|
58
52
|
}
|
|
59
53
|
catch (e) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../../../src/api/store/paypal-complete/route.ts"],"names":[],"mappings":";;AAKA,
|
|
1
|
+
{"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../../../src/api/store/paypal-complete/route.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paypal-webhook-retry.d.ts","sourceRoot":"","sources":["../../../../src/jobs/paypal-webhook-retry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAUhE,wBAA8B,kBAAkB,CAAC,SAAS,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"paypal-webhook-retry.d.ts","sourceRoot":"","sources":["../../../../src/jobs/paypal-webhook-retry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAUhE,wBAA8B,kBAAkB,CAAC,SAAS,EAAE,eAAe,iBAqI1E;AAED,eAAO,MAAM,MAAM;;;CAGlB,CAAA"}
|
|
@@ -3,71 +3,125 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.config = void 0;
|
|
4
4
|
exports.default = paypalWebhookRetry;
|
|
5
5
|
const webhook_processor_1 = require("../modules/paypal/webhook-processor");
|
|
6
|
-
const MAX_WEBHOOK_ATTEMPTS = 5;
|
|
7
6
|
async function paypalWebhookRetry(container) {
|
|
8
7
|
const paypal = container.resolve("paypal_onboarding");
|
|
9
8
|
const now = Date.now();
|
|
10
9
|
const candidates = await paypal.listPayPalWebhookEvents({ status: "failed" });
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
if (!candidates?.length)
|
|
11
|
+
return;
|
|
12
|
+
console.info(`[PayPal] webhook-retry: evaluating ${candidates.length} failed event(s)`);
|
|
13
|
+
for (const event of candidates) {
|
|
14
|
+
const nextRetryAt = event?.next_retry_at
|
|
15
|
+
? new Date(event.next_retry_at).getTime()
|
|
16
|
+
: null;
|
|
17
|
+
if (!nextRetryAt || nextRetryAt > now)
|
|
14
18
|
continue;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
19
|
+
const attemptCount = Number(event.attempt_count || 0);
|
|
20
|
+
if (attemptCount >= webhook_processor_1.MAX_WEBHOOK_ATTEMPTS) {
|
|
21
|
+
await paypal
|
|
22
|
+
.updateWebhookEventRecord({
|
|
23
|
+
id: event.id,
|
|
24
|
+
status: "dead_letter",
|
|
25
|
+
next_retry_at: null,
|
|
26
|
+
last_error: `Exceeded max attempts (${webhook_processor_1.MAX_WEBHOOK_ATTEMPTS})`,
|
|
27
|
+
})
|
|
28
|
+
.catch(() => { });
|
|
29
|
+
console.warn("[PayPal] webhook-retry: dead-lettered (max attempts)", {
|
|
30
|
+
id: event.id,
|
|
31
|
+
event_type: event.event_type,
|
|
32
|
+
attempts: attemptCount,
|
|
33
|
+
});
|
|
34
|
+
await paypal.recordMetric("webhook_dead_letter").catch(() => { });
|
|
18
35
|
continue;
|
|
19
36
|
}
|
|
20
|
-
await paypal
|
|
37
|
+
await paypal
|
|
38
|
+
.updateWebhookEventRecord({
|
|
21
39
|
id: event.id,
|
|
22
40
|
status: "processing",
|
|
23
|
-
attempt_count: attemptCount,
|
|
41
|
+
attempt_count: attemptCount + 1,
|
|
24
42
|
next_retry_at: null,
|
|
25
43
|
last_error: null,
|
|
26
|
-
})
|
|
44
|
+
})
|
|
45
|
+
.catch(() => { });
|
|
46
|
+
const eventType = String(event.event_type || "");
|
|
47
|
+
if (!(0, webhook_processor_1.isAllowedEventType)(eventType)) {
|
|
48
|
+
await paypal
|
|
49
|
+
.updateWebhookEventRecord({
|
|
50
|
+
id: event.id,
|
|
51
|
+
status: "ignored",
|
|
52
|
+
processed_at: new Date(),
|
|
53
|
+
})
|
|
54
|
+
.catch(() => { });
|
|
55
|
+
console.info("[PayPal] webhook-retry: ignored unsupported event type", {
|
|
56
|
+
id: event.id,
|
|
57
|
+
event_type: eventType,
|
|
58
|
+
});
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
27
61
|
try {
|
|
28
|
-
const eventType = String(event.event_type || "");
|
|
29
|
-
if (!(0, webhook_processor_1.isAllowedEventType)(eventType)) {
|
|
30
|
-
await paypal.updateWebhookEventRecord({
|
|
31
|
-
id: event.id,
|
|
32
|
-
status: "ignored",
|
|
33
|
-
processed_at: new Date(),
|
|
34
|
-
});
|
|
35
|
-
continue;
|
|
36
|
-
}
|
|
37
62
|
const payload = (event.payload || {});
|
|
38
|
-
const processed = await (0, webhook_processor_1.processPayPalWebhookEvent)(container, {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
});
|
|
42
|
-
await paypal.updateWebhookEventRecord({
|
|
63
|
+
const processed = await (0, webhook_processor_1.processPayPalWebhookEvent)(container, { eventType, payload });
|
|
64
|
+
await paypal
|
|
65
|
+
.updateWebhookEventRecord({
|
|
43
66
|
id: event.id,
|
|
44
67
|
status: "processed",
|
|
45
68
|
processed_at: new Date(),
|
|
46
69
|
resource_id: processed.refundId || processed.captureId || processed.orderId || null,
|
|
70
|
+
})
|
|
71
|
+
.catch(() => { });
|
|
72
|
+
console.info("[PayPal] webhook-retry: processed successfully", {
|
|
73
|
+
id: event.id,
|
|
74
|
+
event_type: eventType,
|
|
75
|
+
attempt: attemptCount + 1,
|
|
76
|
+
order_id: processed.orderId,
|
|
77
|
+
capture_id: processed.captureId,
|
|
78
|
+
cart_id: processed.cartId,
|
|
79
|
+
session_updated: processed.sessionUpdated,
|
|
47
80
|
});
|
|
48
|
-
|
|
49
|
-
await paypal.recordMetric("webhook_retry_success");
|
|
50
|
-
}
|
|
51
|
-
catch {
|
|
52
|
-
// ignore metrics failures
|
|
53
|
-
}
|
|
81
|
+
await paypal.recordMetric("webhook_retry_success").catch(() => { });
|
|
54
82
|
}
|
|
55
83
|
catch (error) {
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
84
|
+
const retryable = (0, webhook_processor_1.isRetryableError)(error);
|
|
85
|
+
const nextAttempt = attemptCount + 1;
|
|
86
|
+
if (!retryable || nextAttempt >= webhook_processor_1.MAX_WEBHOOK_ATTEMPTS) {
|
|
87
|
+
await paypal
|
|
88
|
+
.updateWebhookEventRecord({
|
|
89
|
+
id: event.id,
|
|
90
|
+
status: "dead_letter",
|
|
91
|
+
attempt_count: nextAttempt,
|
|
92
|
+
next_retry_at: null,
|
|
93
|
+
last_error: error?.message || String(error),
|
|
94
|
+
})
|
|
95
|
+
.catch(() => { });
|
|
96
|
+
console.error("[PayPal] webhook-retry: dead-lettered after error", {
|
|
97
|
+
id: event.id,
|
|
98
|
+
event_type: eventType,
|
|
99
|
+
attempt: nextAttempt,
|
|
100
|
+
retryable,
|
|
101
|
+
error: error?.message,
|
|
102
|
+
});
|
|
103
|
+
await paypal.recordMetric("webhook_dead_letter").catch(() => { });
|
|
66
104
|
}
|
|
67
|
-
|
|
68
|
-
|
|
105
|
+
else {
|
|
106
|
+
const nextRetry = (0, webhook_processor_1.computeNextRetryAt)(nextAttempt);
|
|
107
|
+
await paypal
|
|
108
|
+
.updateWebhookEventRecord({
|
|
109
|
+
id: event.id,
|
|
110
|
+
status: "failed",
|
|
111
|
+
attempt_count: nextAttempt,
|
|
112
|
+
next_retry_at: nextRetry,
|
|
113
|
+
last_error: error?.message || String(error),
|
|
114
|
+
})
|
|
115
|
+
.catch(() => { });
|
|
116
|
+
console.warn("[PayPal] webhook-retry: scheduled retry", {
|
|
117
|
+
id: event.id,
|
|
118
|
+
event_type: eventType,
|
|
119
|
+
attempt: nextAttempt,
|
|
120
|
+
next_retry_at: nextRetry?.toISOString(),
|
|
121
|
+
error: error?.message,
|
|
122
|
+
});
|
|
123
|
+
await paypal.recordMetric("webhook_retry_failed").catch(() => { });
|
|
69
124
|
}
|
|
70
|
-
console.error("[PayPal] webhook retry error", error);
|
|
71
125
|
}
|
|
72
126
|
}
|
|
73
127
|
}
|