我很好奇乔纳森你是怎么做到的,我没有采用你的方法,我的方法有点复杂。我的确实允许有人在 url 中发布优惠券代码,但我设置了一个 cookie 和所有这些。我基本上在标题中设置了我自己的表单,用户可以输入优惠券代码并应用它,并将优惠券放在电子邮件活动的 url 中。
我需要一段时间才能详细回顾它,所以我将发布一些代码片段,也许可以帮助您继续前进,并尝试 Jonathan 所说的方式。
覆盖购物车控制器并添加您自己的操作。
public function couponExternalPostAction()
{
$quote = $this->_getQuote();
$couponCode = (string) $this->getRequest()->getParam('coupon_code');
$validateCoupon = Mage::getModel('package_module/coupon');
$json = $validateCoupon->addCouponCode($couponCode, $quote, $this->getRequest());
echo $json;
return;
}
我还必须重写 couponPostAction() 才能让事情以正常方式正常工作。
我自己的模型中有一个 addCoupon 方法
public function addCouponCode($code, $quote, $request){
$couponCode = (string) $code;
$removed = false;
if ($request->getParam('remove') == 1) {
$couponCode = '';
$removed = true;
}
$oldCouponCode = $quote->getCouponCode();
/* No point in applying the rule again if it is the same coupon code that is in the quote */
if ($couponCode === $oldCouponCode) {
$json = $this->_getResponseJson($removed, $couponCode, $quote, false, true);
return $json;
}
// Set the code get the rule base on validation even if it doesn't validate (false), which will also add it to the session, then get our response
$quote->setCouponCode(strlen($couponCode) ? $couponCode : '');
$rule = $this->_validateCoupon($quote,$couponCode);
// add coupon code to cookie, so we can delete from quote if the user closes their browser and comes back
if($rule && !$removed){
Mage::getModel('core/cookie')->set('coupon_code', $couponCode, 0, '/', null, null, null, false);
}else{
Mage::getModel('core/cookie')->delete('coupon_code');
}
$json = $this->_getResponseJson($removed, $couponCode, $quote, $rule);
//See if the quote id is set before saving
$quoteId = $quote->getQuoteId();
//Save the quote since everything has been set if not the data wont be set on page refresh
$quote->save();
//Set the quote id if it wasn't set before saving the quote. This makes sure we work off the same quote and a new one isn't created.
if(empty($quoteId)){
$this->_setQuoteId($quote);
}
return $json;
}
验证优惠券
protected function _validateCoupon($quote,$couponCode){
$store = Mage::app()->getStore($quote->getStoreId());
$validator = Mage::getModel('package_module/validator');
$validator->init($store->getWebsiteId(), $quote->getCustomerGroupId(), $quote->getCouponCode());
return $validator->isValidExternalCode($couponCode, $quote->getShippingAddress(),false);
}
我Mage_SalesRule_Model_Validator
用自己的验证器功能进行了扩展
public function isValidExternalCode($couponCode, $address, $setCoupon = true){
foreach ($this->_getRules() as $rule) {
if ($rule->getCode() && (in_array(strtolower($couponCode),explode(',',strtolower($rule->getCode()))))) {
if($setCoupon){
$address->setCouponCode($couponCode);
}
return $rule;
}
}
return false;
}
在这里我生成json响应
rotected function _getResponseJson($removed, $couponCode, $quote, $rule = false, $isDup = false){
$json = '{"Response":{';
if($removed){
$json .= '"success":"Promotional code was cancelled successfully."';
Mage::getSingleton('checkout/session')->setData('coupon_rule',null);
}
if(!$removed && $isDup){
$json .= '"error":"' . $couponCode . ' is already applied"';
}else if(!$removed && $rule){
$json .= '"success":"Promotional code ' . $couponCode . ' has been applied",';
$json .= '"couponMessage":"<span>' . $rule->getName() . '</span>"';
Mage::getSingleton('checkout/session')->setData('coupon_rule','<span>' . $rule->getName() .'</span>');
}else if(!$removed){
$json .= '"error":"' . $couponCode . ' is not valid"';
$quote->setCouponCode('');
}
$json .= '}}';
return $json;
}
我还必须在Mage_SalesRule_Model_Quote_Discount
public function collect(Mage_Sales_Model_Quote_Address $address)
{
Mage_Sales_Model_Quote_Address_Total_Abstract::collect($address);
$quote = $address->getQuote();
$store = Mage::app()->getStore($quote->getStoreId());
$eventArgs = array(
'website_id' => $store->getWebsiteId(),
'customer_group_id' => $quote->getCustomerGroupId(),
'coupon_code' => $quote->getCouponCode(),
);
$this->_calculator->init($store->getWebsiteId(), $quote->getCustomerGroupId(), $quote->getCouponCode());
$items = $address->getAllItems();
/* EDITS
* Moved the if statement for no items in cart down past these previous methods and then if the address type is shipping and the coupon is set
* add the coupon code to the address to allow the validation to still pick up the coupon code
*/
if($quote->getCouponCode() && ($address->getAddressType() == Mage_Sales_Model_Quote_Address::TYPE_SHIPPING)){
$address->setCouponCode($quote->getCouponCode());
}
if (!count($items)) {
return $this;
}
$address->setDiscountDescription(array());
foreach ($items as $item) {
if ($item->getNoDiscount()) {
$item->setDiscountAmount(0);
$item->setBaseDiscountAmount(0);
}
else {
/**
* Child item discount we calculate for parent
*/
if ($item->getParentItemId()) {
continue;
}
$eventArgs['item'] = $item;
Mage::dispatchEvent('sales_quote_address_discount_item', $eventArgs);
if ($item->getHasChildren() && $item->isChildrenCalculated()) {
foreach ($item->getChildren() as $child) {
$this->_calculator->process($child);
$eventArgs['item'] = $child;
Mage::dispatchEvent('sales_quote_address_discount_item', $eventArgs);
$this->_aggregateItemDiscount($child);
}
} else {
$this->_calculator->process($item);
$this->_aggregateItemDiscount($item);
}
}
}
/**
* Process shipping amount discount
*/
$address->setShippingDiscountAmount(0);
$address->setBaseShippingDiscountAmount(0);
if ($address->getShippingAmount()) {
$this->_calculator->processShippingAmount($address);
$this->_addAmount(-$address->getShippingDiscountAmount());
$this->_addBaseAmount(-$address->getBaseShippingDiscountAmount());
}
$this->_calculator->prepareDescription($address);
return $this;
}