<?php
/**
 * tpshop 支付宝插件
 * ============================================================================
 * 版权所有 2015-2027 素玄科技有限公司，并保留所有权利。
 * 网站地址: http://www.tp-shop.cn
 * ----------------------------------------------------------------------------
 * 这不是一个自由软件！您只能在不用于商业目的的前提下对程序代码进行修改和使用 .
 * 不允许对程序代码以任何形式任何目的的再发布。
 * 如果商业用途务必到官方购买正版授权, 以免引起不必要的法律纠纷.
 * ============================================================================
 * Author: IT宇宙人
 * Date: 2015-09-09
 */

//namespace plugins\payment\alipay;

use think\Model; 
use think\Request;
/**
 * 支付 逻辑定义
 * Class tenpay
 * @package Home\Payment
 */

class tenpay extends Model
{    
    public $tableName = 'plugin'; // 插件表        
    public $alipay_config = array();// 支付宝支付配置参数
    
    /**
     * 析构流函数
     */
    public function  __construct() {   
        parent::__construct();     
        unset($_GET['pay_code']);   // 删除掉 以免被进入签名
        unset($_REQUEST['pay_code']);// 删除掉 以免被进入签名
        
        $paymentPlugin = M('Plugin')->where("code='tenpay' and  type = 'payment' ")->find(); // 找到支付插件的配置
        $config_value = unserialize($paymentPlugin['config_value']); // 配置反序列化                
        $this->alipay_config['partner'] = $config_value['partner'];// 
        $this->alipay_config['key']  = $config_value['key'];//         
    }    
    /**
     * 生成支付代码
     * @param   array   $order      订单信息
     * @param   array   $config_value    支付方式信息
     */
    function get_code($order, $config_value)
    {                           
            require_once ("classes/RequestHandler.class.php");                     
            //4位随机数
            $randNum = rand(1000, 9999);
          
            /* 创建支付请求对象 */
            $reqHandler = new RequestHandler();
            $reqHandler->init();
            $reqHandler->setKey($this->alipay_config['key']);
            $reqHandler->setGateUrl("https://gw.tenpay.com/gateway/pay.htm");

            //----------------------------------------
            //设置支付参数 
            //----------------------------------------
            $reqHandler->setParameter("partner", $this->alipay_config['partner']);
            $reqHandler->setParameter("out_trade_no", $order['order_sn']);//商户订单号
            $reqHandler->setParameter("total_fee", ($order['order_amount'] * 100));  //总金额
            $reqHandler->setParameter("notify_url", SITE_URL.U('Payment/notifyUrl',array('pay_code'=>'tenpay'))); //服务器异步通知页面路径 //必填，不能修改
            $reqHandler->setParameter("return_url",  SITE_URL.U('Payment/returnUrl',array('pay_code'=>'tenpay')));//页面跳转同步通知页面路径            
            $reqHandler->setParameter("body", "TPshop 商城");
            $reqHandler->setParameter("bank_type", "DEFAULT");  	  //银行类型，默认为财付通
            //用户ip
            $reqHandler->setParameter("spbill_create_ip", $_SERVER['REMOTE_ADDR']);//客户端IP
            $reqHandler->setParameter("fee_type", "1");               //币种
            $reqHandler->setParameter("subject","TPshop商品");          //商品名称，（中介交易时必填）

            //系统可选参数
            $reqHandler->setParameter("sign_type", "MD5");  	 	  //签名方式，默认为MD5，可选RSA
            $reqHandler->setParameter("service_version", "1.0"); 	  //接口版本号
            $reqHandler->setParameter("input_charset", "utf-8");   	  //字符集
            $reqHandler->setParameter("sign_key_index", "1");    	  //密钥序号

            //业务可选参数
            /*
            $reqHandler->setParameter("attach", "");             	  //附件数据，原样返回就可以了
            $reqHandler->setParameter("product_fee", "");        	  //商品费用
            $reqHandler->setParameter("transport_fee", "0");      	  //物流费用
            $reqHandler->setParameter("time_start", date("YmdHis"));  //订单生成时间
            $reqHandler->setParameter("time_expire", "");             //订单失效时间
            $reqHandler->setParameter("buyer_id", "");                //买方财付通帐号
            $reqHandler->setParameter("goods_tag", "");               //商品标记
            $reqHandler->setParameter("trade_mode","1");              //交易模式（1.即时到帐模式，2.中介担保模式，3.后台选择（卖家进入支付中心列表选择））
            $reqHandler->setParameter("transport_desc","");              //物流说明
            $reqHandler->setParameter("trans_type","1");              //交易类型
            $reqHandler->setParameter("agentid","");                  //平台ID
            $reqHandler->setParameter("agent_type","");               //代理模式（0.无代理，1.表示卡易售模式，2.表示网店模式）
            $reqHandler->setParameter("seller_id","");                //卖家的商户号
            */
            
            //请求的URL
            $reqUrl = $reqHandler->getRequestURL();

            //获取debug信息,建议把请求和debug信息写入日志，方便定位问题
            /**/
            $debugInfo = $reqHandler->getDebugInfo();
            //echo "<br/>" . $reqUrl . "<br/>";
            //echo "<br/>" . $debugInfo . "<br/>";
            
            $html_text = "<form style='display:none' id='tenpaysubmit' name='tenpaysubmit' action='".$reqHandler->getGateUrl()."' method='post'>";

            $params = $reqHandler->getAllParameters();
            foreach($params as $k => $v) {
                    $html_text .= "<input type=\"hidden\" name=\"{$k}\" value=\"{$v}\" />\n";
            }
            $html_text .= "<input type='submit' value='财付通支付'>"; //submit按钮控件请不要含有name属性
            $html_text .= "</form>";
            $html_text .= "<script>document.forms['tenpaysubmit'].submit();</script>";
            return $html_text;
            

    }
    
