@easypayment/medusa-payment-paypal 0.7.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 (268) hide show
  1. package/.medusa/server/src/admin/index.js +1267 -0
  2. package/.medusa/server/src/admin/index.mjs +1268 -0
  3. package/.medusa/server/src/api/admin/payment-collections/[id]/payment-sessions/route.d.ts +3 -0
  4. package/.medusa/server/src/api/admin/payment-collections/[id]/payment-sessions/route.d.ts.map +1 -0
  5. package/.medusa/server/src/api/admin/payment-collections/[id]/payment-sessions/route.js +18 -0
  6. package/.medusa/server/src/api/admin/payment-collections/[id]/payment-sessions/route.js.map +1 -0
  7. package/.medusa/server/src/api/admin/paypal/disconnect/route.d.ts +3 -0
  8. package/.medusa/server/src/api/admin/paypal/disconnect/route.d.ts.map +1 -0
  9. package/.medusa/server/src/api/admin/paypal/disconnect/route.js +9 -0
  10. package/.medusa/server/src/api/admin/paypal/disconnect/route.js.map +1 -0
  11. package/.medusa/server/src/api/admin/paypal/environment/route.d.ts +4 -0
  12. package/.medusa/server/src/api/admin/paypal/environment/route.d.ts.map +1 -0
  13. package/.medusa/server/src/api/admin/paypal/environment/route.js +23 -0
  14. package/.medusa/server/src/api/admin/paypal/environment/route.js.map +1 -0
  15. package/.medusa/server/src/api/admin/paypal/onboard-complete/route.d.ts +4 -0
  16. package/.medusa/server/src/api/admin/paypal/onboard-complete/route.d.ts.map +1 -0
  17. package/.medusa/server/src/api/admin/paypal/onboard-complete/route.js +31 -0
  18. package/.medusa/server/src/api/admin/paypal/onboard-complete/route.js.map +1 -0
  19. package/.medusa/server/src/api/admin/paypal/onboarding-link/route.d.ts +4 -0
  20. package/.medusa/server/src/api/admin/paypal/onboarding-link/route.d.ts.map +1 -0
  21. package/.medusa/server/src/api/admin/paypal/onboarding-link/route.js +35 -0
  22. package/.medusa/server/src/api/admin/paypal/onboarding-link/route.js.map +1 -0
  23. package/.medusa/server/src/api/admin/paypal/onboarding-status/route.d.ts +3 -0
  24. package/.medusa/server/src/api/admin/paypal/onboarding-status/route.d.ts.map +1 -0
  25. package/.medusa/server/src/api/admin/paypal/onboarding-status/route.js +19 -0
  26. package/.medusa/server/src/api/admin/paypal/onboarding-status/route.js.map +1 -0
  27. package/.medusa/server/src/api/admin/paypal/save-credentials/route.d.ts +3 -0
  28. package/.medusa/server/src/api/admin/paypal/save-credentials/route.d.ts.map +1 -0
  29. package/.medusa/server/src/api/admin/paypal/save-credentials/route.js +17 -0
  30. package/.medusa/server/src/api/admin/paypal/save-credentials/route.js.map +1 -0
  31. package/.medusa/server/src/api/admin/paypal/settings/route.d.ts +4 -0
  32. package/.medusa/server/src/api/admin/paypal/settings/route.d.ts.map +1 -0
  33. package/.medusa/server/src/api/admin/paypal/settings/route.js +14 -0
  34. package/.medusa/server/src/api/admin/paypal/settings/route.js.map +1 -0
  35. package/.medusa/server/src/api/admin/paypal/status/route.d.ts +3 -0
  36. package/.medusa/server/src/api/admin/paypal/status/route.d.ts.map +1 -0
  37. package/.medusa/server/src/api/admin/paypal/status/route.js +11 -0
  38. package/.medusa/server/src/api/admin/paypal/status/route.js.map +1 -0
  39. package/.medusa/server/src/api/middlewares.d.ts +3 -0
  40. package/.medusa/server/src/api/middlewares.d.ts.map +1 -0
  41. package/.medusa/server/src/api/middlewares.js +16 -0
  42. package/.medusa/server/src/api/middlewares.js.map +1 -0
  43. package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.d.ts +3 -0
  44. package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.d.ts.map +1 -0
  45. package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.js +43 -0
  46. package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.js.map +1 -0
  47. package/.medusa/server/src/api/store/paypal/capture-order/route.d.ts +3 -0
  48. package/.medusa/server/src/api/store/paypal/capture-order/route.d.ts.map +1 -0
  49. package/.medusa/server/src/api/store/paypal/capture-order/route.js +204 -0
  50. package/.medusa/server/src/api/store/paypal/capture-order/route.js.map +1 -0
  51. package/.medusa/server/src/api/store/paypal/config/route.d.ts +3 -0
  52. package/.medusa/server/src/api/store/paypal/config/route.d.ts.map +1 -0
  53. package/.medusa/server/src/api/store/paypal/config/route.js +77 -0
  54. package/.medusa/server/src/api/store/paypal/config/route.js.map +1 -0
  55. package/.medusa/server/src/api/store/paypal/create-order/route.d.ts +3 -0
  56. package/.medusa/server/src/api/store/paypal/create-order/route.d.ts.map +1 -0
  57. package/.medusa/server/src/api/store/paypal/create-order/route.js +361 -0
  58. package/.medusa/server/src/api/store/paypal/create-order/route.js.map +1 -0
  59. package/.medusa/server/src/api/store/paypal/settings/route.d.ts +3 -0
  60. package/.medusa/server/src/api/store/paypal/settings/route.d.ts.map +1 -0
  61. package/.medusa/server/src/api/store/paypal/settings/route.js +20 -0
  62. package/.medusa/server/src/api/store/paypal/settings/route.js.map +1 -0
  63. package/.medusa/server/src/api/store/paypal/webhook/route.d.ts +3 -0
  64. package/.medusa/server/src/api/store/paypal/webhook/route.d.ts.map +1 -0
  65. package/.medusa/server/src/api/store/paypal/webhook/route.js +250 -0
  66. package/.medusa/server/src/api/store/paypal/webhook/route.js.map +1 -0
  67. package/.medusa/server/src/api/store/paypal-complete/route.d.ts +3 -0
  68. package/.medusa/server/src/api/store/paypal-complete/route.d.ts.map +1 -0
  69. package/.medusa/server/src/api/store/paypal-complete/route.js +76 -0
  70. package/.medusa/server/src/api/store/paypal-complete/route.js.map +1 -0
  71. package/.medusa/server/src/index.d.ts +2 -0
  72. package/.medusa/server/src/index.d.ts.map +1 -0
  73. package/.medusa/server/src/index.js +9 -0
  74. package/.medusa/server/src/index.js.map +1 -0
  75. package/.medusa/server/src/jobs/paypal-webhook-retry.d.ts +7 -0
  76. package/.medusa/server/src/jobs/paypal-webhook-retry.d.ts.map +1 -0
  77. package/.medusa/server/src/jobs/paypal-webhook-retry.js +132 -0
  78. package/.medusa/server/src/jobs/paypal-webhook-retry.js.map +1 -0
  79. package/.medusa/server/src/modules/paypal/clients/paypal-seller.client.d.ts +15 -0
  80. package/.medusa/server/src/modules/paypal/clients/paypal-seller.client.d.ts.map +1 -0
  81. package/.medusa/server/src/modules/paypal/clients/paypal-seller.client.js +67 -0
  82. package/.medusa/server/src/modules/paypal/clients/paypal-seller.client.js.map +1 -0
  83. package/.medusa/server/src/modules/paypal/index.d.ts +64 -0
  84. package/.medusa/server/src/modules/paypal/index.d.ts.map +1 -0
  85. package/.medusa/server/src/modules/paypal/index.js +13 -0
  86. package/.medusa/server/src/modules/paypal/index.js.map +1 -0
  87. package/.medusa/server/src/modules/paypal/migrations/20260115120000_create_paypal_connection.d.ts +6 -0
  88. package/.medusa/server/src/modules/paypal/migrations/20260115120000_create_paypal_connection.d.ts.map +1 -0
  89. package/.medusa/server/src/modules/paypal/migrations/20260115120000_create_paypal_connection.js +36 -0
  90. package/.medusa/server/src/modules/paypal/migrations/20260115120000_create_paypal_connection.js.map +1 -0
  91. package/.medusa/server/src/modules/paypal/migrations/20260123090000_create_paypal_settings.d.ts +6 -0
  92. package/.medusa/server/src/modules/paypal/migrations/20260123090000_create_paypal_settings.d.ts.map +1 -0
  93. package/.medusa/server/src/modules/paypal/migrations/20260123090000_create_paypal_settings.js +25 -0
  94. package/.medusa/server/src/modules/paypal/migrations/20260123090000_create_paypal_settings.js.map +1 -0
  95. package/.medusa/server/src/modules/paypal/migrations/20260201090000_create_paypal_webhook_event.d.ts +6 -0
  96. package/.medusa/server/src/modules/paypal/migrations/20260201090000_create_paypal_webhook_event.d.ts.map +1 -0
  97. package/.medusa/server/src/modules/paypal/migrations/20260201090000_create_paypal_webhook_event.js +32 -0
  98. package/.medusa/server/src/modules/paypal/migrations/20260201090000_create_paypal_webhook_event.js.map +1 -0
  99. package/.medusa/server/src/modules/paypal/migrations/20260401090000_create_paypal_metric.d.ts +6 -0
  100. package/.medusa/server/src/modules/paypal/migrations/20260401090000_create_paypal_metric.d.ts.map +1 -0
  101. package/.medusa/server/src/modules/paypal/migrations/20260401090000_create_paypal_metric.js +30 -0
  102. package/.medusa/server/src/modules/paypal/migrations/20260401090000_create_paypal_metric.js.map +1 -0
  103. package/.medusa/server/src/modules/paypal/migrations/20260701090000_add_paypal_webhook_event_processing.d.ts +6 -0
  104. package/.medusa/server/src/modules/paypal/migrations/20260701090000_add_paypal_webhook_event_processing.d.ts.map +1 -0
  105. package/.medusa/server/src/modules/paypal/migrations/20260701090000_add_paypal_webhook_event_processing.js +34 -0
  106. package/.medusa/server/src/modules/paypal/migrations/20260701090000_add_paypal_webhook_event_processing.js.map +1 -0
  107. package/.medusa/server/src/modules/paypal/migrations/20261101090000_remove_paypal_reconciliation_status.d.ts +6 -0
  108. package/.medusa/server/src/modules/paypal/migrations/20261101090000_remove_paypal_reconciliation_status.d.ts.map +1 -0
  109. package/.medusa/server/src/modules/paypal/migrations/20261101090000_remove_paypal_reconciliation_status.js +28 -0
  110. package/.medusa/server/src/modules/paypal/migrations/20261101090000_remove_paypal_reconciliation_status.js.map +1 -0
  111. package/.medusa/server/src/modules/paypal/migrations/20261201090000_remove_paypal_audit_log.d.ts +6 -0
  112. package/.medusa/server/src/modules/paypal/migrations/20261201090000_remove_paypal_audit_log.d.ts.map +1 -0
  113. package/.medusa/server/src/modules/paypal/migrations/20261201090000_remove_paypal_audit_log.js +29 -0
  114. package/.medusa/server/src/modules/paypal/migrations/20261201090000_remove_paypal_audit_log.js.map +1 -0
  115. package/.medusa/server/src/modules/paypal/migrations/20270101090000_set_paypal_environment_default_live.d.ts +6 -0
  116. package/.medusa/server/src/modules/paypal/migrations/20270101090000_set_paypal_environment_default_live.d.ts.map +1 -0
  117. package/.medusa/server/src/modules/paypal/migrations/20270101090000_set_paypal_environment_default_live.js +14 -0
  118. package/.medusa/server/src/modules/paypal/migrations/20270101090000_set_paypal_environment_default_live.js.map +1 -0
  119. package/.medusa/server/src/modules/paypal/migrations/20270102090000_add_paypal_seller_email.d.ts +6 -0
  120. package/.medusa/server/src/modules/paypal/migrations/20270102090000_add_paypal_seller_email.d.ts.map +1 -0
  121. package/.medusa/server/src/modules/paypal/migrations/20270102090000_add_paypal_seller_email.js +14 -0
  122. package/.medusa/server/src/modules/paypal/migrations/20270102090000_add_paypal_seller_email.js.map +1 -0
  123. package/.medusa/server/src/modules/paypal/migrations/20270103090000_add_paypal_seller_merchant_id.d.ts +6 -0
  124. package/.medusa/server/src/modules/paypal/migrations/20270103090000_add_paypal_seller_merchant_id.d.ts.map +1 -0
  125. package/.medusa/server/src/modules/paypal/migrations/20270103090000_add_paypal_seller_merchant_id.js +14 -0
  126. package/.medusa/server/src/modules/paypal/migrations/20270103090000_add_paypal_seller_merchant_id.js.map +1 -0
  127. package/.medusa/server/src/modules/paypal/migrations/20270201000000_add_webhook_dead_letter.d.ts +6 -0
  128. package/.medusa/server/src/modules/paypal/migrations/20270201000000_add_webhook_dead_letter.d.ts.map +1 -0
  129. package/.medusa/server/src/modules/paypal/migrations/20270201000000_add_webhook_dead_letter.js +20 -0
  130. package/.medusa/server/src/modules/paypal/migrations/20270201000000_add_webhook_dead_letter.js.map +1 -0
  131. package/.medusa/server/src/modules/paypal/models/paypal_connection.d.ts +16 -0
  132. package/.medusa/server/src/modules/paypal/models/paypal_connection.d.ts.map +1 -0
  133. package/.medusa/server/src/modules/paypal/models/paypal_connection.js +19 -0
  134. package/.medusa/server/src/modules/paypal/models/paypal_connection.js.map +1 -0
  135. package/.medusa/server/src/modules/paypal/models/paypal_metric.d.ts +7 -0
  136. package/.medusa/server/src/modules/paypal/models/paypal_metric.d.ts.map +1 -0
  137. package/.medusa/server/src/modules/paypal/models/paypal_metric.js +10 -0
  138. package/.medusa/server/src/modules/paypal/models/paypal_metric.js.map +1 -0
  139. package/.medusa/server/src/modules/paypal/models/paypal_settings.d.ts +6 -0
  140. package/.medusa/server/src/modules/paypal/models/paypal_settings.d.ts.map +1 -0
  141. package/.medusa/server/src/modules/paypal/models/paypal_settings.js +9 -0
  142. package/.medusa/server/src/modules/paypal/models/paypal_settings.js.map +1 -0
  143. package/.medusa/server/src/modules/paypal/models/paypal_webhook_event.d.ts +17 -0
  144. package/.medusa/server/src/modules/paypal/models/paypal_webhook_event.d.ts.map +1 -0
  145. package/.medusa/server/src/modules/paypal/models/paypal_webhook_event.js +20 -0
  146. package/.medusa/server/src/modules/paypal/models/paypal_webhook_event.js.map +1 -0
  147. package/.medusa/server/src/modules/paypal/payment-provider/card-service.d.ts +32 -0
  148. package/.medusa/server/src/modules/paypal/payment-provider/card-service.d.ts.map +1 -0
  149. package/.medusa/server/src/modules/paypal/payment-provider/card-service.js +625 -0
  150. package/.medusa/server/src/modules/paypal/payment-provider/card-service.js.map +1 -0
  151. package/.medusa/server/src/modules/paypal/payment-provider/index.d.ts +6 -0
  152. package/.medusa/server/src/modules/paypal/payment-provider/index.d.ts.map +1 -0
  153. package/.medusa/server/src/modules/paypal/payment-provider/index.js +18 -0
  154. package/.medusa/server/src/modules/paypal/payment-provider/index.js.map +1 -0
  155. package/.medusa/server/src/modules/paypal/payment-provider/service.d.ts +39 -0
  156. package/.medusa/server/src/modules/paypal/payment-provider/service.d.ts.map +1 -0
  157. package/.medusa/server/src/modules/paypal/payment-provider/service.js +869 -0
  158. package/.medusa/server/src/modules/paypal/payment-provider/service.js.map +1 -0
  159. package/.medusa/server/src/modules/paypal/payment-provider/webhook-utils.d.ts +3 -0
  160. package/.medusa/server/src/modules/paypal/payment-provider/webhook-utils.d.ts.map +1 -0
  161. package/.medusa/server/src/modules/paypal/payment-provider/webhook-utils.js +74 -0
  162. package/.medusa/server/src/modules/paypal/payment-provider/webhook-utils.js.map +1 -0
  163. package/.medusa/server/src/modules/paypal/service.d.ts +266 -0
  164. package/.medusa/server/src/modules/paypal/service.d.ts.map +1 -0
  165. package/.medusa/server/src/modules/paypal/service.js +1149 -0
  166. package/.medusa/server/src/modules/paypal/service.js.map +1 -0
  167. package/.medusa/server/src/modules/paypal/types/config.d.ts +12 -0
  168. package/.medusa/server/src/modules/paypal/types/config.d.ts.map +1 -0
  169. package/.medusa/server/src/modules/paypal/types/config.js +24 -0
  170. package/.medusa/server/src/modules/paypal/types/config.js.map +1 -0
  171. package/.medusa/server/src/modules/paypal/utils/amounts.d.ts +3 -0
  172. package/.medusa/server/src/modules/paypal/utils/amounts.d.ts.map +1 -0
  173. package/.medusa/server/src/modules/paypal/utils/amounts.js +40 -0
  174. package/.medusa/server/src/modules/paypal/utils/amounts.js.map +1 -0
  175. package/.medusa/server/src/modules/paypal/utils/currencies.d.ts +19 -0
  176. package/.medusa/server/src/modules/paypal/utils/currencies.d.ts.map +1 -0
  177. package/.medusa/server/src/modules/paypal/utils/currencies.js +69 -0
  178. package/.medusa/server/src/modules/paypal/utils/currencies.js.map +1 -0
  179. package/.medusa/server/src/modules/paypal/utils/paypal-auth.d.ts +10 -0
  180. package/.medusa/server/src/modules/paypal/utils/paypal-auth.d.ts.map +1 -0
  181. package/.medusa/server/src/modules/paypal/utils/paypal-auth.js +30 -0
  182. package/.medusa/server/src/modules/paypal/utils/paypal-auth.js.map +1 -0
  183. package/.medusa/server/src/modules/paypal/utils/provider-ids.d.ts +5 -0
  184. package/.medusa/server/src/modules/paypal/utils/provider-ids.d.ts.map +1 -0
  185. package/.medusa/server/src/modules/paypal/utils/provider-ids.js +16 -0
  186. package/.medusa/server/src/modules/paypal/utils/provider-ids.js.map +1 -0
  187. package/.medusa/server/src/modules/paypal/webhook-processor.d.ts +29 -0
  188. package/.medusa/server/src/modules/paypal/webhook-processor.d.ts.map +1 -0
  189. package/.medusa/server/src/modules/paypal/webhook-processor.js +267 -0
  190. package/.medusa/server/src/modules/paypal/webhook-processor.js.map +1 -0
  191. package/.medusa/server/src/providers/paypal/index.d.ts +5 -0
  192. package/.medusa/server/src/providers/paypal/index.d.ts.map +1 -0
  193. package/.medusa/server/src/providers/paypal/index.js +10 -0
  194. package/.medusa/server/src/providers/paypal/index.js.map +1 -0
  195. package/.medusa/server/src/providers/paypal_card/index.d.ts +5 -0
  196. package/.medusa/server/src/providers/paypal_card/index.d.ts.map +1 -0
  197. package/.medusa/server/src/providers/paypal_card/index.js +10 -0
  198. package/.medusa/server/src/providers/paypal_card/index.js.map +1 -0
  199. package/.medusa/server/src/subscribers/paypal-order-invoice.d.ts +6 -0
  200. package/.medusa/server/src/subscribers/paypal-order-invoice.d.ts.map +1 -0
  201. package/.medusa/server/src/subscribers/paypal-order-invoice.js +124 -0
  202. package/.medusa/server/src/subscribers/paypal-order-invoice.js.map +1 -0
  203. package/LICENSE +21 -0
  204. package/README.md +172 -0
  205. package/package.json +80 -0
  206. package/src/admin/index.ts +7 -0
  207. package/src/admin/routes/settings/paypal/_components/Tabs.tsx +48 -0
  208. package/src/admin/routes/settings/paypal/_components/Toast.tsx +51 -0
  209. package/src/admin/routes/settings/paypal/additional-settings/page.tsx +199 -0
  210. package/src/admin/routes/settings/paypal/advanced-card-payments/page.tsx +183 -0
  211. package/src/admin/routes/settings/paypal/apple-pay/page.tsx +5 -0
  212. package/src/admin/routes/settings/paypal/connection/page.tsx +699 -0
  213. package/src/admin/routes/settings/paypal/google-pay/page.tsx +5 -0
  214. package/src/admin/routes/settings/paypal/page.tsx +13 -0
  215. package/src/admin/routes/settings/paypal/pay-later-messaging/page.tsx +5 -0
  216. package/src/admin/routes/settings/paypal/paypal-settings/page.tsx +351 -0
  217. package/src/api/admin/payment-collections/[id]/payment-sessions/route.ts +24 -0
  218. package/src/api/admin/paypal/disconnect/route.ts +8 -0
  219. package/src/api/admin/paypal/environment/route.ts +25 -0
  220. package/src/api/admin/paypal/onboard-complete/route.ts +34 -0
  221. package/src/api/admin/paypal/onboarding-link/route.ts +45 -0
  222. package/src/api/admin/paypal/onboarding-status/route.ts +17 -0
  223. package/src/api/admin/paypal/save-credentials/route.ts +22 -0
  224. package/src/api/admin/paypal/settings/route.ts +14 -0
  225. package/src/api/admin/paypal/status/route.ts +12 -0
  226. package/src/api/middlewares.ts +14 -0
  227. package/src/api/store/payment-collections/[id]/payment-sessions/route.ts +56 -0
  228. package/src/api/store/paypal/capture-order/route.ts +265 -0
  229. package/src/api/store/paypal/config/route.ts +100 -0
  230. package/src/api/store/paypal/create-order/route.ts +449 -0
  231. package/src/api/store/paypal/settings/route.ts +19 -0
  232. package/src/api/store/paypal/webhook/route.ts +325 -0
  233. package/src/api/store/paypal-complete/route.ts +95 -0
  234. package/src/index.ts +1 -0
  235. package/src/jobs/paypal-webhook-retry.ts +149 -0
  236. package/src/modules/paypal/clients/paypal-seller.client.ts +62 -0
  237. package/src/modules/paypal/index.ts +8 -0
  238. package/src/modules/paypal/migrations/20260115120000_create_paypal_connection.ts +33 -0
  239. package/src/modules/paypal/migrations/20260123090000_create_paypal_settings.ts +22 -0
  240. package/src/modules/paypal/migrations/20260201090000_create_paypal_webhook_event.ts +29 -0
  241. package/src/modules/paypal/migrations/20260401090000_create_paypal_metric.ts +27 -0
  242. package/src/modules/paypal/migrations/20260701090000_add_paypal_webhook_event_processing.ts +31 -0
  243. package/src/modules/paypal/migrations/20261101090000_remove_paypal_reconciliation_status.ts +25 -0
  244. package/src/modules/paypal/migrations/20261201090000_remove_paypal_audit_log.ts +26 -0
  245. package/src/modules/paypal/migrations/20270101090000_set_paypal_environment_default_live.ts +11 -0
  246. package/src/modules/paypal/migrations/20270102090000_add_paypal_seller_email.ts +11 -0
  247. package/src/modules/paypal/migrations/20270103090000_add_paypal_seller_merchant_id.ts +11 -0
  248. package/src/modules/paypal/migrations/20270201000000_add_webhook_dead_letter.ts +17 -0
  249. package/src/modules/paypal/models/paypal_connection.ts +23 -0
  250. package/src/modules/paypal/models/paypal_metric.ts +9 -0
  251. package/src/modules/paypal/models/paypal_settings.ts +8 -0
  252. package/src/modules/paypal/models/paypal_webhook_event.ts +19 -0
  253. package/src/modules/paypal/payment-provider/README.md +22 -0
  254. package/src/modules/paypal/payment-provider/card-service.ts +767 -0
  255. package/src/modules/paypal/payment-provider/index.ts +15 -0
  256. package/src/modules/paypal/payment-provider/service.ts +1039 -0
  257. package/src/modules/paypal/payment-provider/webhook-utils.ts +88 -0
  258. package/src/modules/paypal/service.ts +1416 -0
  259. package/src/modules/paypal/types/config.ts +33 -0
  260. package/src/modules/paypal/utils/amounts.ts +41 -0
  261. package/src/modules/paypal/utils/currencies.ts +84 -0
  262. package/src/modules/paypal/utils/paypal-auth.ts +31 -0
  263. package/src/modules/paypal/utils/provider-ids.ts +15 -0
  264. package/src/modules/paypal/webhook-processor.ts +363 -0
  265. package/src/providers/paypal/index.ts +8 -0
  266. package/src/providers/paypal_card/index.ts +8 -0
  267. package/src/subscribers/paypal-order-invoice.ts +171 -0
  268. package/tsconfig.json +31 -0
