@easypayment/medusa-paypal 0.4.1 → 0.4.3

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 (31) hide show
  1. package/.medusa/server/src/admin/index.js +54 -135
  2. package/.medusa/server/src/admin/index.mjs +54 -135
  3. package/.medusa/server/src/api/admin/paypal/environment/route.js +1 -1
  4. package/.medusa/server/src/api/admin/paypal/environment/route.js.map +1 -1
  5. package/.medusa/server/src/api/admin/paypal/onboarding-status/route.js +1 -1
  6. package/.medusa/server/src/api/admin/paypal/onboarding-status/route.js.map +1 -1
  7. package/.medusa/server/src/api/store/paypal/config/route.d.ts.map +1 -1
  8. package/.medusa/server/src/api/store/paypal/config/route.js +0 -4
  9. package/.medusa/server/src/api/store/paypal/config/route.js.map +1 -1
  10. package/.medusa/server/src/api/store/paypal/create-order/route.d.ts.map +1 -1
  11. package/.medusa/server/src/api/store/paypal/create-order/route.js +32 -6
  12. package/.medusa/server/src/api/store/paypal/create-order/route.js.map +1 -1
  13. package/.medusa/server/src/modules/paypal/migrations/20270101090000_set_paypal_environment_default_live.d.ts +6 -0
  14. package/.medusa/server/src/modules/paypal/migrations/20270101090000_set_paypal_environment_default_live.d.ts.map +1 -0
  15. package/.medusa/server/src/modules/paypal/migrations/20270101090000_set_paypal_environment_default_live.js +14 -0
  16. package/.medusa/server/src/modules/paypal/migrations/20270101090000_set_paypal_environment_default_live.js.map +1 -0
  17. package/.medusa/server/src/modules/paypal/service.d.ts +2 -4
  18. package/.medusa/server/src/modules/paypal/service.d.ts.map +1 -1
  19. package/.medusa/server/src/modules/paypal/service.js +8 -46
  20. package/.medusa/server/src/modules/paypal/service.js.map +1 -1
  21. package/README.md +130 -102
  22. package/package.json +1 -1
  23. package/src/admin/routes/settings/paypal/additional-settings/page.tsx +0 -2
  24. package/src/admin/routes/settings/paypal/connection/page.tsx +25 -21
  25. package/src/admin/routes/settings/paypal/paypal-settings/page.tsx +3 -126
  26. package/src/api/admin/paypal/environment/route.ts +1 -1
  27. package/src/api/admin/paypal/onboarding-status/route.ts +1 -1
  28. package/src/api/store/paypal/config/route.ts +0 -4
  29. package/src/api/store/paypal/create-order/route.ts +34 -7
  30. package/src/modules/paypal/migrations/20270101090000_set_paypal_environment_default_live.ts +11 -0
  31. package/src/modules/paypal/service.ts +9 -51
@@ -136,6 +136,12 @@ export async function POST(req: MedusaRequest, res: MedusaResponse) {
136
136
  "gift_card_total",
137
137
  "currency_code",
138
138
  "region.currency_code",
139
+ "items.title",
140
+ "items.quantity",
141
+ "items.unit_price",
142
+ "items.subtotal",
143
+ "items.tax_total",
144
+ "items.total",
139
145
  ],
140
146
  filters: { id: cartId },
141
147
  })
