<?php defined('CORE_DIR') || exit('入口错误'); 

/******************
Certificate 处理 授权机制需要优化
******************/

class mdl_certificate extends modelFactory {

    function getSessValid(){
        if( !$sess = $this->system->getConf('system.sess') ) {
            $sess = microtime();
            $this->system->setConf('system.sess',$sess);
        }
        return $sess;
    }

    function getCerti(){
        return $this->system->getConf('certificate.id');
    }

    function getToken(){
        return $this->system->getConf('certificate.token');
    }

    function getNodeid(){
        return $this->system->getConf('certificate.node_id');
    }

    function getent_id(){
        return $this->system->getConf('enterprise.ent_id');
    }
    
    function getent_ac(){
        return $this->system->getConf('enterprise.ent_ac');
    }
    
    function getent_sign(){
        return $this->system->getConf('enterprise.ent_sign');
    }
    
    function getent_email(){
        return $this->system->getConf('enterprise.ent_email');
    }

    
    function get_app_instance_id($app_id){
        if(empty($this->app_instance_id)){
            $return = "";
            
            $post = array(
                'certi_app' => 'app.get_instance_list',
                'app_id' => VERIFY_APP_ID,
                'version' => '1.0',
                'certi_url' => $this->system->base_url(),
                'certi_validate_url' => $this->system->base_url().SHOPADMIN_PATH."/index.php?ctl=passport&act=certi_validate",
                'format' => 'json'
            );
            $post['certi_ac'] = $this->make_shopex_ac($post,$this->getToken());
            $sess_id = $this->getSessValid();
               $post['certi_session'] = $sess_id; 

            $instance_list = $this->read_shopex_server($post);
            
            if($instance_list['res'] == 'succ'){
                $return = implode("|",$instance_list['info']);
            }else{
                $return = "";
            }
            
            $this->app_instance_id = $return;
        }else{
            $return = $this->app_instance_id;
        }
        
        return $return;
    }

    function to_shopex_certificate($certi_app,$format='json'){
        $post = array(
            'certi_app' => $certi_app,
            'certificate_id' => $this->getCerti(),
            'app_id' => VERIFY_APP_ID,
            'app_instance_id' => $this->get_app_instance_id(VERIFY_APP_ID),
            'version' => '0.14',//1.0
            'certi_url' => $this->system->base_url(),
            'certi_validate_url' => $this->system->base_url().SHOPADMIN_PATH."/index.php?ctl=passport&act=certi_validate",
            'format' => $format,
            'ver_detail'=>$this->getVersion()//shop_version
        );
        
        if( $certi_app == 'certi.login' ) {
            $post['email']=$this->getent_email();
            $post['entid']=$this->getent_id();
        } elseif($certi_app=='certi.reg') {
            $post['refer']='yikaidan';
            unset($post['version'],$post['certificate_id']);
            $post['product_key'] = VERIFY_APP_ID;
            $post['identifier']=$this->getent_id();
            $post['password']=$this->getent_ac();
            $post['version']='1.2';
        }
        
        $post['certi_session'] = $this->getSessValid();
        $post['certi_ac'] = $this->make_shopex_ac($post,$this->getToken());

        $callback=$this->read_shopex_server($post);

        return $callback;
    }

    function ent_to_shopex_enterprise($certi_app,$ent_data){
        $post_entlogin['certi_app']=$certi_app;
        $post_entlogin['identifier']=$ent_data;
        $post_entlogin['version']='1.0';
        $post_entlogin['format']='json';
        $post_entlogin['certi_ac']=$this->make_shopex_ac($post_entlogin,'962d93c3702255fc40cbcc6fe766c6a8');

        $resp = $this->system->loadModel('utility/http_client')->post(SHOP_USER_ENTERPRISE_API, $post_entlogin);
        $resp = json_decode($resp,1);
        return 'succ' == $resp['res'];
    }

    function make_shopex_ac($temp_arr,$token=''){
        ksort($temp_arr);
        $str = '';
        foreach($temp_arr as $key=>$value){
            if('certi_ac' != $key && 'sign' != $key ) {
                $str.=$value;
            }
        }
        return md5($str.($token ? $token : $this->getToken()));
    }

    function get_sess(){
        return $this->system->getConf('system.sess');
    }

    function read_shopex_server($post){
        $net = $this->system->loadModel('utility/http_client');
        $results=$net->post(LICENSE_CENTER,$post);
        return json_decode(strstr($results,'{'),true);
    }

    function checkValid($sStr){
        return 'valid'==$sStr ?__('激活') : __('未激活');
    }
    
