@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.
- package/.medusa/server/src/admin/index.js +2127 -0
- package/.medusa/server/src/admin/index.mjs +2128 -0
- package/.medusa/server/src/api/admin/payment-collections/[id]/payment-sessions/route.d.ts +3 -0
- package/.medusa/server/src/api/admin/payment-collections/[id]/payment-sessions/route.d.ts.map +1 -0
- package/.medusa/server/src/api/admin/payment-collections/[id]/payment-sessions/route.js +25 -0
- package/.medusa/server/src/api/admin/payment-collections/[id]/payment-sessions/route.js.map +1 -0
- package/.medusa/server/src/api/admin/paypal/audit-logs/route.d.ts +3 -0
- package/.medusa/server/src/api/admin/paypal/audit-logs/route.d.ts.map +1 -0
- package/.medusa/server/src/api/admin/paypal/audit-logs/route.js +12 -0
- package/.medusa/server/src/api/admin/paypal/audit-logs/route.js.map +1 -0
- package/.medusa/server/src/api/admin/paypal/disconnect/route.d.ts +3 -0
- package/.medusa/server/src/api/admin/paypal/disconnect/route.d.ts.map +1 -0
- package/.medusa/server/src/api/admin/paypal/disconnect/route.js +9 -0
- package/.medusa/server/src/api/admin/paypal/disconnect/route.js.map +1 -0
- package/.medusa/server/src/api/admin/paypal/disputes/[id]/route.d.ts +3 -0
- package/.medusa/server/src/api/admin/paypal/disputes/[id]/route.d.ts.map +1 -0
- package/.medusa/server/src/api/admin/paypal/disputes/[id]/route.js +17 -0
- package/.medusa/server/src/api/admin/paypal/disputes/[id]/route.js.map +1 -0
- package/.medusa/server/src/api/admin/paypal/disputes/route.d.ts +3 -0
- package/.medusa/server/src/api/admin/paypal/disputes/route.d.ts.map +1 -0
- package/.medusa/server/src/api/admin/paypal/disputes/route.js +27 -0
- package/.medusa/server/src/api/admin/paypal/disputes/route.js.map +1 -0
- package/.medusa/server/src/api/admin/paypal/disputes/summary/route.d.ts +3 -0
- package/.medusa/server/src/api/admin/paypal/disputes/summary/route.d.ts.map +1 -0
- package/.medusa/server/src/api/admin/paypal/disputes/summary/route.js +17 -0
- package/.medusa/server/src/api/admin/paypal/disputes/summary/route.js.map +1 -0
- package/.medusa/server/src/api/admin/paypal/environment/route.d.ts +4 -0
- package/.medusa/server/src/api/admin/paypal/environment/route.d.ts.map +1 -0
- package/.medusa/server/src/api/admin/paypal/environment/route.js +23 -0
- package/.medusa/server/src/api/admin/paypal/environment/route.js.map +1 -0
- package/.medusa/server/src/api/admin/paypal/onboard-complete/route.d.ts +8 -0
- package/.medusa/server/src/api/admin/paypal/onboard-complete/route.d.ts.map +1 -0
- package/.medusa/server/src/api/admin/paypal/onboard-complete/route.js +41 -0
- package/.medusa/server/src/api/admin/paypal/onboard-complete/route.js.map +1 -0
- package/.medusa/server/src/api/admin/paypal/onboarding-link/route.d.ts +4 -0
- package/.medusa/server/src/api/admin/paypal/onboarding-link/route.d.ts.map +1 -0
- package/.medusa/server/src/api/admin/paypal/onboarding-link/route.js +35 -0
- package/.medusa/server/src/api/admin/paypal/onboarding-link/route.js.map +1 -0
- package/.medusa/server/src/api/admin/paypal/onboarding-status/route.d.ts +3 -0
- package/.medusa/server/src/api/admin/paypal/onboarding-status/route.d.ts.map +1 -0
- package/.medusa/server/src/api/admin/paypal/onboarding-status/route.js +20 -0
- package/.medusa/server/src/api/admin/paypal/onboarding-status/route.js.map +1 -0
- package/.medusa/server/src/api/admin/paypal/reconciliation-status/route.d.ts +3 -0
- package/.medusa/server/src/api/admin/paypal/reconciliation-status/route.d.ts.map +1 -0
- package/.medusa/server/src/api/admin/paypal/reconciliation-status/route.js +8 -0
- package/.medusa/server/src/api/admin/paypal/reconciliation-status/route.js.map +1 -0
- package/.medusa/server/src/api/admin/paypal/rotate-credentials/route.d.ts +3 -0
- package/.medusa/server/src/api/admin/paypal/rotate-credentials/route.d.ts.map +1 -0
- package/.medusa/server/src/api/admin/paypal/rotate-credentials/route.js +9 -0
- package/.medusa/server/src/api/admin/paypal/rotate-credentials/route.js.map +1 -0
- package/.medusa/server/src/api/admin/paypal/save-credentials/route.d.ts +3 -0
- package/.medusa/server/src/api/admin/paypal/save-credentials/route.d.ts.map +1 -0
- package/.medusa/server/src/api/admin/paypal/save-credentials/route.js +13 -0
- package/.medusa/server/src/api/admin/paypal/save-credentials/route.js.map +1 -0
- package/.medusa/server/src/api/admin/paypal/settings/route.d.ts +4 -0
- package/.medusa/server/src/api/admin/paypal/settings/route.d.ts.map +1 -0
- package/.medusa/server/src/api/admin/paypal/settings/route.js +14 -0
- package/.medusa/server/src/api/admin/paypal/settings/route.js.map +1 -0
- package/.medusa/server/src/api/admin/paypal/status/route.d.ts +3 -0
- package/.medusa/server/src/api/admin/paypal/status/route.d.ts.map +1 -0
- package/.medusa/server/src/api/admin/paypal/status/route.js +11 -0
- package/.medusa/server/src/api/admin/paypal/status/route.js.map +1 -0
- package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.d.ts +3 -0
- package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.d.ts.map +1 -0
- package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.js +43 -0
- package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.js.map +1 -0
- package/.medusa/server/src/api/store/paypal/capture-order/route.d.ts +3 -0
- package/.medusa/server/src/api/store/paypal/capture-order/route.d.ts.map +1 -0
- package/.medusa/server/src/api/store/paypal/capture-order/route.js +215 -0
- package/.medusa/server/src/api/store/paypal/capture-order/route.js.map +1 -0
- package/.medusa/server/src/api/store/paypal/config/route.d.ts +3 -0
- package/.medusa/server/src/api/store/paypal/config/route.d.ts.map +1 -0
- package/.medusa/server/src/api/store/paypal/config/route.js +45 -0
- package/.medusa/server/src/api/store/paypal/config/route.js.map +1 -0
- package/.medusa/server/src/api/store/paypal/create-order/route.d.ts +3 -0
- package/.medusa/server/src/api/store/paypal/create-order/route.d.ts.map +1 -0
- package/.medusa/server/src/api/store/paypal/create-order/route.js +305 -0
- package/.medusa/server/src/api/store/paypal/create-order/route.js.map +1 -0
- package/.medusa/server/src/api/store/paypal/disputes/route.d.ts +3 -0
- package/.medusa/server/src/api/store/paypal/disputes/route.d.ts.map +1 -0
- package/.medusa/server/src/api/store/paypal/disputes/route.js +46 -0
- package/.medusa/server/src/api/store/paypal/disputes/route.js.map +1 -0
- package/.medusa/server/src/api/store/paypal/settings/route.d.ts +3 -0
- package/.medusa/server/src/api/store/paypal/settings/route.d.ts.map +1 -0
- package/.medusa/server/src/api/store/paypal/settings/route.js +14 -0
- package/.medusa/server/src/api/store/paypal/settings/route.js.map +1 -0
- package/.medusa/server/src/api/store/paypal/webhook/route.d.ts +3 -0
- package/.medusa/server/src/api/store/paypal/webhook/route.d.ts.map +1 -0
- package/.medusa/server/src/api/store/paypal/webhook/route.js +203 -0
- package/.medusa/server/src/api/store/paypal/webhook/route.js.map +1 -0
- package/.medusa/server/src/jobs/paypal-reconcile.d.ts +7 -0
- package/.medusa/server/src/jobs/paypal-reconcile.d.ts.map +1 -0
- package/.medusa/server/src/jobs/paypal-reconcile.js +131 -0
- package/.medusa/server/src/jobs/paypal-reconcile.js.map +1 -0
- package/.medusa/server/src/jobs/paypal-webhook-retry.d.ts +7 -0
- package/.medusa/server/src/jobs/paypal-webhook-retry.d.ts.map +1 -0
- package/.medusa/server/src/jobs/paypal-webhook-retry.js +78 -0
- package/.medusa/server/src/jobs/paypal-webhook-retry.js.map +1 -0
- package/.medusa/server/src/modules/paypal/clients/paypal-seller.client.d.ts +14 -0
- package/.medusa/server/src/modules/paypal/clients/paypal-seller.client.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/clients/paypal-seller.client.js +65 -0
- package/.medusa/server/src/modules/paypal/clients/paypal-seller.client.js.map +1 -0
- package/.medusa/server/src/modules/paypal/index.d.ts +92 -0
- package/.medusa/server/src/modules/paypal/index.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/index.js +13 -0
- package/.medusa/server/src/modules/paypal/index.js.map +1 -0
- package/.medusa/server/src/modules/paypal/migrations/20260115120000_create_paypal_connection.d.ts +6 -0
- package/.medusa/server/src/modules/paypal/migrations/20260115120000_create_paypal_connection.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/migrations/20260115120000_create_paypal_connection.js +36 -0
- package/.medusa/server/src/modules/paypal/migrations/20260115120000_create_paypal_connection.js.map +1 -0
- package/.medusa/server/src/modules/paypal/migrations/20260123090000_create_paypal_settings.d.ts +6 -0
- package/.medusa/server/src/modules/paypal/migrations/20260123090000_create_paypal_settings.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/migrations/20260123090000_create_paypal_settings.js +25 -0
- package/.medusa/server/src/modules/paypal/migrations/20260123090000_create_paypal_settings.js.map +1 -0
- package/.medusa/server/src/modules/paypal/migrations/20260201090000_create_paypal_webhook_event.d.ts +6 -0
- package/.medusa/server/src/modules/paypal/migrations/20260201090000_create_paypal_webhook_event.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/migrations/20260201090000_create_paypal_webhook_event.js +32 -0
- package/.medusa/server/src/modules/paypal/migrations/20260201090000_create_paypal_webhook_event.js.map +1 -0
- package/.medusa/server/src/modules/paypal/migrations/20260301090000_create_paypal_audit_log.d.ts +6 -0
- package/.medusa/server/src/modules/paypal/migrations/20260301090000_create_paypal_audit_log.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/migrations/20260301090000_create_paypal_audit_log.js +29 -0
- package/.medusa/server/src/modules/paypal/migrations/20260301090000_create_paypal_audit_log.js.map +1 -0
- package/.medusa/server/src/modules/paypal/migrations/20260401090000_create_paypal_metric.d.ts +6 -0
- package/.medusa/server/src/modules/paypal/migrations/20260401090000_create_paypal_metric.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/migrations/20260401090000_create_paypal_metric.js +30 -0
- package/.medusa/server/src/modules/paypal/migrations/20260401090000_create_paypal_metric.js.map +1 -0
- package/.medusa/server/src/modules/paypal/migrations/20260501090000_create_paypal_dispute.d.ts +6 -0
- package/.medusa/server/src/modules/paypal/migrations/20260501090000_create_paypal_dispute.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/migrations/20260501090000_create_paypal_dispute.js +43 -0
- package/.medusa/server/src/modules/paypal/migrations/20260501090000_create_paypal_dispute.js.map +1 -0
- package/.medusa/server/src/modules/paypal/migrations/20260701090000_add_paypal_webhook_event_processing.d.ts +6 -0
- package/.medusa/server/src/modules/paypal/migrations/20260701090000_add_paypal_webhook_event_processing.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/migrations/20260701090000_add_paypal_webhook_event_processing.js +34 -0
- package/.medusa/server/src/modules/paypal/migrations/20260701090000_add_paypal_webhook_event_processing.js.map +1 -0
- package/.medusa/server/src/modules/paypal/models/paypal_audit_log.d.ts +7 -0
- package/.medusa/server/src/modules/paypal/models/paypal_audit_log.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/models/paypal_audit_log.js +10 -0
- package/.medusa/server/src/modules/paypal/models/paypal_audit_log.js.map +1 -0
- package/.medusa/server/src/modules/paypal/models/paypal_connection.d.ts +14 -0
- package/.medusa/server/src/modules/paypal/models/paypal_connection.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/models/paypal_connection.js +17 -0
- package/.medusa/server/src/modules/paypal/models/paypal_connection.js.map +1 -0
- package/.medusa/server/src/modules/paypal/models/paypal_dispute.d.ts +16 -0
- package/.medusa/server/src/modules/paypal/models/paypal_dispute.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/models/paypal_dispute.js +19 -0
- package/.medusa/server/src/modules/paypal/models/paypal_dispute.js.map +1 -0
- package/.medusa/server/src/modules/paypal/models/paypal_metric.d.ts +7 -0
- package/.medusa/server/src/modules/paypal/models/paypal_metric.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/models/paypal_metric.js +10 -0
- package/.medusa/server/src/modules/paypal/models/paypal_metric.js.map +1 -0
- package/.medusa/server/src/modules/paypal/models/paypal_settings.d.ts +6 -0
- package/.medusa/server/src/modules/paypal/models/paypal_settings.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/models/paypal_settings.js +9 -0
- package/.medusa/server/src/modules/paypal/models/paypal_settings.js.map +1 -0
- package/.medusa/server/src/modules/paypal/models/paypal_webhook_event.d.ts +17 -0
- package/.medusa/server/src/modules/paypal/models/paypal_webhook_event.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/models/paypal_webhook_event.js +20 -0
- package/.medusa/server/src/modules/paypal/models/paypal_webhook_event.js.map +1 -0
- package/.medusa/server/src/modules/paypal/payment-provider/card-service.d.ts +35 -0
- package/.medusa/server/src/modules/paypal/payment-provider/card-service.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/payment-provider/card-service.js +569 -0
- package/.medusa/server/src/modules/paypal/payment-provider/card-service.js.map +1 -0
- package/.medusa/server/src/modules/paypal/payment-provider/index.d.ts +10 -0
- package/.medusa/server/src/modules/paypal/payment-provider/index.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/payment-provider/index.js +22 -0
- package/.medusa/server/src/modules/paypal/payment-provider/index.js.map +1 -0
- package/.medusa/server/src/modules/paypal/payment-provider/service.d.ts +44 -0
- package/.medusa/server/src/modules/paypal/payment-provider/service.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/payment-provider/service.js +825 -0
- package/.medusa/server/src/modules/paypal/payment-provider/service.js.map +1 -0
- package/.medusa/server/src/modules/paypal/payment-provider/webhook-utils.d.ts +3 -0
- package/.medusa/server/src/modules/paypal/payment-provider/webhook-utils.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/payment-provider/webhook-utils.js +74 -0
- package/.medusa/server/src/modules/paypal/payment-provider/webhook-utils.js.map +1 -0
- package/.medusa/server/src/modules/paypal/service.d.ts +362 -0
- package/.medusa/server/src/modules/paypal/service.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/service.js +1180 -0
- package/.medusa/server/src/modules/paypal/service.js.map +1 -0
- package/.medusa/server/src/modules/paypal/types/config.d.ts +14 -0
- package/.medusa/server/src/modules/paypal/types/config.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/types/config.js +33 -0
- package/.medusa/server/src/modules/paypal/types/config.js.map +1 -0
- package/.medusa/server/src/modules/paypal/utils/amounts.d.ts +3 -0
- package/.medusa/server/src/modules/paypal/utils/amounts.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/utils/amounts.js +40 -0
- package/.medusa/server/src/modules/paypal/utils/amounts.js.map +1 -0
- package/.medusa/server/src/modules/paypal/utils/crypto.d.ts +4 -0
- package/.medusa/server/src/modules/paypal/utils/crypto.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/utils/crypto.js +47 -0
- package/.medusa/server/src/modules/paypal/utils/crypto.js.map +1 -0
- package/.medusa/server/src/modules/paypal/utils/currencies.d.ts +19 -0
- package/.medusa/server/src/modules/paypal/utils/currencies.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/utils/currencies.js +69 -0
- package/.medusa/server/src/modules/paypal/utils/currencies.js.map +1 -0
- package/.medusa/server/src/modules/paypal/utils/provider-ids.d.ts +9 -0
- package/.medusa/server/src/modules/paypal/utils/provider-ids.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/utils/provider-ids.js +50 -0
- package/.medusa/server/src/modules/paypal/utils/provider-ids.js.map +1 -0
- package/.medusa/server/src/modules/paypal/webhook-processor.d.ts +38 -0
- package/.medusa/server/src/modules/paypal/webhook-processor.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/webhook-processor.js +265 -0
- package/.medusa/server/src/modules/paypal/webhook-processor.js.map +1 -0
- package/LICENSE +21 -0
- package/README.md +67 -0
- package/package.json +61 -0
- package/postcss.config.cjs +3 -0
- package/src/admin/index.ts +7 -0
- package/src/admin/routes/settings/paypal/_components/Tabs.tsx +55 -0
- package/src/admin/routes/settings/paypal/_components/Toast.tsx +51 -0
- package/src/admin/routes/settings/paypal/additional-settings/page.tsx +346 -0
- package/src/admin/routes/settings/paypal/advanced-card-payments/page.tsx +381 -0
- package/src/admin/routes/settings/paypal/apple-pay/page.tsx +5 -0
- package/src/admin/routes/settings/paypal/audit-logs/page.tsx +131 -0
- package/src/admin/routes/settings/paypal/connection/page.tsx +750 -0
- package/src/admin/routes/settings/paypal/disputes/page.tsx +259 -0
- package/src/admin/routes/settings/paypal/google-pay/page.tsx +5 -0
- package/src/admin/routes/settings/paypal/page.tsx +16 -0
- package/src/admin/routes/settings/paypal/pay-later-messaging/page.tsx +5 -0
- package/src/admin/routes/settings/paypal/paypal-settings/page.tsx +557 -0
- package/src/admin/routes/settings/paypal/reconciliation-status/page.tsx +165 -0
- package/src/api/admin/payment-collections/[id]/payment-sessions/route.ts +32 -0
- package/src/api/admin/paypal/audit-logs/route.ts +13 -0
- package/src/api/admin/paypal/disconnect/route.ts +8 -0
- package/src/api/admin/paypal/disputes/[id]/route.ts +19 -0
- package/src/api/admin/paypal/disputes/route.ts +30 -0
- package/src/api/admin/paypal/disputes/summary/route.ts +18 -0
- package/src/api/admin/paypal/environment/route.ts +25 -0
- package/src/api/admin/paypal/onboard-complete/route.ts +44 -0
- package/src/api/admin/paypal/onboarding-link/route.ts +45 -0
- package/src/api/admin/paypal/onboarding-status/route.ts +18 -0
- package/src/api/admin/paypal/reconciliation-status/route.ts +7 -0
- package/src/api/admin/paypal/rotate-credentials/route.ts +8 -0
- package/src/api/admin/paypal/save-credentials/route.ts +14 -0
- package/src/api/admin/paypal/settings/route.ts +14 -0
- package/src/api/admin/paypal/status/route.ts +12 -0
- package/src/api/store/payment-collections/[id]/payment-sessions/route.ts +51 -0
- package/src/api/store/paypal/capture-order/route.ts +270 -0
- package/src/api/store/paypal/config/route.ts +59 -0
- package/src/api/store/paypal/create-order/route.ts +374 -0
- package/src/api/store/paypal/disputes/route.ts +67 -0
- package/src/api/store/paypal/settings/route.ts +12 -0
- package/src/api/store/paypal/webhook/route.ts +247 -0
- package/src/jobs/paypal-reconcile.ts +135 -0
- package/src/jobs/paypal-webhook-retry.ts +86 -0
- package/src/modules/paypal/clients/paypal-seller.client.ts +59 -0
- package/src/modules/paypal/index.ts +8 -0
- package/src/modules/paypal/migrations/20260115120000_create_paypal_connection.ts +33 -0
- package/src/modules/paypal/migrations/20260123090000_create_paypal_settings.ts +22 -0
- package/src/modules/paypal/migrations/20260201090000_create_paypal_webhook_event.ts +29 -0
- package/src/modules/paypal/migrations/20260301090000_create_paypal_audit_log.ts +26 -0
- package/src/modules/paypal/migrations/20260401090000_create_paypal_metric.ts +27 -0
- package/src/modules/paypal/migrations/20260501090000_create_paypal_dispute.ts +40 -0
- package/src/modules/paypal/migrations/20260701090000_add_paypal_webhook_event_processing.ts +31 -0
- package/src/modules/paypal/models/paypal_audit_log.ts +9 -0
- package/src/modules/paypal/models/paypal_connection.ts +21 -0
- package/src/modules/paypal/models/paypal_dispute.ts +18 -0
- package/src/modules/paypal/models/paypal_metric.ts +9 -0
- package/src/modules/paypal/models/paypal_settings.ts +8 -0
- package/src/modules/paypal/models/paypal_webhook_event.ts +19 -0
- package/src/modules/paypal/payment-provider/README.md +22 -0
- package/src/modules/paypal/payment-provider/card-service.ts +710 -0
- package/src/modules/paypal/payment-provider/index.ts +19 -0
- package/src/modules/paypal/payment-provider/service.ts +1035 -0
- package/src/modules/paypal/payment-provider/webhook-utils.ts +88 -0
- package/src/modules/paypal/service.ts +1422 -0
- package/src/modules/paypal/types/config.ts +47 -0
- package/src/modules/paypal/utils/amounts.ts +41 -0
- package/src/modules/paypal/utils/crypto.ts +51 -0
- package/src/modules/paypal/utils/currencies.ts +84 -0
- package/src/modules/paypal/utils/provider-ids.ts +53 -0
- package/src/modules/paypal/webhook-processor.ts +313 -0
- package/tsconfig.json +31 -0
|
@@ -0,0 +1,750 @@
|
|
|
1
|
+
import React, {
|
|
2
|
+
useCallback,
|
|
3
|
+
useEffect,
|
|
4
|
+
useLayoutEffect,
|
|
5
|
+
useMemo,
|
|
6
|
+
useRef,
|
|
7
|
+
useState,
|
|
8
|
+
} from "react"
|
|
9
|
+
import { defineRouteConfig } from "@medusajs/admin-sdk"
|
|
10
|
+
import PayPalTabs from "../_components/Tabs"
|
|
11
|
+
|
|
12
|
+
export const config = defineRouteConfig({
|
|
13
|
+
label: "PayPal Connection",
|
|
14
|
+
hide: true,
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
/* ------------------------------------------------------------------ */
|
|
18
|
+
/* HIGH PRIORITY EXECUTION - RUNS BEFORE COMPONENT MOUNTS */
|
|
19
|
+
/* ------------------------------------------------------------------ */
|
|
20
|
+
|
|
21
|
+
// 1. Inject Preload Link IMMEDIATELY
|
|
22
|
+
if (typeof window !== "undefined") {
|
|
23
|
+
const preloadHref =
|
|
24
|
+
"https://www.paypal.com/webapps/merchantboarding/js/lib/lightbox/partner.js"
|
|
25
|
+
|
|
26
|
+
const existingPreload = document.head.querySelector(
|
|
27
|
+
`link[rel="preload"][href="${preloadHref}"]`
|
|
28
|
+
)
|
|
29
|
+
if (!existingPreload) {
|
|
30
|
+
const preloadLink = document.createElement("link")
|
|
31
|
+
preloadLink.rel = "preload"
|
|
32
|
+
preloadLink.href = preloadHref
|
|
33
|
+
preloadLink.as = "script"
|
|
34
|
+
document.head.appendChild(preloadLink)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// 2. Inject PayPal Script IMMEDIATELY (before React renders)
|
|
38
|
+
const existingScript = document.getElementById(
|
|
39
|
+
"paypal-partner-js"
|
|
40
|
+
) as HTMLScriptElement | null
|
|
41
|
+
if (!existingScript) {
|
|
42
|
+
const ppScript = document.createElement("script")
|
|
43
|
+
ppScript.id = "paypal-partner-js"
|
|
44
|
+
ppScript.src = preloadHref
|
|
45
|
+
ppScript.async = true
|
|
46
|
+
document.head.appendChild(ppScript)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
declare global {
|
|
51
|
+
interface Window {
|
|
52
|
+
PAYPAL?: {
|
|
53
|
+
apps?: {
|
|
54
|
+
Signup?: {
|
|
55
|
+
miniBrowser?: { init: () => void }
|
|
56
|
+
// some partner.js builds expose MiniBrowser (capital M)
|
|
57
|
+
MiniBrowser?: { closeFlow?: () => void }
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
onboardingCallback?: (authCode: string, sharedId: string) => void
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Partner.js is now loaded lazily only when needed (removed global injection)
|
|
66
|
+
|
|
67
|
+
const SERVICE_URL = "/admin/paypal/onboarding-link"
|
|
68
|
+
const CACHE_KEY = "pp_onboard_cache"
|
|
69
|
+
const RELOAD_KEY = "pp_onboard_reloaded_once"
|
|
70
|
+
const CACHE_EXPIRY = 10 * 60 * 1000 // 10 minutes
|
|
71
|
+
|
|
72
|
+
// ✅ backend endpoint to exchange authCode/sharedId (medusa)
|
|
73
|
+
const ONBOARDING_COMPLETE_ENDPOINT = "/admin/paypal/onboard-complete"
|
|
74
|
+
const STATUS_ENDPOINT = "/admin/paypal/status"
|
|
75
|
+
const SAVE_CREDENTIALS_ENDPOINT = "/admin/paypal/save-credentials"
|
|
76
|
+
const DISCONNECT_ENDPOINT = "/admin/paypal/disconnect"
|
|
77
|
+
|
|
78
|
+
// 3. Immediate Cache Check (runs before React component)
|
|
79
|
+
let cachedUrl: string | null = null
|
|
80
|
+
if (typeof window !== "undefined") {
|
|
81
|
+
try {
|
|
82
|
+
const cached = localStorage.getItem(CACHE_KEY)
|
|
83
|
+
if (cached) {
|
|
84
|
+
const data = JSON.parse(cached)
|
|
85
|
+
if (new Date().getTime() - data.ts < CACHE_EXPIRY) {
|
|
86
|
+
cachedUrl = data.url
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
} catch (e) {
|
|
90
|
+
console.error("Cache read error:", e)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* ------------------------------------------------------------------ */
|
|
95
|
+
/* REACT COMPONENT */
|
|
96
|
+
/* ------------------------------------------------------------------ */
|
|
97
|
+
|
|
98
|
+
export default function PayPalConnectionPage() {
|
|
99
|
+
const [env, setEnv] = useState<"sandbox" | "live">("sandbox")
|
|
100
|
+
|
|
101
|
+
// Sync initial environment from backend
|
|
102
|
+
useEffect(() => {
|
|
103
|
+
fetch("/admin/paypal/environment", { method: "GET" })
|
|
104
|
+
.then((r) => r.json())
|
|
105
|
+
.then((d) => {
|
|
106
|
+
const v = d?.environment === "live" ? "live" : "sandbox"
|
|
107
|
+
setEnv(v)
|
|
108
|
+
})
|
|
109
|
+
.catch(() => {})
|
|
110
|
+
}, [])
|
|
111
|
+
const [connState, setConnState] = useState<
|
|
112
|
+
"loading" | "ready" | "connected" | "error"
|
|
113
|
+
>("loading")
|
|
114
|
+
const [error, setError] = useState<string | null>(null)
|
|
115
|
+
const [finalUrl, setFinalUrl] = useState<string>("")
|
|
116
|
+
const [showManual, setShowManual] = useState(false)
|
|
117
|
+
const [clientId, setClientId] = useState("")
|
|
118
|
+
const [secret, setSecret] = useState("")
|
|
119
|
+
const [merchantId, setMerchantId] = useState("")
|
|
120
|
+
const [statusInfo, setStatusInfo] = useState<{
|
|
121
|
+
seller_client_id_masked?: string | null
|
|
122
|
+
seller_client_secret_masked?: string | null
|
|
123
|
+
seller_email?: string | null
|
|
124
|
+
} | null>(null)
|
|
125
|
+
|
|
126
|
+
// ✅ onboarding in progress (for disabling UI)
|
|
127
|
+
const [onboardingInProgress, setOnboardingInProgress] = useState(false)
|
|
128
|
+
|
|
129
|
+
const initLoaderRef = useRef<HTMLDivElement>(null)
|
|
130
|
+
const paypalButtonRef = useRef<HTMLAnchorElement>(null)
|
|
131
|
+
const errorLogRef = useRef<HTMLDivElement>(null)
|
|
132
|
+
const runIdRef = useRef(0)
|
|
133
|
+
const currentRunId = useRef(0)
|
|
134
|
+
|
|
135
|
+
// Measure PayPal button width for OR centering (Woo-style)
|
|
136
|
+
const ppBtnMeasureRef = useRef<HTMLAnchorElement | null>(null)
|
|
137
|
+
const [ppBtnWidth, setPpBtnWidth] = useState<number | null>(null)
|
|
138
|
+
|
|
139
|
+
const canSaveManual = useMemo(() => {
|
|
140
|
+
return clientId.trim().length > 0 && secret.trim().length > 0
|
|
141
|
+
}, [clientId, secret])
|
|
142
|
+
|
|
143
|
+
const maskValue = useCallback((value: string, visibleChars = 4) => {
|
|
144
|
+
if (!value) return ""
|
|
145
|
+
if (value.length <= visibleChars) {
|
|
146
|
+
return "•".repeat(value.length)
|
|
147
|
+
}
|
|
148
|
+
return `${"•".repeat(Math.max(0, value.length - visibleChars))}${value.slice(
|
|
149
|
+
-visibleChars
|
|
150
|
+
)}`
|
|
151
|
+
}, [])
|
|
152
|
+
|
|
153
|
+
// Exact copy of fetchFreshLink from original JS (+ reload-once logic ONLY)
|
|
154
|
+
const fetchFreshLink = useCallback(
|
|
155
|
+
(runId: number) => {
|
|
156
|
+
if (initLoaderRef.current) {
|
|
157
|
+
const loaderText = initLoaderRef.current.querySelector("#loader-text")
|
|
158
|
+
if (loaderText)
|
|
159
|
+
loaderText.textContent = "Generating onboarding session..."
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
fetch(SERVICE_URL, {
|
|
163
|
+
method: "POST",
|
|
164
|
+
headers: { "content-type": "application/json" },
|
|
165
|
+
body: JSON.stringify({
|
|
166
|
+
products: ["PPCP"],
|
|
167
|
+
}),
|
|
168
|
+
})
|
|
169
|
+
.then((r) => r.json())
|
|
170
|
+
.then((data) => {
|
|
171
|
+
if (runId !== currentRunId.current) return
|
|
172
|
+
|
|
173
|
+
const href = data?.onboarding_url
|
|
174
|
+
if (!href) {
|
|
175
|
+
showError("Onboarding URL not returned.")
|
|
176
|
+
return
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const finalUrl =
|
|
180
|
+
href + (href.includes("?") ? "&" : "?") + "displayMode=minibrowser"
|
|
181
|
+
|
|
182
|
+
localStorage.setItem(
|
|
183
|
+
CACHE_KEY,
|
|
184
|
+
JSON.stringify({
|
|
185
|
+
url: finalUrl,
|
|
186
|
+
ts: Date.now(),
|
|
187
|
+
})
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
if (!localStorage.getItem(RELOAD_KEY)) {
|
|
191
|
+
localStorage.setItem(RELOAD_KEY, "1")
|
|
192
|
+
window.location.reload()
|
|
193
|
+
return
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
activatePayPal(finalUrl, runId)
|
|
197
|
+
})
|
|
198
|
+
.catch(() => {
|
|
199
|
+
if (runId !== currentRunId.current) return
|
|
200
|
+
showError("Unable to connect to service.")
|
|
201
|
+
})
|
|
202
|
+
},
|
|
203
|
+
[env]
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
// Exact copy of showUI from original JS (safe: only init when button exists)
|
|
207
|
+
const showUI = useCallback(() => {
|
|
208
|
+
const btn = document.querySelector('[data-paypal-button="true"]')
|
|
209
|
+
if (btn && window.PAYPAL?.apps?.Signup?.miniBrowser?.init) {
|
|
210
|
+
window.PAYPAL.apps.Signup.miniBrowser.init()
|
|
211
|
+
}
|
|
212
|
+
setConnState("ready")
|
|
213
|
+
}, [])
|
|
214
|
+
|
|
215
|
+
// Exact copy of showError from original JS
|
|
216
|
+
const showError = useCallback((msg: string) => {
|
|
217
|
+
setConnState("error")
|
|
218
|
+
setError(msg)
|
|
219
|
+
}, [])
|
|
220
|
+
|
|
221
|
+
// activatePayPal (keeps PayPal partner.js global injection; waits for PAYPAL then inits)
|
|
222
|
+
const activatePayPal = useCallback(
|
|
223
|
+
(url: string, runId: number) => {
|
|
224
|
+
if (paypalButtonRef.current) {
|
|
225
|
+
paypalButtonRef.current.href = url
|
|
226
|
+
}
|
|
227
|
+
setFinalUrl(url)
|
|
228
|
+
|
|
229
|
+
const tryInit = () => {
|
|
230
|
+
if (runId !== currentRunId.current) return
|
|
231
|
+
if (window.PAYPAL?.apps?.Signup) {
|
|
232
|
+
showUI()
|
|
233
|
+
return
|
|
234
|
+
}
|
|
235
|
+
// wait briefly for partner.js to finish loading
|
|
236
|
+
setTimeout(tryInit, 50)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
tryInit()
|
|
240
|
+
},
|
|
241
|
+
[showUI]
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
// Initialize - runs on mount and env change
|
|
245
|
+
useEffect(() => {
|
|
246
|
+
currentRunId.current = ++runIdRef.current
|
|
247
|
+
const runId = currentRunId.current
|
|
248
|
+
|
|
249
|
+
let cancelled = false
|
|
250
|
+
|
|
251
|
+
const run = async () => {
|
|
252
|
+
setConnState("loading")
|
|
253
|
+
setError(null)
|
|
254
|
+
setFinalUrl("")
|
|
255
|
+
|
|
256
|
+
// 1) If already connected in DB, don't ask to onboard again
|
|
257
|
+
try {
|
|
258
|
+
const r = await fetch(`${STATUS_ENDPOINT}?environment=${env}`, {
|
|
259
|
+
method: "GET",
|
|
260
|
+
})
|
|
261
|
+
const st = await r.json().catch(() => ({}))
|
|
262
|
+
|
|
263
|
+
if (cancelled || runId !== currentRunId.current) return
|
|
264
|
+
|
|
265
|
+
setStatusInfo(st)
|
|
266
|
+
|
|
267
|
+
const isConnected =
|
|
268
|
+
st?.status === "connected" && st?.seller_client_id_present === true
|
|
269
|
+
|
|
270
|
+
if (isConnected) {
|
|
271
|
+
setConnState("connected")
|
|
272
|
+
setShowManual(false)
|
|
273
|
+
return
|
|
274
|
+
}
|
|
275
|
+
} catch (e) {
|
|
276
|
+
// ignore status errors; proceed with onboarding
|
|
277
|
+
console.error(e)
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// 2) Not connected -> continue onboarding flow
|
|
281
|
+
if (cachedUrl) {
|
|
282
|
+
console.log("Using prioritized cache...")
|
|
283
|
+
activatePayPal(cachedUrl, runId)
|
|
284
|
+
} else {
|
|
285
|
+
fetchFreshLink(runId)
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
run()
|
|
290
|
+
|
|
291
|
+
return () => {
|
|
292
|
+
cancelled = true
|
|
293
|
+
currentRunId.current = 0
|
|
294
|
+
}
|
|
295
|
+
}, [env, fetchFreshLink, activatePayPal])
|
|
296
|
+
|
|
297
|
+
// ✅ setupOnboarding() behavior (Woo-style) inside callback
|
|
298
|
+
useLayoutEffect(() => {
|
|
299
|
+
window.onboardingCallback = async function (authCode: string, sharedId: string) {
|
|
300
|
+
// Woo sets this; keep safe
|
|
301
|
+
try {
|
|
302
|
+
;(window as any).onbeforeunload = ""
|
|
303
|
+
} catch {}
|
|
304
|
+
|
|
305
|
+
// show blocking state (no new UI components, just disable + loader text)
|
|
306
|
+
setOnboardingInProgress(true)
|
|
307
|
+
setConnState("loading")
|
|
308
|
+
setError(null)
|
|
309
|
+
|
|
310
|
+
// post to backend (authCode/sharedId/env)
|
|
311
|
+
const payload = {
|
|
312
|
+
authCode,
|
|
313
|
+
sharedId,
|
|
314
|
+
env: env === "sandbox" ? "sandbox" : "live",
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
try {
|
|
318
|
+
const res = await fetch(ONBOARDING_COMPLETE_ENDPOINT, {
|
|
319
|
+
method: "POST",
|
|
320
|
+
headers: { "content-type": "application/json" },
|
|
321
|
+
body: JSON.stringify(payload),
|
|
322
|
+
})
|
|
323
|
+
|
|
324
|
+
if (!res.ok) {
|
|
325
|
+
const txt = await res.text().catch(() => "")
|
|
326
|
+
throw new Error(txt || `Onboarding exchange failed (${res.status})`)
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// ✅ ONLY NOW close the mini-browser flow
|
|
330
|
+
try {
|
|
331
|
+
const close1 = window.PAYPAL?.apps?.Signup?.MiniBrowser?.closeFlow
|
|
332
|
+
if (typeof close1 === "function") close1()
|
|
333
|
+
} catch {}
|
|
334
|
+
try {
|
|
335
|
+
const close2 =
|
|
336
|
+
window.PAYPAL?.apps?.Signup?.miniBrowser &&
|
|
337
|
+
(window.PAYPAL.apps.Signup.miniBrowser as any).closeFlow
|
|
338
|
+
if (typeof close2 === "function") close2()
|
|
339
|
+
} catch {}
|
|
340
|
+
|
|
341
|
+
// clear cache so next run fetches new url
|
|
342
|
+
try {
|
|
343
|
+
localStorage.removeItem(CACHE_KEY)
|
|
344
|
+
localStorage.removeItem(RELOAD_KEY)
|
|
345
|
+
} catch {}
|
|
346
|
+
|
|
347
|
+
// Woo does: window.location.href = window.location.href;
|
|
348
|
+
window.location.href = window.location.href
|
|
349
|
+
} catch (e: any) {
|
|
350
|
+
console.error(e)
|
|
351
|
+
setConnState("error")
|
|
352
|
+
setError(e?.message || "Exchange failed while saving credentials.")
|
|
353
|
+
setOnboardingInProgress(false)
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
return () => {
|
|
358
|
+
window.onboardingCallback = undefined
|
|
359
|
+
}
|
|
360
|
+
}, [env])
|
|
361
|
+
|
|
362
|
+
// Measure PayPal button width (for OR centering under button)
|
|
363
|
+
useLayoutEffect(() => {
|
|
364
|
+
const el = ppBtnMeasureRef.current
|
|
365
|
+
if (!el) return
|
|
366
|
+
|
|
367
|
+
const update = () => {
|
|
368
|
+
const w = Math.round(el.getBoundingClientRect().width || 0)
|
|
369
|
+
if (w > 0) setPpBtnWidth(w)
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
update()
|
|
373
|
+
|
|
374
|
+
let ro: ResizeObserver | null = null
|
|
375
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
376
|
+
ro = new ResizeObserver(() => update())
|
|
377
|
+
ro.observe(el)
|
|
378
|
+
} else {
|
|
379
|
+
window.addEventListener("resize", update)
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
return () => {
|
|
383
|
+
if (ro) ro.disconnect()
|
|
384
|
+
else window.removeEventListener("resize", update)
|
|
385
|
+
}
|
|
386
|
+
}, [connState, env, finalUrl])
|
|
387
|
+
|
|
388
|
+
const handleConnectClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
|
|
389
|
+
if (connState !== "ready" || !finalUrl || onboardingInProgress) {
|
|
390
|
+
e.preventDefault()
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
const handleSaveManual = async () => {
|
|
395
|
+
if (!canSaveManual || onboardingInProgress) return
|
|
396
|
+
setOnboardingInProgress(true)
|
|
397
|
+
setConnState("loading")
|
|
398
|
+
setError(null)
|
|
399
|
+
|
|
400
|
+
try {
|
|
401
|
+
const res = await fetch(SAVE_CREDENTIALS_ENDPOINT, {
|
|
402
|
+
method: "POST",
|
|
403
|
+
headers: { "content-type": "application/json" },
|
|
404
|
+
body: JSON.stringify({
|
|
405
|
+
clientId: clientId.trim(),
|
|
406
|
+
clientSecret: secret.trim(),
|
|
407
|
+
}),
|
|
408
|
+
})
|
|
409
|
+
|
|
410
|
+
if (!res.ok) {
|
|
411
|
+
const txt = await res.text().catch(() => "")
|
|
412
|
+
throw new Error(txt || `Save credentials failed (${res.status})`)
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
setConnState("connected")
|
|
416
|
+
setStatusInfo({
|
|
417
|
+
seller_client_id_masked: maskValue(clientId.trim()),
|
|
418
|
+
seller_client_secret_masked: "••••••••",
|
|
419
|
+
})
|
|
420
|
+
setShowManual(false)
|
|
421
|
+
|
|
422
|
+
try {
|
|
423
|
+
localStorage.removeItem(CACHE_KEY)
|
|
424
|
+
localStorage.removeItem(RELOAD_KEY)
|
|
425
|
+
} catch {}
|
|
426
|
+
} catch (e: any) {
|
|
427
|
+
console.error(e)
|
|
428
|
+
setConnState("error")
|
|
429
|
+
setError(e?.message || "Failed to save credentials.")
|
|
430
|
+
} finally {
|
|
431
|
+
setOnboardingInProgress(false)
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
const handleDisconnect = async () => {
|
|
436
|
+
if (onboardingInProgress) return
|
|
437
|
+
if (!window.confirm("Disconnect PayPal for this environment?")) return
|
|
438
|
+
|
|
439
|
+
setOnboardingInProgress(true)
|
|
440
|
+
setConnState("loading")
|
|
441
|
+
setError(null)
|
|
442
|
+
setFinalUrl("")
|
|
443
|
+
setShowManual(false)
|
|
444
|
+
|
|
445
|
+
try {
|
|
446
|
+
const res = await fetch(DISCONNECT_ENDPOINT, {
|
|
447
|
+
method: "POST",
|
|
448
|
+
headers: { "content-type": "application/json" },
|
|
449
|
+
body: JSON.stringify({ environment: env }),
|
|
450
|
+
})
|
|
451
|
+
|
|
452
|
+
if (!res.ok) {
|
|
453
|
+
const t = await res.text().catch(() => "")
|
|
454
|
+
throw new Error(t || `Disconnect failed (${res.status})`)
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
try {
|
|
458
|
+
localStorage.removeItem(CACHE_KEY)
|
|
459
|
+
localStorage.removeItem(RELOAD_KEY)
|
|
460
|
+
} catch {}
|
|
461
|
+
|
|
462
|
+
// Restart onboarding link generation for current env
|
|
463
|
+
currentRunId.current = ++runIdRef.current
|
|
464
|
+
const runId = currentRunId.current
|
|
465
|
+
fetchFreshLink(runId)
|
|
466
|
+
} catch (e: any) {
|
|
467
|
+
console.error(e)
|
|
468
|
+
setConnState("error")
|
|
469
|
+
setError(e?.message || "Failed to disconnect.")
|
|
470
|
+
} finally {
|
|
471
|
+
setOnboardingInProgress(false)
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
const handleEnvChange = async (e: React.ChangeEvent<HTMLSelectElement>) => {
|
|
476
|
+
const next = e.target.value as "sandbox" | "live"
|
|
477
|
+
setEnv(next)
|
|
478
|
+
cachedUrl = null
|
|
479
|
+
|
|
480
|
+
try {
|
|
481
|
+
await fetch("/admin/paypal/environment", {
|
|
482
|
+
method: "POST",
|
|
483
|
+
headers: { "content-type": "application/json" },
|
|
484
|
+
body: JSON.stringify({ environment: next }),
|
|
485
|
+
})
|
|
486
|
+
} catch {}
|
|
487
|
+
|
|
488
|
+
try {
|
|
489
|
+
localStorage.removeItem(CACHE_KEY)
|
|
490
|
+
localStorage.removeItem(RELOAD_KEY)
|
|
491
|
+
} catch {}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
return (
|
|
495
|
+
<div className="p-6">
|
|
496
|
+
<div className="flex flex-col gap-6">
|
|
497
|
+
<h1 className="text-xl font-semibold">PayPal Gateway By Easy Payment</h1>
|
|
498
|
+
|
|
499
|
+
{/* Tabs header */}
|
|
500
|
+
<PayPalTabs />
|
|
501
|
+
|
|
502
|
+
{/* Main container */}
|
|
503
|
+
<div className="rounded-md border border-ui-border-base p-4 shadow-sm">
|
|
504
|
+
<div className="grid grid-cols-1 gap-y-6 md:grid-cols-[260px_1fr] md:items-start">
|
|
505
|
+
{/* Environment */}
|
|
506
|
+
<div className="text-sm font-medium pt-2">Environment</div>
|
|
507
|
+
<div className="max-w-xl">
|
|
508
|
+
<select
|
|
509
|
+
value={env}
|
|
510
|
+
onChange={handleEnvChange}
|
|
511
|
+
disabled={onboardingInProgress}
|
|
512
|
+
className="w-full rounded-md border border-ui-border-base bg-transparent px-3 py-2 text-sm"
|
|
513
|
+
>
|
|
514
|
+
<option value="sandbox">Sandbox (Test Mode)</option>
|
|
515
|
+
<option value="live">Live (Production)</option>
|
|
516
|
+
</select>
|
|
517
|
+
</div>
|
|
518
|
+
|
|
519
|
+
{/* Connect */}
|
|
520
|
+
<div className="text-sm font-medium pt-2">
|
|
521
|
+
{env === "sandbox" ? "Connect to PayPal Sandbox" : "Connect to PayPal Live"}
|
|
522
|
+
</div>
|
|
523
|
+
|
|
524
|
+
<div className="max-w-xl">
|
|
525
|
+
{connState === "connected" ? (
|
|
526
|
+
<div>
|
|
527
|
+
<div className="text-sm text-green-600 bg-green-50 p-3 rounded border border-green-200">
|
|
528
|
+
✅ Successfully connected to PayPal!
|
|
529
|
+
{/* Hidden PayPal button anchor to satisfy partner.js DOM expectations */}
|
|
530
|
+
<a
|
|
531
|
+
data-paypal-button="true"
|
|
532
|
+
data-paypal-onboard-complete="onboardingCallback"
|
|
533
|
+
href="#"
|
|
534
|
+
style={{ display: "none" }}
|
|
535
|
+
>
|
|
536
|
+
PayPal
|
|
537
|
+
</a>
|
|
538
|
+
</div>
|
|
539
|
+
<div className="mt-3 rounded-md border border-ui-border-base bg-ui-bg-subtle p-3 text-xs text-ui-fg-subtle">
|
|
540
|
+
<div className="font-medium text-ui-fg-base">
|
|
541
|
+
Connected PayPal account
|
|
542
|
+
</div>
|
|
543
|
+
<div className="mt-1">
|
|
544
|
+
Email:{" "}
|
|
545
|
+
<span className="font-mono text-ui-fg-base">
|
|
546
|
+
{statusInfo?.seller_email || "Unavailable"}
|
|
547
|
+
</span>
|
|
548
|
+
</div>
|
|
549
|
+
</div>
|
|
550
|
+
<div className="mt-3 flex items-center gap-2">
|
|
551
|
+
<button
|
|
552
|
+
type="button"
|
|
553
|
+
onClick={handleDisconnect}
|
|
554
|
+
disabled={onboardingInProgress}
|
|
555
|
+
className="rounded-md border border-ui-border-base px-3 py-2 text-sm font-medium hover:bg-ui-bg-subtle disabled:opacity-50 disabled:cursor-not-allowed"
|
|
556
|
+
>
|
|
557
|
+
Disconnect
|
|
558
|
+
</button>
|
|
559
|
+
</div>
|
|
560
|
+
</div>
|
|
561
|
+
) : (
|
|
562
|
+
<>
|
|
563
|
+
{/* Status Loader */}
|
|
564
|
+
<div
|
|
565
|
+
ref={initLoaderRef}
|
|
566
|
+
id="init-loader"
|
|
567
|
+
className={`status-msg mb-4 ${
|
|
568
|
+
connState !== "loading" ? "hidden" : "block"
|
|
569
|
+
}`}
|
|
570
|
+
>
|
|
571
|
+
<div className="loader inline-block align-middle mr-2"></div>
|
|
572
|
+
<span id="loader-text" className="text-sm">
|
|
573
|
+
{onboardingInProgress
|
|
574
|
+
? "Configuring connection to PayPal…"
|
|
575
|
+
: "Checking connection..."}
|
|
576
|
+
</span>
|
|
577
|
+
</div>
|
|
578
|
+
|
|
579
|
+
{/* PayPal Button */}
|
|
580
|
+
<div className={`${connState === "ready" ? "block" : "hidden"}`}>
|
|
581
|
+
{/* Row 1: button (left aligned) */}
|
|
582
|
+
<a
|
|
583
|
+
ref={(node) => {
|
|
584
|
+
paypalButtonRef.current = node
|
|
585
|
+
ppBtnMeasureRef.current = node
|
|
586
|
+
}}
|
|
587
|
+
id="paypal-button"
|
|
588
|
+
data-paypal-button="true"
|
|
589
|
+
href={finalUrl || "#"}
|
|
590
|
+
data-paypal-onboard-complete="onboardingCallback"
|
|
591
|
+
onClick={handleConnectClick}
|
|
592
|
+
className="btn-paypal"
|
|
593
|
+
style={{
|
|
594
|
+
borderRadius: "50px",
|
|
595
|
+
textDecoration: "none",
|
|
596
|
+
display: "inline-block",
|
|
597
|
+
fontWeight: "bold",
|
|
598
|
+
border: "none",
|
|
599
|
+
cursor: onboardingInProgress ? "not-allowed" : "pointer",
|
|
600
|
+
opacity: onboardingInProgress ? 0.6 : 1,
|
|
601
|
+
pointerEvents: onboardingInProgress ? "none" : "auto",
|
|
602
|
+
}}
|
|
603
|
+
>
|
|
604
|
+
Connect to PayPal
|
|
605
|
+
</a>
|
|
606
|
+
|
|
607
|
+
{/* Row 2: OR centered under button width */}
|
|
608
|
+
<div
|
|
609
|
+
className="mt-2"
|
|
610
|
+
style={{
|
|
611
|
+
width: ppBtnWidth ? `${ppBtnWidth}px` : "auto",
|
|
612
|
+
marginTop: "20px",
|
|
613
|
+
marginBottom: "10px",
|
|
614
|
+
}}
|
|
615
|
+
>
|
|
616
|
+
<div className="flex justify-center">
|
|
617
|
+
<span className="text-[11px] text-ui-fg-muted leading-none">
|
|
618
|
+
OR
|
|
619
|
+
</span>
|
|
620
|
+
</div>
|
|
621
|
+
</div>
|
|
622
|
+
|
|
623
|
+
{/* Row 3: manual link aligned to button LEFT */}
|
|
624
|
+
<div className="mt-1">
|
|
625
|
+
<button
|
|
626
|
+
type="button"
|
|
627
|
+
onClick={() => setShowManual(!showManual)}
|
|
628
|
+
disabled={onboardingInProgress}
|
|
629
|
+
className="text-sm text-ui-fg-interactive underline whitespace-nowrap disabled:opacity-50 disabled:cursor-not-allowed"
|
|
630
|
+
>
|
|
631
|
+
Click here to insert credentials manually
|
|
632
|
+
</button>
|
|
633
|
+
</div>
|
|
634
|
+
</div>
|
|
635
|
+
|
|
636
|
+
{/* If not ready yet, show manual link still */}
|
|
637
|
+
<div className={`${connState === "ready" ? "hidden" : "block"} mt-3`}>
|
|
638
|
+
<button
|
|
639
|
+
type="button"
|
|
640
|
+
onClick={() => setShowManual(!showManual)}
|
|
641
|
+
disabled={onboardingInProgress}
|
|
642
|
+
className="text-sm text-ui-fg-interactive underline whitespace-nowrap disabled:opacity-50 disabled:cursor-not-allowed"
|
|
643
|
+
>
|
|
644
|
+
Click here to insert credentials manually
|
|
645
|
+
</button>
|
|
646
|
+
</div>
|
|
647
|
+
|
|
648
|
+
{/* Error Log */}
|
|
649
|
+
<div
|
|
650
|
+
ref={errorLogRef}
|
|
651
|
+
id="error-log"
|
|
652
|
+
className={`mt-4 text-left text-xs bg-red-50 text-red-600 p-3 border border-red-200 rounded ${
|
|
653
|
+
connState === "error" && error ? "block" : "hidden"
|
|
654
|
+
}`}
|
|
655
|
+
>
|
|
656
|
+
{error}
|
|
657
|
+
</div>
|
|
658
|
+
</>
|
|
659
|
+
)}
|
|
660
|
+
</div>
|
|
661
|
+
|
|
662
|
+
{/* Manual credentials section */}
|
|
663
|
+
{showManual && (
|
|
664
|
+
<div className="md:col-span-2">
|
|
665
|
+
<div className="ml-[260px] max-w-xl mt-4 grid grid-cols-1 gap-3 md:grid-cols-2">
|
|
666
|
+
<div className="flex flex-col gap-1">
|
|
667
|
+
<label className="text-sm font-medium">Client ID</label>
|
|
668
|
+
<input
|
|
669
|
+
type="text"
|
|
670
|
+
value={clientId}
|
|
671
|
+
onChange={(e) => setClientId(e.target.value)}
|
|
672
|
+
disabled={onboardingInProgress}
|
|
673
|
+
className="rounded-md border border-ui-border-base bg-transparent px-3 py-2 text-sm disabled:opacity-50"
|
|
674
|
+
placeholder={
|
|
675
|
+
env === "sandbox" ? "Sandbox Client ID" : "Live Client ID"
|
|
676
|
+
}
|
|
677
|
+
/>
|
|
678
|
+
</div>
|
|
679
|
+
|
|
680
|
+
<div className="flex flex-col gap-1">
|
|
681
|
+
<label className="text-sm font-medium">Client Secret</label>
|
|
682
|
+
<input
|
|
683
|
+
type="password"
|
|
684
|
+
value={secret}
|
|
685
|
+
onChange={(e) => setSecret(e.target.value)}
|
|
686
|
+
disabled={onboardingInProgress}
|
|
687
|
+
className="rounded-md border border-ui-border-base bg-transparent px-3 py-2 text-sm disabled:opacity-50"
|
|
688
|
+
placeholder={env === "sandbox" ? "Sandbox Secret" : "Live Secret"}
|
|
689
|
+
/>
|
|
690
|
+
</div>
|
|
691
|
+
|
|
692
|
+
<div className="flex flex-col gap-1 md:col-span-2">
|
|
693
|
+
<label className="text-sm font-medium">Merchant ID (optional)</label>
|
|
694
|
+
<input
|
|
695
|
+
type="text"
|
|
696
|
+
value={merchantId}
|
|
697
|
+
onChange={(e) => setMerchantId(e.target.value)}
|
|
698
|
+
disabled={onboardingInProgress}
|
|
699
|
+
className="rounded-md border border-ui-border-base bg-transparent px-3 py-2 text-sm disabled:opacity-50"
|
|
700
|
+
placeholder="Merchant ID"
|
|
701
|
+
/>
|
|
702
|
+
</div>
|
|
703
|
+
|
|
704
|
+
<div className="md:col-span-2 flex items-center gap-2 mt-2">
|
|
705
|
+
<button
|
|
706
|
+
type="button"
|
|
707
|
+
className="rounded-md border border-ui-border-base px-3 py-2 text-sm font-medium hover:bg-ui-bg-subtle disabled:opacity-50 disabled:cursor-not-allowed"
|
|
708
|
+
onClick={() => setShowManual(false)}
|
|
709
|
+
disabled={onboardingInProgress}
|
|
710
|
+
>
|
|
711
|
+
Cancel
|
|
712
|
+
</button>
|
|
713
|
+
|
|
714
|
+
<button
|
|
715
|
+
type="button"
|
|
716
|
+
className="rounded-md border border-ui-border-base px-3 py-2 text-sm font-medium bg-ui-bg-base hover:bg-ui-bg-subtle disabled:opacity-50 disabled:cursor-not-allowed"
|
|
717
|
+
disabled={!canSaveManual || onboardingInProgress}
|
|
718
|
+
onClick={handleSaveManual}
|
|
719
|
+
>
|
|
720
|
+
Save credentials
|
|
721
|
+
</button>
|
|
722
|
+
</div>
|
|
723
|
+
</div>
|
|
724
|
+
</div>
|
|
725
|
+
)}
|
|
726
|
+
</div>
|
|
727
|
+
</div>
|
|
728
|
+
</div>
|
|
729
|
+
|
|
730
|
+
{/* Loader styles */}
|
|
731
|
+
<style>{`
|
|
732
|
+
.loader {
|
|
733
|
+
border: 3px solid #f3f3f3;
|
|
734
|
+
border-top: 3px solid #0070ba;
|
|
735
|
+
border-radius: 50%;
|
|
736
|
+
width: 18px;
|
|
737
|
+
height: 18px;
|
|
738
|
+
animation: spin 1s linear infinite;
|
|
739
|
+
display: inline-block;
|
|
740
|
+
vertical-align: middle;
|
|
741
|
+
margin-right: 8px;
|
|
742
|
+
}
|
|
743
|
+
@keyframes spin {
|
|
744
|
+
0% { transform: rotate(0deg); }
|
|
745
|
+
100% { transform: rotate(360deg); }
|
|
746
|
+
}
|
|
747
|
+
`}</style>
|
|
748
|
+
</div>
|
|
749
|
+
)
|
|
750
|
+
}
|