UNPKG

@blocklet/payment-react

Version:

Reusable react components for payment kit v2

169 lines (168 loc) 5.45 kB
import { jsx } from "react/jsx-runtime"; import { Alert } from "@mui/material"; import { useLocalStorageState, useRequest } from "ahooks"; import { createContext, useContext, useEffect, useState } from "react"; import axios from "axios"; import { joinURL } from "ufo"; import api from "../libs/api.js"; import { getPrefix, PAYMENT_KIT_DID } from "../libs/util.js"; import { CachedRequest } from "../libs/cached-request.js"; const formatData = (data) => { if (!data) { return { paymentMethods: [], baseCurrency: {} }; } return { ...data, paymentMethods: data.paymentMethods || [], baseCurrency: data.baseCurrency || {} }; }; const PaymentContext = createContext({ api }); const { Provider, Consumer } = PaymentContext; const getSettings = (forceRefresh = false) => { const livemode = localStorage.getItem("livemode") !== "false"; const cacheKey = `payment-settings-${window.location.pathname}-${livemode}`; const cachedRequest = new CachedRequest(cacheKey, () => api.get("/api/settings", { params: { livemode } })); return cachedRequest.fetch(forceRefresh); }; const getCurrency = (currencyId, methods) => { const currencies = methods.reduce((acc, x) => acc.concat(x.payment_currencies), []); return currencies.find((x) => x.id === currencyId); }; const getMethod = (methodId, methods) => { return methods.find((x) => x.id === methodId); }; const syncToSpaceRequest = (userDid, spaceDid) => { const cacheKey = `sync-space-${userDid}-${spaceDid}`; const cachedRequest = new CachedRequest(cacheKey, () => api.post("/api/customers/sync-to-space"), { ttl: 1e3 * 60 * 60 // 1 hour }); return cachedRequest.fetch(false).then((res) => { if (!res.success) { cachedRequest.clearCache(); } return res; }); }; function PaymentProvider({ session, connect, children, baseUrl = void 0, authToken = void 0 }) { const [crossOriginLoading, setCrossOriginLoading] = useState(false); if (authToken) { window.__PAYMENT_KIT_AUTH_TOKEN = authToken; } else { window.__PAYMENT_KIT_AUTH_TOKEN = ""; } useEffect(() => { const fetchCrossOriginBlockletInfo = async () => { if (!baseUrl) { window.__PAYMENT_KIT_BASE_URL = ""; setCrossOriginLoading(false); return; } const tmp = new URL(baseUrl); if (tmp.origin === window.location.origin) { window.__PAYMENT_KIT_BASE_URL = ""; setCrossOriginLoading(false); return; } setCrossOriginLoading(true); try { const scriptUrl = joinURL(tmp.origin, "__blocklet__.js?type=json"); const cacheKey = `cross-origin-blocklet-${tmp.origin}`; const cachedRequest = new CachedRequest( cacheKey, () => axios.get(scriptUrl).then((res) => ({ data: res.data })), { strategy: "session", ttl: 10 * 60 * 1e3 // 10 minutes TTL } ); const blockletInfo = await cachedRequest.fetch(); const componentId = (blockletInfo?.componentId || "").split("/").pop(); if (componentId === PAYMENT_KIT_DID) { window.__PAYMENT_KIT_BASE_URL = joinURL(tmp.origin, blockletInfo.prefix || "/"); } else { const component = (blockletInfo?.componentMountPoints || []).find((x) => x?.did === PAYMENT_KIT_DID); window.__PAYMENT_KIT_BASE_URL = component ? joinURL(tmp.origin, component.mountPoint) : baseUrl; } } catch (err) { console.warn(`Failed to fetch blocklet json from ${baseUrl}:`, err); window.__PAYMENT_KIT_BASE_URL = baseUrl; } finally { setCrossOriginLoading(false); } }; fetchCrossOriginBlockletInfo(); }, [baseUrl]); const [livemode, setLivemode] = useLocalStorageState("livemode", { defaultValue: true }); const { data = { paymentMethods: [], baseCurrency: {} }, error, run, loading } = useRequest(getSettings, { refreshDeps: [livemode] }); useEffect(() => { const didSpace = session?.user?.didSpace; const userDid = session?.user?.did; if (userDid && didSpace && didSpace.endpoint && didSpace.did) { syncToSpaceRequest(userDid, didSpace.did); } }, [session?.user]); const prefix = getPrefix(); const [payable, setPayable] = useState(true); const [paymentState, setPaymentState] = useState({ paying: false, stripePaying: false }); const updatePaymentState = (state) => { setPaymentState((prev) => ({ ...prev, ...state })); }; if (error) { return /* @__PURE__ */ jsx(Alert, { severity: "error", children: error.message }); } if (loading || crossOriginLoading) { return null; } return /* @__PURE__ */ jsx( Provider, { value: { session, connect, prefix, livemode: !!livemode, settings: formatData(data), getCurrency: (currencyId) => getCurrency(currencyId, data?.paymentMethods || []), getMethod: (methodId) => getMethod(methodId, data?.paymentMethods || []), refresh: run, setLivemode, api, payable, setPayable, paymentState, setPaymentState: updatePaymentState }, children } ); } function usePaymentContext() { const context = useContext(PaymentContext); return context; } export { PaymentContext, PaymentProvider, Consumer as SettingsConsumer, usePaymentContext };