    function delLicense(){
        $this->system->setConf('certificate.*','',true);
    }

    function delEnterprise() {
        $this->system->setConf('enterprise.*','',true);
    }

    function explodeStr($sStr){
        $aTmp = explode("|||", $sStr);
        return $aTmp;
    }

    function setCerti($certi_id){
        return $this->system->setConf('certificate.id',$certi_id,true);    
    }
    function setToken($token){
        return $this->system->setConf('certificate.token',$token,true);    
    }
    function setNodeid($nodeid){
        return $this->system->setConf('certificate.node_id',$nodeid,true);    
    }
     function setent_id($ent_id){
        return $this->system->setConf('enterprise.ent_id',$ent_id,true);    
    }
    function setent_ac($ent_ac){
        return $this->system->setConf('enterprise.ent_ac',$ent_ac,true);    
    }
   function setent_sign($ent_sign){
        return $this->system->setConf('enterprise.ent_sign',$ent_sign,true);    
    }
    function setent_email($ent_email){
        return $this->system->setConf('enterprise.ent_email',$ent_email,true);    
    }

    function setStr($str){
        $this->system->setConf('certificate.str',$str);
    }

    function setFormal($state){
        $this->system->setConf('certificate.formal',$state);
    }

    function set_channel_url($url){
        $this->system->setConf('certificate.channel.url',$url);
    }
    
    function set_channel_name($name){
        $this->system->setConf('certificate.channel.name',$name);    
    }

    function set_channel_is($status){
        $this->system->setConf('certificate.channel.status',$status);
    }

    function set_channel_service($service){
        $this->system->setConf('certificate.channel.service',$service);
    }

    function get_channel_url(){
        return $this->system->getConf('certificate.channel.url');
    }
    
    function get_channel_name($name){
       return  $this->system->getConf('certificate.channel.name');    
    }
    
    function getName(){
        return $this->system->getConf('system.shopname');
    }
    
    function getSess($sess_id){
        return !!$this->db->selectrow("select * from sdb_op_sessions where sess_id=".$this->db->quote($sess_id));
    }

    function setEncode($sess_id,$certi_id){
        $ENCODEKEY='ShopEx@License';
        $confirmkey = md5($sess_id.$ENCODEKEY.$certi_id);
        return $confirmkey;
    }

    function checkFile($files){
        return !empty($files);
    }

    function checkPass($aIn){
        $aIn['userpass'] = $this->system->loadModel('admin/operator')->_md5_password($aIn['userpass'],$aIn['username']);
        $sSql = "select 1 from sdb_operators where username = '".$aIn['username']."' and userpass = '".$aIn['userpass']."' and super='1' and status='1'";
        return !!$this->db->selectrow($sSql);
    }

    function upload($tmp){
        if(!$this->checkFile($tmp)){
            return false;
        }
        $certInfo = @file($tmp);
        $line = $certInfo[0];
        list($certid,$token, $nodeid) = explode('|||',$line);
        if ( (!$certid) || (!$token || strlen($token) != 64) || (!$nodeid) ) {
            return false;
        }

        $this->delLicense();

        $this->setCerti($certid);
        $this->setToken($token);
        $this->setNodeid($nodeid);

        return true;
    }

    function msg_pack(){
        $data['ip'] = remote_addr();
        $data['url'] = $this->system->base_url();
        $data['login_time'] = mktime();
        $data['certificate_id'] = $this->getCerti();
        $data['shopname'] = $this->system->getConf('system.shopname');
        $data['ac'] = $this->make_shopex_ac($data,'ShopEx_LOG');
        return $data;
    }
    function post_data($data){
        $url = 'http://service.shopex.cn/class.license_log.php';
        $httpd=$this->system->loadModel('utility/http_client');
        $results = $httpd->post($url,$data);
        return $results;
    }

    function show_channel(){
        $net = $this->system->loadModel("utility/http_client");
        $url = 'http://service.shopex.cn/class.channel.php';
        $certificate_id=$this->getCerti();
        $ac = md5($certificate_id.'ShopEx_CHANNEL');
        $data= array('certificate_id'=>$certificate_id,
            'ac'=>$ac
        );
       $msg = $net->post($url,$data);
        if($msg && !(strpos($msg, 'true') === false)){
            $tmp=$this->explodeStr($msg);
            $this->set_channel_name($tmp[1]);
            $this->set_channel_url($tmp[2]);
            $this->set_channel_service($tmp[3]);
            $this->set_channel_is(true);
        }else{
            $this->set_channel_is(false);
        }
    }

