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 make 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.

Set up a test return URL

You’ll use your ngrok URL as the return URL while testing your app’s billing process. In a production app you would use your production URL for the return URL.

  1. Add the HTTPS version of your ngrok forwarding URL and your API version to your .env file:

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 getSubscriptionUrl = async (ctx, accessToken, shop) => { const query = JSON.stringify({ query: `mutation { appSubscriptionCreate( name: "Super Duper Plan" returnUrl: "${process.env.HOST}" 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 response = await fetch(`https://${shop}/admin/api/2019-10/graphql.json`, { method: 'POST', headers: { 'Content-Type': 'application/json', "X-Shopify-Access-Token": accessToken, }, body: query }) const responseJson = await response.json(); const confirmationUrl = return ctx.redirect(confirmationUrl) }; module.exports = getSubscriptionUrl;
  4. In your server.js file, add the call 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'); dotenv.config(); const { default: graphQLProxy } = require('@shopify/koa-shopify-graphql-proxy'); const { ApiVersion } = require('@shopify/koa-shopify-graphql-proxy'); Add: const getSubscriptionUrl = require('./server/getSubscriptionUrl'); const port = parseInt(process.env.PORT, 10) || 3000; const dev = process.env.NODE_ENV !== 'production'; const app = next({ dev }); const handle = app.getRequestHandler(); const { SHOPIFY_API_SECRET_KEY, SHOPIFY_API_KEY, API_VERSION } = process.env; app.prepare().then(() => { const server = new Koa(); server.use(session({ secure: true, sameSite: 'none' }, server)); server.keys = [SHOPIFY_API_SECRET_KEY]; server.use( createShopifyAuth({ apiKey: SHOPIFY_API_KEY, secret: SHOPIFY_API_SECRET_KEY, scopes: ['write_products', 'read_products'], Remove: afterAuth(ctx) { Add: async afterAuth(ctx) { const { shop, accessToken } = ctx.session; ctx.cookies.set('shopOrigin', shop, { httpOnly: false secure: true, sameSite: 'none' }); Remove: ctx.redirect('/'); Add: await getSubscriptionUrl(ctx, accessToken, shop); }, }), ); server.use(graphQLProxy({version: ApiVersion.October19})) server.use(verifyRequest()); server.use(async (ctx) => { await handle(ctx.req, ctx.res); ctx.respond = false; ctx.res.statusCode = 200; return }); server.listen(port, () => { console.log(`> Ready on http://localhost:${port}`); }); });

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.

    email alt
Continue to Listen for store events with Webhooks