    /**
     * 服务器点对点响应操作给支付接口方调用
     * 
     */
    function response() {
        require ("classes/ResponseHandler.class.php");
        require ("classes/RequestHandler.class.php");
        require ("classes/client/ClientResponseHandler.class.php");
        require ("classes/client/TenpayHttpClient.class.php");
        require ("classes/function.php");

        /* 创建支付应答对象 */
        $resHandler = new ResponseHandler();
        $resHandler->setKey($this->alipay_config['key']);
        //判断签名
        if ($resHandler->isTenpaySign()) {
            //通知id
            $notify_id = $resHandler->getParameter("notify_id");
            //通过通知ID查询，确保通知来至财付通
            //创建查询请求
            $queryReq = new RequestHandler();
            $queryReq->init();
            $queryReq->setKey($this->alipay_config['key']);
            $queryReq->setGateUrl("https://gw.tenpay.com/gateway/simpleverifynotifyid.xml");
            $queryReq->setParameter("partner", $this->alipay_config['partner']);
            $queryReq->setParameter("notify_id", $notify_id);
            //通信对象
            $httpClient = new TenpayHttpClient();
            $httpClient->setTimeOut(5);
            //设置请求内容
            $httpClient->setReqContent($queryReq->getRequestURL());

            //后台调用
            if ($httpClient->call()) {
                //设置结果参数
                $queryRes = new ClientResponseHandler();
                $queryRes->setContent($httpClient->getResContent());
                $queryRes->setKey($this->alipay_config['key']);
                if ($resHandler->getParameter("trade_mode") == "1") {
                    //判断签名及结果（即时到帐）
                    //只有签名正确,retcode为0，trade_state为0才是支付成功
                    if ($queryRes->isTenpaySign() && $queryRes->getParameter("retcode") == "0" && $resHandler->getParameter("trade_state") == "0") {
                        log_result("即时到帐验签ID成功");
                        //取结果参数做业务处理
                        $out_trade_no = $resHandler->getParameter("out_trade_no");
                        //财付通订单号
                        $transaction_id = $resHandler->getParameter("transaction_id");
                        //金额,以分为单位
                        $total_fee = $resHandler->getParameter("total_fee");
                        //如果有使用折扣券，discount有值，total_fee+discount=原请求的total_fee
                        $discount = $resHandler->getParameter("discount");

                        //------------------------------
                        //处理业务开始
                        //------------------------------
                        //处理数据库逻辑
                        //注意交易单不要重复处理
                        //注意判断返回金额
                        
						//用户在线充值
						if (stripos($out_trade_no, 'recharge') !== false)
							$order_amount = M('recharge')->where(['order_sn' => $out_trade_no, 'pay_status' => 0])->value('account');
						else						
	                        $order_amount = M('order')->where(['order_sn'=>"$out_trade_no"])->value('order_amount');
                               if((string)($order_amount * 100) != (string)$total_fee) 
                                      exit('fail'); //验证失败                                                       
                        
                        update_pay_status($out_trade_no,array('transaction_id'=>$transaction_id)); // 修改订单支付状态
                        //------------------------------
                        //处理业务完毕
                        //------------------------------
                        log_result("即时到帐后台回调成功");
                        echo "success";
                    } else {
                        //错误时，返回结果可能没有签名，写日志trade_state、retcode、retmsg看失败详情。
                        //echo "验证签名失败 或 业务错误信息:trade_state=" . $resHandler->getParameter("trade_state") . ",retcode=" . $queryRes->                         getParameter("retcode"). ",retmsg=" . $queryRes->getParameter("retmsg") . "<br/>" ;
                        log_result("即时到帐后台回调失败");
                        echo "fail";
                    }
                } elseif ($resHandler->getParameter("trade_mode") == "2") {
                    //判断签名及结果（中介担保）
                    //只有签名正确,retcode为0，trade_state为0才是支付成功
                    if ($queryRes->isTenpaySign() && $queryRes->getParameter("retcode") == "0") {
                        log_result("中介担保验签ID成功");
                        //取结果参数做业务处理
                        $out_trade_no = $resHandler->getParameter("out_trade_no");
                        //财付通订单号
                        $transaction_id = $resHandler->getParameter("transaction_id");
                        //金额,以分为单位
                        $total_fee = $resHandler->getParameter("total_fee");
                        //如果有使用折扣券，discount有值，total_fee+discount=原请求的total_fee
                        $discount = $resHandler->getParameter("discount");

                        //------------------------------
                        //处理业务开始
                        //------------------------------
                        //处理数据库逻辑
                        //注意交易单不要重复处理
                        //注意判断返回金额                        

                        log_result("中介担保后台回调，trade_state=" + $resHandler->getParameter("trade_state"));
                        switch ($resHandler->getParameter("trade_state")) {
                            case "0": //付款成功
                                break;
                            case "1": //交易创建
                                break;
                            case "2": //收获地址填写完毕
                                break;
                            case "4": //卖家发货成功
                                break;
                            case "5": //买家收货确认，交易成功
                                break;
                            case "6": //交易关闭，未完成超时关闭
                                break;
                            case "7": //修改交易价格成功
                                break;
                            case "8": //买家发起退款
                                break;
                            case "9": //退款成功
                                break;
                            case "10": //退款关闭			
                                break;
                            default:
                                //nothing to do
                                break;
                        }
                        //------------------------------
                        //处理业务完毕
                        //------------------------------
						
							//用户在线充值
							if (stripos($out_trade_no, 'recharge') !== false)
								$order_amount = M('recharge')->where(['order_sn' => $out_trade_no, 'pay_status' => 0])->value('account');
							else						
		                        $order_amount = M('order')->where(['order_sn'=>"$out_trade_no"])->value('order_amount');
                               if((string)($order_amount * 100) != (string)$total_fee) 
                                      exit('fail'); //验证失败                                 
                        update_pay_status($out_trade_no,array('transaction_id'=>$transaction_id)); // 修改订单支付状态
                        echo "success";
                    } else {
                        //错误时，返回结果可能没有签名，写日志trade_state、retcode、retmsg看失败详情。
                        //echo "验证签名失败 或 业务错误信息:trade_state=" . $resHandler->getParameter("trade_state") . ",retcode=" . $queryRes->             										       getParameter("retcode"). ",retmsg=" . $queryRes->getParameter("retmsg") . "<br/>" ;
                        log_result("中介担保后台回调失败");
                        echo "fail";
                    }
                }
                //获取查询的debug信息,建议把请求、应答内容、debug信息，通信返回码写入日志，方便定位问题
                /*
                  echo "<br>------------------------------------------------------<br>";
                  echo "http res:" . $httpClient->getResponseCode() . "," . $httpClient->getErrInfo() . "<br>";
                  echo "query req:" . htmlentities($queryReq->getRequestURL(), ENT_NOQUOTES, "GB2312") . "<br><br>";
                  echo "query res:" . htmlentities($queryRes->getContent(), ENT_NOQUOTES, "GB2312") . "<br><br>";
                  echo "query reqdebug:" . $queryReq->getDebugInfo() . "<br><br>" ;
                  echo "query resdebug:" . $queryRes->getDebugInfo() . "<br><br>";
                 */
            } else {
                //通信失败
                echo "fail";
                //后台调用通信失败,写日志，方便定位问题
                echo "<br>call err:" . $httpClient->getResponseCode() . "," . $httpClient->getErrInfo() . "<br>";
            }
        } else {
            echo "<br/>" . "认证签名失败" . "<br/>";
            echo $resHandler->getDebugInfo() . "<br>";
        }
    }

