@easypayment/medusa-paypal 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (272) hide show
  1. package/.medusa/server/src/admin/index.js +2127 -0
  2. package/.medusa/server/src/admin/index.mjs +2128 -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 +25 -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/audit-logs/route.d.ts +3 -0
  8. package/.medusa/server/src/api/admin/paypal/audit-logs/route.d.ts.map +1 -0
  9. package/.medusa/server/src/api/admin/paypal/audit-logs/route.js +12 -0
  10. package/.medusa/server/src/api/admin/paypal/audit-logs/route.js.map +1 -0
  11. package/.medusa/server/src/api/admin/paypal/disconnect/route.d.ts +3 -0
  12. package/.medusa/server/src/api/admin/paypal/disconnect/route.d.ts.map +1 -0
  13. package/.medusa/server/src/api/admin/paypal/disconnect/route.js +9 -0
  14. package/.medusa/server/src/api/admin/paypal/disconnect/route.js.map +1 -0
  15. package/.medusa/server/src/api/admin/paypal/disputes/[id]/route.d.ts +3 -0
  16. package/.medusa/server/src/api/admin/paypal/disputes/[id]/route.d.ts.map +1 -0
  17. package/.medusa/server/src/api/admin/paypal/disputes/[id]/route.js +17 -0
  18. package/.medusa/server/src/api/admin/paypal/disputes/[id]/route.js.map +1 -0
  19. package/.medusa/server/src/api/admin/paypal/disputes/route.d.ts +3 -0
  20. package/.medusa/server/src/api/admin/paypal/disputes/route.d.ts.map +1 -0
  21. package/.medusa/server/src/api/admin/paypal/disputes/route.js +27 -0
  22. package/.medusa/server/src/api/admin/paypal/disputes/route.js.map +1 -0
  23. package/.medusa/server/src/api/admin/paypal/disputes/summary/route.d.ts +3 -0
  24. package/.medusa/server/src/api/admin/paypal/disputes/summary/route.d.ts.map +1 -0
  25. package/.medusa/server/src/api/admin/paypal/disputes/summary/route.js +17 -0
  26. package/.medusa/server/src/api/admin/paypal/disputes/summary/route.js.map +1 -0
  27. package/.medusa/server/src/api/admin/paypal/environment/route.d.ts +4 -0
  28. package/.medusa/server/src/api/admin/paypal/environment/route.d.ts.map +1 -0
  29. package/.medusa/server/src/api/admin/paypal/environment/route.js +23 -0
  30. package/.medusa/server/src/api/admin/paypal/environment/route.js.map +1 -0
  31. package/.medusa/server/src/api/admin/paypal/onboard-complete/route.d.ts +8 -0
  32. package/.medusa/server/src/api/admin/paypal/onboard-complete/route.d.ts.map +1 -0
  33. package/.medusa/server/src/api/admin/paypal/onboard-complete/route.js +41 -0
  34. package/.medusa/server/src/api/admin/paypal/onboard-complete/route.js.map +1 -0
  35. package/.medusa/server/src/api/admin/paypal/onboarding-link/route.d.ts +4 -0
  36. package/.medusa/server/src/api/admin/paypal/onboarding-link/route.d.ts.map +1 -0
  37. package/.medusa/server/src/api/admin/paypal/onboarding-link/route.js +35 -0
  38. package/.medusa/server/src/api/admin/paypal/onboarding-link/route.js.map +1 -0
  39. package/.medusa/server/src/api/admin/paypal/onboarding-status/route.d.ts +3 -0
  40. package/.medusa/server/src/api/admin/paypal/onboarding-status/route.d.ts.map +1 -0
  41. package/.medusa/server/src/api/admin/paypal/onboarding-status/route.js +20 -0
  42. package/.medusa/server/src/api/admin/paypal/onboarding-status/route.js.map +1 -0
  43. package/.medusa/server/src/api/admin/paypal/reconciliation-status/route.d.ts +3 -0
  44. package/.medusa/server/src/api/admin/paypal/reconciliation-status/route.d.ts.map +1 -0
  45. package/.medusa/server/src/api/admin/paypal/reconciliation-status/route.js +8 -0
  46. package/.medusa/server/src/api/admin/paypal/reconciliation-status/route.js.map +1 -0
  47. package/.medusa/server/src/api/admin/paypal/rotate-credentials/route.d.ts +3 -0
  48. package/.medusa/server/src/api/admin/paypal/rotate-credentials/route.d.ts.map +1 -0
  49. package/.medusa/server/src/api/admin/paypal/rotate-credentials/route.js +9 -0
  50. package/.medusa/server/src/api/admin/paypal/rotate-credentials/route.js.map +1 -0
  51. package/.medusa/server/src/api/admin/paypal/save-credentials/route.d.ts +3 -0
  52. package/.medusa/server/src/api/admin/paypal/save-credentials/route.d.ts.map +1 -0
  53. package/.medusa/server/src/api/admin/paypal/save-credentials/route.js +13 -0
  54. package/.medusa/server/src/api/admin/paypal/save-credentials/route.js.map +1 -0
  55. package/.medusa/server/src/api/admin/paypal/settings/route.d.ts +4 -0
  56. package/.medusa/server/src/api/admin/paypal/settings/route.d.ts.map +1 -0
  57. package/.medusa/server/src/api/admin/paypal/settings/route.js +14 -0
  58. package/.medusa/server/src/api/admin/paypal/settings/route.js.map +1 -0
  59. package/.medusa/server/src/api/admin/paypal/status/route.d.ts +3 -0
  60. package/.medusa/server/src/api/admin/paypal/status/route.d.ts.map +1 -0
  61. package/.medusa/server/src/api/admin/paypal/status/route.js +11 -0
  62. package/.medusa/server/src/api/admin/paypal/status/route.js.map +1 -0
  63. package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.d.ts +3 -0
  64. package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.d.ts.map +1 -0
  65. package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.js +43 -0
  66. package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.js.map +1 -0
  67. package/.medusa/server/src/api/store/paypal/capture-order/route.d.ts +3 -0
  68. package/.medusa/server/src/api/store/paypal/capture-order/route.d.ts.map +1 -0
  69. package/.medusa/server/src/api/store/paypal/capture-order/route.js +215 -0
  70. package/.medusa/server/src/api/store/paypal/capture-order/route.js.map +1 -0
  71. package/.medusa/server/src/api/store/paypal/config/route.d.ts +3 -0
  72. package/.medusa/server/src/api/store/paypal/config/route.d.ts.map +1 -0
  73. package/.medusa/server/src/api/store/paypal/config/route.js +45 -0
  74. package/.medusa/server/src/api/store/paypal/config/route.js.map +1 -0
  75. package/.medusa/server/src/api/store/paypal/create-order/route.d.ts +3 -0
  76. package/.medusa/server/src/api/store/paypal/create-order/route.d.ts.map +1 -0
  77. package/.medusa/server/src/api/store/paypal/create-order/route.js +305 -0
  78. package/.medusa/server/src/api/store/paypal/create-order/route.js.map +1 -0
  79. package/.medusa/server/src/api/store/paypal/disputes/route.d.ts +3 -0
  80. package/.medusa/server/src/api/store/paypal/disputes/route.d.ts.map +1 -0
  81. package/.medusa/server/src/api/store/paypal/disputes/route.js +46 -0
  82. package/.medusa/server/src/api/store/paypal/disputes/route.js.map +1 -0
  83. package/.medusa/server/src/api/store/paypal/settings/route.d.ts +3 -0
  84. package/.medusa/server/src/api/store/paypal/settings/route.d.ts.map +1 -0
  85. package/.medusa/server/src/api/store/paypal/settings/route.js +14 -0
  86. package/.medusa/server/src/api/store/paypal/settings/route.js.map +1 -0
  87. package/.medusa/server/src/api/store/paypal/webhook/route.d.ts +3 -0
  88. package/.medusa/server/src/api/store/paypal/webhook/route.d.ts.map +1 -0
  89. package/.medusa/server/src/api/store/paypal/webhook/route.js +203 -0
  90. package/.medusa/server/src/api/store/paypal/webhook/route.js.map +1 -0
  91. package/.medusa/server/src/jobs/paypal-reconcile.d.ts +7 -0
  92. package/.medusa/server/src/jobs/paypal-reconcile.d.ts.map +1 -0
  93. package/.medusa/server/src/jobs/paypal-reconcile.js +131 -0
  94. package/.medusa/server/src/jobs/paypal-reconcile.js.map +1 -0
  95. package/.medusa/server/src/jobs/paypal-webhook-retry.d.ts +7 -0
  96. package/.medusa/server/src/jobs/paypal-webhook-retry.d.ts.map +1 -0
  97. package/.medusa/server/src/jobs/paypal-webhook-retry.js +78 -0
  98. package/.medusa/server/src/jobs/paypal-webhook-retry.js.map +1 -0
  99. package/.medusa/server/src/modules/paypal/clients/paypal-seller.client.d.ts +14 -0
  100. package/.medusa/server/src/modules/paypal/clients/paypal-seller.client.d.ts.map +1 -0
  101. package/.medusa/server/src/modules/paypal/clients/paypal-seller.client.js +65 -0
  102. package/.medusa/server/src/modules/paypal/clients/paypal-seller.client.js.map +1 -0
  103. package/.medusa/server/src/modules/paypal/index.d.ts +92 -0
  104. package/.medusa/server/src/modules/paypal/index.d.ts.map +1 -0
  105. package/.medusa/server/src/modules/paypal/index.js +13 -0
  106. package/.medusa/server/src/modules/paypal/index.js.map +1 -0
  107. package/.medusa/server/src/modules/paypal/migrations/20260115120000_create_paypal_connection.d.ts +6 -0
  108. package/.medusa/server/src/modules/paypal/migrations/20260115120000_create_paypal_connection.d.ts.map +1 -0
  109. package/.medusa/server/src/modules/paypal/migrations/20260115120000_create_paypal_connection.js +36 -0
  110. package/.medusa/server/src/modules/paypal/migrations/20260115120000_create_paypal_connection.js.map +1 -0
  111. package/.medusa/server/src/modules/paypal/migrations/20260123090000_create_paypal_settings.d.ts +6 -0
  112. package/.medusa/server/src/modules/paypal/migrations/20260123090000_create_paypal_settings.d.ts.map +1 -0
  113. package/.medusa/server/src/modules/paypal/migrations/20260123090000_create_paypal_settings.js +25 -0
  114. package/.medusa/server/src/modules/paypal/migrations/20260123090000_create_paypal_settings.js.map +1 -0
  115. package/.medusa/server/src/modules/paypal/migrations/20260201090000_create_paypal_webhook_event.d.ts +6 -0
  116. package/.medusa/server/src/modules/paypal/migrations/20260201090000_create_paypal_webhook_event.d.ts.map +1 -0
  117. package/.medusa/server/src/modules/paypal/migrations/20260201090000_create_paypal_webhook_event.js +32 -0
  118. package/.medusa/server/src/modules/paypal/migrations/20260201090000_create_paypal_webhook_event.js.map +1 -0
  119. package/.medusa/server/src/modules/paypal/migrations/20260301090000_create_paypal_audit_log.d.ts +6 -0
  120. package/.medusa/server/src/modules/paypal/migrations/20260301090000_create_paypal_audit_log.d.ts.map +1 -0
  121. package/.medusa/server/src/modules/paypal/migrations/20260301090000_create_paypal_audit_log.js +29 -0
  122. package/.medusa/server/src/modules/paypal/migrations/20260301090000_create_paypal_audit_log.js.map +1 -0
  123. package/.medusa/server/src/modules/paypal/migrations/20260401090000_create_paypal_metric.d.ts +6 -0
  124. package/.medusa/server/src/modules/paypal/migrations/20260401090000_create_paypal_metric.d.ts.map +1 -0
  125. package/.medusa/server/src/modules/paypal/migrations/20260401090000_create_paypal_metric.js +30 -0
  126. package/.medusa/server/src/modules/paypal/migrations/20260401090000_create_paypal_metric.js.map +1 -0
  127. package/.medusa/server/src/modules/paypal/migrations/20260501090000_create_paypal_dispute.d.ts +6 -0
  128. package/.medusa/server/src/modules/paypal/migrations/20260501090000_create_paypal_dispute.d.ts.map +1 -0
  129. package/.medusa/server/src/modules/paypal/migrations/20260501090000_create_paypal_dispute.js +43 -0
  130. package/.medusa/server/src/modules/paypal/migrations/20260501090000_create_paypal_dispute.js.map +1 -0
  131. package/.medusa/server/src/modules/paypal/migrations/20260701090000_add_paypal_webhook_event_processing.d.ts +6 -0
  132. package/.medusa/server/src/modules/paypal/migrations/20260701090000_add_paypal_webhook_event_processing.d.ts.map +1 -0
  133. package/.medusa/server/src/modules/paypal/migrations/20260701090000_add_paypal_webhook_event_processing.js +34 -0
  134. package/.medusa/server/src/modules/paypal/migrations/20260701090000_add_paypal_webhook_event_processing.js.map +1 -0
  135. package/.medusa/server/src/modules/paypal/models/paypal_audit_log.d.ts +7 -0
  136. package/.medusa/server/src/modules/paypal/models/paypal_audit_log.d.ts.map +1 -0
  137. package/.medusa/server/src/modules/paypal/models/paypal_audit_log.js +10 -0
  138. package/.medusa/server/src/modules/paypal/models/paypal_audit_log.js.map +1 -0
  139. package/.medusa/server/src/modules/paypal/models/paypal_connection.d.ts +14 -0
  140. package/.medusa/server/src/modules/paypal/models/paypal_connection.d.ts.map +1 -0
  141. package/.medusa/server/src/modules/paypal/models/paypal_connection.js +17 -0
  142. package/.medusa/server/src/modules/paypal/models/paypal_connection.js.map +1 -0
  143. package/.medusa/server/src/modules/paypal/models/paypal_dispute.d.ts +16 -0
  144. package/.medusa/server/src/modules/paypal/models/paypal_dispute.d.ts.map +1 -0
  145. package/.medusa/server/src/modules/paypal/models/paypal_dispute.js +19 -0
  146. package/.medusa/server/src/modules/paypal/models/paypal_dispute.js.map +1 -0
  147. package/.medusa/server/src/modules/paypal/models/paypal_metric.d.ts +7 -0
  148. package/.medusa/server/src/modules/paypal/models/paypal_metric.d.ts.map +1 -0
  149. package/.medusa/server/src/modules/paypal/models/paypal_metric.js +10 -0
  150. package/.medusa/server/src/modules/paypal/models/paypal_metric.js.map +1 -0
  151. package/.medusa/server/src/modules/paypal/models/paypal_settings.d.ts +6 -0
  152. package/.medusa/server/src/modules/paypal/models/paypal_settings.d.ts.map +1 -0
  153. package/.medusa/server/src/modules/paypal/models/paypal_settings.js +9 -0
  154. package/.medusa/server/src/modules/paypal/models/paypal_settings.js.map +1 -0
  155. package/.medusa/server/src/modules/paypal/models/paypal_webhook_event.d.ts +17 -0
  156. package/.medusa/server/src/modules/paypal/models/paypal_webhook_event.d.ts.map +1 -0
  157. package/.medusa/server/src/modules/paypal/models/paypal_webhook_event.js +20 -0
  158. package/.medusa/server/src/modules/paypal/models/paypal_webhook_event.js.map +1 -0
  159. package/.medusa/server/src/modules/paypal/payment-provider/card-service.d.ts +35 -0
  160. package/.medusa/server/src/modules/paypal/payment-provider/card-service.d.ts.map +1 -0
  161. package/.medusa/server/src/modules/paypal/payment-provider/card-service.js +569 -0
  162. package/.medusa/server/src/modules/paypal/payment-provider/card-service.js.map +1 -0
  163. package/.medusa/server/src/modules/paypal/payment-provider/index.d.ts +10 -0
  164. package/.medusa/server/src/modules/paypal/payment-provider/index.d.ts.map +1 -0
  165. package/.medusa/server/src/modules/paypal/payment-provider/index.js +22 -0
  166. package/.medusa/server/src/modules/paypal/payment-provider/index.js.map +1 -0
  167. package/.medusa/server/src/modules/paypal/payment-provider/service.d.ts +44 -0
  168. package/.medusa/server/src/modules/paypal/payment-provider/service.d.ts.map +1 -0
  169. package/.medusa/server/src/modules/paypal/payment-provider/service.js +825 -0
  170. package/.medusa/server/src/modules/paypal/payment-provider/service.js.map +1 -0
  171. package/.medusa/server/src/modules/paypal/payment-provider/webhook-utils.d.ts +3 -0
  172. package/.medusa/server/src/modules/paypal/payment-provider/webhook-utils.d.ts.map +1 -0
  173. package/.medusa/server/src/modules/paypal/payment-provider/webhook-utils.js +74 -0
  174. package/.medusa/server/src/modules/paypal/payment-provider/webhook-utils.js.map +1 -0
  175. package/.medusa/server/src/modules/paypal/service.d.ts +362 -0
  176. package/.medusa/server/src/modules/paypal/service.d.ts.map +1 -0
  177. package/.medusa/server/src/modules/paypal/service.js +1180 -0
  178. package/.medusa/server/src/modules/paypal/service.js.map +1 -0
  179. package/.medusa/server/src/modules/paypal/types/config.d.ts +14 -0
  180. package/.medusa/server/src/modules/paypal/types/config.d.ts.map +1 -0
  181. package/.medusa/server/src/modules/paypal/types/config.js +33 -0
  182. package/.medusa/server/src/modules/paypal/types/config.js.map +1 -0
  183. package/.medusa/server/src/modules/paypal/utils/amounts.d.ts +3 -0
  184. package/.medusa/server/src/modules/paypal/utils/amounts.d.ts.map +1 -0
  185. package/.medusa/server/src/modules/paypal/utils/amounts.js +40 -0
  186. package/.medusa/server/src/modules/paypal/utils/amounts.js.map +1 -0
  187. package/.medusa/server/src/modules/paypal/utils/crypto.d.ts +4 -0
  188. package/.medusa/server/src/modules/paypal/utils/crypto.d.ts.map +1 -0
  189. package/.medusa/server/src/modules/paypal/utils/crypto.js +47 -0
  190. package/.medusa/server/src/modules/paypal/utils/crypto.js.map +1 -0
  191. package/.medusa/server/src/modules/paypal/utils/currencies.d.ts +19 -0
  192. package/.medusa/server/src/modules/paypal/utils/currencies.d.ts.map +1 -0
  193. package/.medusa/server/src/modules/paypal/utils/currencies.js +69 -0
  194. package/.medusa/server/src/modules/paypal/utils/currencies.js.map +1 -0
  195. package/.medusa/server/src/modules/paypal/utils/provider-ids.d.ts +9 -0
  196. package/.medusa/server/src/modules/paypal/utils/provider-ids.d.ts.map +1 -0
  197. package/.medusa/server/src/modules/paypal/utils/provider-ids.js +50 -0
  198. package/.medusa/server/src/modules/paypal/utils/provider-ids.js.map +1 -0
  199. package/.medusa/server/src/modules/paypal/webhook-processor.d.ts +38 -0
  200. package/.medusa/server/src/modules/paypal/webhook-processor.d.ts.map +1 -0
  201. package/.medusa/server/src/modules/paypal/webhook-processor.js +265 -0
  202. package/.medusa/server/src/modules/paypal/webhook-processor.js.map +1 -0
  203. package/LICENSE +21 -0
  204. package/README.md +67 -0
  205. package/package.json +61 -0
  206. package/postcss.config.cjs +3 -0
  207. package/src/admin/index.ts +7 -0
  208. package/src/admin/routes/settings/paypal/_components/Tabs.tsx +55 -0
  209. package/src/admin/routes/settings/paypal/_components/Toast.tsx +51 -0
  210. package/src/admin/routes/settings/paypal/additional-settings/page.tsx +346 -0
  211. package/src/admin/routes/settings/paypal/advanced-card-payments/page.tsx +381 -0
  212. package/src/admin/routes/settings/paypal/apple-pay/page.tsx +5 -0
  213. package/src/admin/routes/settings/paypal/audit-logs/page.tsx +131 -0
  214. package/src/admin/routes/settings/paypal/connection/page.tsx +750 -0
  215. package/src/admin/routes/settings/paypal/disputes/page.tsx +259 -0
  216. package/src/admin/routes/settings/paypal/google-pay/page.tsx +5 -0
  217. package/src/admin/routes/settings/paypal/page.tsx +16 -0
  218. package/src/admin/routes/settings/paypal/pay-later-messaging/page.tsx +5 -0
  219. package/src/admin/routes/settings/paypal/paypal-settings/page.tsx +557 -0
  220. package/src/admin/routes/settings/paypal/reconciliation-status/page.tsx +165 -0
  221. package/src/api/admin/payment-collections/[id]/payment-sessions/route.ts +32 -0
  222. package/src/api/admin/paypal/audit-logs/route.ts +13 -0
  223. package/src/api/admin/paypal/disconnect/route.ts +8 -0
  224. package/src/api/admin/paypal/disputes/[id]/route.ts +19 -0
  225. package/src/api/admin/paypal/disputes/route.ts +30 -0
  226. package/src/api/admin/paypal/disputes/summary/route.ts +18 -0
  227. package/src/api/admin/paypal/environment/route.ts +25 -0
  228. package/src/api/admin/paypal/onboard-complete/route.ts +44 -0
  229. package/src/api/admin/paypal/onboarding-link/route.ts +45 -0
  230. package/src/api/admin/paypal/onboarding-status/route.ts +18 -0
  231. package/src/api/admin/paypal/reconciliation-status/route.ts +7 -0
  232. package/src/api/admin/paypal/rotate-credentials/route.ts +8 -0
  233. package/src/api/admin/paypal/save-credentials/route.ts +14 -0
  234. package/src/api/admin/paypal/settings/route.ts +14 -0
  235. package/src/api/admin/paypal/status/route.ts +12 -0
  236. package/src/api/store/payment-collections/[id]/payment-sessions/route.ts +51 -0
  237. package/src/api/store/paypal/capture-order/route.ts +270 -0
  238. package/src/api/store/paypal/config/route.ts +59 -0
  239. package/src/api/store/paypal/create-order/route.ts +374 -0
  240. package/src/api/store/paypal/disputes/route.ts +67 -0
  241. package/src/api/store/paypal/settings/route.ts +12 -0
  242. package/src/api/store/paypal/webhook/route.ts +247 -0
  243. package/src/jobs/paypal-reconcile.ts +135 -0
  244. package/src/jobs/paypal-webhook-retry.ts +86 -0
  245. package/src/modules/paypal/clients/paypal-seller.client.ts +59 -0
  246. package/src/modules/paypal/index.ts +8 -0
  247. package/src/modules/paypal/migrations/20260115120000_create_paypal_connection.ts +33 -0
  248. package/src/modules/paypal/migrations/20260123090000_create_paypal_settings.ts +22 -0
  249. package/src/modules/paypal/migrations/20260201090000_create_paypal_webhook_event.ts +29 -0
  250. package/src/modules/paypal/migrations/20260301090000_create_paypal_audit_log.ts +26 -0
  251. package/src/modules/paypal/migrations/20260401090000_create_paypal_metric.ts +27 -0
  252. package/src/modules/paypal/migrations/20260501090000_create_paypal_dispute.ts +40 -0
  253. package/src/modules/paypal/migrations/20260701090000_add_paypal_webhook_event_processing.ts +31 -0
  254. package/src/modules/paypal/models/paypal_audit_log.ts +9 -0
  255. package/src/modules/paypal/models/paypal_connection.ts +21 -0
  256. package/src/modules/paypal/models/paypal_dispute.ts +18 -0
  257. package/src/modules/paypal/models/paypal_metric.ts +9 -0
  258. package/src/modules/paypal/models/paypal_settings.ts +8 -0
  259. package/src/modules/paypal/models/paypal_webhook_event.ts +19 -0
  260. package/src/modules/paypal/payment-provider/README.md +22 -0
  261. package/src/modules/paypal/payment-provider/card-service.ts +710 -0
  262. package/src/modules/paypal/payment-provider/index.ts +19 -0
  263. package/src/modules/paypal/payment-provider/service.ts +1035 -0
  264. package/src/modules/paypal/payment-provider/webhook-utils.ts +88 -0
  265. package/src/modules/paypal/service.ts +1422 -0
  266. package/src/modules/paypal/types/config.ts +47 -0
  267. package/src/modules/paypal/utils/amounts.ts +41 -0
  268. package/src/modules/paypal/utils/crypto.ts +51 -0
  269. package/src/modules/paypal/utils/currencies.ts +84 -0
  270. package/src/modules/paypal/utils/provider-ids.ts +53 -0
  271. package/src/modules/paypal/webhook-processor.ts +313 -0
  272. package/tsconfig.json +31 -0
