---
title: "Pay with store credit — Shops for Laravel | Roundly"
description: "Let buyers pay all or part of an order from a currency-denominated credits bucket, and refund orders back as store credit."
url: https://roundly-consulting.com/open-source/docs/shops-for-laravel/store-credit
language: en
---

[All packages](https://roundly-consulting.com/open-source.md)

[Shops for Laravel](https://roundly-consulting.com/open-source/docs/shops-for-laravel.md)

# Pay with store credit

With credits-for-laravel, buyers can pay all or part of an order from a store-credit bucket denominated in the order’s currency. Map the bucket and switch the tender on:

```php
// config/credits.php — denominate the bucket in your shop currency (one bucket per currency)
'currencies' => ['store_credit' => 'EUR'],
```

```bash
SHOPS_ALLOW_STORE_CREDIT=true
SHOPS_STORE_CREDIT_BUCKET=store_credit
SHOPS_REFUND_TO_STORE_CREDIT=false
```

The buyer model must implement credits’ RoundlyConsulting\\Credits\\Interfaces\\Creditable and use its HasCredits trait — the trait alone is not enough: an order whose customer is not Creditable is charged in full through the gateway, with no credit applied:

```php
use Illuminate\Foundation\Auth\User as Authenticatable;
use RoundlyConsulting\Credits\Interfaces\Creditable;
use RoundlyConsulting\Credits\Traits\HasCredits;

class User extends Authenticatable implements Creditable
{
    use HasCredits;
}
```

## Applying credit

With allow\_store\_credit on, Shops::order($order)->charge() debits available credit before charging the gateway for the remainder ($order->gatewayAmount()). An order that credit covers in full is marked paid without a gateway charge:

```php
use RoundlyConsulting\Money\Money;
use RoundlyConsulting\Shops\Facades\Shops;
use RoundlyConsulting\Shops\Payments\StoreCreditTender;

// Automatic: with allow_store_credit on, credit goes first and the gateway gets the rest.
$result = Shops::order($order)->charge();

// Or apply it yourself (once per order):
$owed = app(StoreCreditTender::class)->apply($order, $customer);                              // as much as possible
$owed = app(StoreCreditTender::class)->apply($order, $customer, Money::ofMinor(500, 'EUR')); // or cap the debit

$order->store_credit_applied;   // ?Money, in the order currency
$order->gatewayAmount();        // what is still due through the gateway

app(StoreCreditTender::class)->restore($order);   // ?Money — hand it back (cancel() does this)
```

- apply() debits the smallest of the order total, the bucket balance and your cap, records it on store\_credit\_applied and returns what is still owed — in one transaction.
- A zero applicable amount changes nothing and returns the full total.
- A declined charge keeps none of the credit it applied — the whole charge rolls back — and canceling an order returns any credit applied to it, also credit you applied yourself with apply(). restore() hands it back on demand; a second call returns nothing.
- StoreCreditAlreadyAppliedException — credit was already applied to this order (re-checked under the order’s row lock).
- StoreCreditBucketNotDenominated — the bucket has no currency in credits.currencies.
- StoreCreditCurrencyMismatch — the bucket is in another currency. All three throw before any credit moves.

## Refunding as store credit

With payment.refund\_to\_store\_credit on, the GrantStoreCreditOnRefund listener credits the order’s whole final price back to the bucket when the order is refunded — so skip the gateway refund, or the buyer is refunded twice. It does nothing without a Creditable customer or a positive total; a bucket that is undenominated or in another currency is skipped with a Log::warning() instead of throwing, since the refund already happened.

## Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

[More ways to support, including crypto](https://roundly-consulting.com/support-us.md)

By donating, you agree to our [donation terms](https://roundly-consulting.com/donation-terms.md).

[Support our open source work (opens in a new tab)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Join us on Patreon (opens in a new tab)](https://www.patreon.com/cw/roundly)

## Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.

[Get a quote in 48 hours](https://roundly-consulting.com/contact.md) [Browse all packages](https://roundly-consulting.com/open-source/docs/shops-for-laravel.md)