    /**
     * 页面跳转响应操作给支付接口方调用
     */
    function respond2()
    {
        require_once ("classes/ResponseHandler.class.php");
        require_once ("classes/function.php");
        //require_once ("tenpay_config.php");  
        log_result("进入前台回调页面");

        /* 创建支付应答对象 */
        $resHandler = new ResponseHandler();
        $resHandler->setKey($this->alipay_config['key']);        
        //判断签名
        if($resHandler->isTenpaySign()) {
                //通知id
                $notify_id = $resHandler->getParameter("notify_id");
                //商户订单号
                $out_trade_no = $resHandler->getParameter("out_trade_no");
                //财付通订单号
                $transaction_id = $resHandler->getParameter("transaction_id");
                //金额,以分为单位
                $total_fee = $resHandler->getParameter("total_fee");
                //如果有使用折扣券，discount有值，total_fee+discount=原请求的total_fee
                $discount = $resHandler->getParameter("discount");
                //支付结果
                $trade_state = $resHandler->getParameter("trade_state");
                //交易模式,1即时到账
                $trade_mode = $resHandler->getParameter("trade_mode");
                if("1" == $trade_mode ) {
                        if( "0" == $trade_state){ 
                                //------------------------------
                                //处理业务开始
                                //------------------------------

                                //注意交易单不要重复处理
                                //注意判断返回金额

                                //------------------------------
                                //处理业务完毕
                                //------------------------------	
                                
                                return array('status'=>1,'order_sn'=>$out_trade_no);//跳转至成功页面
                                //echo "<br/>" . "即时到帐支付成功" . "<br/>";

                        } else {
                                //当做不成功处理
                                return array('status'=>0,'order_sn'=>$out_trade_no);//跳转至失败页面    
                                //echo "<br/>" . "即时到帐支付失败" . "<br/>";
                        }
                }elseif( "2" == $trade_mode  ) {
                        if( "0" == $trade_state) {

                                //------------------------------
                                //处理业务开始
                                //------------------------------

                                //注意交易单不要重复处理
                                //注意判断返回金额

                                //------------------------------
                                //处理业务完毕
                                //------------------------------	
                                return array('status'=>1,'order_sn'=>$out_trade_no);//跳转至成功页面
                                //echo "<br/>" . "中介担保支付成功" . "<br/>";

                        } else {
                                //当做不成功处理
                                return array('status'=>0,'order_sn'=>$out_trade_no);//跳转至失败页面    
                                //echo "<br/>" . "中介担保支付失败" . "<br/>";
                        }
                }

        } else {
                return array('status'=>0,'order_sn'=>$out_trade_no);//跳转至失败页面
                //echo "<br/>" . "认证签名失败" . "<br/>";
                //echo $resHandler->getDebugInfo() . "<br>";
        }        
        
    }
    
}