Installation

Getting started

Installation

Install and configure the package using the following command :

node ace add @foadonis/shopkeeper
  1. Installs the @foadonis/shopkeeper package using the detected package manager.

  2. Registers the following service provider inside the adonisrc.ts file.

    {
    providers: [
    // ...other providers
    () => import('@foadonis/shopkeeper/providers/shopkeeper')
    ]
    }
  3. Creates the config/shopkeeper.ts file.

  4. Defines the environment variables to store STRIPE_KEY, STRIPE_SECRET and STRIPE_WEBHOOK_SECRET.

  5. Creates the database migrations files for the tables users, suscriptions and subscription_items.

Then migrate your database:

node ace migration:run

Shopkeeper's migrations will add several columns to your users table. They will also create a new subscriptions table to hold all of your customer's subscriptions and a subscription_items table for subscriptions with multiple prices.

Lastly, to ensure Shopkeeper properly handles all Stripe events, remember to configure Shopkeeper's webhook handling.

Configuration

Billable Model

Before using Shopkeeper, add the Billable mixin to your billable model definition. Typically, this will be the User model. This trait provides various methods to allow you to perform common billing tasks, such as creating subscriptions, applying coupons, and updating payment method information:

app/models/user.ts
import { compose } from '@adonisjs/core/helpers'
import { BaseModel } from '@adonisjs/lucid/orm'
import { Billable } from '@foadonis/shopkeeper/mixins'
export default class User extends compose(BaseModel, Billable) {}

In your Shopkeeper configuration file, define your User as the Customer model:

config/shopkeeper.ts
import { defineConfig } from '@foadonis/shopkeeper'
export default defineConfig({
customerModel: () => import('#models/user')
...
})

When using a model with a different name than User, make sure to change the table name in the generated migration.

API Keys

Next, you should configure your Stripe API keys in your application's .env file. You can retrieve your Stripe API keys from the Stripe control panel:

.env
STRIPE_KEY=your-stripe-key
STRIPE_SECRET=your-stripe-secret
STRIPE_WEBHOOK_SECRET=your-stripe-webhook-secret

[!WARNING]
You should ensure that the STRIPE_WEBHOOK_SECRET environment variable is defined in your application's .env file, as this variable is used to ensure that incoming webhooks are actually from Stripe.

Currency Configuration

The default Shopkeeper currency is United States Dollars (USD). You can change the default currency by setting the SHOPKEEPER_CURRENCY environment variable within your application's .env file:

.env
SHOPKEEPER_CURRENCY=eur

In addition to configuring Shopkeeper's currency, you may also specify a locale to be used when formatting money values for display on invoices. Internally, Shopkeeper utilizes Intl.NumberFormat to set the currency locale:

.env
SHOPKEEPER_CURRENCY_LOCALE=de-DE

Tax Configuration

Thanks to Stripe Tax, it's possible to automatically calculate taxes for all invoices generated by Stripe. You can enable automatic tax calculation by setting calculateTaxes option to true in the Shopkeeper's configuration file:

config/shopkeeper.ts
import { defineConfig } from '@foadonis/shopkeeper'
export default defineConfig({
calculateTaxes: true
...
})

Once tax calculation has been enabled, any new subscriptions and any one-off invoices that are generated will receive automatic tax calculation.

For this feature to work properly, your customer's billing details, such as the customer's name, address, and tax ID, need to be synced to Stripe. You may use the customer data synchronization and Tax ID methods offered by Shopkeeper to accomplish this.

Using custom models

You are free to extend the models used internally by Shopkeeper by defining your own model and extending the corresponding Shopkeeper model:

app/models/user.ts
import { Subscription as ShopkeeperSubscription } from '@foadonis/shopkeeper/models'
export default class Subscription extends ShopkeeperSubscription {
// ...
}

After defining your model, you may instruct Shopkeeper to use your custom model via the configuration file:

config/shopkeeper.ts
import { defineConfig } from '@foadonis/shopkeeper'
export default defineConfig({
subscriptionModel: () => import('#models/subscription')
subscriptionItemModel: () => import('#models/subscription_item')
...
})