opus-online/yii2-ecom

Yii2 的电子商务扩展

这个软件包的官方仓库似乎已消失,因此软件包已被冻结。

维护者

详细信息

github.com/opus-online/yii2-ecom

安装数: 6,115

依赖者: 1

建议者: 0

安全: 0

星标: 29

关注者: 18

分支: 19

类型:yii2-extension

v1.0.1 2014-11-10 16:49 UTC

This package is not auto-updated.

Last update: 2024-01-20 11:51:04 UTC


README

警告:此软件包不再维护。

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

主要功能

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

安装

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

{
	"require": {
			"opus-online/yii2-ecom": "*"
	}
}

技术概述

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

  1. 购物车 - 提供购物车功能
  2. 支付 - 提供接收支付的功能
  3. 格式化器 - 用于网格视图的帮助类

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

配置

安装后,您可能想

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

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

$config = [
	'components' => [
        'ecom' => [
            'class' => 'app\components\MyEcomComponent',
            'payment' => [
                'class' => 'opus\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 \opus\ecom\Component
{
  // override methods here to customize
}

您可以使用 banks-default.php 来存储通用的银行配置(例如,使用哪些银行)并在 banks-local.php 中定义更具体的访问参数,该文件与环境相关,不在 CVS 中保存。您可以从 此处 下载示例文件。

使用

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

使用 ActiveRecord 集成

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

  1. 在您的 AR 模型类中实现 opus\ecom\models\BasketProductInterface 以添加对产品和服务支持
  2. 实现 opus\ecom\models\BasketDiscountInterface 以添加对折扣支持
  3. 实现 opus\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 \opus\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;
    }
}

使用支付

生成支付表单

如果您已保存订单对象,可以使用包含的控件 opus\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();

接收来自银行的请求

支付后,用户会被重定向回应用程序,到配置中通过 bankReturnRoutepayment 子组件下指定的 URL。在您的控制器操作中,您可以像这样将请求传递给组件

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' => 'opus\ecom\Basket',
        'storage' => [
            'class' => 'opus\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);