@easypayment/medusa-paypal 0.6.3 โ†’ 0.6.4

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.
Files changed (68) hide show
  1. package/.medusa/server/src/admin/index.js +12 -15
  2. package/.medusa/server/src/admin/index.mjs +12 -15
  3. package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.d.ts.map +1 -1
  4. package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.js.map +1 -1
  5. package/.medusa/server/src/api/store/paypal/capture-order/route.d.ts.map +1 -1
  6. package/.medusa/server/src/api/store/paypal/capture-order/route.js +1 -11
  7. package/.medusa/server/src/api/store/paypal/capture-order/route.js.map +1 -1
  8. package/.medusa/server/src/api/store/paypal/create-order/route.d.ts.map +1 -1
  9. package/.medusa/server/src/api/store/paypal/create-order/route.js +0 -9
  10. package/.medusa/server/src/api/store/paypal/create-order/route.js.map +1 -1
  11. package/.medusa/server/src/api/store/paypal/webhook/route.d.ts.map +1 -1
  12. package/.medusa/server/src/api/store/paypal/webhook/route.js +162 -115
  13. package/.medusa/server/src/api/store/paypal/webhook/route.js.map +1 -1
  14. package/.medusa/server/src/api/store/paypal-complete/route.d.ts.map +1 -1
  15. package/.medusa/server/src/api/store/paypal-complete/route.js +0 -6
  16. package/.medusa/server/src/api/store/paypal-complete/route.js.map +1 -1
  17. package/.medusa/server/src/jobs/paypal-webhook-retry.d.ts.map +1 -1
  18. package/.medusa/server/src/jobs/paypal-webhook-retry.js +97 -43
  19. package/.medusa/server/src/jobs/paypal-webhook-retry.js.map +1 -1
  20. package/.medusa/server/src/modules/paypal/migrations/20270201000000_add_webhook_dead_letter.d.ts +6 -0
  21. package/.medusa/server/src/modules/paypal/migrations/20270201000000_add_webhook_dead_letter.d.ts.map +1 -0
  22. package/.medusa/server/src/modules/paypal/migrations/20270201000000_add_webhook_dead_letter.js +20 -0
  23. package/.medusa/server/src/modules/paypal/migrations/20270201000000_add_webhook_dead_letter.js.map +1 -0
  24. package/.medusa/server/src/modules/paypal/payment-provider/service.d.ts.map +1 -1
  25. package/.medusa/server/src/modules/paypal/payment-provider/service.js +0 -42
  26. package/.medusa/server/src/modules/paypal/payment-provider/service.js.map +1 -1
  27. package/.medusa/server/src/modules/paypal/service.d.ts +0 -8
  28. package/.medusa/server/src/modules/paypal/service.d.ts.map +1 -1
  29. package/.medusa/server/src/modules/paypal/service.js +6 -114
  30. package/.medusa/server/src/modules/paypal/service.js.map +1 -1
  31. package/.medusa/server/src/modules/paypal/types/config.d.ts +0 -2
  32. package/.medusa/server/src/modules/paypal/types/config.d.ts.map +1 -1
  33. package/.medusa/server/src/modules/paypal/types/config.js +0 -9
  34. package/.medusa/server/src/modules/paypal/types/config.js.map +1 -1
  35. package/.medusa/server/src/modules/paypal/webhook-processor.d.ts +21 -17
  36. package/.medusa/server/src/modules/paypal/webhook-processor.d.ts.map +1 -1
  37. package/.medusa/server/src/modules/paypal/webhook-processor.js +195 -99
  38. package/.medusa/server/src/modules/paypal/webhook-processor.js.map +1 -1
  39. package/README.md +156 -152
  40. package/package.json +1 -1
  41. package/src/admin/routes/settings/paypal/_components/Tabs.tsx +48 -52
  42. package/src/admin/routes/settings/paypal/paypal-settings/page.tsx +0 -23
  43. package/src/api/store/payment-collections/[id]/payment-sessions/route.ts +56 -65
  44. package/src/api/store/paypal/capture-order/route.ts +266 -276
  45. package/src/api/store/paypal/create-order/route.ts +0 -9
  46. package/src/api/store/paypal/webhook/route.ts +325 -246
  47. package/src/api/store/paypal-complete/route.ts +69 -75
  48. package/src/jobs/paypal-webhook-retry.ts +149 -85
  49. package/src/modules/paypal/migrations/20270201000000_add_webhook_dead_letter.ts +17 -0
  50. package/src/modules/paypal/payment-provider/service.ts +1079 -1121
  51. package/src/modules/paypal/service.ts +6 -127
  52. package/src/modules/paypal/types/config.ts +33 -47
  53. package/src/modules/paypal/webhook-processor.ts +377 -215
  54. package/.medusa/server/src/api/admin/paypal/rotate-credentials/route.d.ts +0 -3
  55. package/.medusa/server/src/api/admin/paypal/rotate-credentials/route.d.ts.map +0 -1
  56. package/.medusa/server/src/api/admin/paypal/rotate-credentials/route.js +0 -9
  57. package/.medusa/server/src/api/admin/paypal/rotate-credentials/route.js.map +0 -1
  58. package/.medusa/server/src/jobs/paypal-reconcile.d.ts +0 -7
  59. package/.medusa/server/src/jobs/paypal-reconcile.d.ts.map +0 -1
  60. package/.medusa/server/src/jobs/paypal-reconcile.js +0 -109
  61. package/.medusa/server/src/jobs/paypal-reconcile.js.map +0 -1
  62. package/.medusa/server/src/modules/paypal/utils/crypto.d.ts +0 -4
  63. package/.medusa/server/src/modules/paypal/utils/crypto.d.ts.map +0 -1
  64. package/.medusa/server/src/modules/paypal/utils/crypto.js +0 -47
  65. package/.medusa/server/src/modules/paypal/utils/crypto.js.map +0 -1
  66. package/src/api/admin/paypal/rotate-credentials/route.ts +0 -8
  67. package/src/jobs/paypal-reconcile.ts +0 -113
  68. package/src/modules/paypal/utils/crypto.ts +0 -51