@@ -211,14 +217,15 @@ export async function POST(req: MedusaRequest, res: MedusaResponse) {
211
217
  : landingPageRaw === "no_preference"
212
218
  ? "NO_PREFERENCE"
213
219
  : undefined
214
- const skipReview =
215
- typeof additionalSettings.skipOrderReviewPage === "boolean"
216
- ? additionalSettings.skipOrderReviewPage
217
- : undefined
218
220
  const requireInstantPayment =
219
221
  typeof additionalSettings.requireInstantPayment === "boolean"
220
222
  ? additionalSettings.requireInstantPayment
221
223
  : undefined
224
+ const sendItemDetails = additionalSettings.sendItemDetails !== false
225
+ const statementName =
226
+ typeof additionalSettings.creditCardStatementName === "string"
227
+ ? additionalSettings.creditCardStatementName.trim()
228
+ : ""
222
229
  const invoicePrefix =
223
230
  typeof additionalSettings.invoicePrefix === "string"
224
231
  ? additionalSettings.invoicePrefix
@@ -236,9 +243,6 @@ export async function POST(req: MedusaRequest, res: MedusaResponse) {
236
243
  const applicationContext: Record<string, any> = {
237
244
  ...(brandName ? { brand_name: brandName } : {}),
238
245
  ...(landingPage ? { landing_page: landingPage } : {}),
239
- ...(typeof skipReview === "boolean"
240
- ? { user_action: skipReview ? "PAY_NOW" : "CONTINUE" }
241
- : {}),
242
246
  ...(requireInstantPayment ? { payment_method_preference: "IMMEDIATE_PAYMENT_REQUIRED" } : {}),
243
247
  ...(returnUrl ? { return_url: returnUrl } : {}),
244
248
  ...(cancelUrl ? { cancel_url: cancelUrl } : {}),
@@ -280,6 +284,27 @@ export async function POST(req: MedusaRequest, res: MedusaResponse) {
280
284
  }
281
285
  }
282
286
 
287
+ const lineItems = Array.isArray((cart as any).items) ? (cart as any).items : []
288
+ const purchaseItems = sendItemDetails
289
+ ? lineItems
290
+ .map((item: any) => {
291
+ const quantity = Number(item?.quantity || 0)
292
+ const unitMinor = Number(item?.unit_price || 0)
293
+ if (!quantity || Number.isNaN(quantity) || Number.isNaN(unitMinor)) {
294
+ return null
295
+ }
296
+ return {
297
+ name: String(item?.title || "Item").slice(0, 127),
298
+ quantity: String(Math.max(1, quantity)),
299
+ unit_amount: {
300
+ currency_code: currency,
301
+ value: formatAmountForPayPal(unitMinor, currency),
302
+ },
303
+ }
304
+ })
305
+ .filter(Boolean)
306
+ : []
307
+
283
308
  const { accessToken, base } = await getPayPalAccessToken({
284
309
  environment: creds.environment,
285
310
  client_id: creds.client_id,
@@ -301,11 +326,13 @@ export async function POST(req: MedusaRequest, res: MedusaResponse) {
301
326
  {
302
327
  reference_id: cart.id,
303
328
  invoice_id: invoiceId,
329
+ ...(statementName ? { soft_descriptor: statementName.slice(0, 22) } : {}),
304
330
  amount: {
305
331
  currency_code: currency,
306
332
  value,
307
333
  ...(Object.keys(breakdown).length > 0 ? { breakdown } : {}),
308
334
  },
335
+ ...(purchaseItems.length > 0 ? { items: purchaseItems } : {}),
309
336
  },
310
337
  ],
311
338
  ...(threeDsMethod
@@ -0,0 +1,11 @@
1
+ import { Migration } from "@mikro-orm/migrations"
2
+
3
+ export class Migration20270101090000 extends Migration {
4
+ override async up(): Promise<void> {
5
+ this.addSql(`alter table if exists "paypal_connection" alter column "environment" set default 'live';`)
6
+ }
7
+
8
+ override async down(): Promise<void> {
9
+ this.addSql(`alter table if exists "paypal_connection" alter column "environment" set default 'sandbox';`)
10
+ }
11
+ }
@@ -159,7 +159,7 @@ class PayPalModuleService extends MedusaService({
159
159
 
160
160
  /**
161
161
  * We keep a single row in DB and store the currently selected environment there.
162
- * If no row exists yet, default to sandbox.
162
+ * If no row exists yet, default to live (production).
163
163
  */
164
164
  private async getCurrentRow(): Promise<any | null> {
165
165
  const rows = await this.listPayPalConnections({})
@@ -169,32 +169,25 @@ class PayPalModuleService extends MedusaService({
169
169
  private async getCurrentEnvironment(): Promise<Environment> {
170
170
  try {
171
171
  const row = await this.getCurrentRow()
172
- const env = (row?.environment as Environment) || "sandbox"
173
- return env === "live" ? "live" : "sandbox"
172
+ const env = (row?.environment as Environment) || "live"
173
+ return env === "sandbox" ? "sandbox" : "live"
174
174
  } catch {
175
- return "sandbox"
175
+ return "live"
176
176
  }
177
177
  }
178
178
 
179
179
  private getEnvCreds(
180
180
  row: any,
181
181
  env: Environment
182
- ): { clientId?: string; clientSecret?: string; merchantId?: string } {
182
+ ): { clientId?: string; clientSecret?: string } {
183
183
  const meta = (row?.metadata || {}) as any
184
184
  const creds = meta?.credentials?.[env] || {}
185
185
  return {
186
186
  clientId: creds.client_id || creds.clientId || undefined,
187
187
  clientSecret: creds.client_secret || creds.clientSecret || undefined,
188
- merchantId: creds.merchant_id || creds.merchantId || undefined,
189
188
  }
190
189
  }
191
190
 
192
- private getMerchantId(row: any, env: Environment) {
193
- const meta = (row?.metadata || {}) as any
194
- const creds = this.getEnvCreds(row, env)
195
- return creds.merchantId || meta?.merchant_id || meta?.merchantId || undefined
196
- }
197
-
198
191
  private async fetchMerchantIntegrationDetails(env: Environment, merchantId: string) {
199
192
  const partnerMerchantId = await this.getPartnerMerchantId(env)
200
193
  if (!partnerMerchantId) {
@@ -256,9 +249,9 @@ class PayPalModuleService extends MedusaService({
256
249
  */
257
250
 
258
251
  async setEnvironment(env: Environment) {
259
- const nextEnv: Environment = env === "live" ? "live" : "sandbox"
252
+ const nextEnv: Environment = env === "sandbox" ? "sandbox" : "live"
260
253
  const row = await this.getCurrentRow()
261
- const previousEnv = (row?.environment as Environment) || "sandbox"
254
+ const previousEnv = (row?.environment as Environment) || "live"
262
255
 
263
256
  if (!row) {
264
257
  // Create a row with no credentials yet for either environment
@@ -586,8 +579,6 @@ class PayPalModuleService extends MedusaService({
586
579
 
587
580
  const clientId = String(credJson.client_id || "")
588
581
  const clientSecret = String(credJson.client_secret || "")
589
- const payerId = String(credJson.payer_id || "")
590
-
591
582
  if (!clientId || !clientSecret) {
592
583
  throw new Error(
593
584
  `PayPal credentials response missing client_id/client_secret. Keys: ${Object.keys(credJson || {}).join(", ")}`
@@ -597,19 +588,6 @@ class PayPalModuleService extends MedusaService({
597
588
  // 4) Save seller credentials (marks status = connected)
598
589
  await this.saveSellerCredentials({ clientId, clientSecret })
599
590
 
600
- // 5) Store payer_id as merchant_id in metadata (optional)
601
- if (payerId) {
602
- const row = await this.getCurrentRow()
603
- if (row) {
604
- const meta = (row.metadata || {}) as any
605
- const creds = { ...(meta.credentials || {}) }
606
- creds[env] = { ...(creds[env] || {}), merchant_id: payerId }
607
- await this.updatePayPalConnections({
608
- id: row.id,
609
- metadata: { ...meta, credentials: creds, merchant_id: payerId },
610
- })
611
- }
612
- }
613
591
  }
614
592
 
615
593
 
@@ -844,7 +822,7 @@ class PayPalModuleService extends MedusaService({
844
822
 
845
823
  const updated = await this.getCurrentRow()
846
824
  if (updated) {
847
- await this.syncRowFieldsFromMetadata(updated, (updated.environment as Environment) || "sandbox")
825
+ await this.syncRowFieldsFromMetadata(updated, (updated.environment as Environment) || "live")
848
826
  }
849
827
 
850
828
  await this.recordAuditEvent("credentials_rotated", {
@@ -864,26 +842,7 @@ class PayPalModuleService extends MedusaService({
864
842
 
865
843
  const c = this.getEnvCreds(row, env)
866
844
  const hasCreds = !!(c.clientId && c.clientSecret)
867
- const merchantId = this.getMerchantId(row, env)
868
- let sellerEmail: string | null = null
869
-
870
- if (hasCreds && merchantId) {
871
- try {
872
- const merchantInfo = await this.fetchMerchantIntegrationDetails(env, merchantId)
873
- sellerEmail = String(
874
- merchantInfo?.primary_email ||
875
- merchantInfo?.merchant_email ||
876
- merchantInfo?.email ||
877
- merchantInfo?.primaryEmail ||
878
- ""
879
- )
880
- if (!sellerEmail) {
881
- sellerEmail = null
882
- }
883
- } catch (error) {
884
- console.warn("[paypal_onboarding] failed to fetch merchant integration details", error)
885
- }
886
- }
845
+ const sellerEmail: string | null = null
887
846
 
888
847
  return {
889
848
  environment: env,
@@ -1091,7 +1050,6 @@ class PayPalModuleService extends MedusaService({
1091
1050
  environment: env,
1092
1051
  client_id: c.clientId,
1093
1052
  client_secret: clientSecret,
1094
- merchant_id: c.merchantId,
1095
1053
  }
1096
1054
  }
1097
1055