ExShopifyApp.Billing (ex_shopify_app v1.2.0)

Shopify-native billing plumbing.

This is the library's billing entry point. It provides the reusable pieces of a Shopify App Pricing integration and leaves the per-app policy to the host:

Metered usage is reported through ExShopifyApp.AppEvents, which lives in its own namespace: the App Events API is billing-agnostic (meters can be billing or tracking-only), so billing uses it but does not own it. See docs/APP_EVENTS.md.

Library vs host responsibilities

The library does not model your plans. The plan catalog (allowances, prices, upgrade rules), what each meter counts, the meter handles, how usage is counted, the idempotency-key strategy, and scheduling all stay in the host app.

Usage is reported against meters configured on the app's Shopify pricing plans, keyed by event_handle (which must match a meter handle exactly). Meters fall into two kinds, by convention:

  • billing meters - the reported value drives the merchant's metered charge. Shopify sums events within a billing cycle and permanently dedupes them on the idempotency key, so the key must be stable: a retry must reuse the same key to avoid double-charging. How you report is up to you — e.g. one unit per chargeable action keyed by that action's id, or a periodic total keyed to the billing cycle (e.g. the subscription's current_period_end). See docs/BILLING.md.
  • tracking-only meters - reported for visibility and not billed.

Docs:

Summary

Functions

Fetches the merchant's active Shopify subscription.

Builds the Shopify-hosted App Pricing page URL the merchant uses to choose or change plans.

Functions

fetch_active_subscription(shop)

@spec fetch_active_subscription(ExShopifyApp.Shop.authorized()) ::
  {:ok, ExShopifyApp.Billing.Subscription.t()} | {:error, term()}

Fetches the merchant's active Shopify subscription.

pricing_url(map, app_handle)

@spec pricing_url(ExShopifyApp.Shop.t(), String.t()) :: String.t()

Builds the Shopify-hosted App Pricing page URL the merchant uses to choose or change plans.

app_handle is the app's handle (e.g. "my-app"); shop carries the :shopify_domain the store handle is derived from.

See https://shopify.dev/docs/apps/launch/billing/shopify-app-pricing#plan-selection-page.

Examples

iex> ExShopifyApp.Billing.pricing_url(%{shopify_domain: "acme.myshopify.com"}, "my-app")
"https://admin.shopify.com/store/acme/charges/my-app/pricing_plans"