@easypayment/medusa-paypal-ui 1.0.6 → 1.0.8
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/LICENSE +1 -1
- package/README.md +1 -1
- package/dist/index.cjs +20 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.mjs +20 -18
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
- package/src/adapters/MedusaNextPayPalAdapter.tsx +72 -0
- package/src/client/http.ts +47 -0
- package/src/client/paypal.ts +33 -0
- package/src/client/types.ts +19 -0
- package/src/components/PayPalAdvancedCard.tsx +99 -0
- package/src/components/PayPalCurrencyNotice.tsx +19 -0
- package/src/components/PayPalProvider.tsx +25 -0
- package/src/components/PayPalSmartButtons.tsx +50 -0
- package/src/hooks/usePayPalConfig.ts +50 -0
- package/src/index.ts +8 -0
package/LICENSE
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
MIT License
|
|
1
|
+
MIT License
|
package/README.md
CHANGED
|
@@ -41,7 +41,7 @@ import { MedusaNextPayPalAdapter } from "@easypayment/medusa-paypal-ui"
|
|
|
41
41
|
selectedProviderId={selectedProviderId}
|
|
42
42
|
baseUrl={process.env.NEXT_PUBLIC_MEDUSA_BACKEND_URL!}
|
|
43
43
|
publishableApiKey={process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY}
|
|
44
|
-
providerIds={{ paypal: "
|
|
44
|
+
providerIds={{ paypal: "pp_paypal_paypal", paypalCard: "pp_paypal_card_paypal_card" }}
|
|
45
45
|
onPaid={() => window.location.reload()}
|
|
46
46
|
/>
|
|
47
47
|
```
|
package/dist/index.cjs
CHANGED
|
@@ -65,7 +65,7 @@ function createPayPalStoreApi(opts) {
|
|
|
65
65
|
}
|
|
66
66
|
};
|
|
67
67
|
}
|
|
68
|
-
function usePayPalConfig({ baseUrl, publishableApiKey, cartId }) {
|
|
68
|
+
function usePayPalConfig({ baseUrl, publishableApiKey, cartId, enabled = true }) {
|
|
69
69
|
const api = react.useMemo(
|
|
70
70
|
() => createPayPalStoreApi({ baseUrl, publishableApiKey }),
|
|
71
71
|
[baseUrl, publishableApiKey]
|
|
@@ -74,6 +74,12 @@ function usePayPalConfig({ baseUrl, publishableApiKey, cartId }) {
|
|
|
74
74
|
const [loading, setLoading] = react.useState(false);
|
|
75
75
|
const [error, setError] = react.useState(null);
|
|
76
76
|
react.useEffect(() => {
|
|
77
|
+
if (!enabled) {
|
|
78
|
+
setLoading(false);
|
|
79
|
+
setError(null);
|
|
80
|
+
setConfig(null);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
77
83
|
let mounted = true;
|
|
78
84
|
(async () => {
|
|
79
85
|
try {
|
|
@@ -90,7 +96,7 @@ function usePayPalConfig({ baseUrl, publishableApiKey, cartId }) {
|
|
|
90
96
|
return () => {
|
|
91
97
|
mounted = false;
|
|
92
98
|
};
|
|
93
|
-
}, [api, cartId]);
|
|
99
|
+
}, [api, cartId, enabled]);
|
|
94
100
|
return { config, loading, error };
|
|
95
101
|
}
|
|
96
102
|
function PayPalProvider(props) {
|
|
@@ -213,30 +219,26 @@ function PayPalAdvancedCard(props) {
|
|
|
213
219
|
}
|
|
214
220
|
);
|
|
215
221
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
function normalizeProviderId(id) {
|
|
219
|
-
if (!id) return id;
|
|
220
|
-
if (!id.startsWith("pp_")) return id;
|
|
221
|
-
if (id === "pp_paypal_paypal") return "paypal";
|
|
222
|
-
if (id === "pp_paypal_card_paypal_card") return "paypal_card";
|
|
223
|
-
const parts = id.split("_");
|
|
224
|
-
return parts.length >= 3 ? parts.slice(2).join("_") : id;
|
|
225
|
-
}
|
|
222
|
+
var DEFAULT_PAYPAL_PROVIDER_ID = "pp_paypal_paypal";
|
|
223
|
+
var DEFAULT_PAYPAL_CARD_PROVIDER_ID = "pp_paypal_card_paypal_card";
|
|
226
224
|
function MedusaNextPayPalAdapter(props) {
|
|
227
225
|
const { cartId, selectedProviderId, baseUrl, publishableApiKey, providerIds, onPaid } = props;
|
|
228
|
-
const paypalProviderId =
|
|
229
|
-
const paypalCardProviderId =
|
|
230
|
-
const
|
|
231
|
-
const
|
|
232
|
-
|
|
226
|
+
const paypalProviderId = providerIds?.paypal || DEFAULT_PAYPAL_PROVIDER_ID;
|
|
227
|
+
const paypalCardProviderId = providerIds?.paypalCard || DEFAULT_PAYPAL_CARD_PROVIDER_ID;
|
|
228
|
+
const shouldRender = selectedProviderId === paypalProviderId || selectedProviderId === paypalCardProviderId;
|
|
229
|
+
const { config, loading, error } = usePayPalConfig({
|
|
230
|
+
baseUrl,
|
|
231
|
+
publishableApiKey,
|
|
232
|
+
cartId,
|
|
233
|
+
enabled: shouldRender
|
|
234
|
+
});
|
|
233
235
|
if (!shouldRender) return null;
|
|
234
236
|
if (loading) return /* @__PURE__ */ jsxRuntime.jsx("div", { children: "Loading PayPal\u2026" });
|
|
235
237
|
if (error) return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "crimson" }, children: error });
|
|
236
238
|
if (!config) return null;
|
|
237
239
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "grid", gap: 12 }, children: [
|
|
238
240
|
/* @__PURE__ */ jsxRuntime.jsx(PayPalCurrencyNotice, { config }),
|
|
239
|
-
/* @__PURE__ */ jsxRuntime.jsx(PayPalProvider, { config, intent: "capture", children:
|
|
241
|
+
/* @__PURE__ */ jsxRuntime.jsx(PayPalProvider, { config, intent: config.intent === "authorize" ? "authorize" : "capture", children: selectedProviderId === paypalCardProviderId ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
240
242
|
PayPalAdvancedCard,
|
|
241
243
|
{
|
|
242
244
|
baseUrl,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client/http.ts","../src/client/paypal.ts","../src/hooks/usePayPalConfig.ts","../src/components/PayPalProvider.tsx","../src/components/PayPalCurrencyNotice.tsx","../src/components/PayPalSmartButtons.tsx","../src/components/PayPalAdvancedCard.tsx","../src/utils/normalize-provider-id.ts","../src/adapters/MedusaNextPayPalAdapter.tsx"],"names":["useMemo","useState","useEffect","jsx","PayPalScriptProvider","jsxs","PayPalButtons","usePayPalCardFields","PayPalCardFieldsProvider","PayPalNameField","PayPalNumberField","PayPalExpiryField","PayPalCVVField"],"mappings":"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","file":"index.cjs","sourcesContent":["export type HttpOptions = {\r\n baseUrl: string\r\n publishableApiKey?: string\r\n}\r\n\r\nfunction toHeaderRecord(headers?: RequestInit[\"headers\"]): Record<string, string> {\r\n if (!headers) {\r\n return {}\r\n }\r\n\r\n if (headers instanceof Headers) {\r\n return Object.fromEntries(headers.entries())\r\n }\r\n\r\n if (Array.isArray(headers)) {\r\n return Object.fromEntries(headers)\r\n }\r\n\r\n return { ...headers }\r\n}\r\n\r\nexport function createHttpClient(opts: HttpOptions) {\r\n const base = opts.baseUrl.replace(/\\/+$/, \"\")\r\n\r\n async function request<T>(path: string, init?: RequestInit): Promise<T> {\r\n const url = `${base}${path.startsWith(\"/\") ? \"\" : \"/\"}${path}`\r\n const headers: Record<string, string> = {\r\n Accept: \"application/json\",\r\n ...toHeaderRecord(init?.headers),\r\n }\r\n\r\n if (opts.publishableApiKey) {\r\n headers[\"x-publishable-api-key\"] = opts.publishableApiKey\r\n }\r\n\r\n const res = await fetch(url, { ...init, headers, credentials: \"include\" })\r\n const text = await res.text().catch(() => \"\")\r\n\r\n if (!res.ok) {\r\n throw new Error(text || `Request failed (${res.status})`)\r\n }\r\n\r\n return (text ? JSON.parse(text) : {}) as T\r\n }\r\n\r\n return { request }\r\n}\r\n","import type { PayPalConfig, PayPalSettingsResponse } from \"./types\"\r\nimport { createHttpClient, type HttpOptions } from \"./http\"\r\n\r\nexport function createPayPalStoreApi(opts: HttpOptions) {\r\n const http = createHttpClient(opts)\r\n\r\n return {\r\n getConfig(cartId?: string) {\r\n const q = cartId ? `?cart_id=${encodeURIComponent(cartId)}` : \"\"\r\n return http.request<PayPalConfig>(`/store/paypal/config${q}`)\r\n },\r\n\r\n getSettings() {\r\n return http.request<PayPalSettingsResponse>(`/store/paypal/settings`)\r\n },\r\n\r\n createOrder(cartId: string) {\r\n return http.request<{ id: string }>(`/store/paypal/create-order`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({ cart_id: cartId }),\r\n })\r\n },\r\n\r\n captureOrder(cartId: string, orderId: string) {\r\n return http.request<Record<string, unknown>>(`/store/paypal/capture-order`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({ cart_id: cartId, order_id: orderId }),\r\n })\r\n },\r\n }\r\n}\r\n","import { useEffect, useMemo, useState } from \"react\"\r\nimport { createPayPalStoreApi } from \"../client/paypal\"\r\nimport type { PayPalConfig } from \"../client/types\"\r\n\r\ntype Args = {\r\n baseUrl: string\r\n publishableApiKey?: string\r\n cartId?: string\r\n}\r\n\r\nexport function usePayPalConfig({ baseUrl, publishableApiKey, cartId }: Args) {\r\n const api = useMemo(\r\n () => createPayPalStoreApi({ baseUrl, publishableApiKey }),\r\n [baseUrl, publishableApiKey]\r\n )\r\n\r\n const [config, setConfig] = useState<PayPalConfig | null>(null)\r\n const [loading, setLoading] = useState(false)\r\n const [error, setError] = useState<string | null>(null)\r\n\r\n useEffect(() => {\r\n let mounted = true\r\n ;(async () => {\r\n try {\r\n setLoading(true)\r\n setError(null)\r\n const cfg = await api.getConfig(cartId)\r\n if (mounted) setConfig(cfg)\r\n } catch (e: unknown) {\r\n if (mounted) setError(e instanceof Error ? e.message : \"Failed to load PayPal config\")\r\n } finally {\r\n if (mounted) setLoading(false)\r\n }\r\n })()\r\n\r\n return () => {\r\n mounted = false\r\n }\r\n }, [api, cartId])\r\n\r\n return { config, loading, error }\r\n}\r\n","\"use client\"\r\n\r\nimport React, { useMemo } from \"react\"\r\nimport { PayPalScriptProvider } from \"@paypal/react-paypal-js\"\r\nimport type { PayPalConfig } from \"../client/types\"\r\n\r\nexport function PayPalProvider(props: {\r\n config: PayPalConfig\r\n intent?: \"capture\" | \"authorize\"\r\n children: React.ReactNode\r\n}) {\r\n const { config, intent = \"capture\", children } = props\r\n\r\n const options = useMemo(() => {\r\n return {\r\n \"client-id\": config.client_id,\r\n currency: config.currency,\r\n intent,\r\n components: config.client_token ? \"buttons,card-fields\" : \"buttons\",\r\n \"data-client-token\": config.client_token || undefined,\r\n } as any\r\n }, [config, intent])\r\n\r\n return <PayPalScriptProvider options={options}>{children}</PayPalScriptProvider>\r\n}\r\n","\"use client\"\r\n\r\nimport React from \"react\"\r\nimport type { PayPalConfig } from \"../client/types\"\r\n\r\nexport function PayPalCurrencyNotice({ config }: { config: PayPalConfig }) {\r\n if (config.currency_supported) return null\r\n\r\n return (\r\n <div style={{ padding: 12, border: \"1px solid #ddd\", borderRadius: 10 }}>\r\n <div style={{ fontWeight: 600, marginBottom: 6 }}>PayPal currency issue</div>\r\n <ul style={{ margin: 0, paddingLeft: 18 }}>\r\n {(config.currency_errors || []).map((e, i) => (\r\n <li key={i}>{e}</li>\r\n ))}\r\n </ul>\r\n </div>\r\n )\r\n}\r\n","\"use client\"\r\n\r\nimport React, { useMemo, useState } from \"react\"\r\nimport { PayPalButtons } from \"@paypal/react-paypal-js\"\r\nimport { createPayPalStoreApi } from \"../client/paypal\"\r\nimport type { PayPalConfig } from \"../client/types\"\r\n\r\nexport function PayPalSmartButtons(props: {\r\n baseUrl: string\r\n publishableApiKey?: string\r\n cartId: string\r\n config: PayPalConfig\r\n onPaid?: (result: Record<string, unknown>) => void\r\n onError?: (message: string) => void\r\n}) {\r\n const { baseUrl, publishableApiKey, cartId, config, onPaid, onError } = props\r\n const api = useMemo(\r\n () => createPayPalStoreApi({ baseUrl, publishableApiKey }),\r\n [baseUrl, publishableApiKey]\r\n )\r\n\r\n const [error, setError] = useState<string | null>(null)\r\n\r\n if (!config.currency_supported) return null\r\n\r\n return (\r\n <div>\r\n <PayPalButtons\r\n style={{ layout: \"vertical\" }}\r\n createOrder={async () => {\r\n setError(null)\r\n const r = await api.createOrder(cartId)\r\n return r.id\r\n }}\r\n onApprove={async (data: { orderID?: string }) => {\r\n setError(null)\r\n const orderId = String(data?.orderID || \"\")\r\n const result = await api.captureOrder(cartId, orderId)\r\n onPaid?.(result)\r\n }}\r\n onError={(err: Error | { message?: string }) => {\r\n const msg = err instanceof Error ? err.message : err?.message || \"PayPal error\"\r\n setError(msg)\r\n onError?.(msg)\r\n }}\r\n />\r\n {error ? <div style={{ marginTop: 10, color: \"crimson\" }}>{error}</div> : null}\r\n </div>\r\n )\r\n}\r\n","\"use client\"\r\n\r\nimport React, { useMemo, useState } from \"react\"\r\nimport {\r\n PayPalCardFieldsProvider,\r\n PayPalNameField,\r\n PayPalNumberField,\r\n PayPalExpiryField,\r\n PayPalCVVField,\r\n usePayPalCardFields,\r\n} from \"@paypal/react-paypal-js\"\r\nimport { createPayPalStoreApi } from \"../client/paypal\"\r\nimport type { PayPalConfig } from \"../client/types\"\r\n\r\nfunction SubmitButton({ disabled, label }: { disabled: boolean; label: string }) {\r\n const { cardFieldsForm } = usePayPalCardFields()\r\n\r\n return (\r\n <button\r\n type=\"button\"\r\n disabled={disabled || !cardFieldsForm}\r\n onClick={() => cardFieldsForm?.submit()}\r\n style={{ padding: \"10px 12px\", borderRadius: 10, border: \"1px solid #ddd\" }}\r\n >\r\n {label}\r\n </button>\r\n )\r\n}\r\n\r\nexport function PayPalAdvancedCard(props: {\r\n baseUrl: string\r\n publishableApiKey?: string\r\n cartId: string\r\n config: PayPalConfig\r\n onPaid?: (result: Record<string, unknown>) => void\r\n onError?: (message: string) => void\r\n}) {\r\n const { baseUrl, publishableApiKey, cartId, config, onPaid, onError } = props\r\n const api = useMemo(\r\n () => createPayPalStoreApi({ baseUrl, publishableApiKey }),\r\n [baseUrl, publishableApiKey]\r\n )\r\n\r\n const [error, setError] = useState<string | null>(null)\r\n const [submitting, setSubmitting] = useState(false)\r\n\r\n if (!config.currency_supported) return null\r\n\r\n if (!config.client_token) {\r\n return (\r\n <div style={{ padding: 12, border: \"1px solid #ddd\", borderRadius: 10 }}>\r\n CardFields unavailable: missing client_token from backend.\r\n </div>\r\n )\r\n }\r\n\r\n return (\r\n <PayPalCardFieldsProvider\r\n createOrder={async () => {\r\n setError(null)\r\n const r = await api.createOrder(cartId)\r\n return r.id\r\n }}\r\n onApprove={async (data: { orderID?: string }) => {\r\n try {\r\n setSubmitting(true)\r\n setError(null)\r\n const orderId = String(data?.orderID || \"\")\r\n const result = await api.captureOrder(cartId, orderId)\r\n onPaid?.(result)\r\n } catch (e: unknown) {\r\n const msg = e instanceof Error ? e.message : \"Card payment failed\"\r\n setError(msg)\r\n onError?.(msg)\r\n } finally {\r\n setSubmitting(false)\r\n }\r\n }}\r\n onError={(e: Error | { message?: string }) => {\r\n const msg = e instanceof Error ? e.message : e?.message || \"CardFields error\"\r\n setError(msg)\r\n onError?.(msg)\r\n }}\r\n >\r\n <div style={{ display: \"grid\", gap: 10 }}>\r\n <PayPalNameField />\r\n <PayPalNumberField />\r\n <div style={{ display: \"grid\", gridTemplateColumns: \"1fr 1fr\", gap: 10 }}>\r\n <PayPalExpiryField />\r\n <PayPalCVVField />\r\n </div>\r\n\r\n <SubmitButton disabled={submitting} label={submitting ? \"Processing...\" : \"Pay by Card\"} />\r\n\r\n {error ? <div style={{ color: \"crimson\" }}>{error}</div> : null}\r\n </div>\r\n </PayPalCardFieldsProvider>\r\n )\r\n}\r\n","export function normalizeProviderId(id?: string) {\r\n if (!id) return id\r\n\r\n if (!id.startsWith(\"pp_\")) return id\r\n\r\n if (id === \"pp_paypal_paypal\") return \"paypal\"\r\n if (id === \"pp_paypal_card_paypal_card\") return \"paypal_card\"\r\n\r\n const parts = id.split(\"_\")\r\n return parts.length >= 3 ? parts.slice(2).join(\"_\") : id\r\n}","\"use client\"\r\n\r\nimport React from \"react\"\r\nimport { PayPalCurrencyNotice } from \"../components/PayPalCurrencyNotice\"\r\nimport { PayPalAdvancedCard } from \"../components/PayPalAdvancedCard\"\r\nimport { PayPalProvider } from \"../components/PayPalProvider\"\r\nimport { PayPalSmartButtons } from \"../components/PayPalSmartButtons\"\r\nimport { usePayPalConfig } from \"../hooks/usePayPalConfig\"\r\nimport { normalizeProviderId } from \"../utils/normalize-provider-id\"\r\n\r\nexport type MedusaNextPayPalAdapterProps = {\r\n cartId: string\r\n selectedProviderId: string | null | undefined\r\n baseUrl: string\r\n publishableApiKey?: string\r\n providerIds?: {\r\n paypal?: string\r\n paypalCard?: string\r\n }\r\n onPaid?: (result: unknown) => void\r\n}\r\n\r\nexport function MedusaNextPayPalAdapter(props: MedusaNextPayPalAdapterProps) {\r\n const { cartId, selectedProviderId, baseUrl, publishableApiKey, providerIds, onPaid } = props\r\n\r\n const paypalProviderId = normalizeProviderId(providerIds?.paypal || \"paypal\")\r\n const paypalCardProviderId = normalizeProviderId(providerIds?.paypalCard || \"paypal_card\")\r\n const normalizedSelectedProviderId = normalizeProviderId(selectedProviderId ?? undefined)\r\n\r\n const shouldRender =\r\n normalizedSelectedProviderId === paypalProviderId ||\r\n normalizedSelectedProviderId === paypalCardProviderId\r\n\r\n const { config, loading, error } = usePayPalConfig({ baseUrl, publishableApiKey, cartId })\r\n\r\n if (!shouldRender) return null\r\n if (loading) return <div>Loading PayPal…</div>\r\n if (error) return <div style={{ color: \"crimson\" }}>{error}</div>\r\n if (!config) return null\r\n\r\n return (\r\n <div style={{ display: \"grid\", gap: 12 }}>\r\n <PayPalCurrencyNotice config={config} />\r\n\r\n <PayPalProvider config={config} intent=\"capture\">\r\n {normalizedSelectedProviderId === paypalCardProviderId ? (\r\n <PayPalAdvancedCard\r\n baseUrl={baseUrl}\r\n publishableApiKey={publishableApiKey}\r\n cartId={cartId}\r\n config={config}\r\n onPaid={onPaid}\r\n />\r\n ) : (\r\n <PayPalSmartButtons\r\n baseUrl={baseUrl}\r\n publishableApiKey={publishableApiKey}\r\n cartId={cartId}\r\n config={config}\r\n onPaid={onPaid}\r\n />\r\n )}\r\n </PayPalProvider>\r\n </div>\r\n )\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/client/http.ts","../src/client/paypal.ts","../src/hooks/usePayPalConfig.ts","../src/components/PayPalProvider.tsx","../src/components/PayPalCurrencyNotice.tsx","../src/components/PayPalSmartButtons.tsx","../src/components/PayPalAdvancedCard.tsx","../src/adapters/MedusaNextPayPalAdapter.tsx"],"names":["useMemo","useState","useEffect","jsx","PayPalScriptProvider","jsxs","PayPalButtons","usePayPalCardFields","PayPalCardFieldsProvider","PayPalNameField","PayPalNumberField","PayPalExpiryField","PayPalCVVField"],"mappings":"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","file":"index.cjs","sourcesContent":["export type HttpOptions = {\r\n baseUrl: string\r\n publishableApiKey?: string\r\n}\r\n\r\nfunction toHeaderRecord(headers?: RequestInit[\"headers\"]): Record<string, string> {\r\n if (!headers) {\r\n return {}\r\n }\r\n\r\n if (headers instanceof Headers) {\r\n return Object.fromEntries(headers.entries())\r\n }\r\n\r\n if (Array.isArray(headers)) {\r\n return Object.fromEntries(headers)\r\n }\r\n\r\n return { ...headers }\r\n}\r\n\r\nexport function createHttpClient(opts: HttpOptions) {\r\n const base = opts.baseUrl.replace(/\\/+$/, \"\")\r\n\r\n async function request<T>(path: string, init?: RequestInit): Promise<T> {\r\n const url = `${base}${path.startsWith(\"/\") ? \"\" : \"/\"}${path}`\r\n const headers: Record<string, string> = {\r\n Accept: \"application/json\",\r\n ...toHeaderRecord(init?.headers),\r\n }\r\n\r\n if (opts.publishableApiKey) {\r\n headers[\"x-publishable-api-key\"] = opts.publishableApiKey\r\n }\r\n\r\n const res = await fetch(url, { ...init, headers, credentials: \"include\" })\r\n const text = await res.text().catch(() => \"\")\r\n\r\n if (!res.ok) {\r\n throw new Error(text || `Request failed (${res.status})`)\r\n }\r\n\r\n return (text ? JSON.parse(text) : {}) as T\r\n }\r\n\r\n return { request }\r\n}\r\n","import type { PayPalConfig, PayPalSettingsResponse } from \"./types\"\r\nimport { createHttpClient, type HttpOptions } from \"./http\"\r\n\r\nexport function createPayPalStoreApi(opts: HttpOptions) {\r\n const http = createHttpClient(opts)\r\n\r\n return {\r\n getConfig(cartId?: string) {\r\n const q = cartId ? `?cart_id=${encodeURIComponent(cartId)}` : \"\"\r\n return http.request<PayPalConfig>(`/store/paypal/config${q}`)\r\n },\r\n\r\n getSettings() {\r\n return http.request<PayPalSettingsResponse>(`/store/paypal/settings`)\r\n },\r\n\r\n createOrder(cartId: string) {\r\n return http.request<{ id: string }>(`/store/paypal/create-order`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({ cart_id: cartId }),\r\n })\r\n },\r\n\r\n captureOrder(cartId: string, orderId: string) {\r\n return http.request<Record<string, unknown>>(`/store/paypal/capture-order`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({ cart_id: cartId, order_id: orderId }),\r\n })\r\n },\r\n }\r\n}\r\n","import { useEffect, useMemo, useState } from \"react\"\r\nimport { createPayPalStoreApi } from \"../client/paypal\"\r\nimport type { PayPalConfig } from \"../client/types\"\r\n\r\ntype Args = {\r\n baseUrl: string\r\n publishableApiKey?: string\r\n cartId?: string\r\n enabled?: boolean\r\n}\r\n\r\nexport function usePayPalConfig({ baseUrl, publishableApiKey, cartId, enabled = true }: Args) {\r\n const api = useMemo(\r\n () => createPayPalStoreApi({ baseUrl, publishableApiKey }),\r\n [baseUrl, publishableApiKey]\r\n )\r\n\r\n const [config, setConfig] = useState<PayPalConfig | null>(null)\r\n const [loading, setLoading] = useState(false)\r\n const [error, setError] = useState<string | null>(null)\r\n\r\n useEffect(() => {\r\n if (!enabled) {\r\n setLoading(false)\r\n setError(null)\r\n setConfig(null)\r\n return\r\n }\r\n\r\n let mounted = true\r\n ;(async () => {\r\n try {\r\n setLoading(true)\r\n setError(null)\r\n const cfg = await api.getConfig(cartId)\r\n if (mounted) setConfig(cfg)\r\n } catch (e: unknown) {\r\n if (mounted) setError(e instanceof Error ? e.message : \"Failed to load PayPal config\")\r\n } finally {\r\n if (mounted) setLoading(false)\r\n }\r\n })()\r\n\r\n return () => {\r\n mounted = false\r\n }\r\n }, [api, cartId, enabled])\r\n\r\n return { config, loading, error }\r\n}\r\n","\"use client\"\n\nimport React, { useMemo } from \"react\"\nimport { PayPalScriptProvider } from \"@paypal/react-paypal-js\"\nimport type { PayPalConfig } from \"../client/types\"\n\nexport function PayPalProvider(props: {\n config: PayPalConfig\n intent?: \"capture\" | \"authorize\"\n children: React.ReactNode\n}) {\n const { config, intent = \"capture\", children } = props\n\n const options = useMemo(() => {\n return {\n \"client-id\": config.client_id,\n currency: config.currency,\n intent,\n components: config.client_token ? \"buttons,card-fields\" : \"buttons\",\n \"data-client-token\": config.client_token || undefined,\n } as any\n }, [config, intent])\n\n return <PayPalScriptProvider options={options}>{children}</PayPalScriptProvider>\n}\n","\"use client\"\n\nimport React from \"react\"\nimport type { PayPalConfig } from \"../client/types\"\n\nexport function PayPalCurrencyNotice({ config }: { config: PayPalConfig }) {\n if (config.currency_supported) return null\n\n return (\n <div style={{ padding: 12, border: \"1px solid #ddd\", borderRadius: 10 }}>\n <div style={{ fontWeight: 600, marginBottom: 6 }}>PayPal currency issue</div>\n <ul style={{ margin: 0, paddingLeft: 18 }}>\n {(config.currency_errors || []).map((e, i) => (\n <li key={i}>{e}</li>\n ))}\n </ul>\n </div>\n )\n}\n","\"use client\"\r\n\r\nimport React, { useMemo, useState } from \"react\"\r\nimport { PayPalButtons } from \"@paypal/react-paypal-js\"\r\nimport { createPayPalStoreApi } from \"../client/paypal\"\r\nimport type { PayPalConfig } from \"../client/types\"\r\n\r\nexport function PayPalSmartButtons(props: {\r\n baseUrl: string\r\n publishableApiKey?: string\r\n cartId: string\r\n config: PayPalConfig\r\n onPaid?: (result: Record<string, unknown>) => void\r\n onError?: (message: string) => void\r\n}) {\r\n const { baseUrl, publishableApiKey, cartId, config, onPaid, onError } = props\r\n const api = useMemo(\r\n () => createPayPalStoreApi({ baseUrl, publishableApiKey }),\r\n [baseUrl, publishableApiKey]\r\n )\r\n\r\n const [error, setError] = useState<string | null>(null)\r\n\r\n if (!config.currency_supported) return null\r\n\r\n return (\r\n <div>\r\n <PayPalButtons\r\n style={{ layout: \"vertical\" }}\r\n createOrder={async () => {\r\n setError(null)\r\n const r = await api.createOrder(cartId)\r\n return r.id\r\n }}\r\n onApprove={async (data: { orderID?: string }) => {\r\n setError(null)\r\n const orderId = String(data?.orderID || \"\")\r\n const result = await api.captureOrder(cartId, orderId)\r\n onPaid?.(result)\r\n }}\r\n onError={(err: Error | { message?: string }) => {\r\n const msg = err instanceof Error ? err.message : err?.message || \"PayPal error\"\r\n setError(msg)\r\n onError?.(msg)\r\n }}\r\n />\r\n {error ? <div style={{ marginTop: 10, color: \"crimson\" }}>{error}</div> : null}\r\n </div>\r\n )\r\n}\r\n","\"use client\"\r\n\r\nimport React, { useMemo, useState } from \"react\"\r\nimport {\r\n PayPalCardFieldsProvider,\r\n PayPalNameField,\r\n PayPalNumberField,\r\n PayPalExpiryField,\r\n PayPalCVVField,\r\n usePayPalCardFields,\r\n} from \"@paypal/react-paypal-js\"\r\nimport { createPayPalStoreApi } from \"../client/paypal\"\r\nimport type { PayPalConfig } from \"../client/types\"\r\n\r\nfunction SubmitButton({ disabled, label }: { disabled: boolean; label: string }) {\r\n const { cardFieldsForm } = usePayPalCardFields()\r\n\r\n return (\r\n <button\r\n type=\"button\"\r\n disabled={disabled || !cardFieldsForm}\r\n onClick={() => cardFieldsForm?.submit()}\r\n style={{ padding: \"10px 12px\", borderRadius: 10, border: \"1px solid #ddd\" }}\r\n >\r\n {label}\r\n </button>\r\n )\r\n}\r\n\r\nexport function PayPalAdvancedCard(props: {\r\n baseUrl: string\r\n publishableApiKey?: string\r\n cartId: string\r\n config: PayPalConfig\r\n onPaid?: (result: Record<string, unknown>) => void\r\n onError?: (message: string) => void\r\n}) {\r\n const { baseUrl, publishableApiKey, cartId, config, onPaid, onError } = props\r\n const api = useMemo(\r\n () => createPayPalStoreApi({ baseUrl, publishableApiKey }),\r\n [baseUrl, publishableApiKey]\r\n )\r\n\r\n const [error, setError] = useState<string | null>(null)\r\n const [submitting, setSubmitting] = useState(false)\r\n\r\n if (!config.currency_supported) return null\r\n\r\n if (!config.client_token) {\r\n return (\r\n <div style={{ padding: 12, border: \"1px solid #ddd\", borderRadius: 10 }}>\r\n CardFields unavailable: missing client_token from backend.\r\n </div>\r\n )\r\n }\r\n\r\n return (\r\n <PayPalCardFieldsProvider\r\n createOrder={async () => {\r\n setError(null)\r\n const r = await api.createOrder(cartId)\r\n return r.id\r\n }}\r\n onApprove={async (data: { orderID?: string }) => {\r\n try {\r\n setSubmitting(true)\r\n setError(null)\r\n const orderId = String(data?.orderID || \"\")\r\n const result = await api.captureOrder(cartId, orderId)\r\n onPaid?.(result)\r\n } catch (e: unknown) {\r\n const msg = e instanceof Error ? e.message : \"Card payment failed\"\r\n setError(msg)\r\n onError?.(msg)\r\n } finally {\r\n setSubmitting(false)\r\n }\r\n }}\r\n onError={(e: Error | { message?: string }) => {\r\n const msg = e instanceof Error ? e.message : e?.message || \"CardFields error\"\r\n setError(msg)\r\n onError?.(msg)\r\n }}\r\n >\r\n <div style={{ display: \"grid\", gap: 10 }}>\r\n <PayPalNameField />\r\n <PayPalNumberField />\r\n <div style={{ display: \"grid\", gridTemplateColumns: \"1fr 1fr\", gap: 10 }}>\r\n <PayPalExpiryField />\r\n <PayPalCVVField />\r\n </div>\r\n\r\n <SubmitButton disabled={submitting} label={submitting ? \"Processing...\" : \"Pay by Card\"} />\r\n\r\n {error ? <div style={{ color: \"crimson\" }}>{error}</div> : null}\r\n </div>\r\n </PayPalCardFieldsProvider>\r\n )\r\n}\r\n","\"use client\"\r\n\r\nimport React from \"react\"\r\nimport { PayPalCurrencyNotice } from \"../components/PayPalCurrencyNotice\"\r\nimport { PayPalAdvancedCard } from \"../components/PayPalAdvancedCard\"\r\nimport { PayPalProvider } from \"../components/PayPalProvider\"\r\nimport { PayPalSmartButtons } from \"../components/PayPalSmartButtons\"\r\nimport { usePayPalConfig } from \"../hooks/usePayPalConfig\"\r\n\r\nconst DEFAULT_PAYPAL_PROVIDER_ID = \"pp_paypal_paypal\"\r\nconst DEFAULT_PAYPAL_CARD_PROVIDER_ID = \"pp_paypal_card_paypal_card\"\r\n\r\nexport type MedusaNextPayPalAdapterProps = {\r\n cartId: string\r\n selectedProviderId: string | null | undefined\r\n baseUrl: string\r\n publishableApiKey?: string\r\n providerIds?: {\r\n paypal?: string\r\n paypalCard?: string\r\n }\r\n onPaid?: (result: unknown) => void\r\n}\r\n\r\nexport function MedusaNextPayPalAdapter(props: MedusaNextPayPalAdapterProps) {\r\n const { cartId, selectedProviderId, baseUrl, publishableApiKey, providerIds, onPaid } = props\r\n\r\n const paypalProviderId = providerIds?.paypal || DEFAULT_PAYPAL_PROVIDER_ID\r\n const paypalCardProviderId = providerIds?.paypalCard || DEFAULT_PAYPAL_CARD_PROVIDER_ID\r\n\r\n const shouldRender =\r\n selectedProviderId === paypalProviderId ||\r\n selectedProviderId === paypalCardProviderId\r\n\r\n const { config, loading, error } = usePayPalConfig({\r\n baseUrl,\r\n publishableApiKey,\r\n cartId,\r\n enabled: shouldRender,\r\n })\r\n\r\n if (!shouldRender) return null\r\n if (loading) return <div>Loading PayPal…</div>\r\n if (error) return <div style={{ color: \"crimson\" }}>{error}</div>\r\n if (!config) return null\r\n\r\n return (\r\n <div style={{ display: \"grid\", gap: 12 }}>\r\n <PayPalCurrencyNotice config={config} />\r\n\r\n <PayPalProvider config={config} intent={config.intent === \"authorize\" ? \"authorize\" : \"capture\"}>\r\n {selectedProviderId === paypalCardProviderId ? (\r\n <PayPalAdvancedCard\r\n baseUrl={baseUrl}\r\n publishableApiKey={publishableApiKey}\r\n cartId={cartId}\r\n config={config}\r\n onPaid={onPaid}\r\n />\r\n ) : (\r\n <PayPalSmartButtons\r\n baseUrl={baseUrl}\r\n publishableApiKey={publishableApiKey}\r\n cartId={cartId}\r\n config={config}\r\n onPaid={onPaid}\r\n />\r\n )}\r\n </PayPalProvider>\r\n </div>\r\n )\r\n}\r\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -9,6 +9,7 @@ type PayPalConfig = {
|
|
|
9
9
|
currency_errors: string[];
|
|
10
10
|
supported_currencies: string[];
|
|
11
11
|
client_token?: string;
|
|
12
|
+
intent?: "capture" | "authorize";
|
|
12
13
|
};
|
|
13
14
|
type PayPalSettingsResponse = {
|
|
14
15
|
data?: {
|
|
@@ -39,8 +40,9 @@ type Args = {
|
|
|
39
40
|
baseUrl: string;
|
|
40
41
|
publishableApiKey?: string;
|
|
41
42
|
cartId?: string;
|
|
43
|
+
enabled?: boolean;
|
|
42
44
|
};
|
|
43
|
-
declare function usePayPalConfig({ baseUrl, publishableApiKey, cartId }: Args): {
|
|
45
|
+
declare function usePayPalConfig({ baseUrl, publishableApiKey, cartId, enabled }: Args): {
|
|
44
46
|
config: PayPalConfig | null;
|
|
45
47
|
loading: boolean;
|
|
46
48
|
error: string | null;
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ type PayPalConfig = {
|
|
|
9
9
|
currency_errors: string[];
|
|
10
10
|
supported_currencies: string[];
|
|
11
11
|
client_token?: string;
|
|
12
|
+
intent?: "capture" | "authorize";
|
|
12
13
|
};
|
|
13
14
|
type PayPalSettingsResponse = {
|
|
14
15
|
data?: {
|
|
@@ -39,8 +40,9 @@ type Args = {
|
|
|
39
40
|
baseUrl: string;
|
|
40
41
|
publishableApiKey?: string;
|
|
41
42
|
cartId?: string;
|
|
43
|
+
enabled?: boolean;
|
|
42
44
|
};
|
|
43
|
-
declare function usePayPalConfig({ baseUrl, publishableApiKey, cartId }: Args): {
|
|
45
|
+
declare function usePayPalConfig({ baseUrl, publishableApiKey, cartId, enabled }: Args): {
|
|
44
46
|
config: PayPalConfig | null;
|
|
45
47
|
loading: boolean;
|
|
46
48
|
error: string | null;
|
package/dist/index.mjs
CHANGED
|
@@ -63,7 +63,7 @@ function createPayPalStoreApi(opts) {
|
|
|
63
63
|
}
|
|
64
64
|
};
|
|
65
65
|
}
|
|
66
|
-
function usePayPalConfig({ baseUrl, publishableApiKey, cartId }) {
|
|
66
|
+
function usePayPalConfig({ baseUrl, publishableApiKey, cartId, enabled = true }) {
|
|
67
67
|
const api = useMemo(
|
|
68
68
|
() => createPayPalStoreApi({ baseUrl, publishableApiKey }),
|
|
69
69
|
[baseUrl, publishableApiKey]
|
|
@@ -72,6 +72,12 @@ function usePayPalConfig({ baseUrl, publishableApiKey, cartId }) {
|
|
|
72
72
|
const [loading, setLoading] = useState(false);
|
|
73
73
|
const [error, setError] = useState(null);
|
|
74
74
|
useEffect(() => {
|
|
75
|
+
if (!enabled) {
|
|
76
|
+
setLoading(false);
|
|
77
|
+
setError(null);
|
|
78
|
+
setConfig(null);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
75
81
|
let mounted = true;
|
|
76
82
|
(async () => {
|
|
77
83
|
try {
|
|
@@ -88,7 +94,7 @@ function usePayPalConfig({ baseUrl, publishableApiKey, cartId }) {
|
|
|
88
94
|
return () => {
|
|
89
95
|
mounted = false;
|
|
90
96
|
};
|
|
91
|
-
}, [api, cartId]);
|
|
97
|
+
}, [api, cartId, enabled]);
|
|
92
98
|
return { config, loading, error };
|
|
93
99
|
}
|
|
94
100
|
function PayPalProvider(props) {
|
|
@@ -211,30 +217,26 @@ function PayPalAdvancedCard(props) {
|
|
|
211
217
|
}
|
|
212
218
|
);
|
|
213
219
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
function normalizeProviderId(id) {
|
|
217
|
-
if (!id) return id;
|
|
218
|
-
if (!id.startsWith("pp_")) return id;
|
|
219
|
-
if (id === "pp_paypal_paypal") return "paypal";
|
|
220
|
-
if (id === "pp_paypal_card_paypal_card") return "paypal_card";
|
|
221
|
-
const parts = id.split("_");
|
|
222
|
-
return parts.length >= 3 ? parts.slice(2).join("_") : id;
|
|
223
|
-
}
|
|
220
|
+
var DEFAULT_PAYPAL_PROVIDER_ID = "pp_paypal_paypal";
|
|
221
|
+
var DEFAULT_PAYPAL_CARD_PROVIDER_ID = "pp_paypal_card_paypal_card";
|
|
224
222
|
function MedusaNextPayPalAdapter(props) {
|
|
225
223
|
const { cartId, selectedProviderId, baseUrl, publishableApiKey, providerIds, onPaid } = props;
|
|
226
|
-
const paypalProviderId =
|
|
227
|
-
const paypalCardProviderId =
|
|
228
|
-
const
|
|
229
|
-
const
|
|
230
|
-
|
|
224
|
+
const paypalProviderId = providerIds?.paypal || DEFAULT_PAYPAL_PROVIDER_ID;
|
|
225
|
+
const paypalCardProviderId = providerIds?.paypalCard || DEFAULT_PAYPAL_CARD_PROVIDER_ID;
|
|
226
|
+
const shouldRender = selectedProviderId === paypalProviderId || selectedProviderId === paypalCardProviderId;
|
|
227
|
+
const { config, loading, error } = usePayPalConfig({
|
|
228
|
+
baseUrl,
|
|
229
|
+
publishableApiKey,
|
|
230
|
+
cartId,
|
|
231
|
+
enabled: shouldRender
|
|
232
|
+
});
|
|
231
233
|
if (!shouldRender) return null;
|
|
232
234
|
if (loading) return /* @__PURE__ */ jsx("div", { children: "Loading PayPal\u2026" });
|
|
233
235
|
if (error) return /* @__PURE__ */ jsx("div", { style: { color: "crimson" }, children: error });
|
|
234
236
|
if (!config) return null;
|
|
235
237
|
return /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: 12 }, children: [
|
|
236
238
|
/* @__PURE__ */ jsx(PayPalCurrencyNotice, { config }),
|
|
237
|
-
/* @__PURE__ */ jsx(PayPalProvider, { config, intent: "capture", children:
|
|
239
|
+
/* @__PURE__ */ jsx(PayPalProvider, { config, intent: config.intent === "authorize" ? "authorize" : "capture", children: selectedProviderId === paypalCardProviderId ? /* @__PURE__ */ jsx(
|
|
238
240
|
PayPalAdvancedCard,
|
|
239
241
|
{
|
|
240
242
|
baseUrl,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client/http.ts","../src/client/paypal.ts","../src/hooks/usePayPalConfig.ts","../src/components/PayPalProvider.tsx","../src/components/PayPalCurrencyNotice.tsx","../src/components/PayPalSmartButtons.tsx","../src/components/PayPalAdvancedCard.tsx","../src/utils/normalize-provider-id.ts","../src/adapters/MedusaNextPayPalAdapter.tsx"],"names":["useMemo","jsx","useState","jsxs"],"mappings":"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","file":"index.mjs","sourcesContent":["export type HttpOptions = {\r\n baseUrl: string\r\n publishableApiKey?: string\r\n}\r\n\r\nfunction toHeaderRecord(headers?: RequestInit[\"headers\"]): Record<string, string> {\r\n if (!headers) {\r\n return {}\r\n }\r\n\r\n if (headers instanceof Headers) {\r\n return Object.fromEntries(headers.entries())\r\n }\r\n\r\n if (Array.isArray(headers)) {\r\n return Object.fromEntries(headers)\r\n }\r\n\r\n return { ...headers }\r\n}\r\n\r\nexport function createHttpClient(opts: HttpOptions) {\r\n const base = opts.baseUrl.replace(/\\/+$/, \"\")\r\n\r\n async function request<T>(path: string, init?: RequestInit): Promise<T> {\r\n const url = `${base}${path.startsWith(\"/\") ? \"\" : \"/\"}${path}`\r\n const headers: Record<string, string> = {\r\n Accept: \"application/json\",\r\n ...toHeaderRecord(init?.headers),\r\n }\r\n\r\n if (opts.publishableApiKey) {\r\n headers[\"x-publishable-api-key\"] = opts.publishableApiKey\r\n }\r\n\r\n const res = await fetch(url, { ...init, headers, credentials: \"include\" })\r\n const text = await res.text().catch(() => \"\")\r\n\r\n if (!res.ok) {\r\n throw new Error(text || `Request failed (${res.status})`)\r\n }\r\n\r\n return (text ? JSON.parse(text) : {}) as T\r\n }\r\n\r\n return { request }\r\n}\r\n","import type { PayPalConfig, PayPalSettingsResponse } from \"./types\"\r\nimport { createHttpClient, type HttpOptions } from \"./http\"\r\n\r\nexport function createPayPalStoreApi(opts: HttpOptions) {\r\n const http = createHttpClient(opts)\r\n\r\n return {\r\n getConfig(cartId?: string) {\r\n const q = cartId ? `?cart_id=${encodeURIComponent(cartId)}` : \"\"\r\n return http.request<PayPalConfig>(`/store/paypal/config${q}`)\r\n },\r\n\r\n getSettings() {\r\n return http.request<PayPalSettingsResponse>(`/store/paypal/settings`)\r\n },\r\n\r\n createOrder(cartId: string) {\r\n return http.request<{ id: string }>(`/store/paypal/create-order`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({ cart_id: cartId }),\r\n })\r\n },\r\n\r\n captureOrder(cartId: string, orderId: string) {\r\n return http.request<Record<string, unknown>>(`/store/paypal/capture-order`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({ cart_id: cartId, order_id: orderId }),\r\n })\r\n },\r\n }\r\n}\r\n","import { useEffect, useMemo, useState } from \"react\"\r\nimport { createPayPalStoreApi } from \"../client/paypal\"\r\nimport type { PayPalConfig } from \"../client/types\"\r\n\r\ntype Args = {\r\n baseUrl: string\r\n publishableApiKey?: string\r\n cartId?: string\r\n}\r\n\r\nexport function usePayPalConfig({ baseUrl, publishableApiKey, cartId }: Args) {\r\n const api = useMemo(\r\n () => createPayPalStoreApi({ baseUrl, publishableApiKey }),\r\n [baseUrl, publishableApiKey]\r\n )\r\n\r\n const [config, setConfig] = useState<PayPalConfig | null>(null)\r\n const [loading, setLoading] = useState(false)\r\n const [error, setError] = useState<string | null>(null)\r\n\r\n useEffect(() => {\r\n let mounted = true\r\n ;(async () => {\r\n try {\r\n setLoading(true)\r\n setError(null)\r\n const cfg = await api.getConfig(cartId)\r\n if (mounted) setConfig(cfg)\r\n } catch (e: unknown) {\r\n if (mounted) setError(e instanceof Error ? e.message : \"Failed to load PayPal config\")\r\n } finally {\r\n if (mounted) setLoading(false)\r\n }\r\n })()\r\n\r\n return () => {\r\n mounted = false\r\n }\r\n }, [api, cartId])\r\n\r\n return { config, loading, error }\r\n}\r\n","\"use client\"\r\n\r\nimport React, { useMemo } from \"react\"\r\nimport { PayPalScriptProvider } from \"@paypal/react-paypal-js\"\r\nimport type { PayPalConfig } from \"../client/types\"\r\n\r\nexport function PayPalProvider(props: {\r\n config: PayPalConfig\r\n intent?: \"capture\" | \"authorize\"\r\n children: React.ReactNode\r\n}) {\r\n const { config, intent = \"capture\", children } = props\r\n\r\n const options = useMemo(() => {\r\n return {\r\n \"client-id\": config.client_id,\r\n currency: config.currency,\r\n intent,\r\n components: config.client_token ? \"buttons,card-fields\" : \"buttons\",\r\n \"data-client-token\": config.client_token || undefined,\r\n } as any\r\n }, [config, intent])\r\n\r\n return <PayPalScriptProvider options={options}>{children}</PayPalScriptProvider>\r\n}\r\n","\"use client\"\r\n\r\nimport React from \"react\"\r\nimport type { PayPalConfig } from \"../client/types\"\r\n\r\nexport function PayPalCurrencyNotice({ config }: { config: PayPalConfig }) {\r\n if (config.currency_supported) return null\r\n\r\n return (\r\n <div style={{ padding: 12, border: \"1px solid #ddd\", borderRadius: 10 }}>\r\n <div style={{ fontWeight: 600, marginBottom: 6 }}>PayPal currency issue</div>\r\n <ul style={{ margin: 0, paddingLeft: 18 }}>\r\n {(config.currency_errors || []).map((e, i) => (\r\n <li key={i}>{e}</li>\r\n ))}\r\n </ul>\r\n </div>\r\n )\r\n}\r\n","\"use client\"\r\n\r\nimport React, { useMemo, useState } from \"react\"\r\nimport { PayPalButtons } from \"@paypal/react-paypal-js\"\r\nimport { createPayPalStoreApi } from \"../client/paypal\"\r\nimport type { PayPalConfig } from \"../client/types\"\r\n\r\nexport function PayPalSmartButtons(props: {\r\n baseUrl: string\r\n publishableApiKey?: string\r\n cartId: string\r\n config: PayPalConfig\r\n onPaid?: (result: Record<string, unknown>) => void\r\n onError?: (message: string) => void\r\n}) {\r\n const { baseUrl, publishableApiKey, cartId, config, onPaid, onError } = props\r\n const api = useMemo(\r\n () => createPayPalStoreApi({ baseUrl, publishableApiKey }),\r\n [baseUrl, publishableApiKey]\r\n )\r\n\r\n const [error, setError] = useState<string | null>(null)\r\n\r\n if (!config.currency_supported) return null\r\n\r\n return (\r\n <div>\r\n <PayPalButtons\r\n style={{ layout: \"vertical\" }}\r\n createOrder={async () => {\r\n setError(null)\r\n const r = await api.createOrder(cartId)\r\n return r.id\r\n }}\r\n onApprove={async (data: { orderID?: string }) => {\r\n setError(null)\r\n const orderId = String(data?.orderID || \"\")\r\n const result = await api.captureOrder(cartId, orderId)\r\n onPaid?.(result)\r\n }}\r\n onError={(err: Error | { message?: string }) => {\r\n const msg = err instanceof Error ? err.message : err?.message || \"PayPal error\"\r\n setError(msg)\r\n onError?.(msg)\r\n }}\r\n />\r\n {error ? <div style={{ marginTop: 10, color: \"crimson\" }}>{error}</div> : null}\r\n </div>\r\n )\r\n}\r\n","\"use client\"\r\n\r\nimport React, { useMemo, useState } from \"react\"\r\nimport {\r\n PayPalCardFieldsProvider,\r\n PayPalNameField,\r\n PayPalNumberField,\r\n PayPalExpiryField,\r\n PayPalCVVField,\r\n usePayPalCardFields,\r\n} from \"@paypal/react-paypal-js\"\r\nimport { createPayPalStoreApi } from \"../client/paypal\"\r\nimport type { PayPalConfig } from \"../client/types\"\r\n\r\nfunction SubmitButton({ disabled, label }: { disabled: boolean; label: string }) {\r\n const { cardFieldsForm } = usePayPalCardFields()\r\n\r\n return (\r\n <button\r\n type=\"button\"\r\n disabled={disabled || !cardFieldsForm}\r\n onClick={() => cardFieldsForm?.submit()}\r\n style={{ padding: \"10px 12px\", borderRadius: 10, border: \"1px solid #ddd\" }}\r\n >\r\n {label}\r\n </button>\r\n )\r\n}\r\n\r\nexport function PayPalAdvancedCard(props: {\r\n baseUrl: string\r\n publishableApiKey?: string\r\n cartId: string\r\n config: PayPalConfig\r\n onPaid?: (result: Record<string, unknown>) => void\r\n onError?: (message: string) => void\r\n}) {\r\n const { baseUrl, publishableApiKey, cartId, config, onPaid, onError } = props\r\n const api = useMemo(\r\n () => createPayPalStoreApi({ baseUrl, publishableApiKey }),\r\n [baseUrl, publishableApiKey]\r\n )\r\n\r\n const [error, setError] = useState<string | null>(null)\r\n const [submitting, setSubmitting] = useState(false)\r\n\r\n if (!config.currency_supported) return null\r\n\r\n if (!config.client_token) {\r\n return (\r\n <div style={{ padding: 12, border: \"1px solid #ddd\", borderRadius: 10 }}>\r\n CardFields unavailable: missing client_token from backend.\r\n </div>\r\n )\r\n }\r\n\r\n return (\r\n <PayPalCardFieldsProvider\r\n createOrder={async () => {\r\n setError(null)\r\n const r = await api.createOrder(cartId)\r\n return r.id\r\n }}\r\n onApprove={async (data: { orderID?: string }) => {\r\n try {\r\n setSubmitting(true)\r\n setError(null)\r\n const orderId = String(data?.orderID || \"\")\r\n const result = await api.captureOrder(cartId, orderId)\r\n onPaid?.(result)\r\n } catch (e: unknown) {\r\n const msg = e instanceof Error ? e.message : \"Card payment failed\"\r\n setError(msg)\r\n onError?.(msg)\r\n } finally {\r\n setSubmitting(false)\r\n }\r\n }}\r\n onError={(e: Error | { message?: string }) => {\r\n const msg = e instanceof Error ? e.message : e?.message || \"CardFields error\"\r\n setError(msg)\r\n onError?.(msg)\r\n }}\r\n >\r\n <div style={{ display: \"grid\", gap: 10 }}>\r\n <PayPalNameField />\r\n <PayPalNumberField />\r\n <div style={{ display: \"grid\", gridTemplateColumns: \"1fr 1fr\", gap: 10 }}>\r\n <PayPalExpiryField />\r\n <PayPalCVVField />\r\n </div>\r\n\r\n <SubmitButton disabled={submitting} label={submitting ? \"Processing...\" : \"Pay by Card\"} />\r\n\r\n {error ? <div style={{ color: \"crimson\" }}>{error}</div> : null}\r\n </div>\r\n </PayPalCardFieldsProvider>\r\n )\r\n}\r\n","export function normalizeProviderId(id?: string) {\r\n if (!id) return id\r\n\r\n if (!id.startsWith(\"pp_\")) return id\r\n\r\n if (id === \"pp_paypal_paypal\") return \"paypal\"\r\n if (id === \"pp_paypal_card_paypal_card\") return \"paypal_card\"\r\n\r\n const parts = id.split(\"_\")\r\n return parts.length >= 3 ? parts.slice(2).join(\"_\") : id\r\n}","\"use client\"\r\n\r\nimport React from \"react\"\r\nimport { PayPalCurrencyNotice } from \"../components/PayPalCurrencyNotice\"\r\nimport { PayPalAdvancedCard } from \"../components/PayPalAdvancedCard\"\r\nimport { PayPalProvider } from \"../components/PayPalProvider\"\r\nimport { PayPalSmartButtons } from \"../components/PayPalSmartButtons\"\r\nimport { usePayPalConfig } from \"../hooks/usePayPalConfig\"\r\nimport { normalizeProviderId } from \"../utils/normalize-provider-id\"\r\n\r\nexport type MedusaNextPayPalAdapterProps = {\r\n cartId: string\r\n selectedProviderId: string | null | undefined\r\n baseUrl: string\r\n publishableApiKey?: string\r\n providerIds?: {\r\n paypal?: string\r\n paypalCard?: string\r\n }\r\n onPaid?: (result: unknown) => void\r\n}\r\n\r\nexport function MedusaNextPayPalAdapter(props: MedusaNextPayPalAdapterProps) {\r\n const { cartId, selectedProviderId, baseUrl, publishableApiKey, providerIds, onPaid } = props\r\n\r\n const paypalProviderId = normalizeProviderId(providerIds?.paypal || \"paypal\")\r\n const paypalCardProviderId = normalizeProviderId(providerIds?.paypalCard || \"paypal_card\")\r\n const normalizedSelectedProviderId = normalizeProviderId(selectedProviderId ?? undefined)\r\n\r\n const shouldRender =\r\n normalizedSelectedProviderId === paypalProviderId ||\r\n normalizedSelectedProviderId === paypalCardProviderId\r\n\r\n const { config, loading, error } = usePayPalConfig({ baseUrl, publishableApiKey, cartId })\r\n\r\n if (!shouldRender) return null\r\n if (loading) return <div>Loading PayPal…</div>\r\n if (error) return <div style={{ color: \"crimson\" }}>{error}</div>\r\n if (!config) return null\r\n\r\n return (\r\n <div style={{ display: \"grid\", gap: 12 }}>\r\n <PayPalCurrencyNotice config={config} />\r\n\r\n <PayPalProvider config={config} intent=\"capture\">\r\n {normalizedSelectedProviderId === paypalCardProviderId ? (\r\n <PayPalAdvancedCard\r\n baseUrl={baseUrl}\r\n publishableApiKey={publishableApiKey}\r\n cartId={cartId}\r\n config={config}\r\n onPaid={onPaid}\r\n />\r\n ) : (\r\n <PayPalSmartButtons\r\n baseUrl={baseUrl}\r\n publishableApiKey={publishableApiKey}\r\n cartId={cartId}\r\n config={config}\r\n onPaid={onPaid}\r\n />\r\n )}\r\n </PayPalProvider>\r\n </div>\r\n )\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/client/http.ts","../src/client/paypal.ts","../src/hooks/usePayPalConfig.ts","../src/components/PayPalProvider.tsx","../src/components/PayPalCurrencyNotice.tsx","../src/components/PayPalSmartButtons.tsx","../src/components/PayPalAdvancedCard.tsx","../src/adapters/MedusaNextPayPalAdapter.tsx"],"names":["useMemo","jsx","useState","jsxs"],"mappings":"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","file":"index.mjs","sourcesContent":["export type HttpOptions = {\r\n baseUrl: string\r\n publishableApiKey?: string\r\n}\r\n\r\nfunction toHeaderRecord(headers?: RequestInit[\"headers\"]): Record<string, string> {\r\n if (!headers) {\r\n return {}\r\n }\r\n\r\n if (headers instanceof Headers) {\r\n return Object.fromEntries(headers.entries())\r\n }\r\n\r\n if (Array.isArray(headers)) {\r\n return Object.fromEntries(headers)\r\n }\r\n\r\n return { ...headers }\r\n}\r\n\r\nexport function createHttpClient(opts: HttpOptions) {\r\n const base = opts.baseUrl.replace(/\\/+$/, \"\")\r\n\r\n async function request<T>(path: string, init?: RequestInit): Promise<T> {\r\n const url = `${base}${path.startsWith(\"/\") ? \"\" : \"/\"}${path}`\r\n const headers: Record<string, string> = {\r\n Accept: \"application/json\",\r\n ...toHeaderRecord(init?.headers),\r\n }\r\n\r\n if (opts.publishableApiKey) {\r\n headers[\"x-publishable-api-key\"] = opts.publishableApiKey\r\n }\r\n\r\n const res = await fetch(url, { ...init, headers, credentials: \"include\" })\r\n const text = await res.text().catch(() => \"\")\r\n\r\n if (!res.ok) {\r\n throw new Error(text || `Request failed (${res.status})`)\r\n }\r\n\r\n return (text ? JSON.parse(text) : {}) as T\r\n }\r\n\r\n return { request }\r\n}\r\n","import type { PayPalConfig, PayPalSettingsResponse } from \"./types\"\r\nimport { createHttpClient, type HttpOptions } from \"./http\"\r\n\r\nexport function createPayPalStoreApi(opts: HttpOptions) {\r\n const http = createHttpClient(opts)\r\n\r\n return {\r\n getConfig(cartId?: string) {\r\n const q = cartId ? `?cart_id=${encodeURIComponent(cartId)}` : \"\"\r\n return http.request<PayPalConfig>(`/store/paypal/config${q}`)\r\n },\r\n\r\n getSettings() {\r\n return http.request<PayPalSettingsResponse>(`/store/paypal/settings`)\r\n },\r\n\r\n createOrder(cartId: string) {\r\n return http.request<{ id: string }>(`/store/paypal/create-order`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({ cart_id: cartId }),\r\n })\r\n },\r\n\r\n captureOrder(cartId: string, orderId: string) {\r\n return http.request<Record<string, unknown>>(`/store/paypal/capture-order`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({ cart_id: cartId, order_id: orderId }),\r\n })\r\n },\r\n }\r\n}\r\n","import { useEffect, useMemo, useState } from \"react\"\r\nimport { createPayPalStoreApi } from \"../client/paypal\"\r\nimport type { PayPalConfig } from \"../client/types\"\r\n\r\ntype Args = {\r\n baseUrl: string\r\n publishableApiKey?: string\r\n cartId?: string\r\n enabled?: boolean\r\n}\r\n\r\nexport function usePayPalConfig({ baseUrl, publishableApiKey, cartId, enabled = true }: Args) {\r\n const api = useMemo(\r\n () => createPayPalStoreApi({ baseUrl, publishableApiKey }),\r\n [baseUrl, publishableApiKey]\r\n )\r\n\r\n const [config, setConfig] = useState<PayPalConfig | null>(null)\r\n const [loading, setLoading] = useState(false)\r\n const [error, setError] = useState<string | null>(null)\r\n\r\n useEffect(() => {\r\n if (!enabled) {\r\n setLoading(false)\r\n setError(null)\r\n setConfig(null)\r\n return\r\n }\r\n\r\n let mounted = true\r\n ;(async () => {\r\n try {\r\n setLoading(true)\r\n setError(null)\r\n const cfg = await api.getConfig(cartId)\r\n if (mounted) setConfig(cfg)\r\n } catch (e: unknown) {\r\n if (mounted) setError(e instanceof Error ? e.message : \"Failed to load PayPal config\")\r\n } finally {\r\n if (mounted) setLoading(false)\r\n }\r\n })()\r\n\r\n return () => {\r\n mounted = false\r\n }\r\n }, [api, cartId, enabled])\r\n\r\n return { config, loading, error }\r\n}\r\n","\"use client\"\n\nimport React, { useMemo } from \"react\"\nimport { PayPalScriptProvider } from \"@paypal/react-paypal-js\"\nimport type { PayPalConfig } from \"../client/types\"\n\nexport function PayPalProvider(props: {\n config: PayPalConfig\n intent?: \"capture\" | \"authorize\"\n children: React.ReactNode\n}) {\n const { config, intent = \"capture\", children } = props\n\n const options = useMemo(() => {\n return {\n \"client-id\": config.client_id,\n currency: config.currency,\n intent,\n components: config.client_token ? \"buttons,card-fields\" : \"buttons\",\n \"data-client-token\": config.client_token || undefined,\n } as any\n }, [config, intent])\n\n return <PayPalScriptProvider options={options}>{children}</PayPalScriptProvider>\n}\n","\"use client\"\n\nimport React from \"react\"\nimport type { PayPalConfig } from \"../client/types\"\n\nexport function PayPalCurrencyNotice({ config }: { config: PayPalConfig }) {\n if (config.currency_supported) return null\n\n return (\n <div style={{ padding: 12, border: \"1px solid #ddd\", borderRadius: 10 }}>\n <div style={{ fontWeight: 600, marginBottom: 6 }}>PayPal currency issue</div>\n <ul style={{ margin: 0, paddingLeft: 18 }}>\n {(config.currency_errors || []).map((e, i) => (\n <li key={i}>{e}</li>\n ))}\n </ul>\n </div>\n )\n}\n","\"use client\"\r\n\r\nimport React, { useMemo, useState } from \"react\"\r\nimport { PayPalButtons } from \"@paypal/react-paypal-js\"\r\nimport { createPayPalStoreApi } from \"../client/paypal\"\r\nimport type { PayPalConfig } from \"../client/types\"\r\n\r\nexport function PayPalSmartButtons(props: {\r\n baseUrl: string\r\n publishableApiKey?: string\r\n cartId: string\r\n config: PayPalConfig\r\n onPaid?: (result: Record<string, unknown>) => void\r\n onError?: (message: string) => void\r\n}) {\r\n const { baseUrl, publishableApiKey, cartId, config, onPaid, onError } = props\r\n const api = useMemo(\r\n () => createPayPalStoreApi({ baseUrl, publishableApiKey }),\r\n [baseUrl, publishableApiKey]\r\n )\r\n\r\n const [error, setError] = useState<string | null>(null)\r\n\r\n if (!config.currency_supported) return null\r\n\r\n return (\r\n <div>\r\n <PayPalButtons\r\n style={{ layout: \"vertical\" }}\r\n createOrder={async () => {\r\n setError(null)\r\n const r = await api.createOrder(cartId)\r\n return r.id\r\n }}\r\n onApprove={async (data: { orderID?: string }) => {\r\n setError(null)\r\n const orderId = String(data?.orderID || \"\")\r\n const result = await api.captureOrder(cartId, orderId)\r\n onPaid?.(result)\r\n }}\r\n onError={(err: Error | { message?: string }) => {\r\n const msg = err instanceof Error ? err.message : err?.message || \"PayPal error\"\r\n setError(msg)\r\n onError?.(msg)\r\n }}\r\n />\r\n {error ? <div style={{ marginTop: 10, color: \"crimson\" }}>{error}</div> : null}\r\n </div>\r\n )\r\n}\r\n","\"use client\"\r\n\r\nimport React, { useMemo, useState } from \"react\"\r\nimport {\r\n PayPalCardFieldsProvider,\r\n PayPalNameField,\r\n PayPalNumberField,\r\n PayPalExpiryField,\r\n PayPalCVVField,\r\n usePayPalCardFields,\r\n} from \"@paypal/react-paypal-js\"\r\nimport { createPayPalStoreApi } from \"../client/paypal\"\r\nimport type { PayPalConfig } from \"../client/types\"\r\n\r\nfunction SubmitButton({ disabled, label }: { disabled: boolean; label: string }) {\r\n const { cardFieldsForm } = usePayPalCardFields()\r\n\r\n return (\r\n <button\r\n type=\"button\"\r\n disabled={disabled || !cardFieldsForm}\r\n onClick={() => cardFieldsForm?.submit()}\r\n style={{ padding: \"10px 12px\", borderRadius: 10, border: \"1px solid #ddd\" }}\r\n >\r\n {label}\r\n </button>\r\n )\r\n}\r\n\r\nexport function PayPalAdvancedCard(props: {\r\n baseUrl: string\r\n publishableApiKey?: string\r\n cartId: string\r\n config: PayPalConfig\r\n onPaid?: (result: Record<string, unknown>) => void\r\n onError?: (message: string) => void\r\n}) {\r\n const { baseUrl, publishableApiKey, cartId, config, onPaid, onError } = props\r\n const api = useMemo(\r\n () => createPayPalStoreApi({ baseUrl, publishableApiKey }),\r\n [baseUrl, publishableApiKey]\r\n )\r\n\r\n const [error, setError] = useState<string | null>(null)\r\n const [submitting, setSubmitting] = useState(false)\r\n\r\n if (!config.currency_supported) return null\r\n\r\n if (!config.client_token) {\r\n return (\r\n <div style={{ padding: 12, border: \"1px solid #ddd\", borderRadius: 10 }}>\r\n CardFields unavailable: missing client_token from backend.\r\n </div>\r\n )\r\n }\r\n\r\n return (\r\n <PayPalCardFieldsProvider\r\n createOrder={async () => {\r\n setError(null)\r\n const r = await api.createOrder(cartId)\r\n return r.id\r\n }}\r\n onApprove={async (data: { orderID?: string }) => {\r\n try {\r\n setSubmitting(true)\r\n setError(null)\r\n const orderId = String(data?.orderID || \"\")\r\n const result = await api.captureOrder(cartId, orderId)\r\n onPaid?.(result)\r\n } catch (e: unknown) {\r\n const msg = e instanceof Error ? e.message : \"Card payment failed\"\r\n setError(msg)\r\n onError?.(msg)\r\n } finally {\r\n setSubmitting(false)\r\n }\r\n }}\r\n onError={(e: Error | { message?: string }) => {\r\n const msg = e instanceof Error ? e.message : e?.message || \"CardFields error\"\r\n setError(msg)\r\n onError?.(msg)\r\n }}\r\n >\r\n <div style={{ display: \"grid\", gap: 10 }}>\r\n <PayPalNameField />\r\n <PayPalNumberField />\r\n <div style={{ display: \"grid\", gridTemplateColumns: \"1fr 1fr\", gap: 10 }}>\r\n <PayPalExpiryField />\r\n <PayPalCVVField />\r\n </div>\r\n\r\n <SubmitButton disabled={submitting} label={submitting ? \"Processing...\" : \"Pay by Card\"} />\r\n\r\n {error ? <div style={{ color: \"crimson\" }}>{error}</div> : null}\r\n </div>\r\n </PayPalCardFieldsProvider>\r\n )\r\n}\r\n","\"use client\"\r\n\r\nimport React from \"react\"\r\nimport { PayPalCurrencyNotice } from \"../components/PayPalCurrencyNotice\"\r\nimport { PayPalAdvancedCard } from \"../components/PayPalAdvancedCard\"\r\nimport { PayPalProvider } from \"../components/PayPalProvider\"\r\nimport { PayPalSmartButtons } from \"../components/PayPalSmartButtons\"\r\nimport { usePayPalConfig } from \"../hooks/usePayPalConfig\"\r\n\r\nconst DEFAULT_PAYPAL_PROVIDER_ID = \"pp_paypal_paypal\"\r\nconst DEFAULT_PAYPAL_CARD_PROVIDER_ID = \"pp_paypal_card_paypal_card\"\r\n\r\nexport type MedusaNextPayPalAdapterProps = {\r\n cartId: string\r\n selectedProviderId: string | null | undefined\r\n baseUrl: string\r\n publishableApiKey?: string\r\n providerIds?: {\r\n paypal?: string\r\n paypalCard?: string\r\n }\r\n onPaid?: (result: unknown) => void\r\n}\r\n\r\nexport function MedusaNextPayPalAdapter(props: MedusaNextPayPalAdapterProps) {\r\n const { cartId, selectedProviderId, baseUrl, publishableApiKey, providerIds, onPaid } = props\r\n\r\n const paypalProviderId = providerIds?.paypal || DEFAULT_PAYPAL_PROVIDER_ID\r\n const paypalCardProviderId = providerIds?.paypalCard || DEFAULT_PAYPAL_CARD_PROVIDER_ID\r\n\r\n const shouldRender =\r\n selectedProviderId === paypalProviderId ||\r\n selectedProviderId === paypalCardProviderId\r\n\r\n const { config, loading, error } = usePayPalConfig({\r\n baseUrl,\r\n publishableApiKey,\r\n cartId,\r\n enabled: shouldRender,\r\n })\r\n\r\n if (!shouldRender) return null\r\n if (loading) return <div>Loading PayPal…</div>\r\n if (error) return <div style={{ color: \"crimson\" }}>{error}</div>\r\n if (!config) return null\r\n\r\n return (\r\n <div style={{ display: \"grid\", gap: 12 }}>\r\n <PayPalCurrencyNotice config={config} />\r\n\r\n <PayPalProvider config={config} intent={config.intent === \"authorize\" ? \"authorize\" : \"capture\"}>\r\n {selectedProviderId === paypalCardProviderId ? (\r\n <PayPalAdvancedCard\r\n baseUrl={baseUrl}\r\n publishableApiKey={publishableApiKey}\r\n cartId={cartId}\r\n config={config}\r\n onPaid={onPaid}\r\n />\r\n ) : (\r\n <PayPalSmartButtons\r\n baseUrl={baseUrl}\r\n publishableApiKey={publishableApiKey}\r\n cartId={cartId}\r\n config={config}\r\n onPaid={onPaid}\r\n />\r\n )}\r\n </PayPalProvider>\r\n </div>\r\n )\r\n}\r\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@easypayment/medusa-paypal-ui",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"description": "Enterprise Gold PayPal UI module for Medusa v2 storefront (Next.js)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"types": "./dist/index.d.ts",
|
|
11
11
|
"files": [
|
|
12
12
|
"dist",
|
|
13
|
+
"src",
|
|
13
14
|
"README.md",
|
|
14
15
|
"LICENSE"
|
|
15
16
|
],
|
|
@@ -46,4 +47,4 @@
|
|
|
46
47
|
"test:watch": "vitest",
|
|
47
48
|
"prepublishOnly": "npm run build"
|
|
48
49
|
}
|
|
49
|
-
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import React from "react"
|
|
4
|
+
import { PayPalCurrencyNotice } from "../components/PayPalCurrencyNotice"
|
|
5
|
+
import { PayPalAdvancedCard } from "../components/PayPalAdvancedCard"
|
|
6
|
+
import { PayPalProvider } from "../components/PayPalProvider"
|
|
7
|
+
import { PayPalSmartButtons } from "../components/PayPalSmartButtons"
|
|
8
|
+
import { usePayPalConfig } from "../hooks/usePayPalConfig"
|
|
9
|
+
|
|
10
|
+
const DEFAULT_PAYPAL_PROVIDER_ID = "pp_paypal_paypal"
|
|
11
|
+
const DEFAULT_PAYPAL_CARD_PROVIDER_ID = "pp_paypal_card_paypal_card"
|
|
12
|
+
|
|
13
|
+
export type MedusaNextPayPalAdapterProps = {
|
|
14
|
+
cartId: string
|
|
15
|
+
selectedProviderId: string | null | undefined
|
|
16
|
+
baseUrl: string
|
|
17
|
+
publishableApiKey?: string
|
|
18
|
+
providerIds?: {
|
|
19
|
+
paypal?: string
|
|
20
|
+
paypalCard?: string
|
|
21
|
+
}
|
|
22
|
+
onPaid?: (result: unknown) => void
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function MedusaNextPayPalAdapter(props: MedusaNextPayPalAdapterProps) {
|
|
26
|
+
const { cartId, selectedProviderId, baseUrl, publishableApiKey, providerIds, onPaid } = props
|
|
27
|
+
|
|
28
|
+
const paypalProviderId = providerIds?.paypal || DEFAULT_PAYPAL_PROVIDER_ID
|
|
29
|
+
const paypalCardProviderId = providerIds?.paypalCard || DEFAULT_PAYPAL_CARD_PROVIDER_ID
|
|
30
|
+
|
|
31
|
+
const shouldRender =
|
|
32
|
+
selectedProviderId === paypalProviderId ||
|
|
33
|
+
selectedProviderId === paypalCardProviderId
|
|
34
|
+
|
|
35
|
+
const { config, loading, error } = usePayPalConfig({
|
|
36
|
+
baseUrl,
|
|
37
|
+
publishableApiKey,
|
|
38
|
+
cartId,
|
|
39
|
+
enabled: shouldRender,
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
if (!shouldRender) return null
|
|
43
|
+
if (loading) return <div>Loading PayPal…</div>
|
|
44
|
+
if (error) return <div style={{ color: "crimson" }}>{error}</div>
|
|
45
|
+
if (!config) return null
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<div style={{ display: "grid", gap: 12 }}>
|
|
49
|
+
<PayPalCurrencyNotice config={config} />
|
|
50
|
+
|
|
51
|
+
<PayPalProvider config={config} intent={config.intent === "authorize" ? "authorize" : "capture"}>
|
|
52
|
+
{selectedProviderId === paypalCardProviderId ? (
|
|
53
|
+
<PayPalAdvancedCard
|
|
54
|
+
baseUrl={baseUrl}
|
|
55
|
+
publishableApiKey={publishableApiKey}
|
|
56
|
+
cartId={cartId}
|
|
57
|
+
config={config}
|
|
58
|
+
onPaid={onPaid}
|
|
59
|
+
/>
|
|
60
|
+
) : (
|
|
61
|
+
<PayPalSmartButtons
|
|
62
|
+
baseUrl={baseUrl}
|
|
63
|
+
publishableApiKey={publishableApiKey}
|
|
64
|
+
cartId={cartId}
|
|
65
|
+
config={config}
|
|
66
|
+
onPaid={onPaid}
|
|
67
|
+
/>
|
|
68
|
+
)}
|
|
69
|
+
</PayPalProvider>
|
|
70
|
+
</div>
|
|
71
|
+
)
|
|
72
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export type HttpOptions = {
|
|
2
|
+
baseUrl: string
|
|
3
|
+
publishableApiKey?: string
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
function toHeaderRecord(headers?: RequestInit["headers"]): Record<string, string> {
|
|
7
|
+
if (!headers) {
|
|
8
|
+
return {}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (headers instanceof Headers) {
|
|
12
|
+
return Object.fromEntries(headers.entries())
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (Array.isArray(headers)) {
|
|
16
|
+
return Object.fromEntries(headers)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return { ...headers }
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function createHttpClient(opts: HttpOptions) {
|
|
23
|
+
const base = opts.baseUrl.replace(/\/+$/, "")
|
|
24
|
+
|
|
25
|
+
async function request<T>(path: string, init?: RequestInit): Promise<T> {
|
|
26
|
+
const url = `${base}${path.startsWith("/") ? "" : "/"}${path}`
|
|
27
|
+
const headers: Record<string, string> = {
|
|
28
|
+
Accept: "application/json",
|
|
29
|
+
...toHeaderRecord(init?.headers),
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (opts.publishableApiKey) {
|
|
33
|
+
headers["x-publishable-api-key"] = opts.publishableApiKey
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const res = await fetch(url, { ...init, headers, credentials: "include" })
|
|
37
|
+
const text = await res.text().catch(() => "")
|
|
38
|
+
|
|
39
|
+
if (!res.ok) {
|
|
40
|
+
throw new Error(text || `Request failed (${res.status})`)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return (text ? JSON.parse(text) : {}) as T
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return { request }
|
|
47
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { PayPalConfig, PayPalSettingsResponse } from "./types"
|
|
2
|
+
import { createHttpClient, type HttpOptions } from "./http"
|
|
3
|
+
|
|
4
|
+
export function createPayPalStoreApi(opts: HttpOptions) {
|
|
5
|
+
const http = createHttpClient(opts)
|
|
6
|
+
|
|
7
|
+
return {
|
|
8
|
+
getConfig(cartId?: string) {
|
|
9
|
+
const q = cartId ? `?cart_id=${encodeURIComponent(cartId)}` : ""
|
|
10
|
+
return http.request<PayPalConfig>(`/store/paypal/config${q}`)
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
getSettings() {
|
|
14
|
+
return http.request<PayPalSettingsResponse>(`/store/paypal/settings`)
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
createOrder(cartId: string) {
|
|
18
|
+
return http.request<{ id: string }>(`/store/paypal/create-order`, {
|
|
19
|
+
method: "POST",
|
|
20
|
+
headers: { "Content-Type": "application/json" },
|
|
21
|
+
body: JSON.stringify({ cart_id: cartId }),
|
|
22
|
+
})
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
captureOrder(cartId: string, orderId: string) {
|
|
26
|
+
return http.request<Record<string, unknown>>(`/store/paypal/capture-order`, {
|
|
27
|
+
method: "POST",
|
|
28
|
+
headers: { "Content-Type": "application/json" },
|
|
29
|
+
body: JSON.stringify({ cart_id: cartId, order_id: orderId }),
|
|
30
|
+
})
|
|
31
|
+
},
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type PayPalConfig = {
|
|
2
|
+
environment: "sandbox" | "live"
|
|
3
|
+
client_id: string
|
|
4
|
+
currency: string
|
|
5
|
+
currency_supported: boolean
|
|
6
|
+
currency_errors: string[]
|
|
7
|
+
supported_currencies: string[]
|
|
8
|
+
client_token?: string
|
|
9
|
+
intent?: "capture" | "authorize"
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type PayPalSettingsResponse = {
|
|
13
|
+
data?: {
|
|
14
|
+
api_details?: { currency_code?: string }
|
|
15
|
+
paypal_settings?: Record<string, unknown>
|
|
16
|
+
onboarding_config?: Record<string, unknown>
|
|
17
|
+
}
|
|
18
|
+
[key: string]: unknown
|
|
19
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import React, { useMemo, useState } from "react"
|
|
4
|
+
import {
|
|
5
|
+
PayPalCardFieldsProvider,
|
|
6
|
+
PayPalNameField,
|
|
7
|
+
PayPalNumberField,
|
|
8
|
+
PayPalExpiryField,
|
|
9
|
+
PayPalCVVField,
|
|
10
|
+
usePayPalCardFields,
|
|
11
|
+
} from "@paypal/react-paypal-js"
|
|
12
|
+
import { createPayPalStoreApi } from "../client/paypal"
|
|
13
|
+
import type { PayPalConfig } from "../client/types"
|
|
14
|
+
|
|
15
|
+
function SubmitButton({ disabled, label }: { disabled: boolean; label: string }) {
|
|
16
|
+
const { cardFieldsForm } = usePayPalCardFields()
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<button
|
|
20
|
+
type="button"
|
|
21
|
+
disabled={disabled || !cardFieldsForm}
|
|
22
|
+
onClick={() => cardFieldsForm?.submit()}
|
|
23
|
+
style={{ padding: "10px 12px", borderRadius: 10, border: "1px solid #ddd" }}
|
|
24
|
+
>
|
|
25
|
+
{label}
|
|
26
|
+
</button>
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function PayPalAdvancedCard(props: {
|
|
31
|
+
baseUrl: string
|
|
32
|
+
publishableApiKey?: string
|
|
33
|
+
cartId: string
|
|
34
|
+
config: PayPalConfig
|
|
35
|
+
onPaid?: (result: Record<string, unknown>) => void
|
|
36
|
+
onError?: (message: string) => void
|
|
37
|
+
}) {
|
|
38
|
+
const { baseUrl, publishableApiKey, cartId, config, onPaid, onError } = props
|
|
39
|
+
const api = useMemo(
|
|
40
|
+
() => createPayPalStoreApi({ baseUrl, publishableApiKey }),
|
|
41
|
+
[baseUrl, publishableApiKey]
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
const [error, setError] = useState<string | null>(null)
|
|
45
|
+
const [submitting, setSubmitting] = useState(false)
|
|
46
|
+
|
|
47
|
+
if (!config.currency_supported) return null
|
|
48
|
+
|
|
49
|
+
if (!config.client_token) {
|
|
50
|
+
return (
|
|
51
|
+
<div style={{ padding: 12, border: "1px solid #ddd", borderRadius: 10 }}>
|
|
52
|
+
CardFields unavailable: missing client_token from backend.
|
|
53
|
+
</div>
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<PayPalCardFieldsProvider
|
|
59
|
+
createOrder={async () => {
|
|
60
|
+
setError(null)
|
|
61
|
+
const r = await api.createOrder(cartId)
|
|
62
|
+
return r.id
|
|
63
|
+
}}
|
|
64
|
+
onApprove={async (data: { orderID?: string }) => {
|
|
65
|
+
try {
|
|
66
|
+
setSubmitting(true)
|
|
67
|
+
setError(null)
|
|
68
|
+
const orderId = String(data?.orderID || "")
|
|
69
|
+
const result = await api.captureOrder(cartId, orderId)
|
|
70
|
+
onPaid?.(result)
|
|
71
|
+
} catch (e: unknown) {
|
|
72
|
+
const msg = e instanceof Error ? e.message : "Card payment failed"
|
|
73
|
+
setError(msg)
|
|
74
|
+
onError?.(msg)
|
|
75
|
+
} finally {
|
|
76
|
+
setSubmitting(false)
|
|
77
|
+
}
|
|
78
|
+
}}
|
|
79
|
+
onError={(e: Error | { message?: string }) => {
|
|
80
|
+
const msg = e instanceof Error ? e.message : e?.message || "CardFields error"
|
|
81
|
+
setError(msg)
|
|
82
|
+
onError?.(msg)
|
|
83
|
+
}}
|
|
84
|
+
>
|
|
85
|
+
<div style={{ display: "grid", gap: 10 }}>
|
|
86
|
+
<PayPalNameField />
|
|
87
|
+
<PayPalNumberField />
|
|
88
|
+
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10 }}>
|
|
89
|
+
<PayPalExpiryField />
|
|
90
|
+
<PayPalCVVField />
|
|
91
|
+
</div>
|
|
92
|
+
|
|
93
|
+
<SubmitButton disabled={submitting} label={submitting ? "Processing..." : "Pay by Card"} />
|
|
94
|
+
|
|
95
|
+
{error ? <div style={{ color: "crimson" }}>{error}</div> : null}
|
|
96
|
+
</div>
|
|
97
|
+
</PayPalCardFieldsProvider>
|
|
98
|
+
)
|
|
99
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import React from "react"
|
|
4
|
+
import type { PayPalConfig } from "../client/types"
|
|
5
|
+
|
|
6
|
+
export function PayPalCurrencyNotice({ config }: { config: PayPalConfig }) {
|
|
7
|
+
if (config.currency_supported) return null
|
|
8
|
+
|
|
9
|
+
return (
|
|
10
|
+
<div style={{ padding: 12, border: "1px solid #ddd", borderRadius: 10 }}>
|
|
11
|
+
<div style={{ fontWeight: 600, marginBottom: 6 }}>PayPal currency issue</div>
|
|
12
|
+
<ul style={{ margin: 0, paddingLeft: 18 }}>
|
|
13
|
+
{(config.currency_errors || []).map((e, i) => (
|
|
14
|
+
<li key={i}>{e}</li>
|
|
15
|
+
))}
|
|
16
|
+
</ul>
|
|
17
|
+
</div>
|
|
18
|
+
)
|
|
19
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import React, { useMemo } from "react"
|
|
4
|
+
import { PayPalScriptProvider } from "@paypal/react-paypal-js"
|
|
5
|
+
import type { PayPalConfig } from "../client/types"
|
|
6
|
+
|
|
7
|
+
export function PayPalProvider(props: {
|
|
8
|
+
config: PayPalConfig
|
|
9
|
+
intent?: "capture" | "authorize"
|
|
10
|
+
children: React.ReactNode
|
|
11
|
+
}) {
|
|
12
|
+
const { config, intent = "capture", children } = props
|
|
13
|
+
|
|
14
|
+
const options = useMemo(() => {
|
|
15
|
+
return {
|
|
16
|
+
"client-id": config.client_id,
|
|
17
|
+
currency: config.currency,
|
|
18
|
+
intent,
|
|
19
|
+
components: config.client_token ? "buttons,card-fields" : "buttons",
|
|
20
|
+
"data-client-token": config.client_token || undefined,
|
|
21
|
+
} as any
|
|
22
|
+
}, [config, intent])
|
|
23
|
+
|
|
24
|
+
return <PayPalScriptProvider options={options}>{children}</PayPalScriptProvider>
|
|
25
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import React, { useMemo, useState } from "react"
|
|
4
|
+
import { PayPalButtons } from "@paypal/react-paypal-js"
|
|
5
|
+
import { createPayPalStoreApi } from "../client/paypal"
|
|
6
|
+
import type { PayPalConfig } from "../client/types"
|
|
7
|
+
|
|
8
|
+
export function PayPalSmartButtons(props: {
|
|
9
|
+
baseUrl: string
|
|
10
|
+
publishableApiKey?: string
|
|
11
|
+
cartId: string
|
|
12
|
+
config: PayPalConfig
|
|
13
|
+
onPaid?: (result: Record<string, unknown>) => void
|
|
14
|
+
onError?: (message: string) => void
|
|
15
|
+
}) {
|
|
16
|
+
const { baseUrl, publishableApiKey, cartId, config, onPaid, onError } = props
|
|
17
|
+
const api = useMemo(
|
|
18
|
+
() => createPayPalStoreApi({ baseUrl, publishableApiKey }),
|
|
19
|
+
[baseUrl, publishableApiKey]
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
const [error, setError] = useState<string | null>(null)
|
|
23
|
+
|
|
24
|
+
if (!config.currency_supported) return null
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<div>
|
|
28
|
+
<PayPalButtons
|
|
29
|
+
style={{ layout: "vertical" }}
|
|
30
|
+
createOrder={async () => {
|
|
31
|
+
setError(null)
|
|
32
|
+
const r = await api.createOrder(cartId)
|
|
33
|
+
return r.id
|
|
34
|
+
}}
|
|
35
|
+
onApprove={async (data: { orderID?: string }) => {
|
|
36
|
+
setError(null)
|
|
37
|
+
const orderId = String(data?.orderID || "")
|
|
38
|
+
const result = await api.captureOrder(cartId, orderId)
|
|
39
|
+
onPaid?.(result)
|
|
40
|
+
}}
|
|
41
|
+
onError={(err: Error | { message?: string }) => {
|
|
42
|
+
const msg = err instanceof Error ? err.message : err?.message || "PayPal error"
|
|
43
|
+
setError(msg)
|
|
44
|
+
onError?.(msg)
|
|
45
|
+
}}
|
|
46
|
+
/>
|
|
47
|
+
{error ? <div style={{ marginTop: 10, color: "crimson" }}>{error}</div> : null}
|
|
48
|
+
</div>
|
|
49
|
+
)
|
|
50
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { useEffect, useMemo, useState } from "react"
|
|
2
|
+
import { createPayPalStoreApi } from "../client/paypal"
|
|
3
|
+
import type { PayPalConfig } from "../client/types"
|
|
4
|
+
|
|
5
|
+
type Args = {
|
|
6
|
+
baseUrl: string
|
|
7
|
+
publishableApiKey?: string
|
|
8
|
+
cartId?: string
|
|
9
|
+
enabled?: boolean
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function usePayPalConfig({ baseUrl, publishableApiKey, cartId, enabled = true }: Args) {
|
|
13
|
+
const api = useMemo(
|
|
14
|
+
() => createPayPalStoreApi({ baseUrl, publishableApiKey }),
|
|
15
|
+
[baseUrl, publishableApiKey]
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
const [config, setConfig] = useState<PayPalConfig | null>(null)
|
|
19
|
+
const [loading, setLoading] = useState(false)
|
|
20
|
+
const [error, setError] = useState<string | null>(null)
|
|
21
|
+
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (!enabled) {
|
|
24
|
+
setLoading(false)
|
|
25
|
+
setError(null)
|
|
26
|
+
setConfig(null)
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let mounted = true
|
|
31
|
+
;(async () => {
|
|
32
|
+
try {
|
|
33
|
+
setLoading(true)
|
|
34
|
+
setError(null)
|
|
35
|
+
const cfg = await api.getConfig(cartId)
|
|
36
|
+
if (mounted) setConfig(cfg)
|
|
37
|
+
} catch (e: unknown) {
|
|
38
|
+
if (mounted) setError(e instanceof Error ? e.message : "Failed to load PayPal config")
|
|
39
|
+
} finally {
|
|
40
|
+
if (mounted) setLoading(false)
|
|
41
|
+
}
|
|
42
|
+
})()
|
|
43
|
+
|
|
44
|
+
return () => {
|
|
45
|
+
mounted = false
|
|
46
|
+
}
|
|
47
|
+
}, [api, cartId, enabled])
|
|
48
|
+
|
|
49
|
+
return { config, loading, error }
|
|
50
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from "./client/types"
|
|
2
|
+
export * from "./client/paypal"
|
|
3
|
+
export * from "./hooks/usePayPalConfig"
|
|
4
|
+
export * from "./components/PayPalProvider"
|
|
5
|
+
export * from "./components/PayPalCurrencyNotice"
|
|
6
|
+
export * from "./components/PayPalSmartButtons"
|
|
7
|
+
export * from "./components/PayPalAdvancedCard"
|
|
8
|
+
export * from "./adapters/MedusaNextPayPalAdapter"
|