Giter Site home page Giter Site logo

offline-gmbh / oc-microcart-plugin Goto Github PK

View Code? Open in Web Editor NEW
16.0 4.0 13.0 126 KB

:shopping_cart: Simple shopping cart component for October CMS

License: MIT License

PHP 79.99% CSS 1.27% HTML 18.75%
octobercms octobercms-plugin ecommerce shopping-cart

oc-microcart-plugin's Introduction

oc-microcart-plugin

The OFFLINE.MicroCart plugin aims to provide simple shopping cart and payment features.

This plugin is meant for projects where simple items are sold online (Tickets, Coupons, etc). You will have to implement the "item part" (like a Ticket model) yourself. You can use the plugin as cart and payment solution.

Features

The OFFLINE.MicroCart plugin provides the following features:

  • A Cart model with a nice API to add and remove CartItems
  • A Cart component base, that is meant to be extended by you
  • Stripe, PayPal and SIX SaferPay payment integrations
  • Support to add custom payment gateways
  • Numerous events for you to hook into

It does not provide any of these features:

  • Product data management
  • E-Mail notifications
  • Multi currency support
  • Stock management
  • Shipping rules
  • ... and lots of other extended eCommerce features

If you are looking for a fully featured eCommerce solution for October CMS check out OFFLINE.Mall.

Getting up and running

Create your own plugin that extends MicroCart

The MicroCart plugin is meant to be extended by your own plugins. Refer to the official October CMS docs for a list of all extension possibilities.

php artisan create:plugin YourVendor.PluginName

Backend menu

The plugin does by default not register any backend menu items. You can use the following snippet in your own Plugin.php to use the default orders overview.

    public function registerNavigation()
    {
        return [
            'main-menu-item' => [
                'label'        => 'Your Plugin', // Your label
                'url'          => \Backend::url('offline/microcart/carts'),
                'iconSvg'      => 'plugins/offline/microcart/assets/icon.svg',
            ],
        ];
    }

Cart component

The plugin does not register any components but it provides you with a Cart base component that you can extend.

Simply register your own component and build from there.

php artisan create:component YourVendor.PluginName Cart

Register your component in your Plugin.php.

    public function registerComponents()
    {
        return [
            \YourVendor\YourPlugin\Components\Cart::class => 'cart',
        ];
    }

Make sure the component extends MicroCart's base component.

<?php namespace YourVendor\YourPlugin\Components;

use OFFLINE\MicroCart\Models\CartItem;
use OFFLINE\MicroCart\Classes\Payments\PaymentRedirector;

class Cart extends \OFFLINE\MicroCart\Components\Cart
{        
    public function onRun()
    {
        // An off-site payment has been completed. Important, this code
        // needs to be present if you are using PayPal or Six. 
        if ($type = request()->input('return')) {
            return (new PaymentRedirector($this->page->page->fileName))->handleOffSiteReturn($type);
        }

        // Do something.
    }

    public function onAdd()
    {
        $item           = new CartItem();
        $item->name     = 'Your product';
        $item->quantity = random_int(1, 4);
        $item->price    = 100.00;

        $this->cart->add($item);

        return $this->refreshCart();
    }
}

To modify validation rules and messages take a look at the getValidationRules, getFieldNames and getValidationMessages methods on the base Cart class.

Copy the default partials from MicroCart's base component to your own component. Modify them as needed.

