['_multi' => true, ['egt', $start], ['lt', $end]], 'inner_status' => 0]; $order_id = 0; $i = 0; while (true) { $cond['order_id'] = ['gt', $order_id]; // $start = $i * 1000; $start = 0; $items = Model()->table('refill_order') ->field('order_id,mchid,mch_order,order_time') ->where($cond) ->order('order_id asc')->limit("{$start},1000")->select(); $i++; if(empty($items)) break; $last_item = end($items); $order_id = intval($last_item['order_id']); foreach ($items as $item) { unset($item['order_id']); yield $item; } } }; $mchorder_saver = function ($start,$file) use ($mchorder_gen) { if (file_exists($file)) { return true; } $fp = fopen($file,'w'); if($fp === false) { Log::record("Cannot open file {$file} with write.",Log::ERR); return false; } $end = $start + 86400; for ($hour = $start; $hour < $end; $hour += 3600) { $orders = $mchorder_gen($hour); foreach ($orders as $order) { $ret = fputcsv($fp,$order); if($ret === false) { return false; } } } fclose($fp); return true; }; $handle_days = function ($start_date, $end_date,$line = 0) use ($mchorder_saver) { for ($date = $start_date; $date < $end_date; $date += 86400) { $sdate = date('Y-m-d',$date); $morder_file = BASE_DATA_PATH . "/log/order/{$sdate}-morder.csv"; $check_file = BASE_DATA_PATH . "/log/order/{$sdate}-check.csv"; $refill_file = BASE_DATA_PATH . "/log/order/{$sdate}-refill.csv"; $vr_file = BASE_DATA_PATH . "/log/order/{$sdate}-vr.csv"; $ret = $mchorder_saver($date,$morder_file); if($ret === false) { Log::record("fetch or save {$sdate} mch_order fail.",Log::ERR); break; } $this->order_delete($morder_file,$check_file,$refill_file,$vr_file,$line); } }; $handle_days($start_date, $end_date,$start_line); } private function order_delete($mch_file, $check_file, $refill_file, $vr_file, $line) { $rorder_getter = function ($mchid,$mch_order,$mod_refill) { $result = []; $i = 0; while(true) { $start = $i * 1000; $ritems = $mod_refill->table('refill_order')->field('*') ->where(['mchid' => $mchid, 'mch_order' => $mch_order]) ->order('order_id asc') ->limit("{$start},1000")->master(true)->select(); $i++; $result = array_merge($ritems,$result); if(count($ritems) < 1000) { break; } } return $result; }; $vorder_getter = function ($order_ids,$mod_vr) { $result = []; $i = 0; while(true) { $start = $i * 1000; $vitems = $mod_vr->table('vr_order')->field('*') ->where(['order_id' => ['in', $order_ids]]) ->order('order_id asc') ->limit("{$start},1000")->master(true)->select(); $i++; $result = array_merge($vitems,$result); if(count($vitems) < 1000) { break; } } return $result; }; $order_checker = function ($mchid,$mch_order,$frefill,$fvr) use($rorder_getter,$vorder_getter) { $mod_refill = Model('refill_order'); $ritems = $rorder_getter($mchid,$mch_order,$mod_refill); if(empty($ritems)) { return [false, [], 'order count = 0']; } $oids = []; $inner_state = [0 => 0 ,1 => 0]; $is_retrying = 0; $mch_notify_counts = 0; foreach ($ritems as $item) { $oids[] = $item['order_id']; $state = intval($item['inner_status']); $inner_state[$state] += 1; $mch_notify_counts += intval($item['mch_notify_state']) >= 1 ? 1 : 0; if($state === 0 && $is_retrying === 0) { $is_retrying = intval($item['is_retrying']); } } //检查inner_status=0唯一性。 if($inner_state[0] != 1) { return [false, [], "inner_status=0 counts={$inner_state[0]}"]; } if($mch_notify_counts === 0) { return [false, [], "not notify merchant"]; } elseif($mch_notify_counts > 1) { return [false, [], "more than one order notify merchant"]; } if($is_retrying) { return [false, [], 'is_retrying = 1']; } $mod_vr = Model('vr_order'); $vitems = $vorder_getter($oids,$mod_vr); //检查refill 表记录和vr_order表记录是否一致 if(count($ritems) !== count($vitems)) { return [false, [], 'refill count != vr count']; } $order_state = []; foreach ($vitems as $item) { $state = intval($item['order_state']); if(!array_key_exists($state,$order_state)) { $order_state[$state] = 0; } $order_state[$state] += 1; } //检查一种订单只能有,成功或者失败状态. $vcount = count($vitems); if($vcount != $order_state[ORDER_STATE_SUCCESS] + $order_state[ORDER_STATE_CANCEL]) { return [false, [], 'ORDER: SUCCESS + CANCEL != COUNT.']; } elseif($order_state[ORDER_STATE_SUCCESS] > 1) { //成功订单只能小于等于1,否则为错误 return [false, [], 'ORDER:SUCCESS COUNT > 1']; } else { // foreach ($ritems as $item) { // fputcsv($frefill,$item); // } // foreach ($vitems as $item) { // fputcsv($fvr,$item); // } } $inner_oids = []; foreach ($ritems as $item) { $status = intval($item['inner_status']); if($status === 1) { $inner_oids[] = $item['order_id']; } } return [true,$inner_oids,'']; }; $delter = function ($order_ids,$order_time) { if(empty($order_ids)) return; try { $mod_refill = Model('refill_order'); $mod_vr = Model('vr_order'); $trans = new trans_wapper($mod_refill, __METHOD__); $mod_refill->table('refill_order')->where(['order_id' => ['in',$order_ids],'order_time' => $order_time])->delete(); $mod_vr->table('vr_order')->where(['order_id' => ['in',$order_ids]])->delete(); $trans->commit(); } catch (Exception $e) { $trans->rollback(); } }; $file_opener = function ($mch_file, $check_file, $refill_file, $vr_file) { $fp = fopen($mch_file,'r'); $fcheck = fopen($check_file,'a+'); $frefill = fopen($refill_file,'a+'); $fvr = fopen($vr_file,'a+'); if($fp === false || $fcheck === false || $frefill === false || $fvr === false) { if($fp !== false) { fclose($fp); } if($fcheck !== false) { fclose($fcheck); } if($frefill !== false) { fclose($frefill); } if($fvr !== false) { fclose($fvr); } return [false,false,false,false,false]; } else { return [true,$fp,$fcheck,$frefill,$fvr]; } }; $file_closer = function($files) { foreach ($files as $fp) { fclose($fp); } }; $goto_line = function ($fp,$line) { $index = 0; while(!feof($fp) && $index < $line) { $items = fgetcsv($fp); $index += 1; } }; $mch_order_reader = function($fp) { while(!feof($fp)) { [$mchid, $mch_order, $order_time] = fgetcsv($fp); if(empty($mchid) || empty($mch_order)) continue; yield [$mchid,$mch_order,$order_time]; } }; $mod_refill_err = Model('refill_error'); $err_recorder = function($fcheck,$mchid,$mch_order,$order_time,$err) use($mod_refill_err) { fputcsv($fcheck,[$mchid,$mch_order,$err]); $mod_refill_err->insert(['mchid' => $mchid, 'mch_order' => $mch_order, 'order_time' => $order_time, 'msg' => $err, 'add_time' => time()]); }; //////////////////////////////////////////////////////////////////////////////////////////////////////////////// [$succ,$fp,$fcheck,$frefill,$fvr] = $file_opener($mch_file, $check_file, $refill_file, $vr_file); if(!$succ) { return false; } $goto_line($fp,$line); $mch_orders = $mch_order_reader($fp); foreach ($mch_orders as $order) { [$mchid, $mch_order, $order_time] = $order; [$succ, $order_ids, $err] = $order_checker($mchid, $mch_order, $frefill, $fvr); if ($succ) { $delter($order_ids, $order_time); } else { $err_recorder($fcheck, $mchid, $mch_order, $order_time, $err); } } $file_closer([$fp,$fcheck,$frefill,$fvr]); return true; } }