Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php Magento-付款挂起时标记为已使用的单一优惠券_Php_Sql_Magento_Paypal_Coupon - Fatal编程技术网

Php Magento-付款挂起时标记为已使用的单一优惠券

Php Magento-付款挂起时标记为已使用的单一优惠券,php,sql,magento,paypal,coupon,Php,Sql,Magento,Paypal,Coupon,我对Magento单一优惠券代码有一个问题,该代码在客户单击下订单按钮时被标记为已使用。如果Paypal支付失败或客户在订单完成前离开页面,他将无法返回并重新订购此优惠券,此优惠券设置为仅使用一次,并且已标记为已使用 我发现了一段代码,它可以减少用户使用优惠券的次数,并允许用户重用优惠券。不幸的是,他在尝试连接Paypal页面时,在单击PlaceOrder按钮时出错。为了能够再次使用优惠券并访问Paypal页面,我必须删除SQL数据库表salesrule\u优惠券使用情况和salesrule\u

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

我发现了一段代码,它可以减少用户使用优惠券的次数,并允许用户重用优惠券。不幸的是,他在尝试连接Paypal页面时,在单击PlaceOrder按钮时出错。为了能够再次使用优惠券并访问Paypal页面,我必须删除SQL数据库表salesrule\u优惠券使用情况和salesrule\u customer中包含此客户ID的行

以下是我需要更改的代码,以自动删除客户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\u优惠券\u使用率表。这根本不是你想要的。您希望将其包装到支付事务中。我不知道是因为您有自定义代码还是使用了旧版本的Magento才出现此错误,但我会告诉您如何解决此问题。然后我会给你一个类似于你建议的解决方案:

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

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

这是你需要做的10000英尺的视图

  • 过早地查找更新salesrule\u优惠券\u使用率表的内容并将其删除。我们将添加我们自己的事务安全版本,因此我们不希望它保存在其他任何地方。最简单的方法是找出哪个模型连接到该表,并搜索该模型的创建。对于1.7和1.8,这是规则/客户模型
  • 创建一个观察者来捕捉支付交易的开始。在大多数现代版本的magento中,此事件称为销售\订单\付款\地点\开始,可以在app/code/core/Mage/sales/Model/order/payment.php中看到
  • 将订单从活动中取出,并将优惠券代码从活动中取出
  • 拉取要更新的实际模型。看起来有人在您的代码中找不到它,但应该有一些模型使用隐藏在某处的salesrule\u优惠券\u使用率表。在.xml文件中搜索“salesrule\u优惠券使用情况”,并查看使用该表的模型。同样,对我来说,在1.7中,这是规则/客户模型
  • 加载该模型,让客户更改与优惠券代码相关的值,以表明客户已使用优惠券,但尚未保存
  • 从事件中获取事务,并使用addObject方法注册更新的优惠券对象
你的任务完成了。事务将自动尝试保存已添加到其中的所有对象。如果任何部分失败(包括付款失败),它将回滚整个过程,您的优惠券将不会被使用。耶

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

同样,这里是10000英尺的视图:

  • 创建观察者以捕获失败的付款事件。在大多数版本中,您需要的事件是销售\订单\付款\取消
  • 运行你得到的代码。。。它应该这样做。但要向其他人澄清:
    • 从活动中提取订单,从中提取优惠券代码和客户id
    • 更新客户、规则和销售规则\u优惠券\u使用情况表。(虽然确实应该有一个模型,但我相信你能找到它)
现在,当销售失败时,您可以返回并手动解除所有操作。这并不像我的第一个解决方案那样清晰,但根据您对Magento的熟悉程度,可能会更容易

我相当确信新的、干净的Magento版本没有这个问题,所以让我提供一个相当明显的建议作为第三个解决方案

  • 更新Magento
  • 如果Magento是最新的,测试是否禁用任何自定义模块,因为有什么东西破坏了它。我注意到Amasty优惠券插件特别有缺陷
  • 如果您对Magento core进行了自定义更改。。。祝你好运

祝你好运

您需要更好地格式化代码。目前,它无法作为一行来阅读。代码现在格式良好。这似乎根本不是解决问题的正确地方。您不想取消
订单
,而是首先要阻止创建该订单,或者更确切地说;您需要停止过早保存
优惠券
。我会将整个过程包装在一个事务中,或者使用事件系统触发优惠券减量。如果你真的想解决这个问题,你可能应该使用paypal express checkout。它允许客户转到paypal,直到客户返回站点批准订单后才设置订单。这样,优惠券就不会在结账时创建