PHPackages                             clippings/purchases - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. clippings/purchases

AbandonedArchivedLibrary

clippings/purchases
===================

Multi-Store Marketplace Core Components

0.1.0(11y ago)032BSD-3-ClausePHP

Since Aug 28Pushed 11y agoCompare

[ Source](https://github.com/clippings/purchases)[ Packagist](https://packagist.org/packages/clippings/purchases)[ RSS](/packages/clippings-purchases/feed)WikiDiscussions master Synced today

READMEChangelog (1)Dependencies (6)Versions (2)Used By (0)

Purchases
=========

[](#purchases)

[![Build Status](https://camo.githubusercontent.com/c68cf6e18c9d2fe06790dd4c3ec16c20ad3602933d36dc97b00709fa844932d9/68747470733a2f2f7472617669732d63692e6f72672f636c697070696e67732f7075726368617365732e706e673f6272616e63683d6d6173746572)](https://travis-ci.org/clippings/purchases)[![Scrutinizer Code Quality](https://camo.githubusercontent.com/8d4be2615d7d160aa2cd467ecad5377b1ad8122fd884108977ac1514d64ce055/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f636c697070696e67732f7075726368617365732f6261646765732f7175616c6974792d73636f72652e706e67)](https://scrutinizer-ci.com/g/clippings/purchases/)[![Code Coverage](https://camo.githubusercontent.com/4ee5556214e4b357dac8df6c14698865677bdf1f7abae31e78c6b141f1837332/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f636c697070696e67732f7075726368617365732f6261646765732f636f7665726167652e706e67)](https://scrutinizer-ci.com/g/clippings/purchases/)[![Latest Stable Version](https://camo.githubusercontent.com/ed58ede9627c1e8e81aba5d31fbee2fbc852a7b3baf28631048c41354c9b7a0c/68747470733a2f2f706f7365722e707567782e6f72672f636c697070696e67732f7075726368617365732f762f737461626c652e706e67)](https://packagist.org/packages/clippings/purchases)

This is a Kohana module that gives you out of the box functionality for multi-store purchases (each purchase may have Items from different sellers, each handling their portion of products independently)

It utilizes omnipay package

Usage
-----

[](#usage)

The provided models work out of the box. You'll also have "Product" and "Store" models that you should use and extend.

```
// Initialize some products and stores.
$store1 = new Store(['name' => 'My First Store']);
$product1 = new Product(['name' => 'My First Product', 'currency' => 'GBP', 'value' => 2000]);
$product2 = new Product(['name' => 'My Second Product', 'currency' => 'EUR', 'value' => 1000]);

$store1->getProducts()
    ->add($product1)
    ->add($product2);

$store2 = new Store(['name' => 'My Second Store']);
$product3 = new Product(['name' => 'My Third Product', 'currency' => 'GBP', 'value' => 5000]);

$store2->getProducts()
    ->add($product3);

Store::saveArray([$store1, $store2]);

// Now we can purchase something
$purchase = new Purchase();
$purchase
    ->addProduct($product1)
    ->addProduct($product2)
    ->addProduct($product3, 2);

// Freeze all the values of the order,
// so that it remains "frozen", even if prices of products change
$purchase->freeze();

// Initialize omnipay getway - here you will have Paypal, Stripe etc.
$gateway = Omnipay::getFactory()->create('Dummy');

$parameters = [
    'card' => [
        'number' => '4242424242424242',
        'expiryMonth' => 7,
        'expiryYear' => 2014,
        'cvv' => 123,
    ],
    'clientIp' => '192.168.0.1',
];

$response = $purchase->purchase($gateway, $parameters);

echo $response->isSuccessful();
```

A diagram of the models
-----------------------

[](#a-diagram-of-the-models)

```
┌─────────┐   ┌──────────┐    ┌───────┐
│ Address ├──→│ Purchase │    │ Store │
└─────────┘   └─┬─────┬──┘    └─┬─────┘
                │     ↓         ↓
                │ ┌───────────────┐
                │ │ StorePurchase │
                │ └───────┬───────┘
                │         ↓
                │     ┌──────────────┐
                └────→│ PurchaseItem │
┌─────────┐           ├──────────────┤
│ Product ├──────────→│ ProductItem  │
└─────────┘           └──────────────┘

```

Purchase is comprised of "PurchaseItems", a model which holds all the items that the user purchases.ProductItem exteds PurchaseItem so that they share the same table, using IheritedTrait.

Each PurchaseItem however, also belongs to a "StorePurchase" model, that represents the purchase for a specific store. This relation is managed automatically when you add products via the "addProduct" method or addPurchaseItem

Adding items to a purchase
--------------------------

[](#adding-items-to-a-purchase)

```
$purchase = new Purchase();

// Adding a product
$purchase->addProduct($product);

// Adding multiple products
$purchase->addProduct($product, 5);
```

As the product already belongs to a specific store, this will create a specific StorePurchase for that store, if none exists. otherwise it will add the item to the existing StorePurchase. If this product already is present in the form of ProductItem, then it will increment the quantity.

```
$purchase = new Purchase();

// Adding a purchaseItem
$purchase->addPurchaseItem($store, $purchaseItem);
```

If you need to add some other type of purchase item, that does not have an intrinsic relationship with a store, you can use the addPurchaseItem method. It will add any type of PurchaseItem.

Freezing assets
---------------

[](#freezing-assets)

Since purchases use [harp-orm/transfers](https://github.com/clippings/transfers) package, it has the ability to "freeze" the values of purchase items when a purchase is actually completed.

```
$purchase = new Purchase();
$product = new Product(['price' => 100]);

$purchase->addProduct($product, 3);

$productItem = $purchase->getItems()->getFirst();

// This will return the value of the product * quantity
// In this case 300
echo $productItem->getValue();

// Perform a freeze:
$purchase->freeze();

$product->price = 4000;

// Will still be 300
echo $productItem->getValue();
```

Freezing works by setting an "isFrozen" flag explicitly, so that later calls on `freeze()` will not recalculate values. You can take advantage of this by explicitly setting this flag to false for specific items and calling `freeze()` againg, to "refreeze" those values.

If you freeze a Purchase all the related PurchaseItems and StorePurchases will be frozen alongside it.

Currency Calculatens
--------------------

[](#currency-calculatens)

Purchases have a "currency" value that all the purchase items use. Any products with different currency will be converted using [harp-orm/money](https://github.com/harp-orm/money). That's why purchase items will not function properly, until they are attached to a purchase, which holds the currency for them.

```
$purchase = new Purchase(['currency' => 'GBP']);
$product = new Product(['price' => 100, 'currency' => 'EUR']);

$purchase->addProduct($product, 3);

$productItem = $purchase->getItems()->getFirst();

// This will not 300, but convert it to GBP (around 240)
echo $productItem->getValue();
```

Refunding
---------

[](#refunding)

You can refund individual store purchases in full or with a partial amount.

```
$purchase = Purchase::find(1);
$storePurchase = $purchase->getStorePurchases()->getFirst();

$refund = new Refund();

// This will
$refund->setValue($storePurchase->getValue());

$storePurchase->getRefunds()->add($refund);

// Initialize omnipay getway - here you will have Paypal, Stripe etc.
$gateway = Omnipay::getFactory()->create('Dummy');

$refund->refund($gateway);

```

The refund object has a validation for its value, so that you do not refund more than the remaining amount for the store purchase, taking into account previous refunds.

License
-------

[](#license)

Copyright (c) 2014, Clippings Ltd. Developed by Ivan Kerin

Under BSD-3-Clause license, read LICENSE file.

###  Health Score

24

—

LowBetter than 32% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity7

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity53

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

4274d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/506129?v=4)[Harry Dobrev](/maintainers/hkdobrev)[@hkdobrev](https://github.com/hkdobrev)

![](https://avatars.githubusercontent.com/u/4113307?v=4)[Danail Kyosev](/maintainers/dkyosev)[@dkyosev](https://github.com/dkyosev)

![](https://avatars.githubusercontent.com/u/7592650?v=4)[Evstati Zarkov](/maintainers/EZarkov)[@EZarkov](https://github.com/EZarkov)

![](https://avatars.githubusercontent.com/u/745771?v=4)[Filip Georgiev](/maintainers/phgeorgiev)[@phgeorgiev](https://github.com/phgeorgiev)

![](https://avatars.githubusercontent.com/u/490439?v=4)[Zdravko Evstatiev](/maintainers/zedevs)[@zedevs](https://github.com/zedevs)

---

Top Contributors

[![ivank](https://avatars.githubusercontent.com/u/4976?v=4)](https://github.com/ivank "ivank (33 commits)")

### Embed Badge

![Health badge](/badges/clippings-purchases/health.svg)

```
[![Health](https://phpackages.com/badges/clippings-purchases/health.svg)](https://phpackages.com/packages/clippings-purchases)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
