dlds/yii2-ecom

为Yii2的电子商务扩展

维护者

详细信息

github.com/dlds/yii2-ecom

源代码

安装次数: 1,969

依赖关系: 0

建议者: 0

安全: 0

星标: 1

关注者: 2

分支: 18

类型:yii2-extension

1.2.9 2016-04-28 13:34 UTC

README

提供对基本电子商务操作的支撑,作为 dlds/yii2-payment 的包装器。使用示例请参考 dlds/yii2-app-ecom - 使用此扩展的示例应用程序。本指南假设您熟悉爱沙尼亚银行支付的实施(见 pangalink.net

主要功能

  • 可扩展的代码,几乎可以自定义一切
  • 与ActiveRecord对象(订单、产品)的集成
  • 购物车功能(支持多种存储方法)
  • 支持支付适配器(目前实现了爱沙尼亚银行)
  • 支持折扣
  • 显示购物车内容、支付表单、列表的基本小部件

安装

您可以使用composer安装此包。在您的 composer.json 中添加以下必需的包

{
	"require": {
			"dlds/yii2-ecom": "*"
	}
}

技术概述

该包位于 \dlds\ecom 命名空间下,由3个子组件组成(这些可以在配置中覆盖,并且可以直接作为主组件的属性访问)。

  1. basket - 提供购物车功能
  2. payment - 提供接收支付的功能
  3. formatter - 在网格视图中使用的辅助类

大多数类及其子类都可以在配置中进行覆盖。

配置

安装后,您可能想要

  1. 覆盖并扩展主类以提供一些自定义功能
  2. 将此类注册为应用程序组件
  3. 配置银行支付参数和返回URL

您可以在应用程序配置中使用类似以下内容来实现此功能

$config = [
	'components' => [
        'ecom' => [
            'class' => 'app\components\MyEcomComponent',
            'payment' => [
                'class' => 'dlds\ecom\Payment',
                'bankReturnRoute' => 'bankret', // use url alias to shorten the return url
                'adapterConfig' => \yii\helpers\ArrayHelper::merge(require 'banks-default.php', require 'banks-local.php')
            ],
        ],
	],
];

并定义类 MyEcomComponent 如下

namespace app\components;

class MyEcomComponent extends \dlds\ecom\Component
{
  // override methods here to customize
}

您可以使用 banks-default.php 存储通用银行配置(例如,使用哪些银行)并定义更具体的访问参数在 banks-local.php 中,它特定于环境并且不在CVS中。您可以在此处下载示例文件 这里

使用方法

以下示例假设您已将 dlds\ecom\Component(或其子类)注册为应用程序组件,在 Yii::$app->ecom 下。

使用ActiveRecord集成

ActiveRecord集成使得向购物车添加项目以及使用购物车创建订单和支付表单变得非常容易。目前有三种类型的AR集成可用。

  1. 在您的AR模型类中实现 dlds\ecom\models\BasketProductInterface 以添加对产品和服务的支持
  2. 实现 dlds\ecom\models\BasketDiscountInterface 以添加对折扣的支持
  3. 实现 dlds\ecom\models\OrderInterface 以添加对订单的支持

使用购物车

当使用实现两个购物车接口之一的数据模型时,购物车的操作非常简单。购物车对象可以在 \Yii::$app->ecom->basket 下访问,并且如果需要自定义它,可以在配置中进行覆盖。

// access the basket from "basket" subcomponent
$basket = \Yii::$app->ecom->basket;

// Product is an AR model implementing BasketProductInterface
$product = Product::find(1);

// add an item to the basket
$basket->add($product);

// add a discount object to the basket. AR model is implementing BasketDiscountInterface
$basket->add(Discount::find(1));

// returns the sum of all basket item prices
$sum = $basket->getTotalDue();

// returns the sum of all 'vat' attributes (or return values of getVat()) from all models in the basket.
$totalVat = $basket->getAttributeTotal('vat');

// clear the basket
$basket->clear();

// render the contents of the basket with default parameters
echo \dlds\ecom\widgets\BasketGridView::widget([
    'basket' => $basket,
]);

购物车中的项目

添加到购物车的产品/项目在从购物车存储加载数据时进行序列化/反序列化。如果您使用Active Record模型作为产品/折扣,请确保您从序列化数据中省略任何不必要的引用,以保持其紧凑。

// get all items from the basket
$items = $basket->getItems();

// get only products
$items = $basket->getItems(Basket::ITEM_PRODUCT);

// loop through basket items
foreach ($items as $item) {
	// access any attribute/method from the model
	var_dump($item->getAttributes());

	// remove an item from the basket by its ID
	$basket->remove($item->uniqueId)
}

创建订单

购物车对象可以轻松地转换为订单(实现 OrderInterface 接口的 AR 对象)。

$order = new Order([
	'user_id' = \Yii::$app->user->id,
	'status' => 'new',
]);
\Yii::$app->ecom->basket->createOrder($order);

这会调用你的订单类中的 saveFromBasket 方法,其可能看起来像这样。

public function saveFromBasket(Basket $basket)
{
    $transaction = $this->getDb()->beginTransaction();
    try
    {
        $this->due_amount = $basket->getTotalDue(false);
        if (!$this->save()) {
            throw new \RuntimeException('Could not save order model');
        }

        foreach ($basket->getItems() as $item) {
            // create and save "order line" objects looking up necessary attributes from $item
        }
        $transaction->commit();
    }
    catch (\Exception $exception)
    {
        $transaction->rollback();
        throw $exception;
    }
}

使用支付

生成支付表单

如果你已经保存了订单对象,你可以使用包含的 dlds\ecom\widgets\PaymentButtons 小部件来渲染配置中包含的所有银行表单。如果你需要自定义,可以在配置中提供自己的小部件类(在 payment 子组件下覆盖 widgetClass)。有一个简写方法用于生成带有正确参数的小部件

// generate FORM tags for every bank with hidden inputs and bank logos as submit images
\Yii::$app->ecom
	->payment
	->createWidget($order)
	->run();

接收来自银行的请求

支付后,用户将被重定向回应用程序,并跳转到你在 payment 子组件下配置的 URL(通过 bankReturnRoute)。在你的控制器操作中,你可以这样传递请求到组件

public function actionBankReturn()
{
	// pass in the request data and the name of the class you want to use as order object
	$model = \Yii::$app->ecom->payment->handleResponse($_REQUEST, Order::className());

	$this->redirect(['order/view', 'orderId' => $model->id]);
}

上面的代码从数据库中加载正确的订单,并调用你的订单类中的 bankReturn 方法。您负责保存订单和记录必要的数据。

public function bankReturn(Response $response)
{
    $this->status = $response->isSuccessful() ? 'paid' : 'error';
    $this->save();

    \Yii::$app->log->log('Returned from bank: ' . $response->__toString(), Logger::LEVEL_INFO);

    return $this;
}

高级示例

在数据库中存储购物车数据

有两个内置的适配器用于存储购物车数据:会话存储(默认)和数据库存储。您还可以编写自己的存储类,并在配置文件中的 basket 组件下定义它们

'ecom' => [
    'class' => 'app\components\MyEcomComponent',
    'basket' => [
        'class' => 'dlds\ecom\Basket',
        'storage' => [
            'class' => 'dlds\ecom\basket\storage\Database',
            'table' => 'eco_basket',
        ]
    ],

除了表名之外,您还可以覆盖字段名(一个用于用户标识符,另一个用于会话数据)。如果设置了 Database::$userComponent(例如,设置为 user),则适配器将尝试通过 \Yii::$app->user->getId() 方法获取用户标识符。如果失败或未指定组件名称,则使用会话 ID 来标识用户。会话表应至少包含两个字段,外观类似于以下内容

CREATE TABLE `eco_basket` (
	`session_id` varchar(255) NOT NULL,
	`basket_data` blob NOT NULL,
	PRIMARY KEY (`session_id`)
) ENGINE=InnoDB;

使用折扣

要向购物车/订单添加折扣,只需将实现 BasketDiscountInterface 接口的对象添加到购物车,并在 applyToBasket 方法中指定折扣逻辑。

class MyDiscount implements BasketDiscountInterface
{
    public function applyToBasket(Basket $basket, &$basketTotalSum)
    {
        // subtract a value
        $basketTotalSum -= 10;

        // or add a X percent discount
        $basketTotalSum *= 0.7;
    }
}

\Yii::$app->ecom->basket->add(new MyDiscount);