<?php
include_once(CORE_DIR.'/api/shop_api_object.php');
class api_b2b_2_0_payment extends shop_api_object {
    var $max_number=100;
    var $arr_pay_plugins;
    var $app_error=array(
            'not_valid_payment'=>array('no'=>'b_payment_001','debug'=>'','level'=>'error','desc'=>'支付单无效','info'=>''),
            'fail_to_create_payment'=>array('no'=>'b_payment_002','debug'=>'','level'=>'error','desc'=>'支付单生成失败','info'=>'')
    );

    function getColumns(){
        $columns=array(
            'payment_id'=>array('type'=>'int'),
            'order_id'=>array('type'=>'string'),
            'member_id'=>array('type'=>'string'),
            'account'=>array('type'=>'string'),
            'bank'=>array('type'=>'decimal'),
            'pay_account'=>array('type'=>'string'),
            'currency'=>array('type'=>'int'),  
            'money'=>array('type'=>'string'),
            'paycost'=>array('type'=>'int'),
            'cur_money'=>array('type'=>'int'),
            'pay_type'=>array('type'=>'string'),
            'payment'=>array('type'=>'string'),
            'paymethod'=>array('type'=>'string'),
            'op_id'=>array('type'=>'decimal'),
            'ip'=>array('type'=>'string'),
            't_begin'=>array('type'=>'int'),  
            't_end'=>array('type'=>'string'),
            'status'=>array('type'=>'int'),
            'memo'=>array('type'=>'int'),
            'disabled'=>array('type'=>'string'),
            'trade_no'=>array('type'=>'int')
        );
        return $columns;
    }
    
    /**
     * 获取对帐单
     *
     * @param array $data 
     *
     * @return 获取对帐单
     */
    function search_payments_by_order($data){
        //$result = $this->db->selectrow('select count(*) as all_counts from sdb_payments');
       // $result['last_modify_st_time'] = $data['last_modify_st_time'];
       // $result['last_modify_en_time'] = $data['last_modify_en_time'];
       // $where =$this->_filter($data);
     
        $data_info=$this->db->select('select '.implode(',',$data['columns']).' from sdb_payments where order_id='.$data['order_id']);
        $result['counts'] = count($data_info);
        $result['data_info'] = $data_info;
        $this->api_response('true',false,$result);
    }
    
