ソースを参照

F码增加锁逻辑

stanley-king 8 年 前
コミット
da814edda4

+ 8 - 0
helper/account_helper.php

@@ -14,6 +14,8 @@ require_once (BASE_ROOT_PATH . '/helper/sms_helper.php');
 require_once (BASE_ROOT_PATH . '/helper/bonus/parameters.php');
 require_once (BASE_ROOT_PATH . '/helper/user_session/favorite.php');
 require_once (BASE_ROOT_PATH . '/helper/user_session/anotice.php');
+require_once (BASE_ROOT_PATH . '/helper/fcode/mfcode.php');
+require_once (BASE_ROOT_PATH . '/helper/fcode/operator.php');
 require_once (BASE_ROOT_PATH . '/helper/user_session/fcode.php');
 
 class account_helper
@@ -480,6 +482,12 @@ class account_helper
             return;
         }
 
+        $pay_sn = $order['pay_sn'];
+        $num = \fcode\operator::unlock($pay_sn);
+        if($num > 0) {
+            push_helper::fcode_unlock($buyer_id,$num);
+        }
+
         $bonus_amount = account_helper::paysuccess_bonus($buyer_id,$goods_amount);
         if(intval($bonus_amount * 100) + 0.5 > 10)
         {

+ 1 - 1
helper/buy_first.php

@@ -345,7 +345,7 @@ class buy_first
 
                 if($goods_num <= 0) continue;
 
-                $num = $this->mUserFcode->common_has_code($commonid);
+                $num = $this->mUserFcode->usable_num($commonid,$lock_num);
                 if($num == false) {
                     $err = "您没有购买<{$name}>的F码,请重新选择商品.";
                     return false;

+ 8 - 3
helper/fcode/mfcode.php

@@ -105,10 +105,15 @@ class mfcode
     public function usable_time() {
         return intval($this->mParams['usable_time']);
     }
-    public function expired() {
-        return $this->usable_time() <= time();
+    public function expired()
+    {
+        $tm = $this->usable_time();
+        return ($tm > 0 && $tm <= time());
+    }
+    public function locked() {
+        return (intval($this->mParams['fc_state']) == 3);
     }
     public function can_use() {
-        return ($this->commonid() > 0 && $this->expired() == false && $this->used() == false);
+        return ($this->commonid() > 0 && $this->expired() == false && $this->used() == false && $this->locked() == false);
     }
 }

+ 83 - 0
helper/fcode/operator.php

@@ -122,6 +122,89 @@ class operator
         return $this->bind($fcode,$mobile);
     }
 
+    public function lock($pay_sn)
+    {
+        $fcode = $this->grabed();
+        if($fcode != false) return $fcode;
+        if(!session_helper::logined()) {
+            return false;
+        }
+
+        while(true)
+        {
+            $cond = array('goods_commonid' => $this->mCommonID,
+                'batch_code' => $this->mBatchCode,
+                'fc_state' => '0',
+                'grab_state' => array('in', array(0,1)),
+                'grab_time' => array('lt',time() - self::time_out));
+
+            $fcodes = $this->mod_fcode->where($cond)->field('*')->order('fc_id asc')->limit(1)->select(array('master' => true));
+            if(empty($fcodes) || empty($fcodes[0])) return false;
+
+            $fcode = $this->try_lock($fcodes[0],$pay_sn);
+            if($fcode != false) {
+                return $fcode;
+            }
+        }
+    }
+
+    public static function unlock($pay_sn)
+    {
+        $mod_fcode = Model('goods_fcode');
+        $cur_time = time();
+
+        $ret = $mod_fcode->where(['pay_sn' => $pay_sn,'fc_state' => 3])->update(['fc_state' => 0,
+            'usable_time' => array('exp', "usable_days * 86400 + {$cur_time}")]);
+        $affect_rows = $mod_fcode->affected_rows();
+
+        if($ret != false && $affect_rows > 0) {
+            return $affect_rows;
+        } else {
+            return 0;
+        }
+    }
+
+    private function try_lock($fcode,$pay_sn)
+    {
+        $cond = [];
+        $cond['goods_commonid'] = $this->mCommonID;
+        $cond['batch_code']      = $this->mBatchCode;
+        $cond['user_key']       = $fcode['user_key'];
+        $cond['fc_id']          = $fcode['fc_id'];
+        $cond['fc_state']       = $fcode['fc_state'];
+        $cond['grab_state']     = $fcode['grab_state'];
+        $cond['grab_time']      = $fcode['grab_time'];
+        $cond['session_id']     = $fcode['session_id'];
+        $cond['mobile']         = $fcode['mobile'];
+
+        $datas = array( 'grab_state' => 2,
+            'grab_time' => time(),
+            'session_id' => session_helper::session_id(),
+            'mobile' => session_helper::cur_mobile(),
+            'fc_state' => 3,
+            'pay_sn' => $pay_sn,
+            'user_key' => mt_rand(1000, 9999));
+
+        try
+        {
+            $this->mod_fcode->beginTransaction();
+            $ret = $this->mod_fcode->where($cond)->update($datas);
+            $affect_rows = $this->mod_fcode->affected_rows();
+            $this->mod_fcode->commit();
+
+            Log::record("fcode::grab try_grab ret={$ret} affected_rows={$affect_rows}",Log::DEBUG);
+            if($ret != false && $affect_rows > 0) {
+                $fcode = array_merge($fcode,$datas);
+                return $fcode;
+            } else {
+                return false;
+            }
+        } catch (Exception $ex) {
+            $this->mod_fcode->rollback();
+            return false;
+        }
+    }
+
     private function try_grab($fcode)
     {
         $cond = [];

+ 41 - 20
helper/fcode/send_manager.php

@@ -20,8 +20,8 @@ class send_manager
 {
     public static $stInstance;
     private $mGoodsBlock;
-    private $mConfirmGoods; //确认收获后赠送的F码商品。
-    private $mPayGoods;     //支付后送的F码商品。
+    private $mNormalGoods;
+    private $mAdditionGoods;
 
     private function __construct()
     {
@@ -42,7 +42,7 @@ class send_manager
 
     private function init()
     {
-        $this->mConfirmGoods = [];
+        $this->mNormalGoods = [];
         $this->mGoodsBlock  = [];
 
         global $config;
@@ -67,41 +67,62 @@ class send_manager
             }
         }
 
-        krsort($this->mConfirmGoods);
+        krsort($this->mNormalGoods);
     }
 
     private function add($amount,$item,$block)
     {
         global $config;
-        $pay_gids = $config['autosend_fcodes']['pay_goodsids'];
+        $add_gids = $config['autosend_fcodes']['additional_goodsids'];
 
         $goods_id = intval($item['data']);
         if($goods_id <= 0) return;
 
-        if(!empty($pay_gids) && is_array($pay_gids) && in_array($goods_id,$pay_gids))
+        if(!empty($add_gids) && is_array($add_gids) && in_array($goods_id,$add_gids))
         {
-            if(array_key_exists($amount,$this->mConfirmGoods) == false) {
-                $this->mPayGoods[$amount] = [];
+            if(array_key_exists($amount,$this->mNormalGoods) == false) {
+                $this->mAdditionGoods[$amount] = [];
             }
-            $this->mPayGoods[$amount][] = $goods_id;
+            $this->mAdditionGoods[$amount][] = $goods_id;
         }
         else
         {
-            if(array_key_exists($amount,$this->mConfirmGoods) == false) {
-                $this->mConfirmGoods[$amount] = [];
+            if(array_key_exists($amount,$this->mNormalGoods) == false) {
+                $this->mNormalGoods[$amount] = [];
             }
-            $this->mConfirmGoods[$amount][] = $goods_id;
+            $this->mNormalGoods[$amount][] = $goods_id;
         }
         $this->mGoodsBlock[$goods_id] = $block;
     }
 
-    public function fetch_pay($amount)
+    public function fetch($amount,$pay_sn)
+    {
+        $normal = $this->fetch_normal($amount,$pay_sn);
+        $addition = $this->fetch_addition($amount,$pay_sn);
+
+        $result = [];
+        if(empty($normal)) {
+            return $addition;
+        }
+        if(empty($addition)) {
+            return $normal;
+        }
+
+        $result['banner'][] = $normal['banner'];
+        $result['banner'][] = $addition['banner'];
+        $result['fcode'][]  = $normal['fcode'];
+        $result['fcode'][]  = $addition['fcode'];
+
+        return $result;
+    }
+
+    public function fetch_addition($amount,$pay_sn)
     {
         $amount = intval($amount);
         if($amount <= 0) return false;
 
         $gids = [];
-        foreach ($this->mPayGoods as $key => $goods_ids)
+        foreach ($this->mAdditionGoods as $key => $goods_ids)
         {
             if(empty($goods_ids)) continue;
 
@@ -116,17 +137,17 @@ class send_manager
             return false;
         }
 
-        $result = $this->validate_one($gids);
+        $result = $this->validate_one($gids,$pay_sn);
         return $result;
     }
 
-    public function fetch_confirm($amount)
+    public function fetch_normal($amount,$pay_sn)
     {
         $amount = intval($amount);
         if($amount <= 0) return false;
 
         $gids = [];
-        foreach ($this->mConfirmGoods as $key => $goods_ids)
+        foreach ($this->mNormalGoods as $key => $goods_ids)
         {
             if(empty($goods_ids)) continue;
 
@@ -141,11 +162,11 @@ class send_manager
             return false;
         }
 
-        $result = $this->validate_one($gids);
+        $result = $this->validate_one($gids,$pay_sn);
         return $result;
     }
 
-    private function validate_one($gids)
+    private function validate_one($gids,$pay_sn)
     {
         $mod_goods  = Model('goods');
         $goods_list = $mod_goods->getGoodsOnlineList(array('goods_id' => array('in', $gids),'goods_storage' => array('gt',0),'is_fcode' => 1));
@@ -169,7 +190,7 @@ class send_manager
                 $oper = new operator($commonid,$batch_code);
 
                 if($oper->grabed()) continue;
-                $fcode = $oper->grab();
+                $fcode = $oper->lock($pay_sn);
                 if($fcode != false) {
                     return ['fcode' => $fcode,'banner' => $block];
                 }

+ 1 - 1
helper/model/goods_common.php

@@ -56,7 +56,7 @@ class common_sumary extends common_base
 
         if($is_fcode) {
             $fcode = new user_session\fcode();
-            $ret['has_fcode'] = $fcode->common_has_code($this->commonid) == false ? false : true;
+            $ret['has_fcode'] = $fcode->usable_num($this->commonid,$lock_num) == false ? false : true;
         } else {
             $ret['has_fcode'] = false;
         }

+ 2 - 2
helper/model/goods_summary.php

@@ -153,7 +153,7 @@ class goods_summary
         }
 
         global $config;
-        if($act_id == false) // && empty($this->bundles)
+        if($act_id == false)
         {
             $summary['bonus_price']  = predeposit_helper::login_bonus_price($this->goods_info['goods_price'],$rates);
             $gap = predeposit_helper::discount_gap($summary['bonus_price'],$this->goods_info['goods_price']);
@@ -179,7 +179,7 @@ class goods_summary
 
         if($is_fcode) {
             $fcode = new user_session\fcode();
-            $summary['has_fcode'] = $fcode->goods_has_code($this->goods_id) == false ? false : true;
+            $summary['has_fcode'] = $fcode->goods_has_code($this->goods_id,$lock_num) == false ? false : true;
         } else {
             $summary['has_fcode'] = false;
         }

+ 6 - 1
helper/pay_helper.php

@@ -108,11 +108,16 @@ class pay_helper
         }
     }
 
-    public static function confirm($pay_sn,&$err,&$amount)
+    public static function confirm($pay_sn,&$err,&$amount,&$fcode_state)
     {
         $logic_payment = Logic('payment');
         $result = $logic_payment->getRealOrderInfo($pay_sn);
+        if(empty($result)) {
+            $err = ['code'=> errcode::ErrOrder,'msg' => '无此订单.'];
+            return false;
+        }
         $amount = $result['data']['api_pay_amount'];
+        $fcode_state = intval($result['data']['fcode_state']);
 
         if (intval($result['data']['api_pay_state']) == 0) {
             $err = ['code'=> errcode::ErrOrder,'msg' => '此订单未完成支付.'];

+ 14 - 3
helper/push_helper.php

@@ -109,17 +109,28 @@ class push_helper
         QueueClient::push('upushSendMsg',$push_param);
     }
 
-    public static function notice_expring($member_id,$amount,$remain_days)
+    public static function fcode_unlock($member_id,$num)
     {
         $param = array();
         $param['member_id'] = $member_id;
-        $param['text'] = "红包过期通知:您价值{$amount}元的红包即将在{$remain_days}天内过期,,尽快使用或者慷慨地分享给好朋友吧~";
-        $param['go_type'] = 'bonus';
+        $param['text'] = "F码解锁通知:您有{$num}个F码已成功解锁,请注意过期时间~";
+        $param['go_type'] = 'fcode';
         $param['url']      = 'xmmz://p.lrlz.com/main/index?index=2';
 
+        QueueClient::push('upushSendMsg', $param);
+    }
+
+    public static function notice_expring($member_id,$amount,$remain_days)
+    {
+        $param = array();
+        $param['member_id'] = $member_id;
+        $param['text'] = "红包过期通知:您价值{$amount}元的红包即将在{$remain_days}天内过期,,尽快使用或者慷慨地分享给好朋友吧~";
+        $param['go_type'] = 'fcode';
+        $param['url']      = 'xmmz://p.lrlz.com/mine/fcode';
 
         QueueClient::push('upushSendMsg', $param);
     }
+
     public static function notice_expired($member_id,$amount)
     {
         $param = array();

+ 1 - 1
helper/session.php

@@ -113,7 +113,7 @@ class session
     }
     private function from_uncertain($sid)
     {
-        //$this->set_cookie($sid);
+        $this->set_cookie($sid);
         if(empty($sid))
         {
             return '';

+ 8 - 3
helper/user_session/fcode.php

@@ -78,18 +78,20 @@ class fcode
         }
     }
 
-    public function goods_has_code($goods_id)
+    public function goods_has_code($goods_id,&$lock_num)
     {
+        $lock_num = 0;
         $common_id = commonid_helper::instance()->common_id($goods_id);
         if($common_id == false) {
             return false;
         }
 
-        return $this->common_has_code($common_id);
+        return $this->usable_num($common_id,$lock_num);
     }
 
-    public function common_has_code($common_id)
+    public function usable_num($common_id,&$lock_num)
     {
+        $lock_num = 0;
         if(session_helper::logined() == false) {
             return false;
         }
@@ -105,6 +107,9 @@ class fcode
                 if($fcoder->can_use()) {
                     $total += 1;
                 }
+                if($fcoder->locked()) {
+                    $lock_num += 1;
+                }
             }
             return ($total == 0 ? false : $total);
         }

+ 8 - 3
mobile/control/cart.php

@@ -578,9 +578,14 @@ class cartControl extends mobileControl
                     $this->mUserFcode->onStatus();
                 }
                 $goods_id = intval($goods_info['goods_id']);
-                $num = $this->mUserFcode->goods_has_code($goods_id);
-                if($num == false) {
-                    return array('code' => errcode::ErrLogin, 'msg' => '您没有该商品F码,请领取F码后再购买.');
+                $num = $this->mUserFcode->goods_has_code($goods_id,$lock_num);
+                if($num == false)
+                {
+                    if($lock_num > 0) {
+                        return array('code' => errcode::ErrLogin, 'msg' => '等确认收货后该商品的F码才可以使用.');
+                    } else {
+                        return array('code' => errcode::ErrLogin, 'msg' => '您没有该商品F码,请领取F码后再购买.');
+                    }
                 }
                 elseif($num < $quantity) {
                     return array('code' => errcode::ErrLogin, 'msg' => "该商品F码,只够购买{$num}支.");

+ 42 - 18
mobile/control/member_buy.php

@@ -21,8 +21,13 @@ require_once (BASE_ROOT_PATH . '/helper/user_session/fcode.php');
 
 class member_buyControl extends mbMemberControl
 {
+    private $mFcodeBannerID;
+
     public function __construct() {
         parent::__construct();
+
+        global $config;
+        $this->mFcodeBannerID = $config['autosend_fcodes']['pay_page_specialid'];
     }
 
     public function step_firstOp()
@@ -128,30 +133,14 @@ class member_buyControl extends mbMemberControl
         if(empty($pay_sn)) {
             return self::outerr(errcode::ErrParamter,"支付号或者支付类型错误");
         }
-        $paied = pay_helper::confirm($pay_sn,$err,$amount);
+        $paied = pay_helper::confirm($pay_sn,$err,$amount,$fcode_state);
         if($paied == false) {
             return self::outerr($err['code'],$err['msg']);
         }
         else
         {
-            $amount = 50;
-            $result = fcode\send_manager::instance()->fetch_pay($amount);
-            if($result != false)
+            if($fcode_state == 1)
             {
-                $fcode = new user_session\fcode();
-                $fcode->onStatus();
-
-                $fcode = $result['fcode'];
-                $block = $result['banner'];
-
-                $blocks[] = $block;
-                return self::outsuccess(array('special_list' => $blocks,
-                    'summary'  => null,
-                    'groupbuy' => null,
-                    'limitime' => null,
-                    'bundling' => null,
-                    'mobile_page' => mobile_page(1)));
-            } else {
                 return self::outsuccess(array('special_list' => null,
                     'summary'  => null,
                     'groupbuy' => null,
@@ -159,6 +148,41 @@ class member_buyControl extends mbMemberControl
                     'bundling' => null,
                     'mobile_page' => mobile_page(1)));
             }
+            else
+            {
+                $amount = 500;
+                $result = fcode\send_manager::instance()->fetch($amount,$pay_sn);
+                if($result != false)
+                {
+                    $fcode = new user_session\fcode();
+                    $fcode->onStatus();
+
+                    if($this->mFcodeBannerID > 0) {
+                        $blocks = special_manager::instance()->special($this->mFcodeBannerID,$unused_gids);
+                    }
+                    else {
+                        $blocks = [];
+                    }
+
+                    foreach ($result['banner'] as $block) {
+                        $blocks[] = $block;
+                    }
+
+                    return self::outsuccess(array('special_list' => $blocks,
+                        'summary'  => null,
+                        'groupbuy' => null,
+                        'limitime' => null,
+                        'bundling' => null,
+                        'mobile_page' => mobile_page(1)));
+                } else {
+                    return self::outsuccess(array('special_list' => null,
+                        'summary'  => null,
+                        'groupbuy' => null,
+                        'limitime' => null,
+                        'bundling' => null,
+                        'mobile_page' => mobile_page(1)));
+                }
+            }
         }
     }
 

+ 0 - 1
mobile/control/member_fcode.php

@@ -11,7 +11,6 @@ require_once (BASE_ROOT_PATH . '/helper/fcode/operator.php');
 require_once (BASE_ROOT_PATH . '/helper/user_session/fcode.php');
 require_once (BASE_ROOT_PATH . '/helper/goods_helper.php');
 require_once (BASE_ROOT_PATH . '/helper/special_helper.php');
-require_once (BASE_ROOT_PATH . '/helper/user_session/fcode.php');
 
 
 class member_fcodeControl extends mbMemberControl

+ 1 - 1
test/TestFcode.php

@@ -32,7 +32,7 @@ class TestFcode extends PHPUnit_Framework_TestCase
     public function testSendManager()
     {
         $manager = fcode\send_manager::instance();
-        $manager->fetch_confirm(600,1);
+        $manager->fetch_normal(600,1);
     }
 
     public function testGenerate()

+ 1 - 1
test/account_helperTest.php

@@ -64,7 +64,7 @@ class account_helperTest extends PHPUnit_Framework_TestCase
     }
     public function testOrderSuccess()
     {
-        account_helper::onOrderSuccess(6325);
+        account_helper::onOrderSuccess(6422);
     }
     public function testPayRefund()
     {