@easypayment/medusa-paypal 0.6.4 → 0.6.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.
@@ -38,7 +38,6 @@ function generateSessionId() {
38
38
  try {
39
39
  return randomUUID()
40
40
  } catch {
41
- // Fallback for environments where randomUUID isn't available
42
41
  return `pp_${Date.now()}_${Math.random().toString(16).slice(2)}`
43
42
  }
44
43
  }
@@ -64,65 +63,72 @@ class PayPalPaymentProvider extends AbstractPaymentProvider<Options> {
64
63
  }
65
64
  }
66
65
 
67
- async resolveSettings() {
68
- const paypal = this.resolvePayPalService();
66
+ async resolveSettings() {
67
+ const paypal = this.resolvePayPalService()
69
68
  if (!paypal) {
70
- try {
71
- const { Pool: _SettingsPool } = require("pg")
72
- const _sPool = new _SettingsPool({ connectionString: process.env.DATABASE_URL })
73
- const _sResult = await _sPool
74
- .query("SELECT data FROM paypal_settings ORDER BY created_at DESC LIMIT 1")
75
- .finally(() => _sPool.end())
76
- const _sData = _sResult.rows[0]?.data || {}
77
- return {
78
- additionalSettings: (_sData.additional_settings || {}) as Record<string, unknown>,
79
- apiDetails: (_sData.api_details || {}) as Record<string, unknown>,
80
- }
81
- } catch {
82
- return {
83
- additionalSettings: {} as Record<string, unknown>,
84
- apiDetails: {} as Record<string, unknown>,
85
- }
69
+ try {
70
+ const { Pool: _SettingsPool } = require("pg")
71
+ const _sPool = new _SettingsPool({ connectionString: process.env.DATABASE_URL })
72
+ const _sResult = await _sPool
73
+ .query("SELECT data FROM paypal_settings ORDER BY created_at DESC LIMIT 1")
74
+ .finally(() => _sPool.end())
75
+ const _sData = _sResult.rows[0]?.data || {}
76
+ return {
77
+ additionalSettings: (_sData.additional_settings || {}) as Record<string, unknown>,
78
+ apiDetails: (_sData.api_details || {}) as Record<string, unknown>,
86
79
  }
80
+ } catch {
81
+ return {
82
+ additionalSettings: {} as Record<string, unknown>,
83
+ apiDetails: {} as Record<string, unknown>,
84
+ }
85
+ }
87
86
  }
88
87
  const settings = await paypal.getSettings().catch(() => ({}))
89
- const data = settings && typeof settings === "object" && "data" in settings
88
+ const data =
89
+ settings && typeof settings === "object" && "data" in settings
90
90
  ? ((settings as any).data ?? {})
91
91
  : {}
92
92
  return {
93
- additionalSettings: (data.additional_settings || {}) as Record<string, unknown>,
94
- apiDetails: (data.api_details || {}) as Record<string, unknown>,
93
+ additionalSettings: (data.additional_settings || {}) as Record<string, unknown>,
94
+ apiDetails: (data.api_details || {}) as Record<string, unknown>,
95
95
  }
96
- }
96
+ }
97
97
 
98
98
  private async resolveCurrencyOverride() {
99
99
  const { apiDetails } = await this.resolveSettings()
100
- if (typeof apiDetails.currency_code === "string" && apiDetails.currency_code.trim()) {
101
- return normalizeCurrencyCode(apiDetails.currency_code)
100
+ if (typeof apiDetails.currency_code === "string" && (apiDetails.currency_code as string).trim()) {
101
+ return normalizeCurrencyCode(apiDetails.currency_code as string)
102
102
  }
103
103
  return normalizeCurrencyCode(process.env.PAYPAL_CURRENCY || "EUR")
104
104
  }
105
105
 
106
- private async getPayPalAccessToken() {
106
+ private async getPayPalAccessToken() {
107
107
  const paypal = this.resolvePayPalService()
108
108
  if (!paypal) {
109
- // Fallback: load credentials directly from paypal_connection table
110
109
  const { Pool: _FbPool } = require("pg")
111
110
  const _fbPool = new _FbPool({ connectionString: process.env.DATABASE_URL })
112
- const _fbResult = await _fbPool.query(
113
- "SELECT metadata, environment, seller_client_id, seller_client_secret FROM paypal_connection WHERE status='connected' ORDER BY created_at DESC LIMIT 1"
114
- ).finally(() => _fbPool.end())
111
+ const _fbResult = await _fbPool
112
+ .query(
113
+ "SELECT metadata, environment, seller_client_id, seller_client_secret FROM paypal_connection WHERE status='connected' ORDER BY created_at DESC LIMIT 1"
114
+ )
115
+ .finally(() => _fbPool.end())
115
116
  const _fbRow = _fbResult.rows[0]
116
117
  if (!_fbRow) throw new Error("No active PayPal connection found in DB")
117
118
  const _fbEnv = _fbRow.environment || "sandbox"
118
- const _fbCreds = (_fbRow.metadata && _fbRow.metadata.credentials && _fbRow.metadata.credentials[_fbEnv]) || {}
119
+ const _fbCreds =
120
+ (_fbRow.metadata && _fbRow.metadata.credentials && _fbRow.metadata.credentials[_fbEnv]) || {}
119
121
  const _fbId = _fbCreds.client_id || _fbRow.seller_client_id
120
122
  const _fbSec = _fbCreds.client_secret || _fbRow.seller_client_secret
121
- const _fbBase = _fbEnv === "live" ? "https://api-m.paypal.com" : "https://api-m.sandbox.paypal.com"
123
+ const _fbBase =
124
+ _fbEnv === "live" ? "https://api-m.paypal.com" : "https://api-m.sandbox.paypal.com"
122
125
  const _fbAuth = Buffer.from(`${_fbId}:${_fbSec}`).toString("base64")
123
126
  const _fbResp = await fetch(`${_fbBase}/v1/oauth2/token`, {
124
127
  method: "POST",
125
- headers: { Authorization: `Basic ${_fbAuth}`, "Content-Type": "application/x-www-form-urlencoded" },
128
+ headers: {
129
+ Authorization: `Basic ${_fbAuth}`,
130
+ "Content-Type": "application/x-www-form-urlencoded",
131
+ },
126
132
  body: "grant_type=client_credentials",
127
133
  })
128
134
  const _fbText = await _fbResp.text()
@@ -155,7 +161,6 @@ async resolveSettings() {
155
161
  return { accessToken: String(json.access_token), base }
156
162
  }
157
163
 
158
-
159
164
  private async getOrderDetails(orderId: string) {
160
165
  const { accessToken, base } = await this.getPayPalAccessToken()
161
166
  const resp = await fetch(`${base}/v2/checkout/orders/${orderId}`, {
@@ -174,7 +179,10 @@ async resolveSettings() {
174
179
  return JSON.parse(text)
175
180
  }
176
181
 
177
- private getIdempotencyKey(input: { context?: { idempotency_key?: string } }, suffix: string) {
182
+ private getIdempotencyKey(
183
+ input: { context?: { idempotency_key?: string } },
184
+ suffix: string
185
+ ) {
178
186
  const key = input?.context?.idempotency_key?.trim()
179
187
  if (key) {
180
188
  return `${key}-${suffix}`
@@ -198,47 +206,20 @@ async resolveSettings() {
198
206
 
199
207
  private mapCaptureStatus(status?: string) {
200
208
  const normalized = String(status || "").toUpperCase()
201
- if (!normalized) {
202
- return null
203
- }
204
-
205
- if (normalized === "COMPLETED") {
206
- return "captured"
207
- }
208
-
209
- if (normalized === "PENDING") {
210
- return "pending"
211
- }
212
-
213
- if (["DENIED", "DECLINED", "FAILED"].includes(normalized)) {
214
- return "error"
215
- }
216
-
217
- if (["REFUNDED", "PARTIALLY_REFUNDED", "REVERSED"].includes(normalized)) {
218
- return "canceled"
219
- }
220
-
209
+ if (!normalized) return null
210
+ if (normalized === "COMPLETED") return "captured"
211
+ if (normalized === "PENDING") return "pending"
212
+ if (["DENIED", "DECLINED", "FAILED"].includes(normalized)) return "error"
213
+ if (["REFUNDED", "PARTIALLY_REFUNDED", "REVERSED"].includes(normalized)) return "canceled"
221
214
  return null
222
215
  }
223
216
 
224
217
  private mapAuthorizationStatus(status?: string) {
225
218
  const normalized = String(status || "").toUpperCase()
226
- if (!normalized) {
227
- return null
228
- }
229
-
230
- if (["CREATED", "APPROVED", "PENDING"].includes(normalized)) {
231
- return "authorized"
232
- }
233
-
234
- if (["VOIDED", "EXPIRED"].includes(normalized)) {
235
- return "canceled"
236
- }
237
-
238
- if (["DENIED", "DECLINED", "FAILED"].includes(normalized)) {
239
- return "error"
240
- }
241
-
219
+ if (!normalized) return null
220
+ if (["CREATED", "APPROVED", "PENDING"].includes(normalized)) return "authorized"
221
+ if (["VOIDED", "EXPIRED"].includes(normalized)) return "canceled"
222
+ if (["DENIED", "DECLINED", "FAILED"].includes(normalized)) return "error"
242
223
  return null
243
224
  }
244
225
 
@@ -252,87 +233,53 @@ async resolveSettings() {
252
233
  stack: error.stack,
253
234
  cause:
254
235
  cause instanceof Error
255
- ? {
256
- name: cause.name,
257
- message: cause.message,
258
- stack: cause.stack,
259
- }
236
+ ? { name: cause.name, message: cause.message, stack: cause.stack }
260
237
  : cause,
261
238
  }
262
239
  }
263
-
264
- return {
265
- message: String(error),
266
- }
240
+ return { message: String(error) }
267
241
  }
268
242
 
269
243
  private mapOrderStatus(status?: string) {
270
244
  const normalized = String(status || "").toUpperCase()
271
- if (!normalized) {
272
- return "pending"
273
- }
274
-
275
- if (normalized === "COMPLETED") {
276
- return "captured"
277
- }
278
-
279
- if (normalized === "APPROVED") {
280
- return "authorized"
281
- }
282
-
283
- if (["VOIDED", "CANCELLED"].includes(normalized)) {
284
- return "canceled"
285
- }
286
-
287
- if (["CREATED", "SAVED", "PAYER_ACTION_REQUIRED"].includes(normalized)) {
288
- return "pending"
289
- }
290
-
291
- if (["FAILED", "EXPIRED"].includes(normalized)) {
292
- return "error"
293
- }
294
-
245
+ if (!normalized) return "pending"
246
+ if (normalized === "COMPLETED") return "captured"
247
+ if (normalized === "APPROVED") return "authorized"
248
+ if (["VOIDED", "CANCELLED"].includes(normalized)) return "canceled"
249
+ if (["CREATED", "SAVED", "PAYER_ACTION_REQUIRED"].includes(normalized)) return "pending"
250
+ if (["FAILED", "EXPIRED"].includes(normalized)) return "error"
295
251
  return "pending"
296
252
  }
297
253
 
298
254
  private async recordFailure(eventType: string, metadata?: Record<string, unknown>) {
299
255
  const paypal = this.resolvePayPalService()
300
- if (!paypal) {
301
- return
302
- }
303
-
256
+ if (!paypal) return
304
257
  try {
305
258
  await paypal.recordPaymentLog(eventType, metadata)
306
259
  await paypal.recordAuditEvent(eventType, metadata)
307
260
  await paypal.recordMetric(eventType)
308
261
  } catch {
309
- // ignore audit logging failures
262
+ // ignore
310
263
  }
311
264
  }
312
265
 
313
266
  private async recordSuccess(metricName: string) {
314
267
  const paypal = this.resolvePayPalService()
315
- if (!paypal) {
316
- return
317
- }
318
-
268
+ if (!paypal) return
319
269
  try {
320
270
  await paypal.recordMetric(metricName)
321
271
  } catch {
322
- // ignore metrics failures
272
+ // ignore
323
273
  }
324
274
  }
325
275
 
326
276
  private async recordPaymentEvent(eventType: string, metadata?: Record<string, unknown>) {
327
277
  const paypal = this.resolvePayPalService()
328
- if (!paypal) {
329
- return
330
- }
331
-
278
+ if (!paypal) return
332
279
  try {
333
280
  await paypal.recordPaymentLog(eventType, metadata)
334
281
  } catch {
335
- // ignore payment logging failures
282
+ // ignore
336
283
  }
337
284
  }
338
285
 
@@ -341,7 +288,6 @@ async resolveSettings() {
341
288
  ): Promise<CreateAccountHolderOutput> {
342
289
  const customerId = input.context?.customer?.id
343
290
  const externalId = customerId ? `paypal_${customerId}` : `paypal_${generateSessionId()}`
344
-
345
291
  return {
346
292
  id: externalId,
347
293
  data: {
@@ -351,13 +297,7 @@ async resolveSettings() {
351
297
  }
352
298
  }
353
299
 
354
- /**
355
- * Create a payment session when the customer selects PayPal.
356
- * Must return an object containing an `id` and `data`.
357
- */
358
- async initiatePayment(
359
- input: InitiatePaymentInput
360
- ): Promise<InitiatePaymentOutput> {
300
+ async initiatePayment(input: InitiatePaymentInput): Promise<InitiatePaymentOutput> {
361
301
  const providerId = (input.data as Record<string, any> | undefined)?.provider_id
362
302
  try {
363
303
  const currencyOverride = await this.resolveCurrencyOverride()
@@ -368,8 +308,6 @@ async resolveSettings() {
368
308
  currencyCode,
369
309
  paypalCurrencyOverride: currencyOverride,
370
310
  })
371
-
372
-
373
311
  return {
374
312
  id: generateSessionId(),
375
313
  data: {
@@ -380,15 +318,6 @@ async resolveSettings() {
380
318
  },
381
319
  }
382
320
  } catch (error) {
383
- console.error("[PayPal] provider initiate failed", {
384
- provider_id: providerId,
385
- payment_collection_id: (input.data as Record<string, any> | undefined)
386
- ?.payment_collection_id,
387
- cart_id: (input.data as Record<string, any> | undefined)?.cart_id,
388
- amount: input.amount,
389
- currency_code: input.currency_code,
390
- error: this.serializeError(error),
391
- })
392
321
  await this.recordFailure("initiate_failed", {
393
322
  error: this.serializeError(error),
394
323
  currency_code: input.currency_code,
@@ -409,9 +338,7 @@ async resolveSettings() {
409
338
  currencyCode,
410
339
  paypalCurrencyOverride: currencyOverride,
411
340
  })
412
-
413
341
  const providerId = (input.data as Record<string, any> | undefined)?.provider_id
414
-
415
342
  return {
416
343
  data: {
417
344
  ...(input.data || {}),
@@ -426,104 +353,152 @@ async resolveSettings() {
426
353
  input: AuthorizePaymentInput
427
354
  ): Promise<AuthorizePaymentOutput> {
428
355
  const { data, amount, currencyCode } = await this.normalizePaymentData(input)
429
-
430
356
  const existingPayPal = (data.paypal || {}) as Record<string, any>
431
- if (
432
- existingPayPal.capture_id ||
433
- existingPayPal.authorization_id ||
434
- (data as any).authorized_at ||
435
- (data as any).captured_at
436
- ) {
437
- const { additionalSettings } = await this.resolveSettings()
438
- const paymentAction =
439
- typeof additionalSettings.paymentAction === "string"
440
- ? additionalSettings.paymentAction
441
- : "capture"
442
- const returnStatus = paymentAction === "authorize" ? "authorized" : "captured"
443
- return {
444
- status: returnStatus,
445
- data: {
446
- ...(input.data || {}),
447
- ...(paymentAction === "authorize"
448
- ? { authorized_at: new Date().toISOString() }
449
- : { captured_at: new Date().toISOString() }),
450
- },
451
- }
452
- }
453
-
454
357
 
455
- const requestId = this.getIdempotencyKey(input, "authorize")
456
- let debugId: string | null = null
457
358
  const { additionalSettings } = await this.resolveSettings()
458
359
  const paymentActionRaw =
459
360
  typeof additionalSettings.paymentAction === "string"
460
361
  ? additionalSettings.paymentAction
461
362
  : "capture"
462
- const orderIntent = paymentActionRaw === "authorize" ? "AUTHORIZE" : "CAPTURE"
463
-
464
- try {
465
- const { accessToken, base } = await this.getPayPalAccessToken()
466
- const existingPayPal = (data.paypal || {}) as Record<string, any>
467
- let orderId = String(existingPayPal.order_id || data.order_id || "")
468
- let order: Record<string, any> | null = null
469
- let authorization: any = null
363
+ const returnStatus = paymentActionRaw === "authorize" ? "authorized" : "captured"
364
+ const timestampKey = paymentActionRaw === "authorize" ? "authorized_at" : "captured_at"
365
+
366
+ // ── CASE 1: Already processed (has capture_id, authorization_id, or timestamp) ──
367
+ if (
368
+ existingPayPal.capture_id ||
369
+ existingPayPal.authorization_id ||
370
+ (data as any).authorized_at ||
371
+ (data as any).captured_at
372
+ ) {
373
+ console.info("[PayPal] authorizePayment: session already processed, returning", returnStatus)
374
+ return {
375
+ status: returnStatus,
376
+ data: {
377
+ ...(input.data || {}),
378
+ [timestampKey]: (data as any)[timestampKey] || new Date().toISOString(),
379
+ },
380
+ }
381
+ }
470
382
 
471
- if (!orderId) {
472
- const value = formatAmountForPayPal(amount, currencyCode || "EUR")
383
+ // ── CASE 2: Has order_id — fetch current status from PayPal ──────────────
384
+ // This is the KEY fix: capture-order already processed the payment but
385
+ // Medusa's cart/complete workflow calls authorizePayment again with the
386
+ // original session data (before capture-order wrote authorization_id).
387
+ // We fetch the live PayPal order to get the real status.
388
+ const orderId = String(existingPayPal.order_id || data.order_id || "")
389
+ if (orderId) {
390
+ try {
391
+ console.info("[PayPal] authorizePayment: fetching live order status for", orderId)
392
+ const order = await this.getOrderDetails(orderId)
393
+ const capture = order?.purchase_units?.[0]?.payments?.captures?.[0]
394
+ const authorization = order?.purchase_units?.[0]?.payments?.authorizations?.[0]
395
+
396
+ // Order was already captured or authorized by capture-order route
397
+ if (capture?.id || authorization?.id) {
398
+ console.info("[PayPal] authorizePayment: order already processed by PayPal, returning", returnStatus)
399
+ return {
400
+ status: returnStatus,
401
+ data: {
402
+ ...(input.data || {}),
403
+ paypal: {
404
+ ...existingPayPal,
405
+ order_id: orderId,
406
+ order,
407
+ authorization_id: authorization?.id || existingPayPal.authorization_id,
408
+ capture_id: capture?.id || existingPayPal.capture_id,
409
+ },
410
+ [timestampKey]: new Date().toISOString(),
411
+ },
412
+ }
413
+ }
473
414
 
474
- const orderPayload = {
475
- intent: orderIntent,
476
- purchase_units: [
477
- {
478
- reference_id: data.cart_id || data.payment_collection_id || undefined,
479
- custom_id: data.session_id || data.cart_id || data.payment_collection_id || undefined,
480
- amount: {
481
- currency_code: currencyCode || "EUR",
482
- value,
415
+ // Order exists and is APPROVED — customer completed PayPal flow
416
+ // but capture-order hasn't run yet (edge case). Mark as authorized.
417
+ if (["APPROVED", "CREATED", "SAVED"].includes(String(order?.status || "").toUpperCase())) {
418
+ console.info("[PayPal] authorizePayment: order approved, marking authorized")
419
+ return {
420
+ status: "authorized",
421
+ data: {
422
+ ...(input.data || {}),
423
+ paypal: {
424
+ ...existingPayPal,
425
+ order_id: orderId,
426
+ order,
483
427
  },
428
+ authorized_at: new Date().toISOString(),
484
429
  },
485
- ],
486
- custom_id: data.session_id || data.cart_id || data.payment_collection_id || undefined,
430
+ }
487
431
  }
432
+ } catch (e: any) {
433
+ // Non-fatal — log and fall through to creating a new order below
434
+ console.warn("[PayPal] authorizePayment: order lookup failed:", e?.message)
435
+ }
436
+ }
488
437
 
489
- const ppResp = await fetch(`${base}/v2/checkout/orders`, {
490
- method: "POST",
491
- headers: {
492
- Authorization: `Bearer ${accessToken}`,
493
- "Content-Type": "application/json",
494
- "PayPal-Request-Id": requestId,
438
+ // ── CASE 3: No order_id — create a new PayPal order ──────────────────────
439
+ // This handles the rare case where Medusa calls authorizePayment before
440
+ // the frontend has created a PayPal order (e.g. admin-created orders).
441
+ const requestId = this.getIdempotencyKey(input, "authorize")
442
+ let debugId: string | null = null
443
+ const orderIntent = paymentActionRaw === "authorize" ? "AUTHORIZE" : "CAPTURE"
444
+
445
+ try {
446
+ const { accessToken, base } = await this.getPayPalAccessToken()
447
+ const value = formatAmountForPayPal(amount, currencyCode || "EUR")
448
+
449
+ const orderPayload = {
450
+ intent: orderIntent,
451
+ purchase_units: [
452
+ {
453
+ reference_id: data.cart_id || data.payment_collection_id || undefined,
454
+ custom_id:
455
+ data.session_id || data.cart_id || data.payment_collection_id || undefined,
456
+ amount: {
457
+ currency_code: currencyCode || "EUR",
458
+ value,
459
+ },
495
460
  },
496
- body: JSON.stringify(orderPayload),
497
- })
461
+ ],
462
+ custom_id:
463
+ data.session_id || data.cart_id || data.payment_collection_id || undefined,
464
+ }
498
465
 
499
- const ppText = await ppResp.text()
500
- debugId = ppResp.headers.get("paypal-debug-id")
501
- if (!ppResp.ok) {
502
- throw new Error(
503
- `PayPal create order error (${ppResp.status}): ${ppText}${
504
- debugId ? ` debug_id=${debugId}` : ""
505
- }`
506
- )
507
- }
466
+ const ppResp = await fetch(`${base}/v2/checkout/orders`, {
467
+ method: "POST",
468
+ headers: {
469
+ Authorization: `Bearer ${accessToken}`,
470
+ "Content-Type": "application/json",
471
+ "PayPal-Request-Id": requestId,
472
+ },
473
+ body: JSON.stringify(orderPayload),
474
+ })
508
475
 
509
- order = JSON.parse(ppText) as Record<string, any>
510
- orderId = String(order.id || "")
511
- } else {
512
- order = (await this.getOrderDetails(orderId)) as Record<string, any> | null
476
+ const ppText = await ppResp.text()
477
+ debugId = ppResp.headers.get("paypal-debug-id")
478
+ if (!ppResp.ok) {
479
+ throw new Error(
480
+ `PayPal create order error (${ppResp.status}): ${ppText}${
481
+ debugId ? ` debug_id=${debugId}` : ""
482
+ }`
483
+ )
513
484
  }
514
485
 
515
- if (!order || !orderId) {
486
+ const order = JSON.parse(ppText) as Record<string, any>
487
+ const newOrderId = String(order.id || "")
488
+
489
+ if (!order || !newOrderId) {
516
490
  throw new Error("Unable to resolve PayPal order details for authorization.")
517
491
  }
518
492
 
519
493
  const existingAuthorization =
520
494
  order?.purchase_units?.[0]?.payments?.authorizations?.[0] || null
521
495
 
496
+ let authorization: any = null
522
497
  if (existingAuthorization) {
523
498
  authorization = order
524
499
  } else {
525
500
  const authorizeResp = await fetch(
526
- `${base}/v2/checkout/orders/${orderId}/authorize`,
501
+ `${base}/v2/checkout/orders/${newOrderId}/authorize`,
527
502
  {
528
503
  method: "POST",
529
504
  headers: {
@@ -553,7 +528,7 @@ if (
553
528
 
554
529
  await this.recordSuccess("authorize_success")
555
530
  await this.recordPaymentEvent("authorize", {
556
- order_id: orderId,
531
+ order_id: newOrderId,
557
532
  authorization_id: authorizationId,
558
533
  amount,
559
534
  currency_code: currencyCode,
@@ -566,7 +541,7 @@ if (
566
541
  ...(input.data || {}),
567
542
  paypal: {
568
543
  ...((input.data || {}).paypal as Record<string, unknown>),
569
- order_id: orderId,
544
+ order_id: newOrderId,
570
545
  order: order || authorization,
571
546
  authorization_id: authorizationId,
572
547
  authorizations:
@@ -587,9 +562,7 @@ if (
587
562
  }
588
563
  }
589
564
 
590
- async retrievePayment(
591
- input: RetrievePaymentInput
592
- ): Promise<RetrievePaymentOutput> {
565
+ async retrievePayment(input: RetrievePaymentInput): Promise<RetrievePaymentOutput> {
593
566
  const data = (input.data || {}) as Record<string, any>
594
567
  const paypalData = (data.paypal || {}) as Record<string, any>
595
568
  const orderId = String(paypalData.order_id || data.order_id || "")
@@ -614,9 +587,7 @@ if (
614
587
  }
615
588
  }
616
589
 
617
- async getPaymentStatus(
618
- input: GetPaymentStatusInput
619
- ): Promise<GetPaymentStatusOutput> {
590
+ async getPaymentStatus(input: GetPaymentStatusInput): Promise<GetPaymentStatusOutput> {
620
591
  const data = (input.data || {}) as Record<string, any>
621
592
  const paypalData = (data.paypal || {}) as Record<string, any>
622
593
  const orderId = String(paypalData.order_id || data.order_id || "")
@@ -656,9 +627,7 @@ if (
656
627
  }
657
628
  }
658
629
 
659
- async capturePayment(
660
- input: CapturePaymentInput
661
- ): Promise<CapturePaymentOutput> {
630
+ async capturePayment(input: CapturePaymentInput): Promise<CapturePaymentOutput> {
662
631
  const data = (input.data || {}) as Record<string, any>
663
632
  const paypalData = (data.paypal || {}) as Record<string, any>
664
633
  const orderId = String(paypalData.order_id || data.order_id || "")
@@ -704,9 +673,11 @@ if (
704
673
  },
705
674
  }
706
675
  }
676
+
707
677
  const resolvedIntent = String(
708
678
  order?.intent || paypalData.order?.intent || data.intent || ""
709
679
  ).toUpperCase()
680
+
710
681
  if (!authorizationId && resolvedIntent === "AUTHORIZE") {
711
682
  const authorizeResp = await fetch(
712
683
  `${base}/v2/checkout/orders/${orderId}/authorize`,
@@ -782,9 +753,7 @@ if (
782
753
  const capture = JSON.parse(ppText)
783
754
  const captureId =
784
755
  capture?.id || capture?.purchase_units?.[0]?.payments?.captures?.[0]?.id
785
- const existingCaptures = Array.isArray(paypalData.captures)
786
- ? paypalData.captures
787
- : []
756
+ const existingCaptures = Array.isArray(paypalData.captures) ? paypalData.captures : []
788
757
  const captureEntry = {
789
758
  id: captureId,
790
759
  status: capture?.status,
@@ -827,9 +796,7 @@ if (
827
796
  }
828
797
  }
829
798
 
830
- async refundPayment(
831
- input: RefundPaymentInput
832
- ): Promise<RefundPaymentOutput> {
799
+ async refundPayment(input: RefundPaymentInput): Promise<RefundPaymentOutput> {
833
800
  const data = (input.data || {}) as Record<string, any>
834
801
  const paypalData = (data.paypal || {}) as Record<string, any>
835
802
  const captureId = String(paypalData.capture_id || data.capture_id || "")
@@ -936,9 +903,7 @@ if (
936
903
  }
937
904
  }
938
905
 
939
- async cancelPayment(
940
- input: CancelPaymentInput
941
- ): Promise<CancelPaymentOutput> {
906
+ async cancelPayment(input: CancelPaymentInput): Promise<CancelPaymentOutput> {
942
907
  const data = (input.data || {}) as Record<string, any>
943
908
  const paypalData = (data.paypal || {}) as Record<string, any>
944
909
  const orderId = String(paypalData.order_id || data.order_id || "")
@@ -985,7 +950,6 @@ if (
985
950
  await this.recordPaymentEvent("void", {
986
951
  order_id: orderId,
987
952
  authorization_id: authorizationId,
988
- request_id: requestId,
989
953
  })
990
954
  } else if (captureId) {
991
955
  const { accessToken, base } = await this.getPayPalAccessToken()
@@ -1024,12 +988,6 @@ if (
1024
988
  paypalData.refunds = [...existingRefunds, refundEntry]
1025
989
 
1026
990
  await this.recordSuccess("cancel_refund_success")
1027
- await this.recordPaymentEvent("cancel_refund", {
1028
- order_id: orderId,
1029
- capture_id: captureId,
1030
- refund_id: refund?.id,
1031
- request_id: requestId,
1032
- })
1033
991
  }
1034
992
 
1035
993
  return {
@@ -1058,16 +1016,10 @@ if (
1058
1016
  }
1059
1017
  }
1060
1018
 
1061
- async deletePayment(
1062
- _input: DeletePaymentInput
1063
- ): Promise<DeletePaymentOutput> {
1019
+ async deletePayment(_input: DeletePaymentInput): Promise<DeletePaymentOutput> {
1064
1020
  return { data: {} }
1065
1021
  }
1066
1022
 
1067
- /**
1068
- * Required by AbstractPaymentProvider in Medusa v2.
1069
- * This is used by /hooks/payment/{identifier}_{providerId}
1070
- */
1071
1023
  async getWebhookActionAndData(
1072
1024
  payload: ProviderWebhookPayload["payload"]
1073
1025
  ): Promise<WebhookActionResult> {