Shopify app remix template billing example

Hi

Is there a working example of “shopify remix app template” where recurring charge is used and checking if the customer has any plan associated ?

(I am new to entire node thing and trying to convert on of my dotnet app to node/remix )

thanks

Hi Ishahrier,

We don’t currently have recurring charges and customer plan checks in this example app (it was just released last week), but I’ve passed on this request to our product team. Hopefully other developers in this community will be able to share advice on how to implement these features though :slightly_smiling_face:

@Liam Hey hope u r doing good.
can you please kindly guide me how to add billing in remix template?

In case if someone is finding the answer for this question, I wrote an article regarding App Billing with Shopify Remix Template. Read it here. https://medium.com/breaktheloop/mastering-billing-with-shopify-app-remix-template-5fccca26ac56

Any chance you can post the details here instead of on medium locked behind a paywall?

This medium blog is a fairly a big one. Refer to https://github.com/DanojaDias/remix-billing-api-example-app. It has all the things explained in the blog. Main changes are in shopify.server.ts and app._index.tsx. Hope This helps.

For anyone stumbling to this post looking for a walkthrough I created a video walkthrough for this on my YouTube channel https://www.youtube.com/watch?v=Z3vLfOaLX-o

Thanks for the example app. It’s a good starting point.

To clarify, how does the app handle the following scenario: A shop installs, uses, then uninstalls the app before the trial ends. If the shop reinstalls it later, does the trial period restart? How do you prevent unlimited free use in this case?

I have implemented a solution for this issue. While I’m not entirely certain if it is the optimal approach, it is functioning as expected.

Within the shopify.server.js file, I included a function that retrieves the current active subscriptions using GraphQL, as follows:

/// .... more things on shopify.server.js
export const sessionStorage = shopify.sessionStorage;

const CACHED_SUBSCRIPTIONS: {
  [key: string]: {
    plan: string;
    timestamp: number;
  }
} = {};

export const getPlan = async (session: Session) => {
  // get cached charge if it exists and it is not expired
  if (
    CACHED_SUBSCRIPTIONS[session.shop] &&
    Date.now() - CACHED_SUBSCRIPTIONS[session.shop].timestamp < 1000 * 60 * 5) {
    return CACHED_SUBSCRIPTIONS[session.shop];
  }

  // get the active subscription from graphql
  const query = `#graphql
    {
      currentAppInstallation {
        activeSubscriptions {
          name
        }
      }
    }
  `;
  const {data} = await performQuery(session, query, {});

  // if there are no active subscriptions then return false
  if (data.currentAppInstallation.activeSubscriptions.length === 0) return false;

  // save current subscription in cache
  const subscription = {
    plan: data.currentAppInstallation.activeSubscriptions[0].name,
    timestamp: Date.now()
  }
  CACHED_SUBSCRIPTIONS[session.shop] = subscription;

  // return the current subscription
  return subscription;
}

Subsequently, in the app.jsx file, I perform a check to verify if there is an active subscription plan. If no active plan is found, the user is redirected to the managed charges page provided by Shopify:

export const loader = async ({ request }) => {
  const { session, redirect } = await authenticate.admin(request);

  const currentPlan = await getPlan(session);

  if (!currentPlan)
    throw redirect(
      `https://admin.shopify.com/store/${session.shop.replace(".myshopify.com", "")}/charges/${process.env.APP_HANDLE}/pricing_plans`,
      { target: "_parent" }
    );

  return json({ apiKey: process.env.SHOPIFY_API_KEY || "" });
};

Please note that the redirect I am utilizing comes from authenticate.admin, rather than directly from Remix.

I hope this information is helpful.