@easypayment/medusa-payment-paypal 0.9.4 → 0.9.6

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 (190) hide show
  1. package/.medusa/server/src/admin/index.d.ts +2 -0
  2. package/.medusa/server/src/admin/index.d.ts.map +1 -0
  3. package/.medusa/server/src/admin/index.js +190 -233
  4. package/.medusa/server/src/admin/index.js.map +1 -0
  5. package/.medusa/server/src/admin/index.mjs +191 -234
  6. package/.medusa/server/src/admin/routes/settings/paypal/_components/FieldRow.d.ts +8 -0
  7. package/.medusa/server/src/admin/routes/settings/paypal/_components/FieldRow.d.ts.map +1 -0
  8. package/.medusa/server/src/admin/routes/settings/paypal/_components/FieldRow.js +8 -0
  9. package/.medusa/server/src/admin/routes/settings/paypal/_components/FieldRow.js.map +1 -0
  10. package/.medusa/server/src/admin/routes/settings/paypal/_components/SectionCard.d.ts +8 -0
  11. package/.medusa/server/src/admin/routes/settings/paypal/_components/SectionCard.d.ts.map +1 -0
  12. package/.medusa/server/src/admin/routes/settings/paypal/_components/SectionCard.js +8 -0
  13. package/.medusa/server/src/admin/routes/settings/paypal/_components/SectionCard.js.map +1 -0
  14. package/.medusa/server/src/admin/routes/settings/paypal/_components/Tabs.d.ts +2 -0
  15. package/.medusa/server/src/admin/routes/settings/paypal/_components/Tabs.d.ts.map +1 -0
  16. package/.medusa/server/src/admin/routes/settings/paypal/_components/Tabs.js +25 -0
  17. package/.medusa/server/src/admin/routes/settings/paypal/_components/Tabs.js.map +1 -0
  18. package/.medusa/server/src/admin/routes/settings/paypal/_components/Toast.d.ts +12 -0
  19. package/.medusa/server/src/admin/routes/settings/paypal/_components/Toast.d.ts.map +1 -0
  20. package/.medusa/server/src/admin/routes/settings/paypal/_components/Toast.js +22 -0
  21. package/.medusa/server/src/admin/routes/settings/paypal/_components/Toast.js.map +1 -0
  22. package/.medusa/server/src/admin/routes/settings/paypal/_utils/adminFetch.d.ts +7 -0
  23. package/.medusa/server/src/admin/routes/settings/paypal/_utils/adminFetch.d.ts.map +1 -0
  24. package/.medusa/server/src/admin/routes/settings/paypal/_utils/adminFetch.js +40 -0
  25. package/.medusa/server/src/admin/routes/settings/paypal/_utils/adminFetch.js.map +1 -0
  26. package/.medusa/server/src/admin/routes/settings/paypal/additional-settings/page.d.ts +2 -0
  27. package/.medusa/server/src/admin/routes/settings/paypal/additional-settings/page.d.ts.map +1 -0
  28. package/.medusa/server/src/admin/routes/settings/paypal/additional-settings/page.js +76 -0
  29. package/.medusa/server/src/admin/routes/settings/paypal/additional-settings/page.js.map +1 -0
  30. package/.medusa/server/src/admin/routes/settings/paypal/advanced-card-payments/page.d.ts +2 -0
  31. package/.medusa/server/src/admin/routes/settings/paypal/advanced-card-payments/page.d.ts.map +1 -0
  32. package/.medusa/server/src/admin/routes/settings/paypal/advanced-card-payments/page.js +81 -0
  33. package/.medusa/server/src/admin/routes/settings/paypal/advanced-card-payments/page.js.map +1 -0
  34. package/.medusa/server/src/admin/routes/settings/paypal/apple-pay/page.d.ts +2 -0
  35. package/.medusa/server/src/admin/routes/settings/paypal/apple-pay/page.d.ts.map +1 -0
  36. package/.medusa/server/src/admin/routes/settings/paypal/apple-pay/page.js +9 -0
  37. package/.medusa/server/src/admin/routes/settings/paypal/apple-pay/page.js.map +1 -0
  38. package/.medusa/server/src/admin/routes/settings/paypal/connection/page.d.ts +20 -0
  39. package/.medusa/server/src/admin/routes/settings/paypal/connection/page.d.ts.map +1 -0
  40. package/.medusa/server/src/admin/routes/settings/paypal/connection/page.js +440 -0
  41. package/.medusa/server/src/admin/routes/settings/paypal/connection/page.js.map +1 -0
  42. package/.medusa/server/src/admin/routes/settings/paypal/google-pay/page.d.ts +2 -0
  43. package/.medusa/server/src/admin/routes/settings/paypal/google-pay/page.d.ts.map +1 -0
  44. package/.medusa/server/src/admin/routes/settings/paypal/google-pay/page.js +9 -0
  45. package/.medusa/server/src/admin/routes/settings/paypal/google-pay/page.js.map +1 -0
  46. package/.medusa/server/src/admin/routes/settings/paypal/page.d.ts +4 -0
  47. package/.medusa/server/src/admin/routes/settings/paypal/page.d.ts.map +1 -0
  48. package/.medusa/server/src/admin/routes/settings/paypal/page.js +14 -0
  49. package/.medusa/server/src/admin/routes/settings/paypal/page.js.map +1 -0
  50. package/.medusa/server/src/admin/routes/settings/paypal/pay-later-messaging/page.d.ts +2 -0
  51. package/.medusa/server/src/admin/routes/settings/paypal/pay-later-messaging/page.d.ts.map +1 -0
  52. package/.medusa/server/src/admin/routes/settings/paypal/pay-later-messaging/page.js +9 -0
  53. package/.medusa/server/src/admin/routes/settings/paypal/pay-later-messaging/page.js.map +1 -0
  54. package/.medusa/server/src/admin/routes/settings/paypal/paypal-settings/page.d.ts +2 -0
  55. package/.medusa/server/src/admin/routes/settings/paypal/paypal-settings/page.d.ts.map +1 -0
  56. package/.medusa/server/src/admin/routes/settings/paypal/paypal-settings/page.js +109 -0
  57. package/.medusa/server/src/admin/routes/settings/paypal/paypal-settings/page.js.map +1 -0
  58. package/.medusa/server/src/api/admin/payment-collections/[id]/payment-sessions/route.d.ts +1 -1
  59. package/.medusa/server/src/api/admin/payment-collections/[id]/payment-sessions/route.d.ts.map +1 -1
  60. package/.medusa/server/src/api/admin/payment-collections/[id]/payment-sessions/route.js +24 -9
  61. package/.medusa/server/src/api/admin/payment-collections/[id]/payment-sessions/route.js.map +1 -1
  62. package/.medusa/server/src/api/admin/paypal/disconnect/route.d.ts.map +1 -1
  63. package/.medusa/server/src/api/admin/paypal/disconnect/route.js +10 -3
  64. package/.medusa/server/src/api/admin/paypal/disconnect/route.js.map +1 -1
  65. package/.medusa/server/src/api/admin/paypal/environment/route.js +2 -2
  66. package/.medusa/server/src/api/admin/paypal/environment/route.js.map +1 -1
  67. package/.medusa/server/src/api/admin/paypal/onboard-complete/route.d.ts.map +1 -1
  68. package/.medusa/server/src/api/admin/paypal/onboard-complete/route.js +3 -2
  69. package/.medusa/server/src/api/admin/paypal/onboard-complete/route.js.map +1 -1
  70. package/.medusa/server/src/api/admin/paypal/onboarding-link/route.js +1 -1
  71. package/.medusa/server/src/api/admin/paypal/onboarding-link/route.js.map +1 -1
  72. package/.medusa/server/src/api/admin/paypal/onboarding-status/route.js +4 -4
  73. package/.medusa/server/src/api/admin/paypal/onboarding-status/route.js.map +1 -1
  74. package/.medusa/server/src/api/admin/paypal/save-credentials/route.d.ts.map +1 -1
  75. package/.medusa/server/src/api/admin/paypal/save-credentials/route.js +21 -8
  76. package/.medusa/server/src/api/admin/paypal/save-credentials/route.js.map +1 -1
  77. package/.medusa/server/src/api/admin/paypal/settings/route.d.ts.map +1 -1
  78. package/.medusa/server/src/api/admin/paypal/settings/route.js +34 -4
  79. package/.medusa/server/src/api/admin/paypal/settings/route.js.map +1 -1
  80. package/.medusa/server/src/api/admin/paypal/status/route.d.ts.map +1 -1
  81. package/.medusa/server/src/api/admin/paypal/status/route.js +11 -5
  82. package/.medusa/server/src/api/admin/paypal/status/route.js.map +1 -1
  83. package/.medusa/server/src/api/store/paypal/capture-order/route.d.ts.map +1 -1
  84. package/.medusa/server/src/api/store/paypal/capture-order/route.js +21 -3
  85. package/.medusa/server/src/api/store/paypal/capture-order/route.js.map +1 -1
  86. package/.medusa/server/src/api/store/paypal/config/route.js +2 -2
  87. package/.medusa/server/src/api/store/paypal/config/route.js.map +1 -1
  88. package/.medusa/server/src/api/store/paypal/create-order/route.d.ts.map +1 -1
  89. package/.medusa/server/src/api/store/paypal/create-order/route.js +13 -9
  90. package/.medusa/server/src/api/store/paypal/create-order/route.js.map +1 -1
  91. package/.medusa/server/src/api/store/paypal/settings/route.js +3 -3
  92. package/.medusa/server/src/api/store/paypal/settings/route.js.map +1 -1
  93. package/.medusa/server/src/api/store/paypal/webhook/route.d.ts.map +1 -1
  94. package/.medusa/server/src/api/store/paypal/webhook/route.js +10 -3
  95. package/.medusa/server/src/api/store/paypal/webhook/route.js.map +1 -1
  96. package/.medusa/server/src/api/store/paypal-complete/route.d.ts.map +1 -1
  97. package/.medusa/server/src/api/store/paypal-complete/route.js +7 -4
  98. package/.medusa/server/src/api/store/paypal-complete/route.js.map +1 -1
  99. package/.medusa/server/src/modules/paypal/clients/paypal-seller.client.js +3 -3
  100. package/.medusa/server/src/modules/paypal/clients/paypal-seller.client.js.map +1 -1
  101. package/.medusa/server/src/modules/paypal/migrations/20270101090000_set_paypal_environment_default_live.d.ts +1 -1
  102. package/.medusa/server/src/modules/paypal/migrations/20270101090000_set_paypal_environment_default_live.d.ts.map +1 -1
  103. package/.medusa/server/src/modules/paypal/migrations/20270101090000_set_paypal_environment_default_live.js +1 -1
  104. package/.medusa/server/src/modules/paypal/migrations/20270101090000_set_paypal_environment_default_live.js.map +1 -1
  105. package/.medusa/server/src/modules/paypal/migrations/20270102090000_add_paypal_seller_email.d.ts +1 -1
  106. package/.medusa/server/src/modules/paypal/migrations/20270102090000_add_paypal_seller_email.d.ts.map +1 -1
  107. package/.medusa/server/src/modules/paypal/migrations/20270102090000_add_paypal_seller_email.js +1 -1
  108. package/.medusa/server/src/modules/paypal/migrations/20270102090000_add_paypal_seller_email.js.map +1 -1
  109. package/.medusa/server/src/modules/paypal/migrations/20270103090000_add_paypal_seller_merchant_id.d.ts +1 -1
  110. package/.medusa/server/src/modules/paypal/migrations/20270103090000_add_paypal_seller_merchant_id.d.ts.map +1 -1
  111. package/.medusa/server/src/modules/paypal/migrations/20270103090000_add_paypal_seller_merchant_id.js +1 -1
  112. package/.medusa/server/src/modules/paypal/migrations/20270103090000_add_paypal_seller_merchant_id.js.map +1 -1
  113. package/.medusa/server/src/modules/paypal/migrations/20270202000000_align_nullable_defaults.d.ts +6 -0
  114. package/.medusa/server/src/modules/paypal/migrations/20270202000000_align_nullable_defaults.d.ts.map +1 -0
  115. package/.medusa/server/src/modules/paypal/migrations/20270202000000_align_nullable_defaults.js +25 -0
  116. package/.medusa/server/src/modules/paypal/migrations/20270202000000_align_nullable_defaults.js.map +1 -0
  117. package/.medusa/server/src/modules/paypal/models/paypal_connection.d.ts +1 -1
  118. package/.medusa/server/src/modules/paypal/models/paypal_connection.js +3 -3
  119. package/.medusa/server/src/modules/paypal/models/paypal_connection.js.map +1 -1
  120. package/.medusa/server/src/modules/paypal/models/paypal_metric.d.ts +1 -1
  121. package/.medusa/server/src/modules/paypal/models/paypal_metric.js +1 -1
  122. package/.medusa/server/src/modules/paypal/models/paypal_metric.js.map +1 -1
  123. package/.medusa/server/src/modules/paypal/models/paypal_webhook_event.d.ts +1 -1
  124. package/.medusa/server/src/modules/paypal/models/paypal_webhook_event.js +1 -1
  125. package/.medusa/server/src/modules/paypal/models/paypal_webhook_event.js.map +1 -1
  126. package/.medusa/server/src/modules/paypal/payment-provider/card-service.d.ts.map +1 -1
  127. package/.medusa/server/src/modules/paypal/payment-provider/card-service.js +95 -76
  128. package/.medusa/server/src/modules/paypal/payment-provider/card-service.js.map +1 -1
  129. package/.medusa/server/src/modules/paypal/payment-provider/service.d.ts.map +1 -1
  130. package/.medusa/server/src/modules/paypal/payment-provider/service.js +39 -89
  131. package/.medusa/server/src/modules/paypal/payment-provider/service.js.map +1 -1
  132. package/.medusa/server/src/modules/paypal/payment-provider/webhook-utils.d.ts.map +1 -1
  133. package/.medusa/server/src/modules/paypal/payment-provider/webhook-utils.js +7 -0
  134. package/.medusa/server/src/modules/paypal/payment-provider/webhook-utils.js.map +1 -1
  135. package/.medusa/server/src/modules/paypal/service.d.ts +10 -8
  136. package/.medusa/server/src/modules/paypal/service.d.ts.map +1 -1
  137. package/.medusa/server/src/modules/paypal/service.js +56 -51
  138. package/.medusa/server/src/modules/paypal/service.js.map +1 -1
  139. package/.medusa/server/src/modules/paypal/types/config.d.ts.map +1 -1
  140. package/.medusa/server/src/modules/paypal/types/config.js +11 -2
  141. package/.medusa/server/src/modules/paypal/types/config.js.map +1 -1
  142. package/.medusa/server/src/modules/paypal/utils/paypal-auth.d.ts.map +1 -1
  143. package/.medusa/server/src/modules/paypal/utils/paypal-auth.js +1 -0
  144. package/.medusa/server/src/modules/paypal/utils/paypal-auth.js.map +1 -1
  145. package/.medusa/server/src/modules/paypal/webhook-processor.d.ts.map +1 -1
  146. package/.medusa/server/src/modules/paypal/webhook-processor.js +1 -1
  147. package/.medusa/server/src/modules/paypal/webhook-processor.js.map +1 -1
  148. package/.medusa/server/src/subscribers/paypal-order-invoice.js +4 -4
  149. package/.medusa/server/src/subscribers/paypal-order-invoice.js.map +1 -1
  150. package/package.json +1 -1
  151. package/src/admin/index.ts +1 -7
  152. package/src/admin/routes/settings/paypal/_components/FieldRow.tsx +29 -0
  153. package/src/admin/routes/settings/paypal/_components/SectionCard.tsx +26 -0
  154. package/src/admin/routes/settings/paypal/_components/Toast.tsx +4 -3
  155. package/src/admin/routes/settings/paypal/_utils/adminFetch.ts +32 -0
  156. package/src/admin/routes/settings/paypal/additional-settings/page.tsx +23 -83
  157. package/src/admin/routes/settings/paypal/advanced-card-payments/page.tsx +17 -77
  158. package/src/admin/routes/settings/paypal/connection/page.tsx +88 -45
  159. package/src/admin/routes/settings/paypal/paypal-settings/page.tsx +23 -101
  160. package/src/api/admin/payment-collections/[id]/payment-sessions/route.ts +26 -9
  161. package/src/api/admin/paypal/disconnect/route.ts +9 -3
  162. package/src/api/admin/paypal/environment/route.ts +2 -2
  163. package/src/api/admin/paypal/onboard-complete/route.ts +4 -3
  164. package/src/api/admin/paypal/onboarding-link/route.ts +1 -1
  165. package/src/api/admin/paypal/onboarding-status/route.ts +5 -5
  166. package/src/api/admin/paypal/save-credentials/route.ts +24 -9
  167. package/src/api/admin/paypal/settings/route.ts +35 -4
  168. package/src/api/admin/paypal/status/route.ts +10 -5
  169. package/src/api/store/paypal/capture-order/route.ts +27 -3
  170. package/src/api/store/paypal/config/route.ts +2 -2
  171. package/src/api/store/paypal/create-order/route.ts +16 -10
  172. package/src/api/store/paypal/settings/route.ts +3 -3
  173. package/src/api/store/paypal/webhook/route.ts +13 -3
  174. package/src/api/store/paypal-complete/route.ts +8 -4
  175. package/src/modules/paypal/clients/paypal-seller.client.ts +3 -3
  176. package/src/modules/paypal/migrations/20270101090000_set_paypal_environment_default_live.ts +1 -1
  177. package/src/modules/paypal/migrations/20270102090000_add_paypal_seller_email.ts +1 -1
  178. package/src/modules/paypal/migrations/20270103090000_add_paypal_seller_merchant_id.ts +1 -1
  179. package/src/modules/paypal/migrations/20270202000000_align_nullable_defaults.ts +44 -0
  180. package/src/modules/paypal/models/paypal_connection.ts +3 -3
  181. package/src/modules/paypal/models/paypal_metric.ts +1 -1
  182. package/src/modules/paypal/models/paypal_webhook_event.ts +1 -1
  183. package/src/modules/paypal/payment-provider/card-service.ts +120 -80
  184. package/src/modules/paypal/payment-provider/service.ts +44 -93
  185. package/src/modules/paypal/payment-provider/webhook-utils.ts +9 -0
  186. package/src/modules/paypal/service.ts +79 -66
  187. package/src/modules/paypal/types/config.ts +18 -2
  188. package/src/modules/paypal/utils/paypal-auth.ts +1 -0
  189. package/src/modules/paypal/webhook-processor.ts +8 -5
  190. package/src/subscribers/paypal-order-invoice.ts +4 -4