@@ -0,0 +1,557 @@
1
+ import React, {useEffect, useMemo, useRef, useState} from "react"
2
+ import PayPalTabs from "../_components/Tabs"
3
+
4
+ type ButtonColor = "gold" | "blue" | "silver" | "black" | "white"
5
+ type ButtonShape = "rect" | "pill"
6
+ type ButtonWidth = "small" | "medium" | "large" | "responsive"
7
+ type ButtonLabel = "paypal" | "checkout" | "buynow" | "pay"
8
+
9
+ type DisplayLocation =
10
+ | "product"
11
+ | "cart"
12
+ | "checkout"
13
+ | "express"
14
+ | "mini_cart"
15
+
16
+ type DisabledButton =
17
+ | "paypal"
18
+ | "paylater"
19
+ | "card"
20
+ | "venmo"
21
+ | "applepay"
22
+ | "googlepay"
23
+
24
+ type PayPalSettingsForm = {
25
+ enabled: boolean
26
+ title: string
27
+ description: string
28
+
29
+ displayOn: DisplayLocation[]
30
+
31
+ disableButtons: DisabledButton[]
32
+ buttonColor: ButtonColor
33
+ buttonShape: ButtonShape
34
+ buttonWidth: ButtonWidth
35
+ buttonHeight: number
36
+ buttonLabel: ButtonLabel
37
+ }
38
+
39
+ const DISPLAY_LOCATION_OPTIONS: { value: DisplayLocation; label: string; disabled?: boolean; hint?: string }[] = [
40
+ { value: "product", label: "Product Page" },
41
+ { value: "cart", label: "Cart Page" },
42
+ { value: "express", label: "Express Checkout" },
43
+ { value: "checkout", label: "Checkout Page", disabled: true, hint: "Locked by PayPal eligibility / checkout config" },
44
+ { value: "mini_cart", label: "Mini Cart (Side Cart)" },
45
+ ]
46
+
47
+ const DISABLE_BUTTON_OPTIONS: { value: DisabledButton; label: string }[] = [
48
+ { value: "paypal", label: "PayPal" },
49
+ { value: "paylater", label: "Pay Later" },
50
+ { value: "card", label: "Debit / Credit Card" },
51
+ { value: "venmo", label: "Venmo" },
52
+ { value: "applepay", label: "Apple Pay" },
53
+ { value: "googlepay", label: "Google Pay" },
54
+ ]
55
+
56
+ const HIDDEN_DISABLE_BUTTONS = new Set<DisabledButton>(["applepay", "googlepay", "paylater"])
57
+
58
+ const VISIBLE_DISABLE_BUTTON_OPTIONS = DISABLE_BUTTON_OPTIONS.filter(
59
+ (option) => !HIDDEN_DISABLE_BUTTONS.has(option.value)
60
+ )
61
+
62
+ function filterHiddenDisableButtons(list: DisabledButton[] = []) {
63
+ return list.filter((value) => !HIDDEN_DISABLE_BUTTONS.has(value))
64
+ }
65
+
66
+ const COLOR_OPTIONS: { value: ButtonColor; label: string }[] = [
67
+ { value: "gold", label: "Gold (Recommended)" },
68
+ { value: "blue", label: "Blue" },
69
+ { value: "silver", label: "Silver" },
70
+ { value: "black", label: "Black" },
71
+ { value: "white", label: "White" },
72
+ ]
73
+
74
+ const SHAPE_OPTIONS: { value: ButtonShape; label: string }[] = [
75
+ { value: "rect", label: "Rect (Recommended)" },
76
+ { value: "pill", label: "Pill" },
77
+ ]
78
+
79
+ const WIDTH_OPTIONS: { value: ButtonWidth; label: string }[] = [
80
+ { value: "small", label: "Small" },
81
+ { value: "medium", label: "Medium" },
82
+ { value: "large", label: "Large" },
83
+ { value: "responsive", label: "Responsive" },
84
+ ]
85
+
86
+ const HEIGHT_OPTIONS: number[] = [32, 36, 40, 44, 48, 52, 56]
87
+
88
+ const LABEL_OPTIONS: { value: ButtonLabel; label: string }[] = [
89
+ { value: "paypal", label: "PayPal (Recommended)" },
90
+ { value: "checkout", label: "Checkout" },
91
+ { value: "buynow", label: "Buy Now" },
92
+ { value: "pay", label: "Pay" },
93
+ ]
94
+
95
+ function cx(...parts: Array<string | false | undefined | null>) {
96
+ return parts.filter(Boolean).join(" ")
97
+ }
98
+
99
+ function Pill({
100
+ children,
101
+ onRemove,
102
+ disabled,
103
+ }: {
104
+ children: React.ReactNode
105
+ onRemove?: () => void
106
+ disabled?: boolean
107
+ }) {
108
+ return (
109
+ <span
110
+ className={cx(
111
+ "inline-flex items-center gap-1 rounded-md border px-2 py-1 text-sm",
112
+ disabled ? "opacity-60" : "opacity-100"
113
+ )}
114
+ >
115
+ {children}
116
+ {onRemove ? (
117
+ <button
118
+ type="button"
119
+ onClick={onRemove}
120
+ className="ml-1 rounded px-1 text-ui-fg-subtle hover:text-ui-fg-base"
121
+ aria-label="Remove"
122
+ >
123
+ ×
124
+ </button>
125
+ ) : null}
126
+ </span>
127
+ )
128
+ }
129
+
130
+ function SectionCard({
131
+ title,
132
+ description,
133
+ children,
134
+ right,
135
+ }: {
136
+ title: string
137
+ description?: string
138
+ children: React.ReactNode
139
+ right?: React.ReactNode
140
+ }) {
141
+ return (
142
+ <div className="rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm">
143
+ <div className="flex items-start justify-between gap-4 border-b border-ui-border-base p-4">
144
+ <div>
145
+ <div className="text-base font-semibold text-ui-fg-base">{title}</div>
146
+ {description ? <div className="mt-1 text-sm text-ui-fg-subtle">{description}</div> : null}
147
+ </div>
148
+ {right}
149
+ </div>
150
+ <div className="p-4">{children}</div>
151
+ </div>
152
+ )
153
+ }
154
+
155
+ function FieldRow({
156
+ label,
157
+ hint,
158
+ children,
159
+ }: {
160
+ label: string
161
+ hint?: React.ReactNode
162
+ children: React.ReactNode
163
+ }) {
164
+ return (
165
+ <div className="grid grid-cols-12 items-start gap-4 py-3">
166
+ <div className="col-span-12 md:col-span-4">
167
+ <div className="text-sm font-medium text-ui-fg-base">{label}</div>
168
+ {hint ? <div className="mt-1 text-xs text-ui-fg-subtle">{hint}</div> : null}
169
+ </div>
170
+ <div className="col-span-12 md:col-span-8">{children}</div>
171
+ </div>
172
+ )
173
+ }
174
+
175
+ export default function PayPalSettingsTab() {
176
+ const [form, setForm] = useState<PayPalSettingsForm>({
177
+ enabled: true,
178
+ title: "PayPal",
179
+ description: "Pay via PayPal; you can pay with your credit card if you don’t have a PayPal account",
180
+ displayOn: ["product", "cart", "express", "mini_cart"],
181
+
182
+ disableButtons: [],
183
+ buttonColor: "gold",
184
+ buttonShape: "rect",
185
+ buttonWidth: "medium",
186
+ buttonHeight: 48,
187
+ buttonLabel: "paypal",
188
+ })
189
+ const [loading, setLoading] = useState(false)
190
+ const [saving, setSaving] = useState(false)
191
+
192
+ const [toast, setToast] = useState<{ type: "success" | "error"; message: string } | null>(null)
193
+ const didInit = useRef(false)
194
+
195
+ useEffect(() => {
196
+ if (didInit.current) return
197
+ didInit.current = true
198
+
199
+ ;(async () => {
200
+ try {
201
+ setLoading(true)
202
+ const r = await fetch("/admin/paypal/settings", {
203
+ credentials: "include",
204
+ headers: { Accept: "application/json" },
205
+ })
206
+ if (!r.ok) return
207
+ const json = await r.json()
208
+ const payload = (json?.data ?? json) as any
209
+ const saved = payload?.paypal_settings
210
+ if (saved && typeof saved === "object") {
211
+ setForm((prev) => ({
212
+ ...prev,
213
+ ...saved,
214
+ disableButtons: filterHiddenDisableButtons(saved.disableButtons),
215
+ }))
216
+ }
217
+ } finally {
218
+ setLoading(false)
219
+ }
220
+ })()
221
+ }, [])
222
+
223
+ async function onSave() {
224
+ try {
225
+ setSaving(true)
226
+ const cleaned = {
227
+ ...form,
228
+ disableButtons: filterHiddenDisableButtons(form.disableButtons),
229
+ }
230
+ const r = await fetch("/admin/paypal/settings", {
231
+ method: "POST",
232
+ credentials: "include",
233
+ headers: {
234
+ "Content-Type": "application/json",
235
+ Accept: "application/json",
236
+ },
237
+ body: JSON.stringify({ paypal_settings: cleaned }),
238
+ })
239
+ if (!r.ok) {
240
+ const t = await r.text()
241
+ setToast({ type: "error", message: "Failed to save settings. " + t })
242
+ window.setTimeout(() => setToast(null), 3500)
243
+ return
244
+ }
245
+ const json = await r.json().catch(() => null)
246
+ const payload = (json?.data ?? json) as any
247
+ const saved = payload?.paypal_settings
248
+ if (saved && typeof saved === "object") {
249
+ setForm((prev) => ({
250
+ ...prev,
251
+ ...saved,
252
+ disableButtons: filterHiddenDisableButtons(saved.disableButtons),
253
+ }))
254
+ }
255
+ setToast({ type: "success", message: "Settings saved" })
256
+ window.setTimeout(() => setToast(null), 2500)
257
+ } finally {
258
+ setSaving(false)
259
+ }
260
+ }
261
+
262
+
263
+ const displayOnMap = useMemo(() => new Map(DISPLAY_LOCATION_OPTIONS.map((o) => [o.value, o])), [])
264
+
265
+ function toggleMulti<T extends string>(key: keyof PayPalSettingsForm, value: T) {
266
+ setForm((prev) => {
267
+ const list = (prev[key] as T[]) || []
268
+ const exists = list.includes(value)
269
+ const next = exists ? list.filter((v) => v !== value) : [...list, value]
270
+ return { ...prev, [key]: next }
271
+ })
272
+ }
273
+
274
+ function removeMulti<T extends string>(key: keyof PayPalSettingsForm, value: T) {
275
+ setForm((prev) => {
276
+ const list = (prev[key] as T[]) || []
277
+ return { ...prev, [key]: list.filter((v) => v !== value) }
278
+ })
279
+ }
280
+
281
+
282
+
283
+ return (
284
+ <div className="p-6">
285
+ <div className="flex flex-col gap-6">
286
+ <div className="flex items-start justify-between gap-4">
287
+ <div>
288
+ <h1 className="text-xl font-semibold text-ui-fg-base">PayPal Gateway By Easy Payment</h1>
289
+ </div>
290
+ <div className="flex items-center gap-2">
291
+
292
+ </div>
293
+ </div>
294
+
295
+ <PayPalTabs />
296
+
297
+
298
+ {toast ? (
299
+ <div
300
+ 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"
301
+ role="status"
302
+ aria-live="polite"
303
+ >
304
+ <span className={toast.type === "success" ? "text-ui-fg-base" : "text-ui-fg-error"}>
305
+ {toast.message}
306
+ </span>
307
+ </div>
308
+ ) : null}
309
+ {/* PayPal Settings (Woo-style) */}
310
+ <SectionCard
311
+ title="PayPal Settings"
312
+ description="Enable PayPal, set title/description, and choose where Smart Buttons appear."
313
+
314
+ right={(
315
+ <div className="flex items-center gap-3">
316
+ <button
317
+ type="button"
318
+ onClick={onSave}
319
+ disabled={saving || loading}
320
+ className="rounded-md bg-ui-button-neutral px-4 py-2 text-sm font-medium text-ui-fg-on-color shadow-sm hover:opacity-90 disabled:opacity-60"
321
+ >
322
+ {saving ? "Saving..." : "Save settings"}
323
+ </button>
324
+ {loading ? <span className="text-sm text-ui-fg-subtle">Loading…</span> : null}
325
+ </div>
326
+ )}
327
+ >
328
+ <div className="divide-y divide-ui-border-base">
329
+ <FieldRow label="Enable/Disable">
330
+ <label className="inline-flex items-center gap-2">
331
+ <input
332
+ type="checkbox"
333
+ checked={form.enabled}
334
+ onChange={(e) => setForm((p) => ({ ...p, enabled: e.target.checked }))}
335
+ className="h-4 w-4 rounded border-ui-border-base"
336
+ />
337
+ <span className="text-sm text-ui-fg-base">Enable PayPal</span>
338
+ </label>
339
+ </FieldRow>
340
+
341
+ <FieldRow label="Title">
342
+ <input
343
+ value={form.title}
344
+ onChange={(e) => setForm((p) => ({ ...p, title: e.target.value }))}
345
+ 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"
346
+ placeholder="PayPal"
347
+ />
348
+ </FieldRow>
349
+
350
+ <FieldRow label="Description">
351
+ <textarea
352
+ value={form.description}
353
+ onChange={(e) => setForm((p) => ({ ...p, description: e.target.value }))}
354
+ className="min-h-[84px] w-full resize-y 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"
355
+ placeholder="Pay via PayPal..."
356
+ />
357
+ </FieldRow>
358
+
359
+ <FieldRow
360
+ label="Display PayPal Buttons On"
361
+ hint="Choose where PayPal Smart Buttons should render."
362
+ >
363
+ <div className="flex flex-col gap-2">
364
+ {/* Selected pills */}
365
+ <div className="flex flex-wrap gap-2">
366
+ {DISPLAY_LOCATION_OPTIONS.filter((o) => form.displayOn.includes(o.value)).map((o) => (
367
+ <Pill
368
+ key={o.value}
369
+ disabled={o.disabled}
370
+ onRemove={
371
+ o.disabled
372
+ ? undefined
373
+ : () => removeMulti<DisplayLocation>("displayOn", o.value)
374
+ }
375
+ >
376
+ {o.label}
377
+ {o.disabled ? (
378
+ <span className="ml-1 rounded bg-ui-bg-subtle px-1 py-[1px] text-[10px] text-ui-fg-subtle">
379
+ Locked
380
+ </span>
381
+ ) : null}
382
+ </Pill>
383
+ ))}
384
+ {form.displayOn.length === 0 ? (
385
+ <span className="text-sm text-ui-fg-subtle">No locations selected.</span>
386
+ ) : null}
387
+ </div>
388
+
389
+ {/* Toggle list */}
390
+ <div className="rounded-md border border-ui-border-base p-3">
391
+ <div className="grid gap-2 md:grid-cols-2">
392
+ {DISPLAY_LOCATION_OPTIONS.map((o) => {
393
+ const checked = form.displayOn.includes(o.value)
394
+ return (
395
+ <label
396
+ key={o.value}
397
+ className={cx(
398
+ "flex items-start gap-2 rounded-md p-2",
399
+ o.disabled ? "opacity-60" : "hover:bg-ui-bg-subtle"
400
+ )}
401
+ >
402
+ <input
403
+ type="checkbox"
404
+ disabled={o.disabled}
405
+ checked={checked}
406
+ onChange={() => toggleMulti<DisplayLocation>("displayOn", o.value)}
407
+ className="mt-0.5 h-4 w-4 rounded border-ui-border-base"
408
+ />
409
+ <span className="flex flex-col">
410
+ <span className="text-sm text-ui-fg-base">{o.label}</span>
411
+ {o.hint ? <span className="text-xs text-ui-fg-subtle">{o.hint}</span> : null}
412
+ </span>
413
+ </label>
414
+ )
415
+ })}
416
+ </div>
417
+ </div>
418
+ </div>
419
+ </FieldRow>
420
+ </div>
421
+ </SectionCard>
422
+
423
+ {/* Button Appearance */}
424
+ <SectionCard
425
+ title="Button Appearance"
426
+ description="Control PayPal Smart Button styling (color/shape/size/label) and optionally disable specific buttons."
427
+ >
428
+ <div className="divide-y divide-ui-border-base">
429
+ <FieldRow
430
+ label="Disable Specific Payment Buttons"
431
+ hint="Hide individual funding sources (ex: Card, Venmo)."
432
+ >
433
+ <div className="flex flex-col gap-2">
434
+ <div className="flex flex-wrap gap-2">
435
+ {filterHiddenDisableButtons(form.disableButtons).map((v) => {
436
+ const opt = VISIBLE_DISABLE_BUTTON_OPTIONS.find((o) => o.value === v)
437
+ return (
438
+ <Pill key={v} onRemove={() => removeMulti<DisabledButton>("disableButtons", v)}>
439
+ {opt?.label ?? v}
440
+ </Pill>
441
+ )
442
+ })}
443
+ {filterHiddenDisableButtons(form.disableButtons).length === 0 ? (
444
+ <span className="text-sm text-ui-fg-subtle">No buttons disabled.</span>
445
+ ) : null}
446
+ </div>
447
+
448
+ <div className="rounded-md border border-ui-border-base p-3">
449
+ <div className="grid gap-2 md:grid-cols-2">
450
+ {VISIBLE_DISABLE_BUTTON_OPTIONS.map((o) => {
451
+ const checked = form.disableButtons.includes(o.value)
452
+ return (
453
+ <label key={o.value} className="flex items-center gap-2 rounded-md p-2 hover:bg-ui-bg-subtle">
454
+ <input
455
+ type="checkbox"
456
+ checked={checked}
457
+ onChange={() => toggleMulti<DisabledButton>("disableButtons", o.value)}
458
+ className="h-4 w-4 rounded border-ui-border-base"
459
+ />
460
+ <span className="text-sm text-ui-fg-base">{o.label}</span>
461
+ </label>
462
+ )
463
+ })}
464
+ </div>
465
+ </div>
466
+ </div>
467
+ </FieldRow>
468
+
469
+ <FieldRow label="Button Color">
470
+ <select
471
+ value={form.buttonColor}
472
+ onChange={(e) => setForm((p) => ({ ...p, buttonColor: e.target.value as ButtonColor }))}
473
+ 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"
474
+ >
475
+ {COLOR_OPTIONS.map((o) => (
476
+ <option key={o.value} value={o.value}>
477
+ {o.label}
478
+ </option>
479
+ ))}
480
+ </select>
481
+ </FieldRow>
482
+
483
+ <FieldRow label="Button Shape">
484
+ <select
485
+ value={form.buttonShape}
486
+ onChange={(e) => setForm((p) => ({ ...p, buttonShape: e.target.value as ButtonShape }))}
487
+ 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"
488
+ >
489
+ {SHAPE_OPTIONS.map((o) => (
490
+ <option key={o.value} value={o.value}>
491
+ {o.label}
492
+ </option>
493
+ ))}
494
+ </select>
495
+ </FieldRow>
496
+
497
+ <FieldRow label="Button Width">
498
+ <select
499
+ value={form.buttonWidth}
500
+ onChange={(e) => setForm((p) => ({ ...p, buttonWidth: e.target.value as ButtonWidth }))}
501
+ 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"
502
+ >
503
+ {WIDTH_OPTIONS.map((o) => (
504
+ <option key={o.value} value={o.value}>
505
+ {o.label}
506
+ </option>
507
+ ))}
508
+ </select>
509
+ </FieldRow>
510
+
511
+ <FieldRow label="Button Height">
512
+ <select
513
+ value={String(form.buttonHeight)}
514
+ onChange={(e) => setForm((p) => ({ ...p, buttonHeight: Number(e.target.value) }))}
515
+ 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"
516
+ >
517
+ {HEIGHT_OPTIONS.map((h) => (
518
+ <option key={h} value={h}>
519
+ {h} px
520
+ </option>
521
+ ))}
522
+ </select>
523
+ </FieldRow>
524
+
525
+ <FieldRow label="Button Label">
526
+ <select
527
+ value={form.buttonLabel}
528
+ onChange={(e) => setForm((p) => ({ ...p, buttonLabel: e.target.value as ButtonLabel }))}
529
+ 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"
530
+ >
531
+ {LABEL_OPTIONS.map((o) => (
532
+ <option key={o.value} value={o.value}>
533
+ {o.label}
534
+ </option>
535
+ ))}
536
+ </select>
537
+ </FieldRow>
538
+ </div>
539
+
540
+ {/* Optional: preview block (pure UI) */}
541
+ <div className="mt-6 rounded-md border border-ui-border-base bg-ui-bg-subtle p-4">
542
+ <div className="text-sm font-medium text-ui-fg-base">Preview (UI only)</div>
543
+ <div className="mt-2 text-sm text-ui-fg-subtle">
544
+ Color: <span className="text-ui-fg-base">{form.buttonColor}</span> · Shape:{" "}
545
+ <span className="text-ui-fg-base">{form.buttonShape}</span> · Width:{" "}
546
+ <span className="text-ui-fg-base">{form.buttonWidth}</span> · Height:{" "}
547
+ <span className="text-ui-fg-base">{form.buttonHeight}px</span> · Label:{" "}
548
+ <span className="text-ui-fg-base">{form.buttonLabel}</span>
549
+ </div>
550
+ </div>
551
+ </SectionCard>
552
+
553
+ {/* Remove the placeholder box */}
554
+ </div>
555
+ </div>
556
+ )
557
+ }