Authentication & Session
To authenticate customers with the Recharge JavaScript SDK we will create a utility that validates the customer's session and logs into Recharge as needed and stores the Recharge Session via the rechargeSession.server module we previously setup.
Query & Login Utility Function
Create a rechargeUtil.ts module where we can add a couple utility functions.
- loginRecharge- function encapsulating logic for logging into Recharge and getting a RechargeSession
- rechargeQueryWrapperto help with data fetching (which is covered in the next section). This helper function handles any needed login retries or/and error handling
NOTE In this example rechargeQueryWrapper can update the session object. Make sure you are committing the session (in case it changes) after calling the rechargeQueryWrapper function in the response from your loader/action.
- JavaScript
- TypeScript
/app/lib/rechargeUtils.js
import { loginWithShopifyCustomerAccount } from '@rechargeapps/storefront-client';
import { json } from '@shopify/remix-oxygen';
const RECHARGE_SESSION_KEY = 'rechargeSession';
// loginHelper function
async function loginRecharge(context) {
  const customerAccessToken = await context.customerAccount.getAccessToken();
  const rechargeSession = await loginWithShopifyCustomerAccount(customerAccessToken);
  if (rechargeSession) {
    context.rechargeSession.set(RECHARGE_SESSION_KEY, rechargeSession);
  } else {
    // this should match your catch boundary
    throw json('No session created', { status: 400 });
  }
  return rechargeSession;
}
// helper function for data fetching
export async function rechargeQueryWrapper(rechargeFn, context) {
  let rechargeSession = context.rechargeSession.get(RECHARGE_SESSION_KEY);
  if (!rechargeSession) {
    rechargeSession = await loginRecharge(context);
  }
  try {
    return await rechargeFn(rechargeSession);
  } catch (e) {
    try {
      if (e?.status === 401) {
        // handle auth error, login again and retry request
        rechargeSession = await loginRecharge(context);
        return await rechargeFn(rechargeSession);
      }
      // this should match your catch boundary
      throw json(e.message, { status: e?.status });
    } catch (error) {
      // this should match your catch boundary
      throw json(e.message, { status: e?.status });
    }
  }
}
/app/lib/rechargeUtils.ts
import { loginShopifyApi, Session as RechargeSession } from '@rechargeapps/storefront-client';
import { json } from '@shopify/remix-oxygen';
import { HydrogenSession } from './session.server';
import type { Session as RechargeSession } from '@rechargeapps/storefront-client';
import { loginWithShopifyCustomerAccount } from '@rechargeapps/storefront-client';
import type { AppLoadContext } from '@shopify/remix-oxygen';
import { json } from '@shopify/remix-oxygen';
const RECHARGE_SESSION_KEY = 'rechargeSession';
// loginHelper function
async function loginRecharge(context: AppLoadContext) {
  const customerAccessToken = await context.customerAccount.getAccessToken();
  const rechargeSession = await loginWithShopifyCustomerAccount(customerAccessToken);
  if (rechargeSession) {
    context.rechargeSession.set(RECHARGE_SESSION_KEY, rechargeSession);
  } else {
    // this should match your catch boundary
    throw json('No session created', { status: 400 });
  }
  return rechargeSession;
}
// helper function for data fetching
export async function rechargeQueryWrapper<T>(
  rechargeFn: (session: RechargeSession) => Promise<T>,
  context: AppLoadContext
): Promise<T> {
  let rechargeSession = context.rechargeSession.get(RECHARGE_SESSION_KEY);
  if (!rechargeSession) {
    rechargeSession = await loginRecharge(context);
  }
  try {
    return await rechargeFn(rechargeSession);
  } catch (e: any) {
    try {
      if (e?.status === 401) {
        // handle auth error, login again and retry request
        rechargeSession = await loginRecharge(context);
        return await rechargeFn(rechargeSession);
      }
      // this should match your catch boundary
      throw json(e.message, { status: e?.status });
    } catch (error) {
      // this should match your catch boundary
      throw json(e.message, { status: e?.status });
    }
  }
}
Clear RechargeSession
If you ever want to remove the Recharge Session you can call destroy on it. Again make sure you commit your changes using await context.rechargeSession.commit(). The Recharge Session cookie will automatically expire after 55 minutes.
- JavaScript
- TypeScript
await context.rechargeSession.destroy();
await context.rechargeSession.destroy();