@easypayment/medusa-paypal 0.6.6 → 0.6.8

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.
@@ -0,0 +1,115 @@
1
+ import type { SubscriberArgs, SubscriberConfig } from "@medusajs/framework"
2
+ import type PayPalModuleService from "../modules/paypal/service"
3
+ import { getPayPalAccessToken } from "../modules/paypal/utils/paypal-auth"
4
+ import { isPayPalProviderId } from "../modules/paypal/utils/provider-ids"
5
+
6
+ export default async function paypalOrderInvoiceHandler({
7
+ event,
8
+ container,
9
+ }: SubscriberArgs<{ id: string }>) {
10
+ const orderId = event?.data?.id
11
+ if (!orderId) return
12
+
13
+ try {
14
+ const query = container.resolve("query") as any
15
+ const paypal = container.resolve<PayPalModuleService>("paypal_onboarding")
16
+
17
+ // Fetch the order with payment session data
18
+ const { data: orders } = await query.graph({
19
+ entity: "order",
20
+ fields: [
21
+ "id",
22
+ "display_id",
23
+ "payment_collections.payment_sessions.id",
24
+ "payment_collections.payment_sessions.data",
25
+ "payment_collections.payment_sessions.provider_id",
26
+ "payment_collections.payment_sessions.status",
27
+ "payment_collections.payment_sessions.created_at",
28
+ ],
29
+ filters: { id: orderId },
30
+ })
31
+
32
+ const order = orders?.[0]
33
+ if (!order) return
34
+
35
+ // Find the PayPal session
36
+ const sessions = (order.payment_collections || []).flatMap(
37
+ (pc: any) => pc.payment_sessions || []
38
+ )
39
+
40
+ const paypalSession = sessions
41
+ .filter((s: any) => isPayPalProviderId(s.provider_id))
42
+ .sort(
43
+ (a: any, b: any) =>
44
+ new Date(b.created_at || 0).getTime() -
45
+ new Date(a.created_at || 0).getTime()
46
+ )[0]
47
+
48
+ if (!paypalSession) {
49
+ console.info("[PayPal] invoice subscriber: no PayPal session found for order", orderId)
50
+ return
51
+ }
52
+
53
+ const paypalData = ((paypalSession.data || {}).paypal || {}) as Record<string, any>
54
+ const paypalOrderId = String(paypalData.order_id || "")
55
+ if (!paypalOrderId) {
56
+ console.info("[PayPal] invoice subscriber: no PayPal order_id in session for order", orderId)
57
+ return
58
+ }
59
+
60
+ // Get invoice prefix from settings
61
+ const settings = await paypal.getSettings().catch(() => ({}))
62
+ const settingsData =
63
+ settings && typeof settings === "object" && "data" in settings
64
+ ? ((settings as { data?: Record<string, any> }).data ?? {})
65
+ : {}
66
+ const additionalSettings = (settingsData.additional_settings || {}) as Record<string, any>
67
+ const invoicePrefix =
68
+ typeof additionalSettings.invoicePrefix === "string"
69
+ ? additionalSettings.invoicePrefix
70
+ : ""
71
+
72
+ // Build industry-standard invoice ID: prefix + order display_id
73
+ // e.g. "WC-140" or "ORD-140"
74
+ const displayId = String(order.display_id || "")
75
+ const invoiceId = `${invoicePrefix}${displayId}`.trim()
76
+ if (!invoiceId) return
77
+
78
+ // Patch the PayPal order with the correct invoice_id
79
+ const creds = await paypal.getActiveCredentials()
80
+ const { accessToken, base } = await getPayPalAccessToken(creds)
81
+
82
+ const patchResp = await fetch(`${base}/v2/checkout/orders/${paypalOrderId}`, {
83
+ method: "PATCH",
84
+ headers: {
85
+ Authorization: `Bearer ${accessToken}`,
86
+ "Content-Type": "application/json",
87
+ },
88
+ body: JSON.stringify([
89
+ {
90
+ op: "replace",
91
+ path: "/purchase_units/@reference_id=='default'/invoice_id",
92
+ value: invoiceId,
93
+ },
94
+ ]),
95
+ })
96
+
97
+ if (patchResp.ok || patchResp.status === 204) {
98
+ console.info(
99
+ `[PayPal] invoice_id updated to "${invoiceId}" for PayPal order ${paypalOrderId} (Medusa order #${displayId})`
100
+ )
101
+ } else {
102
+ const text = await patchResp.text().catch(() => "")
103
+ console.warn(
104
+ `[PayPal] invoice_id patch failed (${patchResp.status}) for PayPal order ${paypalOrderId}: ${text}`
105
+ )
106
+ }
107
+ } catch (e: any) {
108
+ // Non-fatal — never block order placement
109
+ console.warn("[PayPal] paypalOrderInvoiceHandler error:", e?.message || e)
110
+ }
111
+ }
112
+
113
+ export const config: SubscriberConfig = {
114
+ event: "order.placed",
115
+ }