@@ -52,6 +52,15 @@ function resolveAmount(resource: any): number | undefined {
52
52
  return Number.isFinite(parsed) ? parsed : undefined
53
53
  }
54
54
 
55
+ function resolveCurrencyCode(resource: any): string | undefined {
56
+ const amount =
57
+ resource?.amount ||
58
+ resource?.purchase_units?.[0]?.amount ||
59
+ resource?.purchase_units?.[0]?.payments?.captures?.[0]?.amount ||
60
+ resource?.purchase_units?.[0]?.payments?.authorizations?.[0]?.amount
61
+ return amount?.currency_code || undefined
62
+ }
63
+
55
64
  function resolveEventType(payload: ProviderWebhookPayload["payload"]) {
56
65
  const raw = payload as { event_type?: string; eventType?: string }
57
66
  return raw?.event_type || raw?.eventType
@@ -22,6 +22,7 @@ class PayPalModuleService extends MedusaService({
22
22
  PayPalWebhookEvent,
23
23
  }) {
24
24
  protected cfg = getPayPalConfig()
25
+ private tokenRefreshPromise: Promise<string> | null = null
25
26
 
26
27
  private get bnCode(): string {
27
28
  return this.cfg.bnCode || "MBJTechnolabs_SI_SPB"
@@ -142,10 +143,14 @@ class PayPalModuleService extends MedusaService({
142
143
  }
143
144
  }
144
145
 
145
- private extractSellerEmail(...candidates: any[]): string | null {
146
+ private extractSellerEmail(...candidates: unknown[]): string | null {
146
147
  const queue = [...candidates]
148
+ const seen = new WeakSet<object>()
149
+ const MAX_ITERATIONS = 500
147
150
 
148
- while (queue.length > 0) {
151
+ let iterations = 0
152
+ while (queue.length > 0 && iterations < MAX_ITERATIONS) {
153
+ iterations++
149
154
  const value = queue.shift()
150
155
  if (!value) {
151
156
  continue
@@ -159,34 +164,41 @@ class PayPalModuleService extends MedusaService({
159
164
  continue
160
165
  }
161
166
 
167
+ if (typeof value !== "object") {
168
+ continue
169
+ }
170
+
171
+ if (seen.has(value as object)) {
172
+ continue
173
+ }
174
+ seen.add(value as object)
175
+
162
176
  if (Array.isArray(value)) {
163
177
  queue.push(...value)
164
178
  continue
165
179
  }
166
180
 
167
- if (typeof value === "object") {
168
- const obj = value as Record<string, any>
169
- const prioritized = [
170
- obj.email,
171
- obj.primary_email,
172
- obj.merchant_email,
173
- obj.email_address,
174
- obj.account_email,
175
- obj.contact_email,
176
- obj.value,
177
- obj.address,
178
- ]
179
- queue.push(...prioritized)
180
-
181
- for (const [k, v] of Object.entries(obj)) {
182
- const key = String(k).toLowerCase()
183
- if (key.includes("email") || key.includes("address")) {
184
- queue.push(v)
185
- }
181
+ const obj = value as Record<string, unknown>
182
+ const prioritized = [
183
+ obj.email,
184
+ obj.primary_email,
185
+ obj.merchant_email,
186
+ obj.email_address,
187
+ obj.account_email,
188
+ obj.contact_email,
189
+ obj.value,
190
+ obj.address,
191
+ ]
192
+ queue.push(...prioritized)
193
+
194
+ for (const [k, v] of Object.entries(obj)) {
195
+ const key = String(k).toLowerCase()
196
+ if (key.includes("email") || key.includes("address")) {
197
+ queue.push(v)
186
198
  }
187
-
188
- queue.push(...Object.values(obj))
189
199
  }
200
+
201
+ queue.push(...Object.values(obj))
190
202
  }
191
203
 
192
204
  return null
@@ -477,8 +489,7 @@ class PayPalModuleService extends MedusaService({
477
489
 
478
490
  const products = input?.products?.length ? input.products : ["PPCP"]
479
491
 
480
- products.forEach((p, i) => {
481
- form.append(`products[${i}]`, p)
492
+ products.forEach((p) => {
482
493
  form.append("products[]", p)
483
494
  })
484
495
 
@@ -758,16 +769,10 @@ class PayPalModuleService extends MedusaService({
758
769
 
759
770
  const nextCreds = {
760
771
  client_id: input.clientId,
761
- clientId: input.clientId,
762
772
  client_secret: input.clientSecret,
763
- clientSecret: input.clientSecret,
764
- merchantId: nextSellerMerchantId,
765
773
  merchant_id: nextSellerMerchantId,
766
- payer_id: nextSellerMerchantId,
767
774
  seller_merchant_id: nextSellerMerchantId,
768
- sellerMerchantId: nextSellerMerchantId,
769
775
  seller_email: nextSellerEmail,
770
- sellerEmail: nextSellerEmail,
771
776
  }
772
777
 
773
778
  if (!row) {
@@ -1082,19 +1087,31 @@ class PayPalModuleService extends MedusaService({
1082
1087
 
1083
1088
  async getAppAccessToken(): Promise<string> {
1084
1089
  const row = await this.getCurrentRow()
1085
- const env = await this.getCurrentEnvironment()
1086
- const creds = await this.getActiveCredentials()
1087
1090
 
1088
1091
  if (!row) {
1089
1092
  throw new Error("PayPal connection row not found. Please complete onboarding.")
1090
1093
  }
1091
1094
 
1092
- const expiresAt = row.app_access_token_expires_at ? new Date(row.app_access_token_expires_at as any) : null
1095
+ const expiresAt = row.app_access_token_expires_at ? new Date(row.app_access_token_expires_at as string) : null
1093
1096
  if (row.app_access_token && expiresAt) {
1094
1097
  const msLeft = expiresAt.getTime() - Date.now()
1095
- if (msLeft > 2 * 60 * 1000) return row.app_access_token
1098
+ if (msLeft > 2 * 60 * 1000) return row.app_access_token as string
1099
+ }
1100
+
1101
+ if (this.tokenRefreshPromise) {
1102
+ return this.tokenRefreshPromise
1096
1103
  }
1097
1104
 
1105
+ this.tokenRefreshPromise = this.refreshAccessToken(row).finally(() => {
1106
+ this.tokenRefreshPromise = null
1107
+ })
1108
+
1109
+ return this.tokenRefreshPromise
1110
+ }
1111
+
1112
+ private async refreshAccessToken(row: { id: string }): Promise<string> {
1113
+ const env = await this.getCurrentEnvironment()
1114
+ const creds = await this.getActiveCredentials()
1098
1115
  const baseUrl = env === "live" ? "https://api-m.paypal.com" : "https://api-m.sandbox.paypal.com"
1099
1116
  const basic = Buffer.from(`${creds.client_id}:${creds.client_secret}`).toString("base64")
1100
1117
 
@@ -1109,19 +1126,23 @@ class PayPalModuleService extends MedusaService({
1109
1126
  "PayPal-Partner-Attribution-Id": this.bnCode,
1110
1127
  },
1111
1128
  body,
1129
+ signal: AbortSignal.timeout(30_000),
1112
1130
  })
1113
1131
 
1114
1132
  const json = await res.json().catch(() => ({}))
1115
1133
  if (!res.ok) throw new Error(`PayPal client_credentials failed (${res.status}): ${JSON.stringify(json)}`)
1116
1134
 
1117
- const accessToken = String(json.access_token)
1135
+ const accessToken = String(json.access_token || "")
1136
+ if (!accessToken) {
1137
+ throw new Error("PayPal client_credentials succeeded but access_token is missing.")
1138
+ }
1118
1139
  const expiresIn = Number(json.expires_in || 3600)
1119
1140
  const newExpiresAt = new Date(Date.now() + expiresIn * 1000)
1120
1141
 
1121
1142
  await this.updatePayPalConnections({
1122
1143
  id: row.id,
1123
1144
  app_access_token: accessToken,
1124
- app_access_token_expires_at: newExpiresAt as any,
1145
+ app_access_token_expires_at: newExpiresAt as unknown as Date,
1125
1146
  })
1126
1147
 
1127
1148
  return accessToken
@@ -1232,39 +1253,26 @@ class PayPalModuleService extends MedusaService({
1232
1253
  throw new Error("PayPal orderId is required")
1233
1254
  }
1234
1255
 
1235
- const creds = await this.getActiveCredentials()
1256
+ const env = await this.getCurrentEnvironment()
1236
1257
  const base =
1237
- creds.environment === "live"
1258
+ env === "live"
1238
1259
  ? "https://api-m.paypal.com"
1239
1260
  : "https://api-m.sandbox.paypal.com"
1240
- const auth = Buffer.from(`${creds.client_id}:${creds.client_secret}`).toString("base64")
1241
1261
 
1242
- const tokenResp = await fetch(`${base}/v1/oauth2/token`, {
1243
- method: "POST",
1244
- headers: {
1245
- Authorization: `Basic ${auth}`,
1246
- "Content-Type": "application/x-www-form-urlencoded",
1247
- "PayPal-Partner-Attribution-Id": this.bnCode,
1248
- },
1249
- body: "grant_type=client_credentials",
1250
- })
1251
-
1252
- const tokenText = await tokenResp.text()
1253
- if (!tokenResp.ok) {
1254
- throw new Error(`PayPal token error (${tokenResp.status}): ${tokenText}`)
1255
- }
1256
-
1257
- const tokenJson = JSON.parse(tokenText)
1258
- const accessToken = String(tokenJson.access_token)
1262
+ const accessToken = await this.getAppAccessToken()
1259
1263
 
1260
- const resp = await fetch(`${base}/v2/checkout/orders/${orderId}`, {
1261
- method: "GET",
1262
- headers: {
1263
- Authorization: `Bearer ${accessToken}`,
1264
- "Content-Type": "application/json",
1265
- "PayPal-Partner-Attribution-Id": this.bnCode,
1266
- },
1267
- })
1264
+ const resp = await fetch(
1265
+ `${base}/v2/checkout/orders/${encodeURIComponent(orderId)}`,
1266
+ {
1267
+ method: "GET",
1268
+ headers: {
1269
+ Authorization: `Bearer ${accessToken}`,
1270
+ "Content-Type": "application/json",
1271
+ "PayPal-Partner-Attribution-Id": this.bnCode,
1272
+ },
1273
+ signal: AbortSignal.timeout(30_000),
1274
+ }
1275
+ )
1268
1276
 
1269
1277
  const text = await resp.text()
1270
1278
  if (!resp.ok) {
@@ -1303,7 +1311,12 @@ class PayPalModuleService extends MedusaService({
1303
1311
  return { created: true, event: created }
1304
1312
  } catch (error: any) {
1305
1313
  const message = String(error?.message || "")
1306
- if (message.includes("paypal_webhook_event_event_id_unique") || message.includes("unique")) {
1314
+ const code = String(error?.code || "")
1315
+ if (
1316
+ message.includes("paypal_webhook_event_event_id_unique") ||
1317
+ code === "23505" ||
1318
+ (message.includes("unique") && message.includes("event_id"))
1319
+ ) {
1307
1320
  const existing = await this.listPayPalWebhookEvents({ event_id: input.event_id })
1308
1321
  return { created: false, event: existing?.[0] ?? null }
1309
1322
  }
@@ -1,3 +1,5 @@
1
+ import { randomBytes } from "crypto"
2
+
1
3
  export type PayPalModuleConfig = {
2
4
  partnerServiceUrl: string
3
5
  partnerJsUrl: string
@@ -13,17 +15,31 @@ const STATIC_CFG: PayPalModuleConfig = {
13
15
  partnerServiceUrl: "https://mbjtechnolabs.com/ppcp-seller-onboarding/seller-onboarding.php?from=medusa",
14
16
  partnerJsUrl: "https://www.paypal.com/webapps/merchantboarding/js/lib/lightbox/partner.js",
15
17
  backendUrl: "http://localhost:9000",
16
- sellerNonce: "a1233wtergfsdt4365tzrshgfbaewa36AGa1233wtergfsdt4365tzrshgfbaewa36AG",
18
+ sellerNonce: "",
17
19
  bnCode: "MBJTechnolabs_SI_SPB",
18
20
  partnerMerchantIdSandbox: "K6QLN2LPGQRHL",
19
21
  partnerMerchantIdLive: "GT5R877JNBPLL",
20
22
  alertWebhookUrls: [],
21
23
  }
22
24
 
25
+ function generateSellerNonce(): string {
26
+ return randomBytes(32).toString("hex")
27
+ }
28
+
23
29
  export function getPayPalConfig(): PayPalModuleConfig {
30
+ const backendUrl = process.env.MEDUSA_BACKEND_URL || STATIC_CFG.backendUrl
31
+
24
32
  return {
25
33
  ...STATIC_CFG,
26
- backendUrl: process.env.MEDUSA_BACKEND_URL || STATIC_CFG.backendUrl,
34
+ partnerServiceUrl:
35
+ process.env.PAYPAL_PARTNER_SERVICE_URL || STATIC_CFG.partnerServiceUrl,
36
+ backendUrl,
37
+ sellerNonce:
38
+ process.env.PAYPAL_SELLER_NONCE || generateSellerNonce(),
39
+ partnerMerchantIdSandbox:
40
+ process.env.PAYPAL_PARTNER_MERCHANT_ID_SANDBOX || STATIC_CFG.partnerMerchantIdSandbox,
41
+ partnerMerchantIdLive:
42
+ process.env.PAYPAL_PARTNER_MERCHANT_ID_LIVE || STATIC_CFG.partnerMerchantIdLive,
27
43
  alertWebhookUrls:
28
44
  (process.env.PAYPAL_ALERT_WEBHOOK_URLS || "")
29
45
  .split(",")
@@ -21,6 +21,7 @@ export async function getPayPalAccessToken(opts: {
21
21
  "PayPal-Partner-Attribution-Id": BN_CODE,
22
22
  },
23
23
  body: "grant_type=client_credentials",
24
+ signal: AbortSignal.timeout(30_000),
24
25
  })
25
26
  const text = await resp.text()
26
27
  if (!resp.ok) {
@@ -297,11 +297,14 @@ export async function processPayPalWebhookEvent(
297
297
  if (!cartId) {
298
298
  try {
299
299
  const paymentModule = container.resolve(Modules.PAYMENT) as any
300
- const allSessions = await paymentModule.listPaymentSessions({
301
- provider_id: ["pp_paypal_paypal", "pp_paypal_card_paypal_card"],
302
- })
303
- const matchedSession = (allSessions || []).find((s: any) => {
304
- const pp = ((s.data || {}) as Record<string, any>).paypal || {}
300
+ const allSessions = await paymentModule.listPaymentSessions(
301
+ {
302
+ provider_id: ["pp_paypal_paypal", "pp_paypal_card_paypal_card"],
303
+ },
304
+ { take: 200 }
305
+ )
306
+ const matchedSession = (allSessions || []).find((s: Record<string, unknown>) => {
307
+ const pp = ((s.data || {}) as Record<string, unknown>).paypal as Record<string, unknown> || {}
305
308
  if (orderId && pp.order_id === orderId) return true
306
309
  if (captureId && pp.capture_id === captureId) return true
307
310
  return false
@@ -89,7 +89,7 @@ export default async function paypalOrderInvoiceHandler({
89
89
  let currentInvoiceId = ""
90
90
  try {
91
91
  const statusResp = await fetch(
92
- `${base}/v2/checkout/orders/${paypalOrderId}`,
92
+ `${base}/v2/checkout/orders/${encodeURIComponent(paypalOrderId)}`,
93
93
  { headers: { Authorization: `Bearer ${accessToken}` } }
94
94
  )
95
95
  if (statusResp.ok) {
@@ -129,7 +129,7 @@ export default async function paypalOrderInvoiceHandler({
129
129
  }
130
130
 
131
131
  const patchResp = await fetch(
132
- `${base}/v2/checkout/orders/${paypalOrderId}`,
132
+ `${base}/v2/checkout/orders/${encodeURIComponent(paypalOrderId)}`,
133
133
  {
134
134
  method: "PATCH",
135
135
  headers: {
@@ -138,8 +138,8 @@ export default async function paypalOrderInvoiceHandler({
138
138
  },
139
139
  body: JSON.stringify([
140
140
  {
141
- op: "replace",
142
- path: "/purchase_units/@reference_id=='default'/invoice_id",
141
+ op: currentInvoiceId ? "replace" : "add",
142
+ path: "/purchase_units/0/invoice_id",
143
143
  value: invoiceId,
144
144
  },
145
145
  ]),