@easypayment/medusa-paypal 0.6.8 → 0.7.0
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 +10 -10
- package/.medusa/server/src/admin/index.mjs +10 -10
- package/.medusa/server/src/api/store/paypal/create-order/route.js +1 -1
- package/.medusa/server/src/api/store/paypal/create-order/route.js.map +1 -1
- 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 +2 -1
- package/.medusa/server/src/modules/paypal/payment-provider/service.js.map +1 -1
- package/.medusa/server/src/subscribers/paypal-order-invoice.d.ts.map +1 -1
- package/.medusa/server/src/subscribers/paypal-order-invoice.js +56 -26
- package/.medusa/server/src/subscribers/paypal-order-invoice.js.map +1 -1
- package/README.md +6 -8
- package/package.json +1 -1
- package/src/api/store/paypal/create-order/route.ts +1 -1
- package/src/modules/paypal/payment-provider/card-service.ts +762 -760
- package/src/modules/paypal/payment-provider/service.ts +1051 -1050
- package/src/subscribers/paypal-order-invoice.ts +172 -115
|
@@ -11,7 +11,7 @@ async function paypalOrderInvoiceHandler({ event, container, }) {
|
|
|
11
11
|
try {
|
|
12
12
|
const query = container.resolve("query");
|
|
13
13
|
const paypal = container.resolve("paypal_onboarding");
|
|
14
|
-
// Fetch the order with payment session data
|
|
14
|
+
// Fetch the Medusa order with payment session data
|
|
15
15
|
const { data: orders } = await query.graph({
|
|
16
16
|
entity: "order",
|
|
17
17
|
fields: [
|
|
@@ -28,23 +28,23 @@ async function paypalOrderInvoiceHandler({ event, container, }) {
|
|
|
28
28
|
const order = orders?.[0];
|
|
29
29
|
if (!order)
|
|
30
30
|
return;
|
|
31
|
-
// Find the PayPal session
|
|
31
|
+
// Find the PayPal payment session
|
|
32
32
|
const sessions = (order.payment_collections || []).flatMap((pc) => pc.payment_sessions || []);
|
|
33
33
|
const paypalSession = sessions
|
|
34
34
|
.filter((s) => (0, provider_ids_1.isPayPalProviderId)(s.provider_id))
|
|
35
35
|
.sort((a, b) => new Date(b.created_at || 0).getTime() -
|
|
36
36
|
new Date(a.created_at || 0).getTime())[0];
|
|
37
37
|
if (!paypalSession) {
|
|
38
|
-
console.info("[PayPal] invoice subscriber: no PayPal session
|
|
38
|
+
console.info("[PayPal] invoice subscriber: no PayPal session for order", orderId);
|
|
39
39
|
return;
|
|
40
40
|
}
|
|
41
41
|
const paypalData = ((paypalSession.data || {}).paypal || {});
|
|
42
42
|
const paypalOrderId = String(paypalData.order_id || "");
|
|
43
43
|
if (!paypalOrderId) {
|
|
44
|
-
console.info("[PayPal] invoice subscriber: no
|
|
44
|
+
console.info("[PayPal] invoice subscriber: no order_id in session for order", orderId);
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
|
-
//
|
|
47
|
+
// Build invoice_id: invoicePrefix + display_id (industry standard)
|
|
48
48
|
const settings = await paypal.getSettings().catch(() => ({}));
|
|
49
49
|
const settingsData = settings && typeof settings === "object" && "data" in settings
|
|
50
50
|
? (settings.data ?? {})
|
|
@@ -53,35 +53,65 @@ async function paypalOrderInvoiceHandler({ event, container, }) {
|
|
|
53
53
|
const invoicePrefix = typeof additionalSettings.invoicePrefix === "string"
|
|
54
54
|
? additionalSettings.invoicePrefix
|
|
55
55
|
: "";
|
|
56
|
-
// Build industry-standard invoice ID: prefix + order display_id
|
|
57
|
-
// e.g. "WC-140" or "ORD-140"
|
|
58
56
|
const displayId = String(order.display_id || "");
|
|
59
57
|
const invoiceId = `${invoicePrefix}${displayId}`.trim();
|
|
60
58
|
if (!invoiceId)
|
|
61
59
|
return;
|
|
62
|
-
//
|
|
60
|
+
// Get PayPal access token
|
|
63
61
|
const creds = await paypal.getActiveCredentials();
|
|
64
62
|
const { accessToken, base } = await (0, paypal_auth_1.getPayPalAccessToken)(creds);
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
63
|
+
// ── HIGH-VOLUME GUARD ──────────────────────────────────────────────
|
|
64
|
+
// Check if invoice_id is already correct before sending a PATCH.
|
|
65
|
+
// Prevents redundant API calls and duplicate-key errors at scale.
|
|
66
|
+
try {
|
|
67
|
+
const currentResp = await fetch(`${base}/v2/checkout/orders/${paypalOrderId}`, { headers: { Authorization: `Bearer ${accessToken}` } });
|
|
68
|
+
if (currentResp.ok) {
|
|
69
|
+
const currentOrder = await currentResp.json().catch(() => ({}));
|
|
70
|
+
const currentInvoiceId = currentOrder?.purchase_units?.[0]?.invoice_id || "";
|
|
71
|
+
if (currentInvoiceId === invoiceId) {
|
|
72
|
+
console.info(`[PayPal] invoice_id already "${invoiceId}" — skipping PATCH`);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch (e) {
|
|
78
|
+
// Non-fatal — proceed with PATCH anyway
|
|
79
|
+
console.warn("[PayPal] pre-PATCH order fetch failed:", e?.message);
|
|
80
|
+
}
|
|
81
|
+
// ──────────────────────────────────────────────────────────────────
|
|
82
|
+
// Try two PATCH paths for robustness:
|
|
83
|
+
// Path 1: standard "default" reference_id (new orders after this fix)
|
|
84
|
+
// Path 2: array index fallback (orders created before this fix)
|
|
85
|
+
const patchPaths = [
|
|
86
|
+
"/purchase_units/@reference_id=='default'/invoice_id",
|
|
87
|
+
"/purchase_units/0/invoice_id",
|
|
88
|
+
];
|
|
89
|
+
let patched = false;
|
|
90
|
+
for (const path of patchPaths) {
|
|
91
|
+
const patchResp = await fetch(`${base}/v2/checkout/orders/${paypalOrderId}`, {
|
|
92
|
+
method: "PATCH",
|
|
93
|
+
headers: {
|
|
94
|
+
Authorization: `Bearer ${accessToken}`,
|
|
95
|
+
"Content-Type": "application/json",
|
|
76
96
|
},
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
97
|
+
body: JSON.stringify([{ op: "replace", path, value: invoiceId }]),
|
|
98
|
+
});
|
|
99
|
+
if (patchResp.ok || patchResp.status === 204) {
|
|
100
|
+
console.info(`[PayPal] invoice_id set to "${invoiceId}"`, `(PayPal order ${paypalOrderId} / Medusa #${displayId})`, `via path: ${path}`);
|
|
101
|
+
patched = true;
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
const errText = await patchResp.text().catch(() => "");
|
|
105
|
+
console.warn("[PayPal] invoice_id PATCH attempt failed", {
|
|
106
|
+
status: patchResp.status,
|
|
107
|
+
path,
|
|
108
|
+
paypalOrderId,
|
|
109
|
+
errText,
|
|
110
|
+
});
|
|
81
111
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
console.
|
|
112
|
+
if (!patched) {
|
|
113
|
+
// Hard error log — failures must never be silently swallowed at scale
|
|
114
|
+
console.error("[PayPal] CRITICAL: invoice_id PATCH failed for ALL paths.", { paypalOrderId, invoiceId, displayId });
|
|
85
115
|
}
|
|
86
116
|
}
|
|
87
117
|
catch (e) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paypal-order-invoice.js","sourceRoot":"","sources":["../../../../src/subscribers/paypal-order-invoice.ts"],"names":[],"mappings":";;;AAKA,
|
|
1
|
+
{"version":3,"file":"paypal-order-invoice.js","sourceRoot":"","sources":["../../../../src/subscribers/paypal-order-invoice.ts"],"names":[],"mappings":"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"}
|
package/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
<h1>🅿
|
|
3
|
+
<h1>🅿 PayPal for Medusa V2</h1>
|
|
4
4
|
|
|
5
|
-
<p><strong>
|
|
5
|
+
<p><strong>PayPal payment plugin for Medusa v2</strong></p>
|
|
6
6
|
|
|
7
7
|
<p>
|
|
8
|
-
<a href="https://www.npmjs.com/package/@easypayment/medusa-paypal
|
|
8
|
+
<a href="https://www.npmjs.com/package/@easypayment/medusa-paypal"><img src="https://img.shields.io/npm/v/@easypayment/medusa-paypal?color=blue&label=npm" alt="npm version" /></a>
|
|
9
9
|
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-green.svg" alt="License: MIT" /></a>
|
|
10
10
|
<a href="https://medusajs.com"><img src="https://img.shields.io/badge/Medusa-v2-9b59b6" alt="Medusa v2" /></a>
|
|
11
11
|
<a href="https://developer.paypal.com"><img src="https://img.shields.io/badge/PayPal-PPCP-003087" alt="PayPal PPCP" /></a>
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
## Step 1 — Install
|
|
29
29
|
|
|
30
30
|
```bash
|
|
31
|
-
npm install @easypayment/medusa-paypal
|
|
31
|
+
npm install @easypayment/medusa-paypal
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
---
|
|
@@ -98,8 +98,6 @@ Add these to your Medusa server `.env`:
|
|
|
98
98
|
MEDUSA_BACKEND_URL=https://your-medusa-server.com
|
|
99
99
|
STOREFRONT_URL=https://your-storefront.com
|
|
100
100
|
|
|
101
|
-
# Recommended for production
|
|
102
|
-
PAYPAL_CURRENCY=EUR
|
|
103
101
|
```
|
|
104
102
|
|
|
105
103
|
---
|
|
@@ -127,8 +125,8 @@ Credentials are saved automatically. To connect manually instead, click **Insert
|
|
|
127
125
|
|
|
128
126
|
1. Medusa Admin → **Settings → Regions → [your region]**
|
|
129
127
|
2. Under **Payment Providers**, enable:
|
|
130
|
-
- `pp_paypal_paypal` —
|
|
131
|
-
- `pp_paypal_card_paypal_card` —
|
|
128
|
+
- `pp_paypal_paypal` — Paypal (PAYPAL)
|
|
129
|
+
- `pp_paypal_card_paypal_card` — Paypal (CARD)
|
|
132
130
|
|
|
133
131
|
---
|
|
134
132
|
|
package/package.json
CHANGED
|
@@ -381,7 +381,7 @@ export async function POST(req: MedusaRequest, res: MedusaResponse) {
|
|
|
381
381
|
intent: paymentAction,
|
|
382
382
|
purchase_units: [
|
|
383
383
|
{
|
|
384
|
-
reference_id:
|
|
384
|
+
reference_id: "default",
|
|
385
385
|
invoice_id: invoiceId,
|
|
386
386
|
...(statementName ? { soft_descriptor: statementName.slice(0, 22) } : {}),
|
|
387
387
|
amount: {
|