    function getInfo(){
        set_time_limit(0);
        $this->Certi = $this->getCerti();
        $this->Token = $this->getToken();
        $this->NodeId = $this->getNodeId();
        $this->setFormal($state);
        
        if($this->Certi && $this->Token && $this->NodeId){
            $this->sendmsg();
            $this->show_channel();
            $this->setStr($str);
            $_r=$this->toLogin();
        }else{
            $this->delLicense();
            $_r=$this->toReg();
            $this->update_node_info();
        }

        $_str = explode('|',$_r);
        if((is_array($_str)&&$_str[0]=='domain_error')|| $_str[1]!=VERIFY_APP_ID){
           if($_str[1]!=VERIFY_APP_ID){
               //echo "<script>alert('由于您当前使用的网店证书不适用于shopex体系，请重新上传证书或联系shopex客服。');</script>";
               $_r = ($_str[0]=='domain_error')?$_str[2]:$_str[0];
               $str=$this->getUrl($_r);
           }else{
               echo "<script>alert('".$_str[1]."');</script>";
               $_r = $_str[2];
               $str=$this->getUrl($_r);
           }
        }else{
            $str=$this->getUrl($_str[0]);
        }

        $deskauth=$this->getUrl('授权');
        
        $str.="<script>\$('authinfo').set('html','".$deskauth."');</script>";
     
        $postionone=strpos($str,'<iframe',1);
        $strone=substr($str,0,$postionone);
        $postiontwo=strpos($str,'</iframe>',1);
        $strtwo=substr($str,$postiontwo);
        $str=$strone. $strtwo;
          
        $this->system->output($str);
    }

    function toLogin(){
        $loginToShopEx = $this->to_shopex_certificate('certi.login');
        $this->version_account();
        $etime = $loginToShopEx['info']['service'][VERIFY_APP_ID]['cert_auth']['service_time']['etime'];
        $btime = $loginToShopEx['info']['service'][VERIFY_APP_ID]['cert_auth']['service_time']['btime'];
        if( ('free' != $loginToShopEx['info']['service'][VERIFY_APP_ID]['cert_auth']['auth_str']) && ($etime < time()) ){
          $this->system->setConf('oem.service_etime','');
          $this->system->setConf('oem.service_btime','');
          //exit('<script>alert("非法授权");window.location.href="index.php?ctl=passport&act=login"</script>');
        }else{
          $this->system->setConf('oem.service_etime',$etime);
          $this->system->setConf('oem.service_btime',$btime);
          if(!class_exists('pageFactory')){
             require('pageFactory.php');
          }
          $pageFactory = new pageFactory();
          $pageFactory->clear_cache('shop:/common/header.html');

        }
        if($loginToShopEx['res'] == 'succ'){
            $str = $loginToShopEx['info']['service'][VERIFY_APP_ID]['cert_auth']['auth_strname'] . '[' . $loginToShopEx['info']['service'][VERIFY_APP_ID]['cert_auth']['auth_typename'] . '] |'.$loginToShopEx['info']['product_type'];
            $auth=$loginToShopEx['info']['service'][VERIFY_APP_ID]['cert_auth']['auth_strname'];
            $autype = $loginToShopEx['info']['service'][VERIFY_APP_ID]['cert_auth']['auth_str'];
            $this->system->setConf('certificate.auth_type',$autype);
            $this->system->setConf('certificate.auth_strname',$auth);
                  $this->setNodeid($loginToShopEx['info']['node_id']);
            if(!$this->system->getConf('certificate.distribute') && $loginToShopEx['info']['service'][VERIFY_APP_ID]['distribute']['status'] == 'open'){
                $this->system->setConf('certificate.distribute',true);
            }

        }else{
            if($loginToShopEx['msg'] == 'domain_error'){
                 $str = 'domain_error|由于您当前使用的域名与申请证书时所使用的不一致，可能会造成网店部分功能无法正常使用。请及时和shopex客服联系。|';

                 if(is_array($loginToShopEx['info']['service'])){
                     $str .= $loginToShopEx['info']['service'][VERIFY_APP_ID]['cert_auth']['auth_strname'] . '[' . $loginToShopEx['info']['service'][VERIFY_APP_ID]['cert_auth']['auth_typename'] . ']';
                 }

            }else{
                 if(is_array($loginToShopEx['info']['service'])){
                     $str = $loginToShopEx['info']['service'][VERIFY_APP_ID]['cert_auth']['auth_strname'] . '[' . $loginToShopEx['info']['service'][VERIFY_APP_ID]['cert_auth']['auth_typename'] . ']';
                 }
            }
        }
        return $str;
    }