cp -rv plugins/offline/microcart/components/cart/* plugins/yourvendor/yourplugin/components/cart/

Updating the cart partials

You can return $this->refreshCart(); from your Cart component's methods to refresh the cart display.

Using payment providers

There are three payment providers supported out-of-the-box:

  • PayPal (composer require omnipay/stripe)
  • Stripe (composer require omnipay/paypal)
  • Six SaferPay (composer require ticketpark/saferpay-json-api)

Run the composer commands beside each provider you plan to use. You can configure the providers via October's backend settings.

Custom payment providers

To register a custom PaymentProvider create a class that extends MicroCart's PaymentProvider class. Check out the existing providers to get some inspiration on how to create your own.

<?php

namespace YourVendor\YourPlugin\Classes;

use OFFLINE\MicroCart\Classes\Payments\PaymentProvider;

class YourCustomProvider extends PaymentProvider
{
    // Implement all abstract methods.
}

In your Plugin.php register this custom provider by returning them from a registerPaymentProviders method.

use OFFLINE\MicroCart\Classes\Payments\PaymentGateway;

class Plugin extends PluginBase
{
    public function registerPaymentProviders()
    {
        return [
            new YourCustomProvider(),
        ];
    }
}

Link your model to cart items

The easiest way to link a model to a CartItem is to add a simple belongsTo relationship.

// Voucher is the thing we are selling (the CartItem)
class Voucher extends Model
{
    public $belongsTo = [
        'cartitem' => CartItem::class
    ];
}

API

Cart

Get the user's cart

// This cart will be unique to the current user.
$cart = Cart::fromSession();

Add an item to the cart

$item           = new CartItem();
$item->name     = 'An item'; // The only required field
$item->quantity = 2;
$item->price    = 20.00;

$cart->add($item);

Ensure an item is in the cart

$item = new CartItem(['name' => 'Shipping fee', 'kind' => CartItem::KIND_SERVICE]);

// A code property is required! A product with the specified
// code is ensured to be present in the Cart.
$item->code = 'shipping'; 

// ensure the item is in the cart. If it's not, it will be added.
$cart->ensure($item);
// A second call will not add the item again.
$cart->ensure($item);
// You can force a new quantity by passing a second parameter.
$cart->ensure($item, 4);

Remove an item from the cart

$item = new CartItem(['name' => 'An item']);

// You can remove an item by passing in a CartItem object or an id.
$cart->remove($item);
$cart->remove($item->id);

Remove all items with a given code from the cart

$item = new CartItem(['name' => 'Shipping fee', 'code' => 'shipping', 'kind' => CartItem::KIND_SERVICE]);

// Removes all items with a given code (reverse of the `ensure` method).
$cart->removeByCode('shipping');

Update an item's quantity

$item = new CartItem(['name' => 'An item']);

// You can set the quantity by passing in a CartItem object or an id.
$cart->setQuantity($item, 4);
$cart->setQuantity($item->id, 4);

Service fees and discounts

Set the kind attribute to either CartItem::KIND_SERVICE or CartItem::KIND_DISCOUNT if the item is a service fee (Shipping, Handling) or a discount. Use the ensure method to make sure it's only added once to the Cart.

$item = new CartItem(['name' => 'Shipping fee', 'kind' => CartItem::KIND_SERVICE, 'price' => 10]);

// The code is required to use the `ensure` method.
$item->code = 'shipping'; 

$cart->ensure($item);


$item = new CartItem(['name' => 'Discount', 'kind' => CartItem::KIND_DISCOUNT, 'price' => -100]);
$item->code = 'discount'; 

$cart->ensure($item);

Access cart contents

You can access all cart items using the $cart->items relation.

You also have access to filtered list_items, service_fees and discounts properties that only contain the given item types.

$item     = new CartItem(['name' => 'A product']);
$shipping = new CartItem(['name' => 'Shipping fee', 'kind' => CartItem::KIND_SERVICE]);
$discount = new CartItem(['name' => 'Discount',     'kind' => CartItem::KIND_DISCOUNT]);

$cart->addMany($item, $shipping, $discount);

$cart->list_items->first()   === $item;     // true
$cart->service_fees->first() === $shipping; // true
$cart->discounts->first()    === $discount; // true

Print the customer's address

After a Cart checkout has been successful, you can use the following helpers to get the customer's address as an array or an escaped HTML string.

$cart->getShippingAddressArray();
// ['Company', 'Firstname Lastname', ...];

$cart->getBillingAddressHtml();
// Company<br />
// Firstname Lastname<br />
// Street 123<br />
// ZIP City

$cart->getBillingAddressHtmlZipReversed();
// Company<br />
// Firstname Lastname<br />
// Street 123<br />
// City ZIP

CartItem

Create an item

// Short format
$item = new CartItem(['name' => 'An item']);

// Or long format
$item = new CartItem();
$item->name = 'An item';
$item->description = 'The description to this item';
$item->price = 20.00; // Includes tax by default.
$item->quantity = 10;
$item->meta = [
    'any' => 'additional',
    'data' => true,
];
// $item->tax_id = 2;           // If not specified the default tax will be used. 
// $item->tax_free = true;      // Don't add taxes to this item, not even the default tax. 
// $item->is_before_tax = true; // The specified price does not include taxes. 

Access item information

// Create an example item
$item           = new CartItem(['name' => 'An item']);
$item->price    = 10.00;
$item->quantity = 2;
$item->tax_id   = 1; // 10% tax

// Access the item's information
$item->price;        // 10.00
$item->quantity;     // 2
$item->subtotal;     // 20.00 => price * quantity
$item->tax_amount;   //  2.00 => 10 % on price 
$item->total;        // 22.00 => (price * quantity) + tax_amount

Money

There is a Money singleton class available to format cents as a string. A microcart_money Twig helper is registered as well.

Money::instance()->format(12000); // 120.00 USD

// or in Twig
{{ 120000 | microcart_money }}   // 120.00 USD

Change the default money formatter

You can register your own formatter function by adding the following code to your Plugin's register method.

    public function register()
    {
        \Event::listen('offline.microcart.moneyformatter', function () {
            return function ($cents): string {
                return 'Your custom implementation to format: ' . $cents;
            };
        });
    }

Events

Cart

offline.microcart.cart.beforeAdd

Fired before an item is added to the Cart. It receives the following arguments:

  • $cart: the Cart of the current user
  • $item: the CartItem being added

offline.microcart.cart.afterAdd

Fired after an item has been added to the Cart. It receives the following arguments:

  • $cart: the Cart of the current user
  • $item: the CartItem added

offline.microcart.cart.beforeRemove

Fired before an item is removed from the Cart. It receives the following arguments:

  • $cart: the Cart of the current user
  • $item: the CartItem being removed

offline.microcart.cart.afterRemove

Fired after an item has been removed from the Cart. It receives the following arguments:

  • $cart: the Cart of the current user
  • $item: the CartItem removed

offline.microcart.cart.quantityChanged

Fired after the quantity of a cart item has changed.

  • $cart: the Cart of the current user
  • $item: the CartItem that was updated

Checkout

offline.microcart.checkout.succeeded

Fired after a checkout was successful.

  • $result: a PaymentResult instance

offline.microcart.checkout.failed

Fired after a checkout has failed.

  • $result: a ?PaymentResult instance (nullable)

offline.microcart.checkout.cancelled

Fired after a checkout has been cancelled.

oc-microcart-plugin's People

Contributors

chrisvidal avatar luketowers avatar tobias-kuendig avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

oc-microcart-plugin's Issues

Problem in develop Custom Payment Provider

hi, I want to develop custom payment provider, in my provider after user select provider he must be redirected to a custom page to enter bank info and after that target provider redirect user again to my site, but I have a problem with this process, I can able to redirect the user to bank page.
my question is there any document to develop custom provider with redirection systems?

Is the plugin maintained?

Here in the GitHub there is version 1.0.1, in the OctoberCMS website's marketplace there is 1.0.3, after installation via php artisan install ... I do not see the plugin in my backend plugin list (althougt db tables has been created) and going to Backend -> Marketplace -> MicroCart i see this

Pic20220130182918

How to handle zero cart value?

Hi!

How can I handle zero cart value? How Can I make a successful checkout without initiating the payment provider? Stripe only accepts 1<= cart values.

Thank you,
David

How to avoid negative cart value?

Hello!

I'm having a hard time trying to override the getTotalsAttribute() method in the Cart Model, but it just won't work. I would like to ensure that the value of the basket cannot go below 0. I also made my own Totals.php, but I can't get the model to use it.

Is there a solution for this or can you modify the Totals.php of the plugin so that the cart value cannot go below 0?

Can't use checkout page without requiring billing and shipping fields

Stripe supports creating customers without any of the information included by default on the checkout page (i.e. all of the shipping and billing fields); see https://stripe.com/docs/api/customers/create.

It would be nice to be able to override the checkout page to remove those fields and not have the checkout process fail on various "index is not defined" errors as the Stripe payment processor attempts to access fields that were not provided.

Additionally, it would be great if one could simply add whatever fields they wanted to the checkout page and have them dump into a jsonable blob column on the Cart row for easy storage of custom data.

Finally, it would also be helpful if the error message logged in the backend when a payment fails included the error message from the provider instead of just "A payment failed."

Unknown records in carts table

Hi, every time I refresh frontend page or visit another page in DB is stored another record with different session_id in carts table. Is this behavior wanted? Does it potentially cause some issues during payment procedure?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.