Credit types in Spike

Spike works best when selling credits which users can then consume when using the app. Sometimes you may have different areas of usage in your app, and you might want to spend different types of credits in each area. A typical example would be sending emails and SMS. You might want to give different amounts of credits for email and SMS because of their different costs to you as a business. That's where credit types come in.

Configuration

First, once you decide what types of credits you would like to sell, you can define them in config/spike.php, like so:

    /*
    |--------------------------------------------------------------------------
    | Credit types
    |--------------------------------------------------------------------------
    |
    | You can have multiple types of credits that you can sell and use,
    | like API credits, SMS, emails, etc. Here you can configure the
    | different credit types that will be available for users.
    |
    */

    'credit_types' => [
        [
            // ID is used when referencing the credit type in the code, i.e. `$user->credits('sms')->balance()`.
            'id' => 'credits',

            // The translation key with inflection to use for this credit type.
            'translation_key' => 'spike::translations.credits',

            // The icon for credit type. Leaving this `null` will use the default icon (coins).
            // Accepted values are: URL string (absolute or relative), SVG string, or null.
            'icon' => null,
            
            // When a credit type is allowed to have a negative balance, Spike will automatically charge for
            // negative balances every month. This price should represent a single credit of this type.
            'payment_provider_price_id' => null,
        ],

        // [
        //     'id' => 'sms',
        //     'translation_key' => 'app.sms',
        //     'icon' => null,
        //     'payment_provider_price_id' => null,
        // ],
    ],
propertytypedescription
idstringThe identifier for this credit type. Used in various places, such as $user->credits($id)->balance()
translation_keystringThe path to the translation which describes this credit type. It should include both singular and plural translations separated with the pipe symbol, i.e. credit|credits
iconURL string, SVG string, or nullThe icon displayed in the UI for this credit type.
payment_provider_price_idstring or nullStripe price ID for a single credit of this type. Only used when charging for negative balances (see below)

Negative balances

By default, negative credit balances are not allowed, and will throw a NotEnoughBalanceException when trying to spend credits you don't have.

If you'd like, you can allow negative balances on all or select credit types by using the Credits facade in your AppServiceProvider::boot() method, like so:

use Opcodes\Spike\Facades\Credits;

public function boot()
{
    // This will allow negative balances on all credit types
    Credits::allowNegativeBalance();
    
    // Optionally, provide a callback. Billable can be null
    Credits::allowNegativeBalance(function ($creditType, $billable = null) {
        return $creditType->type === 'sms';
    });
    
    // You can also scope it to a certain credit type
    Credits::type('sms')->allowNegativeBalance();
    
    // Another example, perhaps you want to ensure that billables have an
    // active subscription in order to accrue negative balances:
    Credits::allowNegativeBalance(function ($creditType, $billable = null) {
        return $billable?->isSubscribed();
    });
}

If you also provide the payment_provider_price_id value in the configuration of the credit type, and you use Stripe payment provider, Spike will automatically charge for the negative balances once a month when running the scheduled spike:renew-subscription-providables command.

Preventing automatic charges for negative balances

If you have a credit type (or a few) that you want to let go into negative and not get charged for, you can disable auto-charging behaviour for each specific credit type. Simply update config/spike.php file for that specific credit type:

    'credit_types' => [
        [
            'id' => 'credits',
            // ...
            
            'charge_negative_balances' => false,
        ],

Empty balances in the UI

Sometimes you may have too many credit types to display them in the billing portal, and most of them will have zero value.

You can hide credit types from the user if they do not have any balance for them. To do that, look at the theme section in the config/spike.php configuration:

    'theme' => [
        // ...

        // Whether to display zero values for credit types that the user did not yet purchase.
        'display_empty_credit_balances' => false,
    ],

Using multiple types of credits

To learn how to spend, adjust, or sell the different types of credits, click one of these links:

Support

If you have any questions, feedback, or need any help setting up Spike within your project, feel free to reach out to me.