php - Magento - 待付款时标记为已使用的单张优惠券

标签 php sql magento paypal coupon

我遇到了 Magento 单一优惠券代码的问题,该代码在客户单击“下订单”按钮时被标记为已使用。如果Paypal支付失败或客户在订单完成前离开页面,将无法使用此优惠券返回重新订购,该优惠券已设置为仅使用一次,并已标记为已使用。

我发现一段代码可以减少用户使用优惠券的次数,并允许他重复使用优惠券。不幸的是,他在单击下订单按钮时​​尝试连接 Paypal 页面时出错。为了能够再次使用优惠券并访问 Paypal 页面,我必须使用该客户的 ID 删除表 salesrule_coupon_usage 和 salesrule_customer 中 SQL 数据库中的行。

这是我需要更改以自动删除客户 ID 的优惠券使用信息的代码:

public function cancel($observer)
{
    $order = $observer->getEvent()->getPayment()->getOrder();
    if ($order->canCancel()) {
        if ($code = $order->getCouponCode()) {
            $coupon = Mage::getModel('salesrule/coupon')->load($code, 'code');
            if ($coupon->getTimesUsed() > 0) {
                $coupon->setTimesUsed($coupon->getTimesUsed() - 1);
                $coupon->save();
            }

            $rule = Mage::getModel('salesrule/rule')->load($coupon->getRuleId());
            error_log("\nrule times used=" . $rule->getTimesUsed(), 3, "var/log/debug.log");
            if ($rule->getTimesUsed() > 0) {
                $rule->setTimesUsed($rule->getTimesUsed()-1);
                $rule->save();
            }

            if ($customerId = $order->getCustomerId()) {
                if ($customerCoupon = Mage::getModel('salesrule/rule_customer')->loadByCustomerRule($customerId, $rule->getId())) {
                    $couponUsage = new Varien_Object();
                    Mage::getResourceModel('salesrule/coupon_usage')->loadByCustomerCoupon($couponUsage, $customerId, $coupon->getId());

                    if ($couponUsage->getTimesUsed() > 0) {
                        /* I can't find any #@$!@$ interface to do anything but increment a coupon_usage record */
                        $resource = Mage::getSingleton('core/resource');
                        $writeConnection = $resource->getConnection('core_write');
                        $tableName = $resource->getTableName('salesrule_coupon_usage');

                        $query = "UPDATE {$tableName} SET times_used = times_used-1 "
                            .  "WHERE coupon_id = {$coupon->getId()} AND customer_id = {$customerId} AND times_used > 0";

                        $writeConnection->query($query);
                    }

                    if ($customerCoupon->getTimesUsed() > 0) {
                        $customerCoupon->setTimesUsed($customerCoupon->getTimesUsed()-1);
                        $customerCoupon->save();
                    }
                }
            }
        }
    }
}

最佳答案

我相信这是一个从 1.4 到 1.6 左右的旧错误。但是,无论您是否拥有旧版本,如果您了解 Magento 的方式,这都可以很容易地修复到位。

问题是,当他们单击支付按钮时,您的代码会立即更新 salesrule_coupon_usage 表。这根本不是你想要的。您希望将其包装到付款交易中。我不知道发生此错误是因为您有自定义代码还是使用旧版本的 Magento,但我会告诉您我将如何解决该问题。然后我会给你一个类似于你建议的修复:

Magento 已经有一个称为“事务”的抽象。事务用于将需要全部成功或全部失败的对象组合在一起,没有半途而废。 Magento 将完成交易并尝试保存您放置在其中的每个对象。如果其中任何一个失败(例如,付款未通过),则所有已保存的事件都将“回滚”。

幸运的是,Magento 已经创建了一个交易对象来处理支付成功时需要一起更新的各种事情。您可以利用该交易并使用它来正确更新优惠券使用情况。

这是您需要做的事情的 10,000 英尺 View 。

  • 过早地找出正在更新 salesrule_coupon_usage 表的任何内容并杀死它。我们将添加我们自己的事务安全版本,所以我们不希望它被保存在其他任何地方。最简单的方法是找出连接到该表的模型并搜索该模型的创建。对于 1.7 和 1.8,这是规则/客户模型。
  • 创建一个观察者来捕捉支付交易的开始。在大多数现代版本的 magento 中,此事件称为 sales_order_payment_place_start 并且可以在 app/code/core/Mage/Sales/Model/Order/Payment.php
  • 中看到
  • 拉出事件订单,拉出事件优惠码。
  • 拉取要更新的实际模型。看起来有人在您的代码中找不到它,但应该有一些模型使用隐藏在某处的 salesrule_coupon_usage 表。通过 .xml 文件搜索“salesrule_coupon_usage”并查看使用该表的模型。同样,对我来说,在 1.7 上,这就是规则/客户模型。
  • 加载该模型,让客户更改与您的优惠券代码相关的值,以表明客户已使用该优惠券,但尚未保存。
  • 从事件中取出交易并使用 addObject 方法注册更新的优惠券对象。

  • 你完成了。事务将自动尝试保存已添加到其中的所有对象。如果任何部分失败(包括支付失败),它将回滚整个过程,您的优惠券将不会被使用。好极了!

    现在,在我看来,以上是处理问题的最佳方法,但如果您由于某种原因遇到问题,这里有一个基于捕获不成功付款然后使用您的代码的替代方法。

    同样,这里是 10,000 英尺的 View :
  • 创建一个观察者来捕捉失败的支付事件。在大多数版本中,您想要的事件是 sales_order_payment_cancel。
  • 运行你得到的代码......它应该这样做。但要为其他人澄清:
  • 从事件中拉出订单,从中拉出优惠券代码和客户 ID。
  • 更新客户、规则和 salesrule_coupon_usage 表。 (虽然确实应该有一个模型,但我相信你可以找到它)

  • 现在,当销售失败时,您可以手动返回并取消所有内容。这不像我的第一个解决方案那么干净,但根据您对 Magento 的熟悉程度,对您来说可能更容易。

    我相当确定新的、干净的 Magento 版本没有这个问题,所以让我提供一个相当明显的建议作为第三个解决方案。
  • 更新 Magento
  • 如果 Magento 是最新的,请测试禁用任何自定义模块,因为某些东西破坏了它。我注意到 Amasty 优惠券插件特别容易出错。
  • 如果您对 Magento 核心进行了自定义更改……祝您好运。

  • 祝你好运!

    关于php - Magento - 待付款时标记为已使用的单张优惠券,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13268938/

    相关文章:

    sql - 如何在 SQL 中获取插入行的 Id

    sql - ORA-01438 : value larger than specified precision allows for this column - How do i get which column it is referring to?

    php - 子查询成为 Magento 中 Mysql 查询中的列

    php - 什么可以更好地节省服务器系统资源

    javascript - 如何从 HTML 页面获取 Javascript 变量?

    MySQL随机与特定选项

    css - Magento CSS 错误路径

    mysql - Magento 报告客户愿望 list

    php - Blade 翻译文件中的断行

    php - 需要检查网站是否包含 ssl 证书,如果是,那么使用 php 脚本证书的过期日期是多少