@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.
@@ -11,21 +11,6 @@ export async function POST(req: MedusaRequest, res: MedusaResponse) {
11
11
  }
12
12
 
13
13
  try {
14
- const paypal = req.scope.resolve<PayPalModuleService>("paypal_onboarding")
15
- const settings = await paypal.getSettings().catch(() => ({}))
16
- const settingsData =
17
- settings && typeof settings === "object" && "data" in settings
18
- ? ((settings as { data?: Record<string, any> }).data ?? {})
19
- : {}
20
- const additionalSettings = (settingsData.additional_settings || {}) as Record<string, any>
21
- const paymentAction =
22
- typeof additionalSettings.paymentAction === "string"
23
- ? additionalSettings.paymentAction
24
- : "capture"
25
-
26
- const sessionStatus = paymentAction === "authorize" ? "authorized" : "captured"
27
- const timestampKey = paymentAction === "authorize" ? "authorized_at" : "captured_at"
28
-
29
14
  const query = req.scope.resolve("query")
30
15
  const { data: carts } = await query.graph({
31
16
  entity: "cart",
@@ -33,6 +18,7 @@ export async function POST(req: MedusaRequest, res: MedusaResponse) {
33
18
  "id",
34
19
  "payment_collection.payment_sessions.id",
35
20
  "payment_collection.payment_sessions.data",
21
+ "payment_collection.payment_sessions.status",
36
22
  "payment_collection.payment_sessions.provider_id",
37
23
  "payment_collection.payment_sessions.created_at",
38
24
  "payment_collection.payment_sessions.amount",
@@ -53,18 +39,67 @@ export async function POST(req: MedusaRequest, res: MedusaResponse) {
53
39
  return res.status(400).json({ error: "No PayPal payment session found for cart" })
54
40
  }
55
41
 
42
+ // If already authorized or captured, nothing to do
43
+ const currentStatus = String(session.status || "")
44
+ if (currentStatus === "authorized" || currentStatus === "captured") {
45
+ console.info("[paypal-complete] session already in terminal status:", currentStatus)
46
+ return res.json({ success: true, session_id: session.id, status: currentStatus })
47
+ }
48
+
56
49
  const paymentModule = req.scope.resolve(Modules.PAYMENT) as IPaymentModuleService
57
- await (paymentModule as any).updatePaymentSession({
58
- id: session.id,
59
- data: { ...(session.data || {}), [timestampKey]: new Date().toISOString() },
60
- status: sessionStatus as any,
61
- amount: session.amount,
62
- currency_code: session.currency_code,
63
- })
50
+
51
+ // Read LIVE session data from DB — gets the latest state written by capture-order
52
+ // (avoids overwriting authorization_id / capture_id that capture-order just saved)
53
+ const [liveSession] = await paymentModule.listPaymentSessions(
54
+ { id: [session.id] },
55
+ { take: 1 }
56
+ )
57
+
58
+ const liveData = (liveSession?.data || {}) as Record<string, any>
59
+
60
+ // Determine payment action from settings
61
+ const paypal = req.scope.resolve<PayPalModuleService>("paypal_onboarding")
62
+ const settings = await paypal.getSettings().catch(() => ({}))
63
+ const settingsData =
64
+ settings && typeof settings === "object" && "data" in settings
65
+ ? ((settings as { data?: Record<string, any> }).data ?? {})
66
+ : {}
67
+ const additionalSettings = (settingsData.additional_settings || {}) as Record<string, any>
68
+ const paymentAction =
69
+ typeof additionalSettings.paymentAction === "string"
70
+ ? additionalSettings.paymentAction
71
+ : "capture"
72
+
73
+ const timestampKey = paymentAction === "authorize" ? "authorized_at" : "captured_at"
74
+
75
+ // Only write timestamp if not already present — avoids overwriting capture-order's data
76
+ if (!liveData[timestampKey]) {
77
+ await (paymentModule as any).updatePaymentSession({
78
+ id: session.id,
79
+ data: {
80
+ ...liveData,
81
+ [timestampKey]: new Date().toISOString(),
82
+ },
83
+ amount: liveSession?.amount ?? session.amount,
84
+ currency_code: liveSession?.currency_code ?? session.currency_code,
85
+ })
86
+ }
87
+
88
+ // Trigger Medusa's payment state machine — the only correct way to move
89
+ // a session from "pending" → "authorized".
90
+ // Calls the provider's authorizePayment() which checks for
91
+ // authorization_id / authorized_at in data and returns status: "authorized".
92
+ try {
93
+ await (paymentModule as any).authorizePaymentSession(session.id, {})
94
+ console.info("[paypal-complete] authorizePaymentSession succeeded for session", session.id)
95
+ } catch (e: any) {
96
+ // Throws if session is already authorized/captured — that's expected and fine
97
+ console.warn("[paypal-complete] authorizePaymentSession non-fatal:", e?.message)
98
+ }
64
99
 
65
100
  return res.json({ success: true, session_id: session.id })
66
101
  } catch (e: any) {
67
102
  console.error("[paypal-complete] error:", e?.message || e)
68
103
  return res.status(500).json({ error: e?.message || "Internal error" })
69
104
  }
70
- }
105
+ }