    function toReg(){
        $regToShopEx = $this->to_shopex_certificate('certi.reg');

        if($regToShopEx['res'] == 'succ'){
            $this->setCerti($regToShopEx['info']['certificate_id']);
            $this->setToken($regToShopEx['info']['token']);
            $this->setNodeid($regToShopEx['info']['node_id']);
            $_r=$this->toLogin();
            return $_r;
        }else{
            return $regToShopEx['info']['auth_strname'] . '[' . $regToShopEx['info']['auth_typename'] . ']';
        }
    }

    function getUrl($str,$unlogin=0){
       
        $this->certi_id=  $this->getCerti();
        $sess_id =$this->get_sess();
        if(empty($this->certi_id)){
            $this->certi_id='error';
        }
        if(empty($sess_id)){
            $this->system->session->sess_id='error';
        }
        $confirmkey=$this->setEncode($sess_id,$this->certi_id);

        $version =$this->system->version();
        $url = '?sess_id='.urlencode($sess_id).'&certi_id='.urlencode($this->certi_id).'&version='.urlencode($this->getVersion()).'&confirmkey='.$confirmkey;
        $url = 'http://service.shopex.cn/info.php'.$url.'&_key_=do&store_refer='.$version['app'];
        
        if ($unlogin) $url.="&state=no";

        if($this->certi_id=='error'){
            unset($this->certi_id);
        }

        $prefix='<a href="'.$url.'" target="_blank" title="'.$this->certi_id.'">'.$str.'</a>';
       
        return $prefix;
    }

    function getVersion(){
        $version =$this->system->version();
        return $version['app'].'#'.$version['rev'];
    }

    /**
    *   to send message to shopex log server
    */
    function sendmsg(){
        $data=$this->msg_pack();
        $date=$this->post_data($data);
        return true;
    }

    function version_account(){

        $account_params = array(
                  'certi_app'=>'certi.ver',
                  'certificate_id'=>$this->getCerti(),
                  'ver'=>$this->getVersion(),
                  'product_key'=>VERIFY_APP_ID,
                  'refer'=>'yikaidian',
                  'api_ver'=>1.2,
                  'format'=>'json',
        );
        $account_params['certi_ac'] = $this->make_shopex_ac($account_params,$this->getToken());
        $net = &$this->system->loadModel('utility/http_client');
        $data = $net->post('http://service.shopex.cn', $account_params);
        $return_msg = json_decode($data,true);
        if($return_msg['res']=="succ"){
            return true;
        }
        return $return_msg;
      }

    function session_vaild($session){
        $vaild_params=array(
            'certi_app' => 'sess.valid_session',
            'certificate_id' => $this->getCerti(),
            'app_id' => VERIFY_APP_ID,
            'app_instance_id' => $this->get_app_instance_id(VERIFY_APP_ID),
            'version' => '1.1',
            'certi_session' => $session,
            'format' => 'json',
        );
        $vaild_params['certi_ac'] = $this->make_shopex_ac($vaild_params,$this->getToken());
        $net = &$this->system->loadModel('utility/http_client');
        $data = $net->post(APP_WLTX_URL, $vaild_params);
        $return_msg = json_decode($data,true);
        if($return_msg['res']=="succ"){
            return true;
        }
        return $return_msg;
    }

    function center_send($function,$params){
        $params['certi_app'] = $function;
        $cer = &$this->system->loadModel('service/certificate');
        $params['certificate_id'] = $cer->getCerti();
        $token = $cer->getToken();
        if((!$token||!$params['certificate_id'])&&$function!='co.show_se'&&$function!='category.get_category_info'){
           return array();
        }
        $params['certi_url'] = $this->system->base_url();
        $params['certi_session'] = $this->get_sess();
        $params['certi_validate_url'] = $this->system->realUrl('tools','checkSession',array($params['certi_session']));
        $params['app_id'] = APP_WLTX_ID;
        $params['version'] = APP_WLTX_VERSION;
        $params['certi_ac'] = $this->make_shopex_ac($params,$token);

        $net = &$this->system->loadModel('utility/http_client');

        $data = $net->post(APP_WLTX_URL, $params, array('User-Agent'=>'ShopEx_Cert_Client'));
        $data = json_decode($data,true);
        return $data;
    }

    function update_info($app_id, $setting_info){     
        $params = array(
            'certi_app' =>  'certi.update_info',
            'certificate_id' => $this->getCerti(),
            'app_id' => VERIFY_APP_ID,
            'app_instance_id' => $this->get_app_instance_id($app_id),
            'version' => '1.0',
            'certi_session' => $this->get_sess(),
            'format' => 'json',
            'shop_name' => $setting_info['system.shopname'],
            'shop_url' => $setting_info['store.shop_url'],
            'shop_type' => $setting_info['typeid'],
            'tel' => $setting_info['store.telephone'],
            'email' => $setting_info['store.email'],
            'address' => $setting_info['store.address'],
        );
        $params['certi_ac'] = $this->make_shopex_ac($params,$this->getToken());
        
        return $params;
    }
    
