Have your say in Community Polls: What was/is your greatest motivation to start your own business?
Our Partner & Developer boards on the community are moving to a brand new home: the .dev community forums! While you can still access past discussions here, for all your future app and storefront building questions, head over to the new forums.

Subscription charge expired different with

Subscription charge expired different with

AndyHung
Shopify Partner
63 0 16

Hi there,

Why this store install and upgrade to my plan Pro of our app, it is show expired with Subscription ID different Subscription ID activated? Our app has 14 trial days, when trial ends, it will auto billing ?

Thank you so much

 

AndyHung_1-1689851801623.png

 

Replies 4 (4)

jfkScollar
Shopify Partner
19 0 3

We are seeing this same message, Subscription charge expired, with two merchants now. We see dozens of entries appear all having the same time and date. Both are on the free version of our app. Were you able to determine why this is happening?

 

sherpabot
Shopify Partner
39 3 4

Has anyone made progress with this question? Since I am providing a free trial and certain stores have less volume than others, how can I ensure that the App still functions as expected when the trial ends? 

ClementOutis
Shopify Partner
25 4 14

Hi,

 

After discussing with the Shopify support for this case, it happens that the "Subscription Charge Expired" in this case is not really a problem.

 

A subscription charge is created when the merchant opens the page where he can accept the charge.

If he does, the charge is activated and we can see the line : "Subscription charge activated".

But if he does not accept it, the charge will be keeping in a temporary state for approximately two days. After that, this temporary charge will be set as expired.

 

So in your case @AndyHung we can imagine these steps :

  • The merchant installs the app
  • He goes to the charge page -> subscription n°1 created
  • He leaves this page
  • After a moment, he tries to access the app and he is redirect to the charge page -> subscription n°2 created
  • He accepts this charge -> subscription n°2 activated
  • After 2 days, Shopify will set the subscription n°1 to expire

 

Here is why we can have multiple charge expired at the same time.

 

And another thing, the ID of the subscription matters, if the merchant unistall your app (and by the way cancel the subscription), you will find the line "Subscription charge canceled" with the same ID as the line "Subscription charge activated".

 

Hope this response gonna help.

 

Regards

- Helpful? Like and Accept a solution
- Casper - Cart, sync and keep saved for a month your customer's cart across multiple device seamlessly.
- BrandCraft, give you all the keys to edit your checkout page, only for Shopify Plus with the Checkout Extensibility.
qfdeveloper
Shopify Partner
14 0 1

I am facing the same issue scribscription getting expired automatically after two days.
Can you please guide me about how could I fix this issue.
Here is the code where I have implemented the shopify billing api.

// @TS-nocheck
import React, { useCallback, useEffect, useState } from "react";
import { Button, Card, Frame, Page, Toast } from "@shopify/polaris";
import { authenticate, MONTHLY_PLAN } from "../shopify.server";
import { Form, useActionData } from "@remix-run/react";
import { json } from "@remix-run/node";

export async function action({ request }) {
    const { billing, admin } = await authenticate.admin(request);

    const result = await admin.graphql(`
        #graphql
        query Shop {
            app {
                installation {
                    activeSubscriptions {
                        status
                    }
                }
            }
        }
    `, { variables: {} });

    const resultJson = await result.json();
    const Subscriptionstatus = resultJson?resultJson.data.app.installation.activeSubscriptions[0]?.status:'';

    if (Subscriptionstatus !== "ACTIVE") {
        const billingCheck = await billing.require({
            plans: [MONTHLY_PLAN],
            isTest: false,
            onFailure: async () => billing.request({
                plan: MONTHLY_PLAN,
                isTest: false,
                returnUrl: '',
            }),
        });

        return json(billingCheck);
    }

    console.log("Subscription status: ", Subscriptionstatus);
    return json({ status: Subscriptionstatus });
}

const BillingComponent = () => {
    const [active, setActive] = useState(false);
    const data = useActionData();
    const subscriptionStatus = data ? data.status : '';

    useEffect(() => {
        if (subscriptionStatus === "ACTIVE") {
            setActive(true);
        }
    }, [subscriptionStatus]); // useEffect dependency

    const toggleActive = useCallback(() => setActive((active) => !active), []);

    const toastMarkup = active ? (
        <Toast content="You already have an active subscription" onDismiss={toggleActive} />
    ) : null;

    return (
        <Page title="Manage Subscription" narrowWidth backAction={{ content: '', url: '/app' }}>
            <Frame>
                <Card>
                    <Form method="post">
                        <div
                            style={{
                                textAlign: "center",
                                display: "flex",
                                flexDirection: "column",
                            }}
                        >
                            <h1 style={{ fontSize: "33px", marginBottom: "19px" }}>
                                Pricing Plan
                            </h1>
                            <span style={{ fontSize: "13px" }}>No additional charges</span>
                            <b>$4.99/month</b>
                            <span style={{ fontSize: "13px" }}>7 days free trial</span>
                            <div>
                                <Button primary submit>
                                    Choose Plan
                                </Button>
                                {toastMarkup}
                            </div>
                        </div>
                    </Form>
                </Card>
            </Frame>
        </Page>
    );
};

export default BillingComponent;


Here is the shopify.server.js file.
// @TS-nocheck
import "@shopify/shopify-app-remix/adapters/node";
import {
  AppDistribution,
  DeliveryMethod,
  shopifyApp,
  BillingInterval,
  LATEST_API_VERSION,
} from "@shopify/shopify-app-remix/server";
import { PrismaSessionStorage } from "@shopify/shopify-app-session-storage-prisma";
import { restResources } from "@shopify/shopify-api/rest/admin/2023-07";

import prisma from "./db.server";
export const MONTHLY_PLAN = 'Monthly subscription';
const shopify = shopifyApp({
  apiKey: process.env.SHOPIFY_API_KEY,
  apiSecretKey: process.env.SHOPIFY_API_SECRET || "",
  apiVersion: LATEST_API_VERSION,
  scopes: process.env.SCOPES?.split(","),
  appUrl: process.env.SHOPIFY_APP_URL || "",
  billing: {
    [MONTHLY_PLAN]: {
      amount: 4.99,
      currencyCode: 'USD',
      trialDays: 3,
      interval: BillingInterval.Every30Days,

    }
  },
  authPathPrefix: "/auth",
  sessionStorage: new PrismaSessionStorage(prisma),
  distribution: AppDistribution.AppStore,
  restResources,
  webhooks: {
    APP_UNINSTALLED: {
      deliveryMethod: DeliveryMethod.Http,
      callbackUrl: "/webhooks",
    },
  },
  hooks: {
    afterAuth: async ({ session }) => {
      shopify.registerWebhooks({ session });
    },
  },
  ...(process.env.SHOP_CUSTOM_DOMAIN
    ? { customShopDomains: [process.env.SHOP_CUSTOM_DOMAIN] }
    : {}),
});

export default shopify;
export const apiVersion = LATEST_API_VERSION;
export const addDocumentResponseHeaders = shopify.addDocumentResponseHeaders;
export const authenticate = shopify.authenticate;
export const unauthenticated = shopify.unauthenticated;
export const login = shopify.login;
export const registerWebhooks = shopify.registerWebhooks;
export const sessionStorage = shopify.sessionStorage;