Issue with hasActivePayment Returning true After App Reinstallation

Hello @KyleG-Shopify and everyone,

I’m encountering an issue with my Shopify app where the [hasActivePayment] flag remains true even after uninstalling and reinstalling the app. Ideally, when the app is uninstalled, the payment status should reset, and [hasActivePayment] should return false upon reinstallation.

Here’s the relevant code snippet from my loader function in [app.jsx]:

export const loader = async ({ request }) => {
  const { billing, session } = await authenticate.admin(request);
  const { shop } = session;
  const storeName = shop.replace(".myshopify.com", "");
  const { hasActivePayment, appSubscriptions } = await billing.check();
  console.log("hasActivePayment: ", hasActivePayment, appSubscriptions);

  if (!hasActivePayment) {
    const returnUrl = `https://admin.shopify.com/store/${storeName}/apps/${process.env.APP_NAME}`;
    const { userErrors, confirmationUrl } = await newSubscription({
      request,
      returnUrl,
    });
    if (userErrors?.length === 0 && userErrors && confirmationUrl) {
      return json({
        apiKey: process.env.SHOPIFY_API_KEY || "",
        bill: confirmationUrl,
      });
    }
  } else {
    updateSellerInstallHistory(shop, appSubscriptions);
  }

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

code snippets of newSubscription() is:

export async function newSubscription({ request, returnUrl }) {
  const { admin } = await authenticate.admin(request);
  const query = `mutation {
          appSubscriptionCreate(
            name: "Super Duper Capped Pricing Plan",
            returnUrl: "${returnUrl}",
            test: true,
            lineItems: [
              {
                plan: {
                  appUsagePricingDetails: {
                    terms: "$10 for 100 Orders",
                    cappedAmount: {
                      amount: 350.00,
                      currencyCode: USD
                    }
                  }
                }
              },
              {
                plan: {
                  appRecurringPricingDetails: {
                    price: {
                      amount: 12.00,
                      currencyCode: USD
                    }
                  }
                }
              }
            ]
          ) {
            userErrors {
              field,
              message
            },
            confirmationUrl,
            appSubscription {
              id,
              lineItems {
                id,
                plan {
                  pricingDetails {
                    __typename
                  }
                }
              }
            }
          }
        }`;
  const response = await admin.graphql(query);
  const responseJson = await response.json();

  return {
    confirmationUrl: responseJson?.data?.appSubscriptionCreate?.confirmationUrl,
    userErrors: responseJson?.data?.appSubscriptionCreate?.userErrors,
    appSubscription: responseJson?.data?.appSubscriptionCreate?.appSubscription,
  };
}

When the app is reinstalled, the [billing.check()] method still detects an active subscription, even though the app was previously uninstalled. This behavior causes the app to skip the subscription flow, which is not the desired outcome.

Steps I’ve Taken:

  1. Verified that the uninstall webhook is triggered and the merchant’s data is updated in the database.
  2. Checked the [billing.check()] logic to confirm it’s fetching the correct subscription status.

Questions:

  • Is there a specific step I’m missing to reset the subscription status upon app uninstallation?
  • Should I explicitly cancel the subscription in the uninstall webhook?
  • Is there a better way to handle this scenario to ensure [hasActivePayment] is reset correctly?

Any insights or suggestions would be greatly appreciated!

Thanks in advance!

2 Likes

Sounds like potentially a bug in the underlying billing module.

An alternative is to make a Admin GraphQL query for the current active subscription (s)and make sure at least one is active active:

  {
    appInstallation {
      activeSubscriptions {
        id
        name
        createdAt
        status
        test
      }
    }
  }
1 Like

Hey @adarsh_anncode,

Are you uninstalling and reinstalling in the same billing cycle? The reason I ask is that would be expected. From our docs:

When an app is uninstalled, Shopify automatically cancels the subscription. A credit isn’t applied to cover the cost of the rest of the billing period. Merchants can reinstall and use the app for the remainder of the billing period.

What Dylan suggests should work to check if the current subscription is active or cancelled and then request billing. Alternatively, to simplify the process, you could just force the billing page on all installations and use the AppSubscriptionReplacementBehavior to determine how to replace the current charge.

Let me know if any of that will work.

2 Likes

Nice, I had no idea AppSubscriptionReplacementBehavior was a thing!

Thanks for sharing that.

2 Likes

Yes @KyleG-Shopify, you are right. But regarding the test charge, it should work. As for the AppSubscriptionReplacementBehavior, I haven’t checked it on my side yet. It looks a bit off, but I will definitely give it a try. I’ll let you know if it works well.

It works for my scenario for now, but I’ll need something more reliable in the long run. Nevertheless, thanks! @Dylan

1 Like

Hey folks,

This has been flagged to the relevant product team, but since there’s a workaround I’ll mark this as solved.

1 Like