    function get_category_info($app_id){
        $cat_params = array(
            'certi_app' =>  'category.get_category_info',
            'certificate_id' => $this->getCerti(),
            'app_id' => VERIFY_APP_ID,
            'version' => '1.0',
            'format' => 'json',
        );
        $cat_params['certi_ac'] = $this->make_shopex_ac($cat_params,$this->getToken());
        
        return $cat_params;
    }

    function get_oem_info(){
        if( !$getent_id = $this->getent_id() ) {
            $active_url=$this->system->base_url().'install/index.php?step=active';
            $msg['res'] =  'fail';
            $msg['msg'] = "企业帐号不存在,暂无法激活。<br>请<a href='".$active_url."' target='_blank'>点击</a>获取企业帐号";
            return $msg;
        }
        
        if( !$cert_id = $this->getCerti() ) {
            $regToShopEx = $this->to_shopex_certificate('certi.reg');
            if( !$cert_id = $regToShopEx['info']['certificate_id'] ) {
                $msg['res'] =  'fail';
                $msg['msg'] = "证书获取失败!";
                return $msg;
            }
            
            $this->setCerti($cert_id);
            $this->setToken($regToShopEx['info']['token']);
        }
        
        if( $this->oem_valid() ) {
            header('Location:index.php?ctl=passport&act=login'); exit;
        }
        
        $msg['res'] =  'succ';
        $msg['msg'] = $this->make_oem_applyurl($cert_id);
        return $msg;
    }

    function oem_valid(){
        $loginToShopEx = $this->to_shopex_certificate('certi.login');
        if( 'succ' != $loginToShopEx['res'] ) {
            return false;
        }
        
        $autype = $loginToShopEx['info']['service'][VERIFY_APP_ID]['cert_auth']['auth_str'];
        $auth = $loginToShopEx['info']['service'][VERIFY_APP_ID]['cert_auth']['auth_strname'];
        $this->system->setConf('certificate.auth_type',$autype);
        $this->system->setConf('certificate.auth_strname',$auth);
        $this->setNodeid($loginToShopEx['info']['node_id']);
        
        $this->system->setConf('certificate.distribute','open'==$loginToShopEx['info']['service'][VERIFY_APP_ID]['distribute']['status']);
        
        $etime = $loginToShopEx['info']['service'][VERIFY_APP_ID]['cert_auth']['service_time']['etime'];
        $btime = $loginToShopEx['info']['service'][VERIFY_APP_ID]['cert_auth']['service_time']['btime'];
        if( !$etime || !$btime ) {
            return false;
        }

        $this->system->setConf('oem.service_etime',$etime);
        $this->system->setConf('oem.service_btime',$btime);

        if(!class_exists('pageFactory')){
            require('pageFactory.php');
        }
        
        $pageFactory = new pageFactory();
        $pageFactory->clear_cache('shop:/common/header.html');
        return true;
    }

    function make_oem_applyurl($certid){
        $url = '?sess_id='.urlencode($this->getSessValid()).'&certi_id='.urlencode($certid).'&version='.urlencode($this->getVersion()).'&confirmkey='.$confirmkey;
        $service_url = 'http://key-service.shopex.cn/index.php'.$url.'&_key_=do&store_refer=yikaidian';
        return $service_url;
    }
    
    function shopex_pwd_encrypt($pwd) {
        return md5($pwd.'ShopEXUser');
    }

    public function update_node_info($certi_app='node.update'){
        $data = array(
            'certi_app' =>  $certi_app,
            'certificate_id'=>$this->getCerti(),
            'node_type'=>'shopex_b2c',
            'api_ver'=>'1.2',
            'node_id'=>$this->getNodeId(),
            'api_url'=>$this->system->base_url().'api.php',
            'url'=>$this->system->base_url(),
            'format' => 'json',
        );
        $data['certi_ac'] = strtoupper($this->make_shopex_ac($data));

        $callback = $this->read_shopex_server($data);

        if ( 'node.reg' == $certi_app && 'succ' == $callback['res'] ) {
            $this->setNodeid($callback['info']['node_id']);
            $this->setCerti($callback['info']['license_id']);
            $this->setToken($callback['info']['token']);
        }

        return $callback;
    }
}