    /**
     * 供应商订单用在线支付
     *
     * @param array $data 
     *
     * @return 供应商订单用在线支付
     */
    function online_pay_center($data){
        $order_id = $data['order_id'];
        $pay_id = $data['pay_id'];//支付方式ID
        $currency = $data['currency'];//支付币别
        
        $obj_order = $this->load_api_instance('set_dead_order','2.0');
        $obj_order->verify_order_valid($order_id,$order,'*');//验证订单有效性 
        $dealer_id = $order['dealer_id'];//todo dealer_id
        $obj_order->checkOrderStatus('pay',$order);//检查订单状态是否能够支付
        $obj_order->verify_order_item_valid($order_id,$local_order_item_list);//验证订单订单商品的有效性

        $obj_member = $this->load_api_instance('verify_member_valid','2.0');    
        $obj_member->verify_member_valid($dealer_id,$member);//根据经销商ID验证会员记录有效性
        
        $oOrder = $this->system->loadModel('trading/order');
        
        // 有预占库存时间点的设置 2010-03-24 11:30 wubin
        if(method_exists($oOrder,'getFreezeStorageStatus')) {
            // 如果没有冻结过库存 2010-03-01 17:30 wubin
            if(!$obj_order->is_freeze_store($order_id)) {
                // 验证是否够库存
                if($aTemp = $oOrder->isNotEnoughStore($order_id)) {
                    $this->api_response('fail','data fail',$result,'订单货品('.$aResult['product']['name'].')没有可下单库存');
                }        
                // 冻结库存
                $oOrder->freezeStorage($order_id);
            
                $obj_order->update_order_freeze($order_id);
            }
        } // 原处理在下订单时就已占库存
        
        
        if($pay_id != -1){
            $obj_payment_cfg = $this->load_api_instance('search_payment_cfg_list','2.0');    
            $obj_payment_cfg->verify_paymentcfg_not_advance($pay_id,$local_payment_cfg);//验证支付方式不应该是预存款支付
            $this->local_payment_cfg = $local_payment_cfg;
            $this->type = $local_payment_cfg['pay_type'];
        }else{//货到付款
            $this->type = 'offline';//与线下支付处理一致
        }
        
        if($this->type == 'offline'){//线下支付
            $act_url = 'index.php'.$this->system->mkUrl('passport','payCenterOffline');
            $html ="<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"
                \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">
                <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en-US\" lang=\"en-US\" dir=\"ltr\">
                <head>
</header><body><div>Redirecting...</div>";
            $html .= '<form id="payment" action="'.$act_url.'" method="post">';
            $html.='
                </form>
                <script language="javascript">
                document.getElementById(\'payment\').submit();
                </script>
                </html>';
                
            echo $html;
            exit;
        }
         
        $last_cost_payment = empty($order['cost_payment']) ? 0 : $order['cost_payment'];//最后次订单支付费用
        //$money = $obj_order->getPayMoney($order_id);
        $money = $order['total_amount'] - $order['payed'];//取支付金额
        $cost_payment = $local_payment_cfg['fee'] * $money;//当前支付金额支付费
        $cost_payment = $this->formatNumber($cost_payment);
        $order['total_amount'] = $order['total_amount'] + $cost_payment;//最新订单总价入库
        $order['total_amount'] = $this->getOrderDecimal($order['total_amount']);    
        $money = $order['total_amount'] - $order['payed'];//需要支付的金额
        //$order['total_amount'] = $order['total_amount'] + $cost_payment;//最新订单总价入库
          $obj_order->is_payed($money);//检查支付金额是否还需要被支付 
        $obj_order->verify_payed_valid($order,$money);//检查支付金额是否大于订单总金额    
        
        $order['payment'] = $pay_id;//指定订单支付方式
        
        $order_payment = array('order_id'=>$data['order_id'],
                               'money'=>$money,
                               'paycost'=>$cost_payment,
                               'member_id'=>$order['member_id'],
                               'currency'=>$order['currency'],
                               'payment'=>$order['payment']
                               
        );
        $payment_id = $this->create_payment($pay_id,$order_payment,'online');//生成支付单
        
        //$this->verify_payment_valid($payment_id,$payment);
        
        //通知平台支付单
        $objPlatform = &$this->system->loadModel('system/platform');
        if($objPlatform->tell_platform('payments',array('pay_id'=>$payment_id)) === false){
            $this->deletePayment($payment_id);
            $this->api_response('fail','data fail',$result,$objPlatform->getErrorInfo());
        }
        
         //设置订单支付费用,加上上次的支付费用
        //$curr_cost_payment = $last_cost_payment + $cost_payment;
        //$obj_order->set_order_payment($order_id,$curr_cost_payment);
        
        $obj_order->changeOrderPayment($order_id,$pay_id);//改变支付方式
        //$obj_order->update_order($order['order_id'],array('total_amount'=>$total_amount));
        //$order['total_amount'] = $total_amount; 
        $this->dopay($order,$member,$payment_id,$money,$currency);//选择支付方式进行支付   
    }
    
    /**
     * 选择支付方式
     *
     *
     *
     * @return 选择支付方式
     */
    function dopay($order,$member,$payment_id,$money,$currency){
        $payObj = $this->loadMethod($this->type);
          if ($payObj->head_charset)
                header("Content-Type: text/html;charset=".$payObj->head_charset);

            $html ="<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"
                \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">
                <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en-US\" lang=\"en-US\" dir=\"ltr\">
                <head>
</header><body><div>Redirecting...</div>";
//            $this->money += $this->paycost;（money中 已经包含paycost）
            $payObj->_payment = $this->payment;
            $toSubmit = $payObj->toSubmit($this->getPaymentInfo($order,$member,$payment_id,$money,$currency));
            if('utf8' != strtolower($payObj->charset)){    
                $charset = &$this->system->loadModel('utility/charset');
                foreach($toSubmit as $k=>$v){
                    if(!is_numeric($v)){
                        $toSubmit[$k] = $charset->utf2local($v,'zh');
                    }
                }
            }

            $html .= '<form id="payment" action="'.$payObj->submitUrl.'" method="'.$payObj->method.'">';
            foreach($toSubmit as $k=>$v){
                if ($k<>"ikey"){
                    $html.='<input name="'.urldecode($k).'" type="hidden" value="'.htmlspecialchars($v).'" />';
                    if ($v){
                        $buffer.=urldecode($k)."=".$v."&";
                    }
                }
            }
            if (strtoupper($this->type)=="TENPAYTRAD"){
                $buffer=substr($buffer,0,strlen($buffer)-1);
                $md5_sign=strtoupper(md5($buffer."&key=".$toSubmit['ikey']));

                $url=$payObj->submitUrl."?".$buffer."&sign=".$md5_sign;
                echo "<script language='javascript'>";
                echo "window.location.href='".$url."';";
                echo "</script>";
            }
            $html.='
            </form>
            <script language="javascript">
            document.getElementById(\'payment\').submit();
            </script>
            </html>';
            
            echo $html;
    }
    
    
      /**
     * 生成付款单
     *
     * @param array $data 
     *
     * @return 生成付款单
     */
    function create_payment($pay_id,$data,$pay_type = 'deposit'){
        $order_id = $data['order_id'];
        $money = $data['money'];
        
        $this->paycost = $data['paycost'];
        $this->payment_id = $this->gen_id();
        $this->order_id = $order_id;
        $this->member_id = $data['member_id'];
        $this->bank = $pay_type;
        $this->currency = !empty($data['currency']) ? $data['currency'] : 'CNY';
        $this->money = $money;
        $this->pay_type = $pay_type;
        $this->payment = $data['payment'];
        $this->t_begin = time();
        $this->t_end = time();
        $this->status = $pay_type == 'deposit' ? 'succ' : 'ready';
        $this->memo = '远程支付成功！';
        
        if($pay_type == 'deposit'){
            $this->cur_money = $this->money;
        }else{
           if($this->currency != 'CNY'){
             //实际费用计算
              $currency = $this->getcur($this->currency);
              $cur_rate = ($currency['cur_rate']>0 ? $currency['cur_rate']:1);
              $this->cur_money = $this->money * $cur_rate;
           }else{
              $this->cur_money = $this->money;
           }
        }
       
        if($payCfg = $this->db->selectrow('SELECT pay_type,fee,custom_name FROM sdb_payment_cfg WHERE id='.intval($pay_id))){
            //$this->paycost = $this->money * $payCfg['fee'] / (1+$payCfg['fee']);
           // $this->paycost = $this->formatNumber($this->paycost);
            $this->paymethod = addslashes($payCfg['custom_name']);//by sy 转义支付方式引号
        }
        $aRs = $this->db->query('SELECT * FROM sdb_payments WHERE 0=1');
        $sSql = $this->db->GetInsertSQL($aRs,$this);
        if($this->db->exec($sSql)){
            return $this->payment_id;
        }else{
            $this->add_application_error('fail_to_create_payment');
        }
    }

    function loadMethod($payPlugin){
        if(!isset($this->arr_pay_plugins[$payPlugin])){
            require_once(PLUGIN_DIR.'/payment/pay.'.$payPlugin.'.php');
    
            $className = 'pay_'.$payPlugin;
            $method = new $className($this->system);
            $this->arr_pay_plugins[$payPlugin] = $method;
        }else{
            $method = $this->arr_pay_plugins[$payPlugin];
        }
        
        return $method;
    }
    
    function getPaymentInfo($order,$member,$payment_id,$money,$currency){
        $payment['M_OrderId'] = $payment_id;        //    订单的id---支付流水号
        $payment['M_OrderNO'] = $order['order_id'];        //    订单号
        $payment['M_Amount'] = $money;        //    本次支付金额        小数点后保留两位，如10或12.34
        $payment['M_Def_Amount'] = $money;        //    本次支付本位币金额        小数点后保留两位，如10或12.34
        $payment['M_Currency'] = $currency;    //    支付币种
        $payment['M_Remark'] = $order['memo'];        //    订单备注
        $payment['M_Time'] = $order['createtime'];        //    订单生成时间
        $payment['M_Language'] = 'zh_CN';    //    语言选择        表示商家使用的页面语言
        $payment['R_Name'] = $order['ship_name'];        //    收货人姓名    订单支付成功后货品收货人的姓名
        $payment['R_Address'] = $order['ship_addr'];        //    收货人住址    订单支付成功后货品收货人的住址
        $payment['R_Postcode'] = $order['ship_zip'];    //    收货人邮政编码    订单支付成功后货品收货人的住址所在地的邮政编码
        $payment['R_Telephone'] = $order['ship_tel'];    //    收货人联系电话    订单支付成功后货品收货人的联系电话
        $payment['R_Mobile'] = $order['ship_mobile'];        //    收货人移动电话    订单支付成功后货品收货人的移动电话
        $payment['R_Email'] = $order['ship_email'];        //    收货人电子邮件地址    订单支付成功后货品收货人的邮件地址
        $payment['P_Name'] = $member['name'];        //    付款人姓名    支付时消费者的姓名
        $payment['P_Address'] = $member['addr'];        //    付款人住址    进行订单支付的消费者的住址
        $payment['P_PostCode'] = $member['zip'];    //    付款人邮政编码        进行订单支付的消费者住址的邮政编码
        $payment['P_Telephone'] = $member['tel'];    //    付款人联系电话     进行订单支付的消费者的联系电话
        $payment['P_Mobile'] = $member['mobile'];        //    付款人移动电话     进行订单支付的消费者的移动电话
        $payment['P_Email'] = $member['email'];        //    付款人电子邮件地址     进行订单支付的消费者的电子邮件地址
        $payment['K_key'] = $this->system->getConf('certificate.token');    //商店Key
        $configinfo = $this->local_payment_cfg;
        $pma=$this->getPaymentFileName($configinfo['config'],$configinfo['pay_type']);
        if (is_array($pma)){
            foreach($pma as $key => $val){
                $payment[$key]=$val;
            }
        }
        return $payment;
    }
  
    function getPaymentFileName($config,$ptype){//获取支付所需文件，如密钥文件、公钥文件
        if(!empty($config)){//添加
            $pmt=$this->loadMethod($ptype);
            $field=$pmt->getfields();
            $config=unserialize($config);
            if (is_array($config)){
                foreach($field as $k => $v){
                    if (strtoupper($v['type'])=="FILE"||$k=="keyPass")//判断支付网关是否有文件或者是私钥保护密码
                        $payment[$k] = $config[$k];
                }
            }
        }
        return $payment;
    }
    
    /**
     * 取回格式化的数据，供运算使用
     *
     * @param int $number
     *
     * @return string $number
     */
    function formatNumber($number){
        $decimals = $this->system->getConf('system.money.operation.decimals');
        $carryset = $this->system->getConf('system.money.operation.carryset');
        if($decimals < 3){
            $mul = 1;
            $mul = pow(10, $decimals);
            switch($carryset){
                case 0:
                $number = number_format($number, $decimals, '.', '');
                break;
                case 1:
                $number = ceil($number*$mul) / $mul;
                break;
                case 2:
                $number = floor($number*$mul) / $mul;
                break;
            }
        }
        return $number;
    }
    
    /**
     * 订单金额 订单金额取整方式 订单金额取整位数
     *
     * @param int $number
     *
     * @return string $number
     */
    function getOrderDecimal($number){
        $decimal_digit = $this->system->getConf('site.decimal_digit');
        $decimal_type = $this->system->getConf('site.decimal_type');
        if($decimal_digit < 3){
            $mul = 1;
            $mul = pow(10, $decimal_digit);
            switch($decimal_type){
                case 0:
                $number = number_format($number, $decimal_digit, '.', '');
                break;
                case 1:
                $number = ceil($number*$mul) / $mul;
                break;
                case 2:
                $number = floor($number*$mul) / $mul;
                break;
            }
        }
        return $number;
    }
    
    /**
     * 生成支付单号
     *
     * @param 
     *
     * @return int $number
     */
    function gen_id(){
        $i = rand(0,9999);
        do{
            if(9999==$i){
                $i=0;
            }
            $i++;
            $payment_id = time().str_pad($i,4,'0',STR_PAD_LEFT);
            $row = $this->db->selectrow('select payment_id from sdb_payments where payment_id =\''.$payment_id.'\'');
        }while($row);
        return $payment_id;
    }
    
    function getcur($id, $getDef=false){
        $aCur = $this->db->selectrow('select * FROM sdb_currency where cur_code="'.$id.'"');
        if($aCur['cur_code'] || !$getDef){
            return $this->_in_cur = $aCur;
        }else{
            return $this->_in_cur = $this->getDefault();
        }
    }
    
    function getDefault(){
        if($cur = $this->db->selectrow('select * from sdb_currency where def_cur=1')){
            return $cur;
        }else{    //if have no default currency, read the first currency as default value
            return $this->db->selectrow('select * FROM sdb_currency');
        }
    }
    
    function verify_payment_valid($paymentId,& $payment){
        $aTemp = $this->db->selectrow('SELECT * FROM sdb_payments WHERE payment_id=\''.$paymentId.'\'');
        if(!$aTemp['payment_id']){
            $this->add_application_error('not_valid_payment');
        }
       
        $payment = $aTemp;
    }
    
    function deletePayment($sId=null){
        if($sId){
            $sSql = 'DELETE FROM sdb_payments WHERE payment_id in ('.$sId.')';
            return (!$sSql || $this->db->exec($sSql));
        }
        return false;
    }
    
    function changer($money){
         $_money_format = array(
            'decimals' => $this->system->getConf('system.money.operation.decimals'),
            'carryset' => $this->system->getConf('system.money.operation.carryset'),
            'dec_point' => $this->system->getConf('system.money.dec_point'),
            'thousands_sep' => $this->system->getConf('system.money.thousands_sep'),
            'decimal_digit' => $this->system->getConf('site.decimal_digit'),
            'decimal_type' => $this->system->getConf('site.decimal_type'),
            'trigger_tax' => $this->system->getConf('site.trigger_tax'),
            'tax_ratio' => $this->system->getConf('site.tax_ratio')
          );
          
          if($_money_format['carryset']){
            $mul = 1;
            $mul = pow(10, $_money_format['decimals']);
            switch($_money_format['carryset']){
                case 0:
                    $money = number_format(trim($money), $_money_format['decimals'], '.', '');
                break;
                case 1:
                    $money = ceil(trim($money)*$mul) / $mul;
                break;
                case 2:
                    $money = floor(trim($money)*$mul) / $mul;
                break;
            }
        }
        return  number_format($money,
                $_money_format['decimals'],
                $_money_format['dec_point'],
                $_money_format['thousands_sep']);
        
    }
}