Contains function used to bill merchants for your app. This object is returned on authenticated Admin requests.
Provides utilities that apps can use to request billing for the app using the Admin API.
Checks if the shop has an active payment for any plan defined in the `billing` config option.
Checks if the shop has an active payment for any plan defined in the `billing` config option.
Requests payment for the plan.
Cancels an ongoing subscription, given its ID.
The plans to check for. Must be one of the values defined in the `billing` config option.
How to handle the request if the shop doesn't have an active payment for any plan.
Whether to consider test purchases.
Whether the user has an active payment method.
The one-time purchases the shop has.
The active subscriptions the shop has.
The ID of the one-time purchase.
The name of the purchased plan.
Whether this is a test purchase.
The status of the one-time purchase.
The ID of the app subscription.
The name of the purchased plan.
Whether this is a test subscription.
BillingConfigSubscriptionPlanDiscountAmount | BillingConfigSubscriptionPlanDiscountPercentage
The amount to discount. Cannot be set if `percentage` is set.
The percentage to discount. Cannot be set if `amount` is set.
The amount to discount. Cannot be set if `percentage` is set.
The percentage to discount. Cannot be set if `amount` is set.
The plans to check for. Must be one of the values defined in the `billing` config option.
Whether to consider test purchases.
The plan to request. Must be one of the values defined in the `billing` config option.
Whether to use the test mode. This prevents the credit card from being charged. Test shops and demo shops cannot be charged.
The URL to return to after the merchant approves the payment.
The ID of the subscription to cancel.
Whether to prorate the cancellation.
Contains function used to bill merchants for your app. This object is returned on authenticated Admin requests.
import { LoaderFunctionArgs } from "@remix-run/node";
import { authenticate, MONTHLY_PLAN } from "../shopify.server";
export const loader = async ({ request }: LoaderFunctionArgs) => {
const { billing } = await authenticate.admin(request);
await billing.require({
plans: [MONTHLY_PLAN],
isTest: true,
onFailure: async () => billing.request({ plan: MONTHLY_PLAN }),
});
// App logic
};
import { shopifyApp, BillingInterval } from "@shopify/shopify-app-remix/server";
export const MONTHLY_PLAN = 'Monthly subscription';
export const ANNUAL_PLAN = 'Annual subscription';
const shopify = shopifyApp({
// ...etc
billing: {
[MONTHLY_PLAN]: {
amount: 5,
currencyCode: 'USD',
interval: BillingInterval.Every30Days,
},
[ANNUAL_PLAN]: {
amount: 50,
currencyCode: 'USD',
interval: BillingInterval.Annual,
},
}
});
export default shopify;
export const authenticate = shopify.authenticate;
import { LoaderFunctionArgs, redirect } from "@remix-run/node";
import { authenticate, MONTHLY_PLAN, ANNUAL_PLAN } from "../shopify.server";
export const loader = async ({ request }: LoaderFunctionArgs) => {
const { billing } = await authenticate.admin(request);
const billingCheck = await billing.require({
plans: [MONTHLY_PLAN, ANNUAL_PLAN],
isTest: true,
onFailure: () => redirect('/select-plan'),
});
const subscription = billingCheck.appSubscriptions[0];
console.log(`Shop is on ${subscription.name} (id ${subscription.id})`);
// App logic
};
import { shopifyApp, BillingInterval } from "@shopify/shopify-app-remix/server";
export const MONTHLY_PLAN = 'Monthly subscription';
export const ANNUAL_PLAN = 'Annual subscription';
const shopify = shopifyApp({
// ...etc
billing: {
[MONTHLY_PLAN]: {
amount: 5,
currencyCode: 'USD',
interval: BillingInterval.Every30Days,
},
[ANNUAL_PLAN]: {
amount: 50,
currencyCode: 'USD',
interval: BillingInterval.Annual,
},
}
});
export default shopify;
export const authenticate = shopify.authenticate;
import { LoaderFunctionArgs } from "@remix-run/node";
import { authenticate, MONTHLY_PLAN } from "../shopify.server";
export const loader = async ({ request }: LoaderFunctionArgs) => {
const { billing } = await authenticate.admin(request);
await billing.require({
plans: [MONTHLY_PLAN],
isTest: true,
onFailure: async () => billing.request({ plan: MONTHLY_PLAN }),
});
// App logic
};
import { shopifyApp, BillingInterval } from "@shopify/shopify-app-remix/server";
export const MONTHLY_PLAN = 'Monthly subscription';
export const ANNUAL_PLAN = 'Annual subscription';
const shopify = shopifyApp({
// ...etc
billing: {
[MONTHLY_PLAN]: {
lineItems: [
{
amount: 5,
currencyCode: 'USD',
interval: BillingInterval.Every30Days,
},
{
amount: 1,
currencyCode: 'USD',
interval: BillingInterval.Usage.
terms: '1 dollar per 1000 emails',
},
],
},
}
future: {v3_lineItemBilling: true}
});
export default shopify;
export const authenticate = shopify.authenticate;
import { LoaderFunctionArgs } from "@remix-run/node";
import { authenticate, MONTHLY_PLAN } from "../shopify.server";
export const loader = async ({ request }: LoaderFunctionArgs) => {
const { billing } = await authenticate.admin(request);
const { hasActivePayment, appSubscriptions } = await billing.check({
plans: [MONTHLY_PLAN],
isTest: false,
});
console.log(hasActivePayment)
console.log(appSubscriptions)
};
import { shopifyApp, BillingInterval } from "@shopify/shopify-app-remix/server";
export const MONTHLY_PLAN = 'Monthly subscription';
export const ANNUAL_PLAN = 'Annual subscription';
const shopify = shopifyApp({
// ...etc
billing: {
[MONTHLY_PLAN]: {
amount: 5,
currencyCode: 'USD',
interval: BillingInterval.Every30Days,
},
[ANNUAL_PLAN]: {
amount: 50,
currencyCode: 'USD',
interval: BillingInterval.Annual,
},
}
});
export default shopify;
export const authenticate = shopify.authenticate;
import { LoaderFunctionArgs } from "@remix-run/node";
import { authenticate, MONTHLY_PLAN } from "../shopify.server";
export const loader = async ({ request }: LoaderFunctionArgs) => {
const { billing } = await authenticate.admin(request);
await billing.require({
plans: [MONTHLY_PLAN],
onFailure: async () => billing.request({
plan: MONTHLY_PLAN,
isTest: true,
returnUrl: 'https://admin.shopify.com/store/my-store/apps/my-app/billing-page',
}),
});
// App logic
};
import { shopifyApp, BillingInterval } from "@shopify/shopify-app-remix/server";
export const MONTHLY_PLAN = 'Monthly subscription';
export const ANNUAL_PLAN = 'Annual subscription';
const shopify = shopifyApp({
// ...etc
billing: {
[MONTHLY_PLAN]: {
amount: 5,
currencyCode: 'USD',
interval: BillingInterval.Every30Days,
},
[ANNUAL_PLAN]: {
amount: 50,
currencyCode: 'USD',
interval: BillingInterval.Annual,
},
}
});
export default shopify;
export const authenticate = shopify.authenticate;
import { LoaderFunctionArgs } from "@remix-run/node";
import { authenticate, MONTHLY_PLAN } from "../shopify.server";
export const loader = async ({ request }: LoaderFunctionArgs) => {
const { billing } = await authenticate.admin(request);
const billingCheck = await billing.require({
plans: [MONTHLY_PLAN],
onFailure: async () => billing.request({ plan: MONTHLY_PLAN }),
});
const subscription = billingCheck.appSubscriptions[0];
const cancelledSubscription = await billing.cancel({
subscriptionId: subscription.id,
isTest: true,
prorate: true,
});
// App logic
};
import { shopifyApp, BillingInterval } from "@shopify/shopify-app-remix/server";
export const MONTHLY_PLAN = 'Monthly subscription';
export const ANNUAL_PLAN = 'Annual subscription';
const shopify = shopifyApp({
// ...etc
billing: {
[MONTHLY_PLAN]: {
amount: 5,
currencyCode: 'USD',
interval: BillingInterval.Every30Days,
},
[ANNUAL_PLAN]: {
amount: 50,
currencyCode: 'USD',
interval: BillingInterval.Annual,
},
}
});
export default shopify;
export const authenticate = shopify.authenticate;