@easypayment/medusa-paypal 0.6.7 → 0.6.9
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/modules/paypal/payment-provider/card-service.d.ts.map +1 -1
- package/.medusa/server/src/modules/paypal/payment-provider/card-service.js +4 -2
- package/.medusa/server/src/modules/paypal/payment-provider/card-service.js.map +1 -1
- package/.medusa/server/src/modules/paypal/payment-provider/service.d.ts.map +1 -1
- package/.medusa/server/src/modules/paypal/payment-provider/service.js +20 -5
- package/.medusa/server/src/modules/paypal/payment-provider/service.js.map +1 -1
- package/.medusa/server/src/subscribers/paypal-order-invoice.d.ts +5 -12
- package/.medusa/server/src/subscribers/paypal-order-invoice.d.ts.map +1 -1
- package/.medusa/server/src/subscribers/paypal-order-invoice.js +17 -11
- package/.medusa/server/src/subscribers/paypal-order-invoice.js.map +1 -1
- package/README.md +4 -4
- package/package.json +8 -5
- package/src/modules/paypal/payment-provider/card-service.ts +762 -760
- package/src/modules/paypal/payment-provider/service.ts +26 -6
- package/src/subscribers/paypal-order-invoice.ts +24 -18
|
@@ -24,7 +24,7 @@ import type {
|
|
|
24
24
|
ProviderWebhookPayload,
|
|
25
25
|
WebhookActionResult,
|
|
26
26
|
} from "@medusajs/framework/types"
|
|
27
|
-
import { formatAmountForPayPal } from "../utils/amounts"
|
|
27
|
+
import { formatAmountForPayPal, getCurrencyExponent } from "../utils/amounts"
|
|
28
28
|
import {
|
|
29
29
|
assertPayPalCurrencySupported,
|
|
30
30
|
normalizeCurrencyCode,
|
|
@@ -709,12 +709,13 @@ class PayPalPaymentProvider extends AbstractPaymentProvider<Options> {
|
|
|
709
709
|
data.is_final_capture ??
|
|
710
710
|
data.final_capture ??
|
|
711
711
|
undefined
|
|
712
|
+
const captureExponent = getCurrencyExponent(currencyCode || "EUR")
|
|
712
713
|
const capturePayload =
|
|
713
714
|
amount > 0
|
|
714
715
|
? {
|
|
715
716
|
amount: {
|
|
716
717
|
currency_code: currencyCode || "EUR",
|
|
717
|
-
value:
|
|
718
|
+
value: amount.toFixed(captureExponent),
|
|
718
719
|
},
|
|
719
720
|
...(typeof isFinalCapture === "boolean"
|
|
720
721
|
? { is_final_capture: isFinalCapture }
|
|
@@ -816,17 +817,36 @@ class PayPalPaymentProvider extends AbstractPaymentProvider<Options> {
|
|
|
816
817
|
}
|
|
817
818
|
|
|
818
819
|
const requestId = this.getIdempotencyKey(input, `refund-${captureId}`)
|
|
819
|
-
|
|
820
|
+
|
|
821
|
+
// ── IMPORTANT: Use input.amount (major units e.g. 20.00) NOT data.amount ──
|
|
822
|
+
// Medusa v2 passes the refund amount via input.amount in major currency units.
|
|
823
|
+
// data.amount is the original session amount in minor units (e.g. 2000 cents).
|
|
824
|
+
// formatAmountForPayPal divides by 100, so using data.amount would give 0.20
|
|
825
|
+
// instead of 20.00. We must use input.amount directly and format it as-is.
|
|
826
|
+
const currencyOverride = await this.resolveCurrencyOverride()
|
|
827
|
+
const currencyCode = normalizeCurrencyCode(
|
|
828
|
+
data.currency_code || currencyOverride || "EUR"
|
|
829
|
+
)
|
|
830
|
+
|
|
831
|
+
// input.amount is already in major units (e.g. 20.00 EUR)
|
|
832
|
+
// Just convert to string with correct decimal places
|
|
833
|
+
// getCurrencyExponent is already available via the amounts utils
|
|
834
|
+
const exponent = currencyCode.toUpperCase() === "JPY" ? 0
|
|
835
|
+
: ["BHD", "JOD", "KWD", "OMR", "TND"].includes(currencyCode.toUpperCase()) ? 3
|
|
836
|
+
: 2
|
|
837
|
+
const refundAmount = Number(input.amount ?? 0)
|
|
838
|
+
const refundValue = refundAmount > 0 ? refundAmount.toFixed(exponent) : null
|
|
839
|
+
|
|
820
840
|
let debugId: string | null = null
|
|
821
841
|
|
|
822
842
|
try {
|
|
823
843
|
const { accessToken, base } = await this.getPayPalAccessToken()
|
|
824
844
|
const refundPayload: Record<string, any> =
|
|
825
|
-
|
|
845
|
+
refundValue
|
|
826
846
|
? {
|
|
827
847
|
amount: {
|
|
828
848
|
currency_code: currencyCode || "EUR",
|
|
829
|
-
value:
|
|
849
|
+
value: refundValue,
|
|
830
850
|
},
|
|
831
851
|
}
|
|
832
852
|
: {}
|
|
@@ -870,7 +890,7 @@ class PayPalPaymentProvider extends AbstractPaymentProvider<Options> {
|
|
|
870
890
|
await this.recordPaymentEvent("refund", {
|
|
871
891
|
capture_id: captureId,
|
|
872
892
|
refund_id: refund?.id,
|
|
873
|
-
amount,
|
|
893
|
+
amount: refundAmount,
|
|
874
894
|
currency_code: currencyCode,
|
|
875
895
|
request_id: requestId,
|
|
876
896
|
reason: refundReason,
|
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SubscriberArgs, SubscriberConfig } from "@medusajs/framework"
|
|
2
2
|
import type PayPalModuleService from "../modules/paypal/service"
|
|
3
3
|
import { getPayPalAccessToken } from "../modules/paypal/utils/paypal-auth"
|
|
4
4
|
import { isPayPalProviderId } from "../modules/paypal/utils/provider-ids"
|
|
5
5
|
|
|
6
|
-
export default async function
|
|
6
|
+
export default async function paypalOrderInvoiceHandler({
|
|
7
7
|
event,
|
|
8
8
|
container,
|
|
9
|
-
}: {
|
|
10
|
-
event: { data: { id: string } }
|
|
11
|
-
container: MedusaContainer
|
|
12
|
-
}) {
|
|
9
|
+
}: SubscriberArgs<{ id: string }>) {
|
|
13
10
|
const orderId = event?.data?.id
|
|
14
11
|
if (!orderId) return
|
|
15
12
|
|
|
@@ -27,6 +24,7 @@ export default async function paypalOrderInvoiceSubscriber({
|
|
|
27
24
|
"payment_collections.payment_sessions.data",
|
|
28
25
|
"payment_collections.payment_sessions.provider_id",
|
|
29
26
|
"payment_collections.payment_sessions.status",
|
|
27
|
+
"payment_collections.payment_sessions.created_at",
|
|
30
28
|
],
|
|
31
29
|
filters: { id: orderId },
|
|
32
30
|
})
|
|
@@ -35,21 +33,29 @@ export default async function paypalOrderInvoiceSubscriber({
|
|
|
35
33
|
if (!order) return
|
|
36
34
|
|
|
37
35
|
// Find the PayPal session
|
|
38
|
-
const sessions = order.payment_collections
|
|
36
|
+
const sessions = (order.payment_collections || []).flatMap(
|
|
39
37
|
(pc: any) => pc.payment_sessions || []
|
|
40
|
-
)
|
|
38
|
+
)
|
|
41
39
|
|
|
42
40
|
const paypalSession = sessions
|
|
43
41
|
.filter((s: any) => isPayPalProviderId(s.provider_id))
|
|
44
|
-
.sort(
|
|
45
|
-
|
|
42
|
+
.sort(
|
|
43
|
+
(a: any, b: any) =>
|
|
44
|
+
new Date(b.created_at || 0).getTime() -
|
|
45
|
+
new Date(a.created_at || 0).getTime()
|
|
46
46
|
)[0]
|
|
47
47
|
|
|
48
|
-
if (!paypalSession)
|
|
48
|
+
if (!paypalSession) {
|
|
49
|
+
console.info("[PayPal] invoice subscriber: no PayPal session found for order", orderId)
|
|
50
|
+
return
|
|
51
|
+
}
|
|
49
52
|
|
|
50
|
-
const paypalData = (paypalSession.data
|
|
53
|
+
const paypalData = ((paypalSession.data || {}).paypal || {}) as Record<string, any>
|
|
51
54
|
const paypalOrderId = String(paypalData.order_id || "")
|
|
52
|
-
if (!paypalOrderId)
|
|
55
|
+
if (!paypalOrderId) {
|
|
56
|
+
console.info("[PayPal] invoice subscriber: no PayPal order_id in session for order", orderId)
|
|
57
|
+
return
|
|
58
|
+
}
|
|
53
59
|
|
|
54
60
|
// Get invoice prefix from settings
|
|
55
61
|
const settings = await paypal.getSettings().catch(() => ({}))
|
|
@@ -64,7 +70,7 @@ export default async function paypalOrderInvoiceSubscriber({
|
|
|
64
70
|
: ""
|
|
65
71
|
|
|
66
72
|
// Build industry-standard invoice ID: prefix + order display_id
|
|
67
|
-
// e.g. "WC-
|
|
73
|
+
// e.g. "WC-140" or "ORD-140"
|
|
68
74
|
const displayId = String(order.display_id || "")
|
|
69
75
|
const invoiceId = `${invoicePrefix}${displayId}`.trim()
|
|
70
76
|
if (!invoiceId) return
|
|
@@ -90,20 +96,20 @@ export default async function paypalOrderInvoiceSubscriber({
|
|
|
90
96
|
|
|
91
97
|
if (patchResp.ok || patchResp.status === 204) {
|
|
92
98
|
console.info(
|
|
93
|
-
`[PayPal] invoice_id updated to "${invoiceId}" for PayPal order ${paypalOrderId} (Medusa order
|
|
99
|
+
`[PayPal] invoice_id updated to "${invoiceId}" for PayPal order ${paypalOrderId} (Medusa order #${displayId})`
|
|
94
100
|
)
|
|
95
101
|
} else {
|
|
96
102
|
const text = await patchResp.text().catch(() => "")
|
|
97
103
|
console.warn(
|
|
98
|
-
`[PayPal] invoice_id patch failed (${patchResp.status}) for order ${paypalOrderId}: ${text}`
|
|
104
|
+
`[PayPal] invoice_id patch failed (${patchResp.status}) for PayPal order ${paypalOrderId}: ${text}`
|
|
99
105
|
)
|
|
100
106
|
}
|
|
101
107
|
} catch (e: any) {
|
|
102
108
|
// Non-fatal — never block order placement
|
|
103
|
-
console.warn("[PayPal]
|
|
109
|
+
console.warn("[PayPal] paypalOrderInvoiceHandler error:", e?.message || e)
|
|
104
110
|
}
|
|
105
111
|
}
|
|
106
112
|
|
|
107
|
-
export const config = {
|
|
113
|
+
export const config: SubscriberConfig = {
|
|
108
114
|
event: "order.placed",
|
|
109
115
|
}
|