All Tutorials

Build a Shopify App with Node and React

Charge a fee using the Billing API

When you’re ready to list your app on the Shopify App Store, you’ll probably need a way to charge the merchants who install your app. You can do this by using the Billing API, which lets third-party app charges be added to a merchant’s monthly invoice. You can query the Billing API via the admin GraphQL endpoint, so you will implement it with fetch using isomporphic fetch in your server.js file.

Because merchants store their payment methods in Shopify, and we aim to provide a simple, streamlined billing experience, all apps that create charges must use the Shopify Billing API. It supports three different billing models:

  • one-time charges
  • 30-day recurring charges
  • usage charges, which charge a merchant based on a variable-value over a recurring 30-day period

Make calls to the Billing API

You’ll need to make an API call to redirect merchants to the billing screen in the Shopify admin. The call will need to come from your server.js file during the authentication process. The Billing API expects the following properties:

  • name - The name of your charge. For example, Sample embedded app 30-day fee.
  • price - The price of the recurring application charge.
  • The return URL - The URL where the merchant is sent after accepting or declining the charge.

The Billing API also has a test property that simulates successful charges.

Call the Billing API and redirect to the confirmation page

You will make a call to the GraphQL endpoint using a POST request, it will return the confirmation_url which you can redirect users to. You’ll set up a getSubscriptionUrl.js file to make the call and then await that in your server file.

  1. Create a server folder in your root project folder.
  2. Create a getSubscriptionUrl.js file in the server folder.
  3. Add the following scaffolding to get charges and check status:


    code contained in /server/getSubscriptionUrl.js
    const { default: Shopify } = require('@shopify/shopify-api'); const getSubscriptionUrl = async (accessToken, shop, returnUrl) => { const query = `mutation { appSubscriptionCreate( name: "Super Duper Plan" returnUrl: "${returnUrl}" test: true lineItems: [ { plan: { appUsagePricingDetails: { cappedAmount: { amount: 10, currencyCode: USD } terms: "$1 for 1000 emails" } } } { plan: { appRecurringPricingDetails: { price: { amount: 10, currencyCode: USD } } } } ] ) { userErrors { field message } confirmationUrl appSubscription { id } } }`; const client = new Shopify.Clients.Graphql(shop, accessToken); const response = await client.query({ data: query, }); return; }; module.exports = getSubscriptionUrl;
  4. In your server.js file, construct your return URL and pass it to getSubscriptionUrl:


    code contained in /server.js
    require('isomorphic-fetch'); const dotenv = require('dotenv'); const Koa = require('koa'); const next = require('next'); const { default: createShopifyAuth } = require('@shopify/koa-shopify-auth'); const { verifyRequest } = require('@shopify/koa-shopify-auth'); const session = require('koa-session'); const { default: Shopify, ApiVersion } = require('@shopify/shopify-api'); Add:const getSubscriptionUrl = require('./server/getSubscriptionUrl'); dotenv.config(); Shopify.Context.initialize({ API_KEY: process.env.SHOPIFY_API_KEY, API_SECRET_KEY: process.env.SHOPIFY_API_SECRET, SCOPES: process.env.SHOPIFY_API_SCOPES.split(","), HOST_NAME: process.env.SHOPIFY_APP_URL.replace(/https:\/\//, ""), API_VERSION: ApiVersion.October20, IS_EMBEDDED_APP: true, SESSION_STORAGE: new Shopify.Session.MemorySessionStorage(), }); const port = parseInt(process.env.PORT, 10) || 3000; const dev = process.env.NODE_ENV !== 'production'; const app = next({ dev }); const handle = app.getRequestHandler(); app.prepare().then(() => { const server = new Koa(); server.use(session({ secure: true, sameSite: 'none' }, server)); server.keys = [Shopify.Context.API_SECRET_KEY]; server.use( createShopifyAuth({ Remove: afterAuth(ctx) { Add: async afterAuth(ctx) { Remove: const { shop, scope } = ctx.state.shopify; Add: const { shop, scope, accessToken } = ctx.state.shopify; ACTIVE_SHOPIFY_SHOPS[shop] = scope; Remove: ctx.redirect(`/?shop=${shop}`); Add: const returnUrl = `https://${Shopify.Context.HOST_NAME}?shop=${shop}`; Add: const subscriptionUrl = await getSubscriptionUrl(accessToken, shop, returnUrl); Add: ctx.redirect(subscriptionUrl); }, }), );"/graphql", verifyRequest({returnHeader: true}), async (ctx, next) => { await Shopify.Utils.graphqlProxy(ctx.req, ctx.res); });

Create a test charge

Test your app charge from your development store to view the output and check its status.

  1. Stop and restart your server.
  2. In your development store’s Shopify admin, go to the Apps page, and then uninstall your app. Apps section of the development store Admin circling the sample embedded app's garbage icon
  3. Reinstall your app using the callback address:

    You should first be prompted to install the app, and then prompted separately to accept the test charges. The billing screen should look like this

    Billing charges screen
  4. Click Approve charges to accept the test charges.
  5. You should receive an email with a confirmation of the test charges.

    <span class="translation_missing" title="translation missing: en.build_a_shopify_app_with_node_and_react.charge_a_fee_using_the_billing_api.email_alt">Email Alt</span>
Continue to Listen for store events with Webhooks