package/README.md CHANGED
@@ -1,153 +1,157 @@
1
- <div align="center">
2
-
3
- <h1>๐Ÿ…ฟ medusa-paypal-backend</h1>
4
-
5
- <p><strong>Production-ready PayPal payment plugin for Medusa v2</strong></p>
6
-
7
- <p>
8
- <a href="https://www.npmjs.com/package/@easypayment/medusa-paypal-backend"><img src="https://img.shields.io/npm/v/@easypayment/medusa-paypal-backend?color=blue&label=npm" alt="npm version" /></a>
9
- <a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-green.svg" alt="License: MIT" /></a>
10
- <a href="https://medusajs.com"><img src="https://img.shields.io/badge/Medusa-v2-9b59b6" alt="Medusa v2" /></a>
11
- <a href="https://developer.paypal.com"><img src="https://img.shields.io/badge/PayPal-PPCP-003087" alt="PayPal PPCP" /></a>
12
- </p>
13
-
14
- <p>Smart Buttons ยท Advanced Card Fields ยท Webhooks</p>
15
-
16
- </div>
17
-
18
- ---
19
-
20
- ## Requirements
21
-
22
- - Medusa v2
23
- - Node.js 18+
24
- - PostgreSQL
25
-
26
- ---
27
-
28
- ## Step 1 โ€” Install
29
-
30
- ```bash
31
- npm install @easypayment/medusa-paypal-backend
32
- ```
33
-
34
- ---
35
-
36
- ## Step 2 โ€” Configure medusa-config.ts
37
-
38
- Add the plugin and both payment providers to your existing `medusa-config.ts`:
39
-
40
- ```ts
41
- import { loadEnv, defineConfig } from "@medusajs/framework/utils"
42
-
43
- loadEnv(process.env.NODE_ENV || "development", process.cwd())
44
-
45
- export default defineConfig({
46
- projectConfig: {
47
- databaseUrl: process.env.DATABASE_URL,
48
- http: {
49
- storeCors: process.env.STORE_CORS!,
50
- adminCors: process.env.ADMIN_CORS!,
51
- authCors: process.env.AUTH_CORS!,
52
- jwtSecret: process.env.JWT_SECRET || "supersecret",
53
- cookieSecret: process.env.COOKIE_SECRET || "supersecret",
54
- },
55
- },
56
-
57
- plugins: [
58
- {
59
- resolve: "@easypayment/medusa-paypal",
60
- options: {},
61
- },
62
- ],
63
-
64
- modules: [
65
- {
66
- resolve: "@medusajs/medusa/payment",
67
- options: {
68
- providers: [
69
- {
70
- // PayPal Smart Buttons (wallet checkout)
71
- resolve: "@easypayment/medusa-paypal/providers/paypal",
72
- id: "paypal",
73
- options: {},
74
- dependencies: ["paypal_onboarding"],
75
- },
76
- {
77
- // Advanced Card Fields (hosted card inputs)
78
- resolve: "@easypayment/medusa-paypal/providers/paypal_card",
79
- id: "paypal_card",
80
- options: {},
81
- dependencies: ["paypal_onboarding"],
82
- },
83
- ],
84
- },
85
- },
86
- ],
87
- })
88
- ```
89
-
90
- ---
91
-
92
- ## Step 3 โ€” Set environment variables
93
-
94
- Add these to your Medusa server `.env`:
95
-
96
- ```env
97
- # Required
98
- MEDUSA_BACKEND_URL=https://your-medusa-server.com
99
- ```
100
-
101
- ---
102
-
103
- ## Step 4 โ€” Run database migrations
104
-
105
- ```bash
106
- npx medusa db:migrate
107
- ```
108
-
109
- ---
110
-
111
- ## Step 5 โ€” Connect your PayPal account
112
-
113
- 1. Start your Medusa server
114
- 2. Open Medusa Admin โ†’ **Settings โ†’ PayPal โ†’ PayPal Connection**
115
- 3. Choose **Sandbox** (testing) or **Live** (production)
116
- 4. Click **Connect to PayPal** and complete the PayPal onboarding flow
117
-
118
- Credentials are saved automatically. To connect manually instead, click **Insert credentials manually** and paste your Client ID and Secret from [developer.paypal.com](https://developer.paypal.com).
119
-
120
- ---
121
-
122
- ## Step 6 โ€” Enable providers in your region
123
-
124
- 1. Medusa Admin โ†’ **Settings โ†’ Regions โ†’ [your region]**
125
- 2. Under **Payment Providers**, enable:
126
- - `pp_paypal_paypal` โ€” Paypal (CARD)
127
- - `pp_paypal_card_paypal_card` โ€” Paypal (PAYPAL)
128
-
129
- ---
130
-
131
- ## Step 7 โ€” Configure settings (optional)
132
-
133
- All settings are in Medusa Admin โ†’ **Settings โ†’ PayPal** and take effect immediately with no server restart.
134
-
135
- | Tab | What you can configure |
136
- |---|---|
137
- | **PayPal Settings** | Enable/disable, button color, shape, label |
138
- | **Advanced Card Payments** | Enable/disable, 3D Secure mode |
139
- | **Additional Settings** | Payment action (capture / authorize), brand name, invoice prefix |
140
-
141
- ---
142
-
143
- ## Step 8 โ€” Connect the frontend package
144
-
145
- Install the storefront UI package to render PayPal at checkout:
146
-
147
- ```bash
148
- npm install @easypayment/medusa-paypal-ui
149
- ```
150
-
151
- See the [medusa-paypal-frontend README](../medusa-paypal-frontend/README.md) for integration steps.
152
-
1
+ <div align="center">
2
+
3
+ <h1>๐Ÿ…ฟ medusa-paypal-backend</h1>
4
+
5
+ <p><strong>Production-ready PayPal payment plugin for Medusa v2</strong></p>
6
+
7
+ <p>
8
+ <a href="https://www.npmjs.com/package/@easypayment/medusa-paypal-backend"><img src="https://img.shields.io/npm/v/@easypayment/medusa-paypal-backend?color=blue&label=npm" alt="npm version" /></a>
9
+ <a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-green.svg" alt="License: MIT" /></a>
10
+ <a href="https://medusajs.com"><img src="https://img.shields.io/badge/Medusa-v2-9b59b6" alt="Medusa v2" /></a>
11
+ <a href="https://developer.paypal.com"><img src="https://img.shields.io/badge/PayPal-PPCP-003087" alt="PayPal PPCP" /></a>
12
+ </p>
13
+
14
+ <p>Smart Buttons ยท Advanced Card Fields ยท Webhooks ยท Reconciliation ยท Credential Encryption</p>
15
+
16
+ </div>
17
+
18
+ ---
19
+
20
+ ## Requirements
21
+
22
+ - Medusa v2
23
+ - Node.js 18+
24
+ - PostgreSQL
25
+
26
+ ---
27
+
28
+ ## Step 1 โ€” Install
29
+
30
+ ```bash
31
+ npm install @easypayment/medusa-paypal-backend
32
+ ```
33
+
34
+ ---
35
+
36
+ ## Step 2 โ€” Configure medusa-config.ts
37
+
38
+ Add the plugin and both payment providers to your existing `medusa-config.ts`:
39
+
40
+ ```ts
41
+ import { loadEnv, defineConfig } from "@medusajs/framework/utils"
42
+
43
+ loadEnv(process.env.NODE_ENV || "development", process.cwd())
44
+
45
+ export default defineConfig({
46
+ projectConfig: {
47
+ databaseUrl: process.env.DATABASE_URL,
48
+ http: {
49
+ storeCors: process.env.STORE_CORS!,
50
+ adminCors: process.env.ADMIN_CORS!,
51
+ authCors: process.env.AUTH_CORS!,
52
+ jwtSecret: process.env.JWT_SECRET || "supersecret",
53
+ cookieSecret: process.env.COOKIE_SECRET || "supersecret",
54
+ },
55
+ },
56
+
57
+ plugins: [
58
+ {
59
+ resolve: "@easypayment/medusa-paypal",
60
+ options: {},
61
+ },
62
+ ],
63
+
64
+ modules: [
65
+ {
66
+ resolve: "@medusajs/medusa/payment",
67
+ options: {
68
+ providers: [
69
+ {
70
+ // PayPal Smart Buttons (wallet checkout)
71
+ resolve: "@easypayment/medusa-paypal/providers/paypal",
72
+ id: "paypal",
73
+ options: {},
74
+ dependencies: ["paypal_onboarding"],
75
+ },
76
+ {
77
+ // Advanced Card Fields (hosted card inputs)
78
+ resolve: "@easypayment/medusa-paypal/providers/paypal_card",
79
+ id: "paypal_card",
80
+ options: {},
81
+ dependencies: ["paypal_onboarding"],
82
+ },
83
+ ],
84
+ },
85
+ },
86
+ ],
87
+ })
88
+ ```
89
+
90
+ ---
91
+
92
+ ## Step 3 โ€” Set environment variables
93
+
94
+ Add these to your Medusa server `.env`:
95
+
96
+ ```env
97
+ # Required
98
+ MEDUSA_BACKEND_URL=https://your-medusa-server.com
99
+ STOREFRONT_URL=https://your-storefront.com
100
+
101
+ # Recommended for production
102
+ PAYPAL_CURRENCY=EUR
103
+ ```
104
+
105
+ ---
106
+
107
+ ## Step 4 โ€” Run database migrations
108
+
109
+ ```bash
110
+ npx medusa db:migrate
111
+ ```
112
+
113
+ ---
114
+
115
+ ## Step 5 โ€” Connect your PayPal account
116
+
117
+ 1. Start your Medusa server
118
+ 2. Open Medusa Admin โ†’ **Settings โ†’ PayPal โ†’ PayPal Connection**
119
+ 3. Choose **Sandbox** (testing) or **Live** (production)
120
+ 4. Click **Connect to PayPal** and complete the PayPal onboarding flow
121
+
122
+ Credentials are saved automatically. To connect manually instead, click **Insert credentials manually** and paste your Client ID and Secret from [developer.paypal.com](https://developer.paypal.com).
123
+
124
+ ---
125
+
126
+ ## Step 6 โ€” Enable providers in your region
127
+
128
+ 1. Medusa Admin โ†’ **Settings โ†’ Regions โ†’ [your region]**
129
+ 2. Under **Payment Providers**, enable:
130
+ - `pp_paypal_paypal` โ€” PayPal Smart Buttons
131
+ - `pp_paypal_card_paypal_card` โ€” Advanced Card Fields
132
+
133
+ ---
134
+
135
+ ## Step 7 โ€” Configure settings (optional)
136
+
137
+ All settings are in Medusa Admin โ†’ **Settings โ†’ PayPal** and take effect immediately with no server restart.
138
+
139
+ | Tab | What you can configure |
140
+ |---|---|
141
+ | **PayPal Settings** | Enable/disable, button color, shape, label |
142
+ | **Advanced Card Payments** | Enable/disable, 3D Secure mode |
143
+ | **Additional Settings** | Payment action (capture / authorize), brand name, invoice prefix |
144
+
145
+ ---
146
+
147
+ ## Step 8 โ€” Connect the frontend package
148
+
149
+ Install the storefront UI package to render PayPal at checkout:
150
+
151
+ ```bash
152
+ npm install @easypayment/medusa-paypal-ui
153
+ ```
154
+
155
+ See the [medusa-paypal-frontend README](../medusa-paypal-frontend/README.md) for integration steps.
156
+
153
157
  ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@easypayment/medusa-paypal",
3
- "version": "0.6.3",
3
+ "version": "0.6.4",
4
4
  "description": "Industry-standard PayPal integration for Medusa v2",
5
5
  "license": "MIT",
6
6
  "main": "./.medusa/server/src/index.js",
@@ -1,52 +1,48 @@
1
- import React from "react"
2
- import { Link, useLocation } from "react-router-dom"
3
-
4
- type Tab = {
5
- label: string
6
- to: string
7
- }
8
-
9
- const BASE = "/settings/paypal"
10
-
11
- const TABS: Tab[] = [
12
- { label: "PayPal Connection", to: `${BASE}/connection` },
13
- { label: "PayPal Settings", to: `${BASE}/paypal-settings` },
14
- { label: "Advanced Card Payments", to: `${BASE}/advanced-card-payments` },
15
- /* { label: "Google Pay", to: `${BASE}/google-pay` },
16
- { label: "Apple Pay", to: `${BASE}/apple-pay` },
17
- { label: "Pay Later Messaging", to: `${BASE}/pay-later-messaging` }, */
18
- { label: "Additional Settings", to: `${BASE}/additional-settings` },
19
- ]
20
-
21
- function isActive(pathname: string, to: string) {
22
- // exact match OR nested route under same tab
23
- return pathname === to || pathname.startsWith(to + "/")
24
- }
25
-
26
- export default function PayPalTabs() {
27
- const { pathname } = useLocation()
28
-
29
- return (
30
- <div className="border-b border-ui-border-base">
31
- <div className="flex flex-wrap gap-6 text-sm">
32
- {TABS.map((t) => {
33
- const active = isActive(pathname, t.to)
34
-
35
- return (
36
- <Link
37
- key={t.to}
38
- to={t.to}
39
- className={
40
- active
41
- ? "border-b-2 border-ui-fg-base pb-2 font-medium text-ui-fg-base"
42
- : "pb-2 text-ui-fg-subtle hover:text-ui-fg-base"
43
- }
44
- >
45
- {t.label}
46
- </Link>
47
- )
48
- })}
49
- </div>
50
- </div>
51
- )
52
- }
1
+ import React from "react"
2
+ import { Link, useLocation } from "react-router-dom"
3
+
4
+ type Tab = {
5
+ label: string
6
+ to: string
7
+ }
8
+
9
+ const BASE = "/settings/paypal"
10
+
11
+ const TABS: Tab[] = [
12
+ { label: "PayPal Connection", to: `${BASE}/connection` },
13
+ { label: "PayPal Settings", to: `${BASE}/paypal-settings` },
14
+ { label: "Advanced Card Payments", to: `${BASE}/advanced-card-payments` },
15
+ { label: "Additional Settings", to: `${BASE}/additional-settings` },
16
+ ]
17
+
18
+ function isActive(pathname: string, to: string) {
19
+ return pathname === to || pathname.startsWith(to + "/")
20
+ }
21
+
22
+ export default function PayPalTabs() {
23
+ const { pathname } = useLocation()
24
+
25
+ return (
26
+ <div className="border-b border-ui-border-base">
27
+ <div className="flex flex-wrap gap-6 text-sm">
28
+ {TABS.map((t) => {
29
+ const active = isActive(pathname, t.to)
30
+
31
+ return (
32
+ <Link
33
+ key={t.to}
34
+ to={t.to}
35
+ className={
36
+ active
37
+ ? "border-b-2 border-ui-fg-base pb-2 font-medium text-ui-fg-base"
38
+ : "pb-2 text-ui-fg-subtle hover:text-ui-fg-base"
39
+ }
40
+ >
41
+ {t.label}
42
+ </Link>
43
+ )
44
+ })}
45
+ </div>
46
+ </div>
47
+ )
48
+ }
@@ -147,16 +147,6 @@ export default function PayPalSettingsTab() {
147
147
  ;(async () => {
148
148
  try {
149
149
  setLoading(true)
150
-
151
- // BEFORE:
152
- // const r = await fetch("/admin/paypal/settings", {
153
- // credentials: "include",
154
- // headers: { Accept: "application/json" },
155
- // })
156
- // if (!r.ok) return
157
- // const json = await r.json()
158
- //
159
- // AFTER: adminFetch attaches the Bearer token automatically
160
150
  const json = await adminFetch<{ data?: { paypal_settings?: PayPalSettingsForm }; paypal_settings?: PayPalSettingsForm }>(
161
151
  "/admin/paypal/settings"
162
152
  )
@@ -180,18 +170,6 @@ export default function PayPalSettingsTab() {
180
170
  try {
181
171
  setSaving(true)
182
172
  const cleaned = { ...form }
183
-
184
- // BEFORE:
185
- // const r = await fetch("/admin/paypal/settings", {
186
- // method: "POST",
187
- // credentials: "include",
188
- // headers: { "Content-Type": "application/json", Accept: "application/json" },
189
- // body: JSON.stringify({ paypal_settings: cleaned }),
190
- // })
191
- // if (!r.ok) { ... }
192
- // const json = await r.json().catch(() => null)
193
- //
194
- // AFTER: adminFetch attaches the Bearer token automatically
195
173
  const json = await adminFetch<{ data?: { paypal_settings?: PayPalSettingsForm }; paypal_settings?: PayPalSettingsForm }>(
196
174
  "/admin/paypal/settings",
197
175
  {
@@ -248,7 +226,6 @@ export default function PayPalSettingsTab() {
248
226
  </div>
249
227
  ) : null}
250
228
 
251
- {/* PayPal Settings */}
252
229
  <SectionCard
253
230
  title="PayPal Settings"
254
231
  description="Enable PayPal and configure checkout title."
@@ -1,66 +1,57 @@
1
- import { createPaymentSessionsWorkflow } from "@medusajs/core-flows"
2
- import { MedusaResponse, MedusaStoreRequest, refetchEntity } from "@medusajs/framework/http"
3
- import { MedusaError } from "@medusajs/framework/utils"
4
-
5
- // FIX 6: Removed the broken import of isPayPalProviderId from provider-ids.
6
- // That import caused TS2307 because the relative path was wrong, and the
7
- // isPayPalProviderId guard was conflicting with the typed body cast below,
8
- // producing two const declarations of provider_id in the same scope.
9
- // This route does not need to filter by provider โ€” it accepts any provider_id
10
- // and delegates to the standard createPaymentSessionsWorkflow. The
11
- // isPayPalProviderId guard (Fix 6b) belongs only in routes that need to
12
- // short-circuit for non-PayPal providers.
13
-
14
- type CreatePaymentSessionBody = {
15
- provider_id: string
16
- data?: Record<string, unknown>
17
- }
18
-
19
- const defaultPaymentCollectionFields = [
20
- "id",
21
- "currency_code",
22
- "amount",
23
- "*payment_sessions",
24
- ]
25
-
26
- export async function POST(req: MedusaStoreRequest, res: MedusaResponse) {
27
- const collectionId = req.params.id
28
-
29
- // Single typed destructure โ€” no redeclaration, req.body cast once
30
- const { provider_id, data } = req.body as CreatePaymentSessionBody
31
-
32
- if (!provider_id || typeof provider_id !== "string") {
33
- throw new MedusaError(
34
- MedusaError.Types.INVALID_DATA,
35
- "provider_id is required to create a payment session"
36
- )
37
- }
38
-
39
- try {
40
- await createPaymentSessionsWorkflow(req.scope).run({
41
- input: {
42
- payment_collection_id: collectionId,
43
- provider_id,
44
- customer_id: req.auth_context?.actor_id,
45
- data,
46
- },
47
- })
48
- } catch (error) {
49
- const message = error instanceof Error ? error.message : String(error)
50
- throw new MedusaError(
51
- MedusaError.Types.UNEXPECTED_STATE,
52
- `Failed to create payment session for provider '${provider_id}': ${message}`
53
- )
54
- }
55
-
56
- const paymentCollection = await refetchEntity({
57
- entity: "payment_collection",
58
- idOrFilter: collectionId,
59
- scope: req.scope,
60
- fields: req.queryConfig?.fields ?? defaultPaymentCollectionFields,
61
- })
62
-
63
- res.status(200).json({
64
- payment_collection: paymentCollection,
65
- })
1
+ import { createPaymentSessionsWorkflow } from "@medusajs/core-flows"
2
+ import { MedusaResponse, MedusaStoreRequest, refetchEntity } from "@medusajs/framework/http"
3
+ import { MedusaError } from "@medusajs/framework/utils"
4
+
5
+ type CreatePaymentSessionBody = {
6
+ provider_id: string
7
+ data?: Record<string, unknown>
8
+ }
9
+
10
+ const defaultPaymentCollectionFields = [
11
+ "id",
12
+ "currency_code",
13
+ "amount",
14
+ "*payment_sessions",
15
+ ]
16
+
17
+ export async function POST(req: MedusaStoreRequest, res: MedusaResponse) {
18
+ const collectionId = req.params.id
19
+
20
+ // Single typed destructure โ€” no redeclaration, req.body cast once
21
+ const { provider_id, data } = req.body as CreatePaymentSessionBody
22
+
23
+ if (!provider_id || typeof provider_id !== "string") {
24
+ throw new MedusaError(
25
+ MedusaError.Types.INVALID_DATA,
26
+ "provider_id is required to create a payment session"
27
+ )
28
+ }
29
+
30
+ try {
31
+ await createPaymentSessionsWorkflow(req.scope).run({
32
+ input: {
33
+ payment_collection_id: collectionId,
34
+ provider_id,
35
+ customer_id: req.auth_context?.actor_id,
36
+ data,
37
+ },
38
+ })
39
+ } catch (error) {
40
+ const message = error instanceof Error ? error.message : String(error)
41
+ throw new MedusaError(
42
+ MedusaError.Types.UNEXPECTED_STATE,
43
+ `Failed to create payment session for provider '${provider_id}': ${message}`
44
+ )
45
+ }
46
+
47
+ const paymentCollection = await refetchEntity({
48
+ entity: "payment_collection",
49
+ idOrFilter: collectionId,
50
+ scope: req.scope,
51
+ fields: req.queryConfig?.fields ?? defaultPaymentCollectionFields,
52
+ })
53
+
54
+ res.status(200).json({
55
+ payment_collection: paymentCollection,
56
+ })
66
57
  }