@@ -0,0 +1,13 @@
1
+ import React from "react"
2
+ import { defineRouteConfig } from "@medusajs/admin-sdk"
3
+ import { Navigate } from "react-router-dom"
4
+
5
+ export const config = defineRouteConfig({
6
+ label: "PayPal",
7
+ })
8
+
9
+ const PayPalSettingsIndexRoute = () => {
10
+ return <Navigate to="connection" replace />
11
+ }
12
+
13
+ export default PayPalSettingsIndexRoute
@@ -0,0 +1,5 @@
1
+ import { Navigate } from "react-router-dom"
2
+
3
+ export default function PayPalPayLaterMessagingPage() {
4
+ return <Navigate to="/settings/paypal/connection" replace />
5
+ }
@@ -0,0 +1,351 @@
1
+ import React, { useEffect, useRef, useState } from "react"
2
+ import PayPalTabs from "../_components/Tabs"
3
+
4
+ type AdminFetchOptions = {
5
+ method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH"
6
+ body?: Record<string, unknown>
7
+ query?: Record<string, string>
8
+ }
9
+
10
+ async function adminFetch<T = unknown>(path: string, opts: AdminFetchOptions = {}): Promise<T> {
11
+ const { method = "GET", body, query } = opts
12
+ let url = path
13
+ if (query && Object.keys(query).length > 0) {
14
+ const params = new URLSearchParams(query)
15
+ url = `${path}?${params.toString()}`
16
+ }
17
+ const headers: Record<string, string> = { Accept: "application/json" }
18
+ if (body !== undefined) headers["Content-Type"] = "application/json"
19
+ if (typeof window !== "undefined") {
20
+ const token = (window as any).__medusa__?.token
21
+ if (token) headers["Authorization"] = `Bearer ${token}`
22
+ }
23
+ const res = await fetch(url, {
24
+ method, headers, credentials: "include",
25
+ body: body !== undefined ? JSON.stringify(body) : undefined,
26
+ })
27
+ const text = await res.text().catch(() => "")
28
+ if (!res.ok) {
29
+ if (res.status === 401) throw new Error("Unauthorized (401) - session may have expired. Please reload and log in again.")
30
+ if (res.status === 403) throw new Error("Forbidden (403) - you do not have permission to perform this action.")
31
+ throw new Error(text || `Request failed with status ${res.status}`)
32
+ }
33
+ if (!text) return {} as T
34
+ try { return JSON.parse(text) as T } catch { return {} as T }
35
+ }
36
+
37
+ type ButtonColor = "gold" | "blue" | "silver" | "black" | "white"
38
+ type ButtonShape = "rect" | "pill"
39
+ type ButtonWidth = "small" | "medium" | "large" | "responsive"
40
+ type ButtonLabel = "paypal" | "checkout" | "buynow" | "pay"
41
+
42
+ type PayPalSettingsForm = {
43
+ enabled: boolean
44
+ title: string
45
+ description: string
46
+ buttonColor: ButtonColor
47
+ buttonShape: ButtonShape
48
+ buttonWidth: ButtonWidth
49
+ buttonHeight: number
50
+ buttonLabel: ButtonLabel
51
+ }
52
+
53
+ const COLOR_OPTIONS: { value: ButtonColor; label: string }[] = [
54
+ { value: "gold", label: "Gold (Recommended)" },
55
+ { value: "blue", label: "Blue" },
56
+ { value: "silver", label: "Silver" },
57
+ { value: "black", label: "Black" },
58
+ { value: "white", label: "White" },
59
+ ]
60
+
61
+ const SHAPE_OPTIONS: { value: ButtonShape; label: string }[] = [
62
+ { value: "rect", label: "Rect (Recommended)" },
63
+ { value: "pill", label: "Pill" },
64
+ ]
65
+
66
+ const WIDTH_OPTIONS: { value: ButtonWidth; label: string }[] = [
67
+ { value: "small", label: "Small" },
68
+ { value: "medium", label: "Medium" },
69
+ { value: "large", label: "Large" },
70
+ { value: "responsive", label: "Responsive" },
71
+ ]
72
+
73
+ const HEIGHT_OPTIONS: number[] = [32, 36, 40, 44, 48, 52, 56]
74
+
75
+ const LABEL_OPTIONS: { value: ButtonLabel; label: string }[] = [
76
+ { value: "paypal", label: "PayPal" },
77
+ { value: "checkout", label: "Checkout" },
78
+ { value: "buynow", label: "Buy Now" },
79
+ { value: "pay", label: "Pay" },
80
+ ]
81
+
82
+ function SectionCard({
83
+ title,
84
+ description,
85
+ children,
86
+ right,
87
+ }: {
88
+ title: string
89
+ description?: string
90
+ children: React.ReactNode
91
+ right?: React.ReactNode
92
+ }) {
93
+ return (
94
+ <div className="rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm">
95
+ <div className="flex items-start justify-between gap-4 border-b border-ui-border-base p-4">
96
+ <div>
97
+ <div className="text-base font-semibold text-ui-fg-base">{title}</div>
98
+ {description ? <div className="mt-1 text-sm text-ui-fg-subtle">{description}</div> : null}
99
+ </div>
100
+ {right}
101
+ </div>
102
+ <div className="p-4">{children}</div>
103
+ </div>
104
+ )
105
+ }
106
+
107
+ function FieldRow({
108
+ label,
109
+ hint,
110
+ children,
111
+ }: {
112
+ label: string
113
+ hint?: React.ReactNode
114
+ children: React.ReactNode
115
+ }) {
116
+ return (
117
+ <div className="grid grid-cols-12 items-start gap-4 py-3">
118
+ <div className="col-span-12 md:col-span-4">
119
+ <div className="text-sm font-medium text-ui-fg-base">{label}</div>
120
+ {hint ? <div className="mt-1 text-xs text-ui-fg-subtle">{hint}</div> : null}
121
+ </div>
122
+ <div className="col-span-12 md:col-span-8">{children}</div>
123
+ </div>
124
+ )
125
+ }
126
+
127
+ export default function PayPalSettingsTab() {
128
+ const [form, setForm] = useState<PayPalSettingsForm>({
129
+ enabled: true,
130
+ title: "PayPal",
131
+ description: "Pay via PayPal; you can pay with your credit card if you don't have a PayPal account",
132
+ buttonColor: "gold",
133
+ buttonShape: "rect",
134
+ buttonWidth: "medium",
135
+ buttonHeight: 48,
136
+ buttonLabel: "paypal",
137
+ })
138
+ const [loading, setLoading] = useState(false)
139
+ const [saving, setSaving] = useState(false)
140
+ const [toast, setToast] = useState<{ type: "success" | "error"; message: string } | null>(null)
141
+ const didInit = useRef(false)
142
+
143
+ useEffect(() => {
144
+ if (didInit.current) return
145
+ didInit.current = true
146
+
147
+ ;(async () => {
148
+ try {
149
+ setLoading(true)
150
+ const json = await adminFetch<{ data?: { paypal_settings?: PayPalSettingsForm }; paypal_settings?: PayPalSettingsForm }>(
151
+ "/admin/paypal/settings"
152
+ )
153
+ const payload = (json?.data ?? json) as any
154
+ const saved = payload?.paypal_settings
155
+ if (saved && typeof saved === "object") {
156
+ setForm((prev) => ({
157
+ ...prev,
158
+ ...saved,
159
+ }))
160
+ }
161
+ } catch {
162
+ } finally {
163
+ setLoading(false)
164
+ }
165
+ })()
166
+ }, [])
167
+
168
+ async function onSave() {
169
+ try {
170
+ setSaving(true)
171
+ const cleaned = { ...form }
172
+ const json = await adminFetch<{ data?: { paypal_settings?: PayPalSettingsForm }; paypal_settings?: PayPalSettingsForm }>(
173
+ "/admin/paypal/settings",
174
+ {
175
+ method: "POST",
176
+ body: { paypal_settings: cleaned as unknown as Record<string, unknown> },
177
+ }
178
+ )
179
+ const payload = (json?.data ?? json) as any
180
+ const saved = payload?.paypal_settings
181
+ if (saved && typeof saved === "object") {
182
+ setForm((prev) => ({
183
+ ...prev,
184
+ ...saved,
185
+ }))
186
+ }
187
+ setToast({ type: "success", message: "Settings saved" })
188
+ window.setTimeout(() => setToast(null), 2500)
189
+ } catch (e: unknown) {
190
+ setToast({
191
+ type: "error",
192
+ message:
193
+ (e instanceof Error ? e.message : "") ||
194
+ "Failed to save settings.",
195
+ })
196
+ window.setTimeout(() => setToast(null), 3500)
197
+ } finally {
198
+ setSaving(false)
199
+ }
200
+ }
201
+
202
+
203
+ return (
204
+ <div className="p-6">
205
+ <div className="flex flex-col gap-6">
206
+ <div className="flex items-start justify-between gap-4">
207
+ <div>
208
+ <h1 className="text-xl font-semibold text-ui-fg-base">PayPal Gateway By Easy Payment</h1>
209
+ </div>
210
+ <div className="flex items-center gap-2">
211
+ </div>
212
+ </div>
213
+
214
+ <PayPalTabs />
215
+
216
+ {toast ? (
217
+ <div
218
+ className="fixed right-6 top-6 z-50 rounded-md border border-ui-border-base bg-ui-bg-base px-4 py-3 text-sm shadow-lg"
219
+ role="status"
220
+ aria-live="polite"
221
+ >
222
+ <span className={toast.type === "success" ? "text-ui-fg-base" : "text-ui-fg-error"}>
223
+ {toast.message}
224
+ </span>
225
+ </div>
226
+ ) : null}
227
+
228
+ <SectionCard
229
+ title="PayPal Settings"
230
+ description="Enable PayPal and configure checkout title."
231
+ right={(
232
+ <div className="flex items-center gap-3">
233
+ <button
234
+ type="button"
235
+ onClick={onSave}
236
+ disabled={saving || loading}
237
+ className="transition-fg relative inline-flex w-fit items-center justify-center overflow-hidden rounded-md outline-none shadow-buttons-neutral text-ui-fg-base bg-ui-button-neutral after:transition-fg after:absolute after:inset-0 after:content-[''] after:button-neutral-gradient hover:bg-ui-button-neutral-hover hover:after:button-neutral-hover-gradient active:bg-ui-button-neutral-pressed active:after:button-neutral-pressed-gradient focus-visible:shadow-buttons-neutral-focus disabled:bg-ui-bg-disabled disabled:border-ui-border-base disabled:text-ui-fg-disabled disabled:shadow-buttons-neutral disabled:after:hidden txt-compact-small-plus px-3 py-1.5"
238
+ >
239
+ {saving ? "Saving..." : "Save settings"}
240
+ </button>
241
+ {loading ? <span className="text-sm text-ui-fg-subtle">Loading…</span> : null}
242
+ </div>
243
+ )}
244
+ >
245
+ <div className="divide-y divide-ui-border-base">
246
+ <FieldRow label="Enable/Disable">
247
+ <label className="inline-flex items-center gap-2">
248
+ <input
249
+ type="checkbox"
250
+ checked={form.enabled}
251
+ onChange={(e) => setForm((p) => ({ ...p, enabled: e.target.checked }))}
252
+ className="h-4 w-4 rounded border-ui-border-base"
253
+ />
254
+ <span className="text-sm text-ui-fg-base">Enable PayPal</span>
255
+ </label>
256
+ </FieldRow>
257
+
258
+ <FieldRow label="Title">
259
+ <input
260
+ value={form.title}
261
+ onChange={(e) => setForm((p) => ({ ...p, title: e.target.value }))}
262
+ className="w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive"
263
+ placeholder="PayPal"
264
+ />
265
+ </FieldRow>
266
+
267
+ </div>
268
+ </SectionCard>
269
+
270
+ <SectionCard
271
+ title="Button Appearance"
272
+ description="Control PayPal Smart Button styling (color/shape/size/label)."
273
+ >
274
+ <div className="divide-y divide-ui-border-base">
275
+
276
+ <FieldRow label="Button Color">
277
+ <select
278
+ value={form.buttonColor}
279
+ onChange={(e) => setForm((p) => ({ ...p, buttonColor: e.target.value as ButtonColor }))}
280
+ className="w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive"
281
+ >
282
+ {COLOR_OPTIONS.map((o) => (
283
+ <option key={o.value} value={o.value}>
284
+ {o.label}
285
+ </option>
286
+ ))}
287
+ </select>
288
+ </FieldRow>
289
+
290
+ <FieldRow label="Button Shape">
291
+ <select
292
+ value={form.buttonShape}
293
+ onChange={(e) => setForm((p) => ({ ...p, buttonShape: e.target.value as ButtonShape }))}
294
+ className="w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive"
295
+ >
296
+ {SHAPE_OPTIONS.map((o) => (
297
+ <option key={o.value} value={o.value}>
298
+ {o.label}
299
+ </option>
300
+ ))}
301
+ </select>
302
+ </FieldRow>
303
+
304
+ <FieldRow label="Button Width">
305
+ <select
306
+ value={form.buttonWidth}
307
+ onChange={(e) => setForm((p) => ({ ...p, buttonWidth: e.target.value as ButtonWidth }))}
308
+ className="w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive"
309
+ >
310
+ {WIDTH_OPTIONS.map((o) => (
311
+ <option key={o.value} value={o.value}>
312
+ {o.label}
313
+ </option>
314
+ ))}
315
+ </select>
316
+ </FieldRow>
317
+
318
+ <FieldRow label="Button Height">
319
+ <select
320
+ value={String(form.buttonHeight)}
321
+ onChange={(e) => setForm((p) => ({ ...p, buttonHeight: Number(e.target.value) }))}
322
+ className="w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive"
323
+ >
324
+ {HEIGHT_OPTIONS.map((h) => (
325
+ <option key={h} value={h}>
326
+ {h} px
327
+ </option>
328
+ ))}
329
+ </select>
330
+ </FieldRow>
331
+
332
+ <FieldRow label="Button Label">
333
+ <select
334
+ value={form.buttonLabel}
335
+ onChange={(e) => setForm((p) => ({ ...p, buttonLabel: e.target.value as ButtonLabel }))}
336
+ className="w-full rounded-md border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm text-ui-fg-base outline-none focus:ring-2 focus:ring-ui-border-interactive"
337
+ >
338
+ {LABEL_OPTIONS.map((o) => (
339
+ <option key={o.value} value={o.value}>
340
+ {o.label}
341
+ </option>
342
+ ))}
343
+ </select>
344
+ </FieldRow>
345
+ </div>
346
+ </SectionCard>
347
+
348
+ </div>
349
+ </div>
350
+ )
351
+ }
@@ -0,0 +1,24 @@
1
+ import { createPaymentSessionsWorkflow } from "@medusajs/core-flows"
2
+ import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
3
+
4
+ type CreatePaymentSessionBody = {
5
+ provider_id: string
6
+ data?: Record<string, unknown>
7
+ customer_id?: string
8
+ }
9
+
10
+ export async function POST(req: MedusaRequest, res: MedusaResponse) {
11
+ const collectionId = req.params.id
12
+ const { provider_id, data, customer_id } = req.body as CreatePaymentSessionBody
13
+
14
+ const { result } = await createPaymentSessionsWorkflow(req.scope).run({
15
+ input: {
16
+ payment_collection_id: collectionId,
17
+ provider_id,
18
+ customer_id,
19
+ data,
20
+ },
21
+ })
22
+
23
+ res.status(200).json({ payment_session: result })
24
+ }
@@ -0,0 +1,8 @@
1
+ import type { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
2
+ import type PayPalModuleService from "../../../../modules/paypal/service"
3
+
4
+ export async function POST(req: MedusaRequest, res: MedusaResponse) {
5
+ const paypal = req.scope.resolve<PayPalModuleService>("paypal_onboarding")
6
+ await paypal.disconnect()
7
+ return res.json({ ok: true })
8
+ }
@@ -0,0 +1,25 @@
1
+ import type { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
2
+ import type PayPalModuleService from "../../../../modules/paypal/service"
3
+
4
+ type Body = {
5
+ environment?: "sandbox" | "live"
6
+ }
7
+
8
+ export async function GET(req: MedusaRequest, res: MedusaResponse) {
9
+ const paypal = req.scope.resolve<PayPalModuleService>("paypal_onboarding")
10
+ const status = await paypal.getStatus()
11
+ return res.json({ environment: status.environment })
12
+ }
13
+
14
+ export async function POST(req: MedusaRequest, res: MedusaResponse) {
15
+ try {
16
+ const paypal = req.scope.resolve<PayPalModuleService>("paypal_onboarding")
17
+ const body = (req.body || {}) as Body
18
+ const env = body.environment === "sandbox" ? "sandbox" : "live"
19
+ await paypal.setEnvironment(env)
20
+ const status = await paypal.getStatus()
21
+ return res.json(status)
22
+ } catch (e: any) {
23
+ return res.status(500).json({ message: e?.message || "Unknown error" })
24
+ }
25
+ }
@@ -0,0 +1,34 @@
1
+ import type { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
2
+ import type PayPalModuleService from "../../../../modules/paypal/service"
3
+
4
+ export async function GET(_req: MedusaRequest, res: MedusaResponse) {
5
+ return res.status(405).json({
6
+ message:
7
+ "Method Not Allowed. Use POST with JSON: { authCode, sharedId, env }. This endpoint is called by the PayPal onboarding callback.",
8
+ })
9
+ }
10
+
11
+ export async function POST(req: MedusaRequest, res: MedusaResponse) {
12
+ const paypal = req.scope.resolve<PayPalModuleService>("paypal_onboarding")
13
+ const body = req.body as { authCode?: string; sharedId?: string; env?: "sandbox" | "live" }
14
+
15
+ if (!body?.authCode || !body?.sharedId) {
16
+ return res.status(400).json({ message: "Missing authCode/sharedId" })
17
+ }
18
+
19
+ try {
20
+
21
+ await paypal.exchangeAndSaveSellerCredentials({
22
+ authCode: body.authCode,
23
+ sharedId: body.sharedId,
24
+ env: body.env,
25
+ })
26
+
27
+ return res.json({ ok: true })
28
+ } catch (e: any) {
29
+ console.error("[PayPal] onboard-complete failed", e)
30
+ return res.status(500).json({
31
+ message: e?.message || "Failed to exchange and save PayPal credentials",
32
+ })
33
+ }
34
+ }
@@ -0,0 +1,45 @@
1
+ import type {
2
+ AuthenticatedMedusaRequest,
3
+ MedusaRequest,
4
+ MedusaResponse,
5
+ } from "@medusajs/framework/http"
6
+ import type PayPalModuleService from "../../../../modules/paypal/service"
7
+
8
+ type Body = {
9
+ email?: string
10
+ products?: string[]
11
+ }
12
+
13
+ export async function POST(req: AuthenticatedMedusaRequest, res: MedusaResponse) {
14
+ try {
15
+ const paypal = req.scope.resolve<PayPalModuleService>("paypal_onboarding")
16
+ const body = (req.body || {}) as Body
17
+ const authEmail =
18
+ typeof req.auth_context?.user_metadata?.email === "string"
19
+ ? String(req.auth_context.user_metadata.email)
20
+ : undefined
21
+ const email = authEmail ?? body.email ?? "admin@paypal.com"
22
+
23
+ const link = await paypal.createOnboardingLink({
24
+ email,
25
+ products: body.products,
26
+ })
27
+
28
+ return res.json({
29
+ status: "pending",
30
+ onboarding_url: link.onboarding_url,
31
+ return_url: link.return_url,
32
+ })
33
+ } catch (e: any) {
34
+ console.error("[paypal_onboarding] onboarding-link error:", e?.message || e, e?.stack)
35
+ return res.status(500).json({
36
+ message: e?.message || "Unknown error",
37
+ })
38
+ }
39
+ }
40
+
41
+ export async function GET(req: MedusaRequest, res: MedusaResponse) {
42
+ return res.status(405).json({
43
+ message: "Use POST /admin/paypal/onboarding-link",
44
+ })
45
+ }
@@ -0,0 +1,17 @@
1
+ import type { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
2
+ import type PayPalModuleService from "../../../../modules/paypal/service"
3
+
4
+ export async function GET(req: MedusaRequest, res: MedusaResponse) {
5
+ try {
6
+ const paypal = req.scope.resolve<PayPalModuleService>("paypal_onboarding")
7
+ const status = await paypal.getStatus()
8
+ return res.json(status)
9
+ } catch (e: any) {
10
+ console.error("[paypal_onboarding] onboarding-status error:", e?.message || e, e?.stack)
11
+ return res.json({
12
+ environment: "live",
13
+ status: "disconnected",
14
+ error: e?.message || "Unknown error",
15
+ })
16
+ }
17
+ }
@@ -0,0 +1,22 @@
1
+ import type { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
2
+ import type PayPalModuleService from "../../../../modules/paypal/service"
3
+
4
+ export async function POST(req: MedusaRequest, res: MedusaResponse) {
5
+ const paypal = req.scope.resolve<PayPalModuleService>("paypal_onboarding")
6
+ const body = req.body as {
7
+ clientId?: string
8
+ clientSecret?: string
9
+ environment?: "sandbox" | "live"
10
+ }
11
+
12
+ if (!body?.clientId || !body?.clientSecret) {
13
+ return res.status(400).json({ message: "Missing clientId/clientSecret" })
14
+ }
15
+
16
+ await paypal.saveAndHydrateSellerCredentials({
17
+ clientId: body.clientId,
18
+ clientSecret: body.clientSecret,
19
+ environment: body.environment,
20
+ })
21
+ return res.json({ ok: true })
22
+ }
@@ -0,0 +1,14 @@
1
+ import type { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
2
+ import type PayPalModuleService from "../../../../modules/paypal/service"
3
+
4
+ export async function GET(req: MedusaRequest, res: MedusaResponse) {
5
+ const paypal = req.scope.resolve<PayPalModuleService>("paypal_onboarding")
6
+ return res.json(await paypal.getSettings())
7
+ }
8
+
9
+ export async function POST(req: MedusaRequest, res: MedusaResponse) {
10
+ const paypal = req.scope.resolve<PayPalModuleService>("paypal_onboarding")
11
+
12
+ const patch = (req.body && typeof req.body === "object") ? (req.body as Record<string, any>) : {}
13
+ return res.json(await paypal.saveSettings(patch))
14
+ }
@@ -0,0 +1,12 @@
1
+ import type { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
2
+ import type PayPalModuleService from "../../../../modules/paypal/service"
3
+
4
+ export async function GET(req: MedusaRequest, res: MedusaResponse) {
5
+ const paypal = req.scope.resolve<PayPalModuleService>("paypal_onboarding")
6
+
7
+ const q = (req.query || {}) as Record<string, any>
8
+ const envParam = (q.environment || q.env) as string | undefined
9
+ const env = envParam === "live" ? "live" : envParam === "sandbox" ? "sandbox" : undefined
10
+
11
+ return res.json(await paypal.getStatus(env))
12
+ }
@@ -0,0 +1,14 @@
1
+ import { defineMiddlewares } from "@medusajs/framework/http"
2
+
3
+ export default defineMiddlewares({
4
+ routes: [
5
+ {
6
+ matcher: "/store/paypal-complete",
7
+ middlewares: [],
8
+ },
9
+ {
10
+ matcher: "/store/paypal/:path*",
11
+ middlewares: [],
12
+ },
13
+ ],
14
+ })
@@ -0,0 +1,56 @@
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
+ const { provider_id, data } = req.body as CreatePaymentSessionBody
21
+
22
+ if (!provider_id || typeof provider_id !== "string") {
23
+ throw new MedusaError(
24
+ MedusaError.Types.INVALID_DATA,
25
+ "provider_id is required to create a payment session"
26
+ )
27
+ }
28
+
29
+ try {
30
+ await createPaymentSessionsWorkflow(req.scope).run({
31
+ input: {
32
+ payment_collection_id: collectionId,
33
+ provider_id,
34
+ customer_id: req.auth_context?.actor_id,
35
+ data,
36
+ },
37
+ })
38
+ } catch (error) {
39
+ const message = error instanceof Error ? error.message : String(error)
40
+ throw new MedusaError(
41
+ MedusaError.Types.UNEXPECTED_STATE,
42
+ `Failed to create payment session for provider '${provider_id}': ${message}`
43
+ )
44
+ }
45
+
46
+ const paymentCollection = await refetchEntity({
47
+ entity: "payment_collection",
48
+ idOrFilter: collectionId,
49
+ scope: req.scope,
50
+ fields: req.queryConfig?.fields ?? defaultPaymentCollectionFields,
51
+ })
52
+
53
+ res.status(200).json({
54
+ payment_collection: paymentCollection,
55
+ })
56
+ }