Shopify Remix Billing Stuck in Loop

Hey Guys, I built my app using shopify remix template. I have the above code setup for request billing. When isTest is true, the code works fine:

  1. User installs the app.
  2. Get redirected to app’s main page – and the billing is requested.
  3. User makes the payment and the main page is visible.

But when the isTest is set to false, The app gets stuck in a loop.

  1. User installs the app.
  2. Gets redirected to app’s main page – and the billing is requested.
  3. Even after user approves the payment, he is redirected back to the billing page.

My app is currently in review and this is the main issue I have from getting it published. Any idea how to fix this?

Try adding a custom return url so you redirect to a “confirm page” or even your app billing/home page.

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

  await billing.require({
    plans: [ONE_TIME_PURCHASE],
    isTest: false,
    onFailure: async () => billing.request({ plan: ONE_TIME_PURCHASE,
      returnUrl: '/billing-complete' }),
  });

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

I updated my code to this :

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

const { oneTimePurchases } = await billing.check({
plans: [ONE_TIME_PURCHASE],
isTest: false,
});

if (oneTimePurchases.length === 0) {
await billing.require({
plans: [ONE_TIME_PURCHASE],
isTest: false,
onFailure: async () =>
billing.request({ plan: ONE_TIME_PURCHASE, isTest: false }),
returnUrl: https://${shop}/admin/apps/playground-52/app,
});
}

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

still have the same issue. no idea why.

I had this same problem. It solved itself when I removed the billing.check and just used the billing.require with billing.request like this:

const billingCheck = await billing.require({
    plans: [MONTHLY_PLAN, ANNUAL_PLAN],
    isTest: false,
    onFailure: async () => billing.request({ plan: MONTHLY_PLAN, isTest: false }),
  });
1 Like