| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- "use client";
- import Script from "next/script";
- import {
- createContext,
- useContext,
- useState
- } from "react";
- type SDKLoadState = "none" | "loading" | "error" | "success";
- type SDKForPaymentMethod = "klarna" | "afterpay" | "clearpay" | "applepay";
- type SDKName = "klarna" | "afterpay" | "applepay";
- interface PaymentSDKState {
- klarna: SDKLoadState;
- afterpay: SDKLoadState;
- applepay: SDKLoadState;
- }
- interface PaymentContextProps {
- loadSdk: (method:string) => void;
- getSDKState: (method:SDKForPaymentMethod) => SDKLoadState | undefined;
- loadSDKState: PaymentSDKState;
- }
- const klarnaSDKURL = "https://x.klarnacdn.net/kp/lib/v1/api.js";
- const afterpaySDKURL = process.env.NEXT_PUBLIC_APP_ENV === "production" ? "https://portal.afterpay.com/afterpay.js" : "https://portal.sandbox.afterpay.com/afterpay.js";
- const applepaySDKURL = "https://applepay.cdn-apple.com/jsapi/1.latest/apple-pay-sdk.js";
- const PaymentSDKContext = createContext<PaymentContextProps|null>(null);
- const normalizeSDKName = (method:string):SDKName| undefined =>{
- switch(method){
- case "clearpay":
- case "afterpay":
- return "afterpay";
- case "klarna":
- return "klarna";
- case "applepay":
- return "applepay";
- default:
- return undefined;
- }
- }
- export function PaymentSDKProvider({
- children
- }: {
- children:React.ReactNode;
- }){
- const [loadSDKState, setLoadSDKState] = useState<PaymentSDKState>({
- klarna: 'none', // none loading error success
- afterpay: 'none', // none loading error success
- applepay: 'none' // none loading error success
- });
- const loadSdk = (method:string) => {
- const m = normalizeSDKName(method);
- if(m) {
- setLoadSDKState((prev) => {
- if(prev[m] !== "none") {
- return prev;
- }
- return {
- ...prev,
- [m]:"loading"
- };
- });
- }
-
- }
- const onSdkLoad = (m:SDKName) => {
- setLoadSDKState((prev) => {
- return {
- ...prev,
- [m]: 'success'
- }
- });
- };
- const onSdkError = (m:SDKName) => {
- setLoadSDKState((prev) => {
- return {
- ...prev,
- [m]: 'error'
- }
- });
- };
- const getSDKState = (method:SDKForPaymentMethod) => {
- const m = normalizeSDKName(method);
- if(m) {
- return loadSDKState[m];
- } else {
- return undefined;
- }
-
- }
- return (
- <PaymentSDKContext.Provider
- value={{
- loadSdk,
- getSDKState,
- loadSDKState
- }}
- >
- {loadSDKState.klarna !== "none" &&
- <Script id="klarna-sdk" strategy="afterInteractive"
- src={klarnaSDKURL}
- onLoad={() => onSdkLoad('klarna')}
- onError={() => {
- onSdkError('klarna');
- }}
- />
- }
- { loadSDKState.afterpay !== "none" &&
- <Script id="afterpay-sdk" strategy="afterInteractive"
- src={afterpaySDKURL}
- onLoad={() => onSdkLoad('afterpay')}
- onError={() => {
- onSdkError('afterpay');
- }}
- />
- }
- { loadSDKState.applepay !== "none" &&
- <Script id="applepay-sdk" strategy="afterInteractive"
- src={applepaySDKURL}
- onLoad={() => onSdkLoad('applepay')}
- onError={() => {
- onSdkError('applepay');
- }}
- />
- }
- {children}
- </PaymentSDKContext.Provider>
- )
- }
- export const usePaymentSDKContext = () => {
- const context = useContext(PaymentSDKContext);
- if (!context) {
- throw new Error("usePaymentSDKContext must be used within a PaymentSDKProvider");
- }
- return context;
- };
|