logdir = Yii::getAlias('@runtime').DIRECTORY_SEPARATOR.'logs'.DIRECTORY_SEPARATOR.'pay'.DIRECTORY_SEPARATOR; dir_create($this->logdir); $this->userInfo = Identify::getUserInfo(); $this->payconfig = Yii::$app->params['pay']; $this->coinconfig = Yii::$app->params['coin']; if($this->payconfig['weixin_pay']) { // 商户号 $merchantId = $this->payconfig['weixin_mchid']; // 从本地文件中加载「商户API私钥」,「商户API私钥」会用来生成请求的签名 $merchantPrivateKeyFilePath = 'file://'.$this->payconfig['weixin_apiclient_key']; $merchantPrivateKeyInstance = Rsa::from($merchantPrivateKeyFilePath, Rsa::KEY_TYPE_PRIVATE); // 「商户API证书」的「证书序列号」 $merchantCertificateSerial = $this->payconfig['weixin_serialnumber']; // 从本地文件中加载「微信支付平台证书」,用来验证微信支付应答的签名 $platformCertificateFilePath = 'file://'.$this->payconfig['weixin_cert']; $platformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC); // 从「微信支付平台证书」中获取「证书序列号」 $platformCertificateSerial = PemUtil::parseCertificateSerialNo($platformCertificateFilePath); // 构造一个 APIv3 客户端实例 $this->wechatPay = Builder::factory([ 'mchid' => $merchantId, 'serial' => $merchantCertificateSerial, 'privateKey' => $merchantPrivateKeyInstance, 'certs' => [ $platformCertificateSerial => $platformPublicKeyInstance, ], ]); } } public function actionDo() { } //处理来自手机端的支付请求 public function actionDowap() { $initData = $_POST; extract($initData); //解决微信跳转后参数传递问题 $state = Yii::$app->request->get('state'); if(!empty($state)&&$state=='MR8888') { $initData = $_GET; extract($initData); } //购买文档时候,调整回跳地址 if($act=='buydoc') { $doc = DocReal::findOne($id); if($doc->doc_type==2) { $return_url = SiteUrl::colDetail($id,$order_sn); } else { $return_url = SiteUrl::docDetail($id,$order_sn); } } //支付宝 if($pay_method=='apw_pay') { require_once(Yii::getAlias('@payerdrivers').'/alipaywap/wappay/service/AlipayTradeService.php'); require_once(Yii::getAlias('@payerdrivers').'/alipaywap/wappay/buildermodel/AlipayTradeWapPayContentBuilder.php'); $order = $this->_initOrder($initData); $config = array ( //应用ID,您的APPID。 'app_id' => $this->payconfig['apw_appid'], //商户私钥,您的原始格式RSA私钥 'merchant_private_key' => $this->payconfig['apw_merchant_private_key'], //异步通知地址 'notify_url' => $this->payconfig['apw_notify_url'], //同步跳转 'return_url' => $return_url, //编码格式 'charset' => "UTF-8", //签名方式 'sign_type'=>"RSA2", //支付宝网关 'gatewayUrl' => "https://openapi.alipay.com/gateway.do", //支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。 'alipay_public_key' => $this->payconfig['apw_alipay_public_key'], //日志路径 'log_path' => $this->logdir.get_date(TIMESTAMP, "Y-m").'.txt', ); //商户订单号,商户网站订单系统中唯一订单号,必填 $out_trade_no = trim($order_sn); //订单名称,必填 $subject = $order->remark; //付款金额,必填 $total_amount = trim($total_price); //商品描述,可空 $body = ''; //超时时间 $timeout_express="1m"; $payRequestBuilder = new \AlipayTradeWapPayContentBuilder(); $payRequestBuilder->setBody($body); $payRequestBuilder->setSubject($subject); $payRequestBuilder->setOutTradeNo($out_trade_no); $payRequestBuilder->setTotalAmount($total_amount); $payRequestBuilder->setTimeExpress($timeout_express); $payResponse = new \AlipayTradeService($config); $result=$payResponse->wapPay($payRequestBuilder,$config['return_url'],$config['notify_url']); return ; } //微信公众号支付 if($pay_method=='weixin_pay'){ $args = array( 'appId'=>$this->payconfig['weixin_appid'], 'appSecret'=>$this->payconfig['weixin_appsecret'], 'token'=>$this->payconfig['weixin_token'], ); $weixin = new WeiXin($args); $weixin->init(); //JS API接口支付(仅在微信里面) if(isset($_GET['code'])&&$_GET['code']!='') { $order = $this->_initOrder($initData); $result = $weixin->getOauthAccessToken($_GET['code']); try { $pay_money = max($total_price, 0.01); $resp = $this->wechatPay->chain('v3/pay/transactions/jsapi') ->post(['json' => [ 'appid' => $this->payconfig['weixin_appid'], 'mchid' => $this->payconfig['weixin_mchid'], 'out_trade_no' => $order_sn, 'description' => $order->remark, 'notify_url' => $this->payconfig['weixin_notify_url'], 'amount' => [ 'total' => $pay_money*100, 'currency' => 'CNY' ], 'payer' => [ 'openid'=>$result['openid'] ], ]]); if($resp->getStatusCode()==200) { $respBody = json_decode($resp->getBody(),true); $prepay_id = $respBody['prepay_id']; if($prepay_id) { $timestamp = TIMESTAMP; $noncestr = TIMESTAMP; $signstr = $this->getWechartSign($this->payconfig['weixin_appid'], strval($timestamp), strval($noncestr), 'prepay_id='.$prepay_id); $jsApiParameters = json_encode([ 'appId' => $this->payconfig['weixin_appid'], 'timeStamp' => strval($timestamp) , 'package' => 'prepay_id=' . $respBody['prepay_id'], 'paySign' => $signstr, 'nonceStr' => strval($noncestr) ]); ob_clean(); require_once(Yii::getAlias('@app/views').DIRECTORY_SEPARATOR.'pay'.DIRECTORY_SEPARATOR.$pay_method.'.php'); exit; } else { exit('支付失败'); } } else { exit('支付失败'); } } catch (\Exception $e) { exit($e->getMessage()); } } else { $redirectUrl = get_url(); $queryParams = http_build_query($initData); if(strpos($redirectUrl,'?')===false) { $redirectUrl = $redirectUrl.'?'.urldecode($queryParams); } else { $redirectUrl = $redirectUrl.'&'.urldecode($queryParams); } $codeUrl = $weixin->getWebAuthUrl(urlencode($redirectUrl),'snsapi_base','MR8888'); echo ""; } } //微信H5支付 if($pay_method=='wxh5_pay'){ $order = $this->_initOrder($initData); // 官方提供网址 $url = "https://api.mch.weixin.qq.com/v3/pay/transactions/h5"; //拆解为:[scheme=>https,host=>api.mch.weixin.qq.com,path=>/v3/pay/transactions/native] $urlarr = parse_url($url); $time = time(); //时间戳 $noncestr = $time; $appid = $this->payconfig['wxh5_appid'];//appID $mchid = $this->payconfig['wxh5_mchid'];//商户ID //秘钥序列号 可在这个网址中查询 https://myssl.com/cert_decode.html $xlid = $this->payconfig['wxh5_serialnumber']; $data = []; $data['appid'] = $appid; $data['mchid'] = $mchid; $data['description'] = $order->remark;//商品描述 $data['out_trade_no'] = $order_sn;//订单编号,订单号在微信支付里是唯一的 $data['notify_url'] = $this->payconfig['wxh5_notify_url'];//需根据自己的情况修改回调接口,也可以为空 $data['amount']['total'] = max($total_price, 0.01)*100;//金额 单位 分 $data['scene_info']['payer_client_ip'] = $_SERVER['REMOTE_ADDR'];//场景 $data['scene_info']['h5_info']['type'] = "Wap";//场景 $data = json_encode($data); //变为json格式 // echo "
";
            // print_r($data);
            // echo "
";die;

            //签名,包含了$data数据、微信指定地址、随机数和时间
            $key = $this->getSign($data,$urlarr['path'],$noncestr,$time);
            //头部信息
            $token = sprintf('mchid="%s",serial_no="%s",nonce_str="%s",timestamp="%d",signature="%s"',$mchid,$xlid,$noncestr,$time,$key);
            //  echo $token;die;
            $header  = array(
                'Content-Type:'.'application/json; charset=UTF-8',
                'Accept:application/json',
                'User-Agent:*/*',
                'Authorization: WECHATPAY2-SHA256-RSA2048 '.$token
            );

            //向微信接口地址提交json格式的$data和header的头部信息,得到返回值
            $ret = $this->curl_post_https($url,$data,$header);
            //如果是个code_url网址,则说明成功了。在浏览器里打开该地址测试是否能付钱。
            // echo $ret;
            $resInfo = json_decode($ret, true);
            // var_dump($resInfo['h5_url']);die;
            // header("Location: ".$resInfo['h5_url']);
            echo "";
            exit;
        }
        //虎皮椒
        if($pay_method=='hpwx_pay'||$pay_method=='hpali_pay')
        {
            require_once(Yii::getAlias('@payerdrivers').'/xunhupay/api.php');
            $order = $this->_initOrder($initData);
            if($pay_method=='hpwx_pay')
            {
                $appid  = Yii::$app->params['pay']['hpwx_appid'];
                $appsecret = Yii::$app->params['pay']['hpwx_appsecret'];
                $my_plugin_id = Yii::$app->params['pay']['hpwx_pluginid'];
                $subject = $order->remark;
                $notify_url = Yii::$app->params['pay']['hpwx_notify_url'];
                //$return_url = Yii::$app->params['pay']['hpwx_return_url'];
            }
            else if($pay_method=='hpali_pay')
            {
                $appid   = Yii::$app->params['pay']['hpali_appid'];
                $appsecret  = Yii::$app->params['pay']['hpali_appsecret'];
                $my_plugin_id = Yii::$app->params['pay']['hpali_pluginid'];
                $subject = $order->remark;
                $notify_url = Yii::$app->params['pay']['hpali_notify_url'];
                //$return_url = Yii::$app->params['pay']['hpali_return_url'];
            }
            $data=array(
                'version'   => '1.1',//固定值,api 版本,目前暂时是1.1
                'lang'       => 'zh-cn', //必须的,zh-cn或en-us 或其他,根据语言显示页面
                'plugins'   => $my_plugin_id,//必须的,根据自己需要自定义插件ID,唯一的,匹配[a-zA-Z\d\-_]+
                'appid'     => $appid, //必须的,APPID
                'trade_order_id'=> $order_sn, //必须的,网站订单ID,唯一的,匹配[a-zA-Z\d\-_]+
                'payment'   => $pay_method=='hpwx_pay'?'wechat':'alipay',//必须的,支付接口标识:wechat(微信接口)|alipay(支付宝接口)
                'total_fee' => max(0,$total_price),//人民币,单位精确到分(测试账户只支持0.1元内付款)
                'title'     => $subject, //必须的,订单标题,长度32或以内
                'time'      => TIMESTAMP,//必须的,当前时间戳,根据此字段判断订单请求是否已超时,防止第三方攻击服务器
                'notify_url'=>  $notify_url, //必须的,支付成功异步回调接口
                'return_url'=> $return_url,//必须的,支付成功后的跳转地址
                'callback_url'=> APP_URL,//必须的,支付发起地址(未支付或支付失败,系统会会跳到这个地址让用户修改支付信息)
                'modal'=>null, //可空,支付模式 ,可选值( full:返回完整的支付网页; qrcode:返回二维码; 空值:返回支付跳转链接)
                'nonce_str' => str_shuffle(TIMESTAMP)//必须的,随机字符串,作用:1.避免服务器缓存,2.防止安全密钥被猜测出来
            );
            $hashkey = $appsecret;
            $data['hash']     = \XH_Payment_Api::generate_xh_hash($data,$hashkey);
            $url              = 'https://api.xunhupay.com/payment/do.html';
            try {
                $response     = \XH_Payment_Api::http_post($url, json_encode($data));
                $result       = $response?json_decode($response,true):null;
                if(!$result){
                    echo_json([
                        'error' => 1,
                        'msg' => 'Internal server error',
                        'code'=>500
                    ]);
                }
                $hash = \XH_Payment_Api::generate_xh_hash($result,$hashkey);
                if(!isset( $result['hash'])|| $hash!=$result['hash']){
                    echo_json([
                        'error' => 1,
                        'msg' => 'Invalid sign!',
                        'code'=>500
                    ]);
                }

                if($result['errcode']!=0){
                    echo_json([
                        'error' => 1,
                        'msg' => $result['errmsg'],
                        'code'=>$result['errcode']
                    ]);
                }

                $pay_url = $result['url'];
                header("Location: $pay_url");
                exit;

            } catch (\Exception $e) {
                $result =  [
                    'error' => 1,
                    'msg' => $e->getMessage(),
                    'data' => [],
                    'code'=>200
                ];
                echo_json($result);
            }
        }



    }

    //生成二维码付款图片
    public function actionCodeimg()
    {
       $initData = $_POST;
       extract($initData);
       //微信支付
       if($paymethod=='weixin_pay')
       {
          if($this->_checkOrder($order_sn,$paymethod))
          {
               $order_sn = getUniOrderNo();
               $result =  [
                   'error' => 2,
                   'msg' => '需要生成新订单',
                   'data' => ['order_sn'=>$order_sn],
                   'code'=>200
               ];
               echo_json($result);
          }
          $order = $this->_initOrder($initData);
          try {
            $pay_money = max($total_price, 0.01);
            $resp = $this->wechatPay->chain('v3/pay/transactions/native')
               ->post(['json' => [
                   'mchid'        => $this->payconfig['weixin_mchid'],
                   'out_trade_no' => $order_sn,
                   'appid'        => $this->payconfig['weixin_appid'],
                   'description'  => $order->remark,
                   'notify_url'   => $this->payconfig['weixin_notify_url'],
                   'amount'       => [
                       'total'    => $pay_money*100,
                       'currency' => 'CNY'
                   ],
               ]]);
               if($resp->getStatusCode()==200)
               {
                   $respBody = json_decode($resp->getBody(),true);
                   $code_url = APP_URL.'ajax/qrcode/?url='.$respBody['code_url'];
                   $result =  [
                       'error' => 0,
                       'msg' => '操作成功',
                       'data' => ['code_url'=>$code_url,'order_sn'=>$order_sn],
                       'code'=>200
                   ];
                   echo_json($result);
               }
           } catch (\Exception $e) {
              $result =  [
                  'error' => 1,
                  'msg' => $e->getMessage(),
                  'data' => [],
                  'code'=>200
              ];
              echo_json($result);
               // 进行错误处理
               /*echo $e->getMessage(), PHP_EOL;
               if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
                   $r = $e->getResponse();
                   echo $r->getStatusCode() . ' ' . $r->getReasonPhrase(), PHP_EOL;
                   echo $r->getBody(), PHP_EOL, PHP_EOL, PHP_EOL;
               }
               echo $e->getTraceAsString(), PHP_EOL;*/
           }

       }
       //支付宝PC
       if($paymethod=='apd_pay')
       {
           require_once(Yii::getAlias('@payerdrivers').'/alipaypage/pagepay/service/AlipayTradeService.php');
           require_once(Yii::getAlias('@payerdrivers').'/alipaypage/pagepay/buildermodel/AlipayTradePagePayContentBuilder.php');
           if($this->_checkOrder($order_sn,$paymethod))
           {
                $order_sn = getUniOrderNo();
                $result =  [
                    'error' => 2,
                    'msg' => '需要生成新订单',
                    'data' => ['order_sn'=>$order_sn],
                    'code'=>200
                ];
                echo_json($result);
           }
           $order = $this->_initOrder($initData);
           $config = array (
               //应用ID,您的APPID。
               'app_id' => $this->payconfig['apd_appid'],
               //商户私钥
               'merchant_private_key' => $this->payconfig['apd_merchant_private_key'],
               //异步通知地址
               'notify_url' => $this->payconfig['apd_notify_url'],
               //同步跳转
               'return_url' => $this->payconfig['apd_return_url'],
               //编码格式
               'charset' => "UTF-8",
               //签名方式
               'sign_type'=>"RSA2",
               //支付宝网关
               'gatewayUrl' => "https://openapi.alipay.com/gateway.do",
               //支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
               'alipay_public_key' => $this->payconfig['apd_alipay_public_key'],
               //日志路径
               'log_path' => $this->logdir.get_date(TIMESTAMP, "Y-m").'.txt',
           );
           //商户订单号,商户网站订单系统中唯一订单号,必填
           $out_trade_no = trim($order_sn);
           //订单名称,必填
           $subject = $order->remark;
           //付款金额,必填
           $total_amount = trim($total_price);
           //商品描述,可空
           $body = '';
           //构造参数
           $payRequestBuilder = new \AlipayTradePagePayContentBuilder();
           $payRequestBuilder->setBody($body);
           $payRequestBuilder->setSubject($subject);
           $payRequestBuilder->setTotalAmount($total_amount);
           $payRequestBuilder->setOutTradeNo($out_trade_no);
           $payRequestBuilder->setQrPayMode(4);
           $payRequestBuilder->setQrPayWidth(110);
           $aop = new \AlipayTradeService($config);
           $response = $aop->pagePay($payRequestBuilder,$config['return_url'],$config['notify_url']);
           //输出表单
           $result =  [
               'error' => 0,
               'msg' => '操作成功',
               'data' => ['code_url'=>APP_URL.'pay/alicode/?response='.urlencode($response),'order_sn'=>$order_sn],
               'code'=>200
           ];
           echo_json($result);
        }
        //虎皮椒
        if($paymethod=='hpwx_pay'||$paymethod=='hpali_pay')
        {

            require_once(Yii::getAlias('@payerdrivers').'/xunhupay/api.php');
            if($this->_checkOrder($order_sn,$paymethod))
            {
                $order_sn = getUniOrderNo();
                $result =  [
                    'error' => 2,
                    'msg' => '需要生成新订单',
                    'data' => ['order_sn'=>$order_sn],
                    'code'=>200
                ];
                echo_json($result);
            }
            $order = $this->_initOrder($initData);
            if($paymethod=='hpwx_pay')
            {
                $appid  = Yii::$app->params['pay']['hpwx_appid'];
                $appsecret = Yii::$app->params['pay']['hpwx_appsecret'];
                $my_plugin_id = Yii::$app->params['pay']['hpwx_pluginid'];
                $subject = $order->remark;
                $notify_url = Yii::$app->params['pay']['hpwx_notify_url'];
                $return_url = Yii::$app->params['pay']['hpwx_return_url'];
            }
            else if($paymethod=='hpali_pay')
            {
                $appid   = Yii::$app->params['pay']['hpali_appid'];
                $appsecret  = Yii::$app->params['pay']['hpali_appsecret'];
                $my_plugin_id = Yii::$app->params['pay']['hpali_pluginid'];
                $subject = $order->remark;
                $notify_url = Yii::$app->params['pay']['hpali_notify_url'];
                $return_url = Yii::$app->params['pay']['hpali_return_url'];
            }
            $data=array(
                'version'   => '1.1',//固定值,api 版本,目前暂时是1.1
                'lang'       => 'zh-cn', //必须的,zh-cn或en-us 或其他,根据语言显示页面
                'plugins'   => $my_plugin_id,//必须的,根据自己需要自定义插件ID,唯一的,匹配[a-zA-Z\d\-_]+
                'appid'     => $appid, //必须的,APPID
                'trade_order_id'=> $order_sn, //必须的,网站订单ID,唯一的,匹配[a-zA-Z\d\-_]+
                'payment'   => $paymethod=='hpwx_pay'?'wechat':'alipay',//必须的,支付接口标识:wechat(微信接口)|alipay(支付宝接口)
                'total_fee' => max(0,trim($total_price)),//人民币,单位精确到分(测试账户只支持0.1元内付款)
                'title'     => $subject, //必须的,订单标题,长度32或以内
                'time'      => TIMESTAMP,//必须的,当前时间戳,根据此字段判断订单请求是否已超时,防止第三方攻击服务器
                'notify_url'=>  $notify_url, //必须的,支付成功异步回调接口
                'return_url'=> $return_url,//必须的,支付成功后的跳转地址
                'callback_url'=> APP_URL,//必须的,支付发起地址(未支付或支付失败,系统会会跳到这个地址让用户修改支付信息)
                'modal'=>null, //可空,支付模式 ,可选值( full:返回完整的支付网页; qrcode:返回二维码; 空值:返回支付跳转链接)
                'nonce_str' => str_shuffle(TIMESTAMP)//必须的,随机字符串,作用:1.避免服务器缓存,2.防止安全密钥被猜测出来
            );
            $hashkey = $appsecret;
            $data['hash']     = \XH_Payment_Api::generate_xh_hash($data,$hashkey);
            $url              = 'https://api.xunhupay.com/payment/do.html';
            try {
                $response     = \XH_Payment_Api::http_post($url, json_encode($data));
                $result       = $response?json_decode($response,true):null;
                if(!$result){
                    echo_json([
                        'error' => 1,
                        'msg' => 'Internal server error',
                        'code'=>500
                    ]);
                }
                $hash = \XH_Payment_Api::generate_xh_hash($result,$hashkey);
                if(!isset( $result['hash'])|| $hash!=$result['hash']){
                    echo_json([
                        'error' => 1,
                        'msg' => 'Invalid sign!',
                        'code'=>500
                    ]);
                }

                if($result['errcode']!=0){
                    echo_json([
                        'error' => 1,
                        'msg' => $result['errmsg'],
                        'code'=>$result['errcode']
                    ]);
                }

                if($paymethod=='hpwx_pay'){
                    echo_json( [
                        'error' => 0,
                        'msg' => '操作成功',
                        'data' => ['code_url'=>$result['url_qrcode'],'order_sn'=>$order_sn],
                        'code'=>200
                    ]);
                }else{
                    echo_json([
                        'error' => 0,
                        'msg' => '操作成功',
                        'data' => ['code_url'=>APP_URL.'pay/paycode/?response='.urlencode($result['url_qrcode']),'order_sn'=>$order_sn],
                        'code'=>200
                    ]);
                }

            } catch (\Exception $e) {
                $result =  [
                    'error' => 1,
                    'msg' => $e->getMessage(),
                    'data' => [],
                    'code'=>200
                ];
                echo_json($result);
            }
        }

    }

    //生成支付宝二维码
    public function actionAlicode()
    {
        echo $_GET['response'];
    }


    //对支付二维码做缩略图
    public function actionPaycode()
    {
        $fileHash = md5($_GET['response']);
        $dstrootdir = THUMB_PATH.'paycode'.DIRECTORY_SEPARATOR;
        dir_create($dstrootdir);
        $resize = new \app\common\components\ResizeImage($_GET['response'], 110, 110,$fileHash, 0,0,$dstrootdir);
        $dstimg = $resize->dstimg;
        ob_clean();
        header('Content-type: image/jpeg');
        echo file_get_contents($dstimg);
        exit;

    }
    //微信支付回调
    public function actionWeixincallback(){
        $headers = $this->_getAllHeader();
        //$this->payLog(var_export($headers,true));
        $inWechatpaySignature = $headers['wechatpay-signature'];
        $inWechatpayTimestamp = $headers['wechatpay-timestamp'];
        $inWechatpaySerial = $headers['wechatpay-serial'];
        $inWechatpayNonce = $headers['wechatpay-nonce'];
        $inBody = file_get_contents('php://input');
        $apiv3Key = $this->payconfig['weixin_v3secret'];// 在商户平台上设置的APIv3密钥
        $platformPublicKeyInstance = Rsa::from('file://'.$this->payconfig['weixin_cert'], Rsa::KEY_TYPE_PUBLIC);
        // 检查通知时间偏移量,允许5分钟之内的偏移
        $timeOffsetStatus = 300 >= abs(Formatter::timestamp() - (int)$inWechatpayTimestamp);
        $verifiedStatus = Rsa::verify(
        // 构造验签名串
            Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, $inBody),
            $inWechatpaySignature,
            $platformPublicKeyInstance
        );
        if ($timeOffsetStatus && $verifiedStatus) {
            // 转换通知的JSON文本消息为PHP Array数组
            $inBodyArray = (array)json_decode($inBody, true);
            // 使用PHP7的数据解构语法,从Array中解构并赋值变量
            ['resource' => [
                'ciphertext'      => $ciphertext,
                'nonce'           => $nonce,
                'associated_data' => $aad
            ]] = $inBodyArray;
            // 加密文本消息解密
            $inBodyResource = AesGcm::decrypt($ciphertext, $apiv3Key, $nonce, $aad);
            // 把解密后的文本转换为PHP Array数组
            $inBodyResourceArray = (array)json_decode($inBodyResource, true);
            //$this->payLog(var_export($inBodyResourceArray,true));
            if ($inBodyResourceArray['trade_state'] == 'SUCCESS') {
                // 这里写业务逻辑
                if($this->_processOrder($inBodyResourceArray['out_trade_no'],($inBodyResourceArray['amount']['payer_total']/100),1,
$inBodyResourceArray['payer']['openid']))
                {
                    $result = ['code'=>'SUCCESS','message'=>'成功',];
                    echo_json($result);
                }

            }
        }
    }

    //支付宝PC扫码支付回调
    public function actionAlipaydirectnotify()
    {
        require_once(Yii::getAlias('@payerdrivers').'/alipaypage/pagepay/service/AlipayTradeService.php');
        $config = array (
            //应用ID,您的APPID。
            'app_id' => $this->payconfig['apd_appid'],
            //商户私钥
            'merchant_private_key' => $this->payconfig['apd_merchant_private_key'],
            //异步通知地址
            'notify_url' => $this->payconfig['apd_notify_url'],
            //同步跳转
            'return_url' => $this->payconfig['apd_return_url'],
            //编码格式
            'charset' => "UTF-8",
            //签名方式
            'sign_type'=>"RSA2",
            //支付宝网关
            'gatewayUrl' => "https://openapi.alipay.com/gateway.do",
            //支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
            'alipay_public_key' => $this->payconfig['apd_alipay_public_key'],
            //日志路径
            'log_path' => $this->logdir.get_date(TIMESTAMP, "Y-m").'.txt',
        );
        $arr=$_POST;
        $alipaySevice = new \AlipayTradeService($config);
        $alipaySevice->writeLog(var_export($_POST,true));
        $result = $alipaySevice->check($arr);
        /* 实际验证过程建议商户添加以下校验。
        1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
        2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
        3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email)
        4、验证app_id是否为该商户本身。
        */
        if($result) {//验证成功
            //请在这里加上商户的业务逻辑程序代
            //——请根据您的业务逻辑来编写程序(以下代码仅作参考)——

            //获取支付宝的通知返回参数,可参考技术文档中服务器异步通知参数列表

            //商户订单号
            $out_trade_no = $_POST['out_trade_no'];
            //支付宝交易号
            $trade_no = $_POST['trade_no'];
            //交易状态
            $trade_status = $_POST['trade_status'];
            $total_amount = $_POST['total_amount'];
            if($_POST['trade_status'] == 'TRADE_FINISHED') {
                $this->_processOrder($out_trade_no,$total_amount,3);
            }
            else if ($_POST['trade_status'] == 'TRADE_SUCCESS') {
                $this->_processOrder($out_trade_no,$total_amount,3);
            }
            //——请根据您的业务逻辑来编写程序(以上代码仅作参考)——
            echo "success";	//请不要修改或删除
        }else {
            //验证失败
            echo "fail";

        }
    }


    //支付成功之后的虎皮椒回调处理(微信)
    public function actionHpwxnotify()
    {
        try
        {
            require_once(Yii::getAlias('@payerdrivers').'/xunhupay/api.php');
            $appid  = Yii::$app->params['pay']['hpwx_appid'];
            $appsecret = Yii::$app->params['pay']['hpwx_appsecret'];
            $my_plugin_id = Yii::$app->params['pay']['hpwx_pluginid'];
            $data = $_POST;
            foreach ($data as $k=>$v){
                $data[$k] = stripslashes($v);
            }
            if(!isset($data['hash'])||!isset($data['trade_order_id'])){
                echo 'failed';exit;
            }
            //自定义插件ID,请与支付请求时一致
            if(isset($data['plugins'])&&$data['plugins']!=$my_plugin_id){
                echo 'failed';exit;
            }
            //APP SECRET
            $appkey =$appsecret;
            $hash =\XH_Payment_Api::generate_xh_hash($data,$appkey);
            if($data['hash']!=$hash){
                //签名验证失败
                echo 'failed';exit;
            }
            //商户订单ID
            $trade_order_id =$data['trade_order_id'];
            $total_fee = $data['total_fee'];
            if($data['status']=='OD'){
                $this->_processOrder($trade_order_id,$total_fee,88);
                echo 'success';
                exit;
            }else{
                echo 'failed';exit;
            }
        }
        catch(\Exception $e)
        {
            $this->payLog($e->getMessage());exit;
        }
    }

    //支付成功之后的虎皮椒回调处理(支付宝)
    public function actionHpalinotify()
    {
        try
        {
            require_once(Yii::getAlias('@payerdrivers').'/xunhupay/api.php');
            $appid   = Yii::$app->params['pay']['hpali_appid'];
            $appsecret  = Yii::$app->params['pay']['hpali_appsecret'];
            $my_plugin_id = Yii::$app->params['pay']['hpali_pluginid'];
            $data = $_POST;
            foreach ($data as $k=>$v){
                $data[$k] = stripslashes($v);
            }
            if(!isset($data['hash'])||!isset($data['trade_order_id'])){
                echo 'failed';exit;
            }
            //自定义插件ID,请与支付请求时一致
            if(isset($data['plugins'])&&$data['plugins']!=$my_plugin_id){
                echo 'failed';exit;
            }
            //APP SECRET
            $appkey =$appsecret;
            $hash =\XH_Payment_Api::generate_xh_hash($data,$appkey);
            if($data['hash']!=$hash){
                //签名验证失败
                echo 'failed';exit;
            }
            //商户订单ID
            $trade_order_id =$data['trade_order_id'];
            $total_fee = $data['total_fee'];
            if($data['status']=='OD'){
                $this->_processOrder($trade_order_id,$total_fee,99);
                echo 'success';
                exit;
            }else{
                echo 'failed';exit;
            }
        }
        catch(\Exception $e)
        {
            $this->payLog($e->getMessage());exit;
        }
    }

    //手机端支付宝回调
    public function actionAlipaywapnotify()
    {
        require_once(Yii::getAlias('@payerdrivers').'/alipaywap/wappay/service/AlipayTradeService.php');
        $config = array (
            //应用ID,您的APPID。
            'app_id' => $this->payconfig['apw_appid'],
            //商户私钥,您的原始格式RSA私钥
            'merchant_private_key' => $this->payconfig['apw_merchant_private_key'],
            //异步通知地址
            'notify_url' => $this->payconfig['apw_notify_url'],
            //同步跳转
            'return_url' => $this->payconfig['apw_return_url'],
            //编码格式
            'charset' => "UTF-8",
            //签名方式
            'sign_type'=>"RSA2",
            //支付宝网关
            'gatewayUrl' => "https://openapi.alipay.com/gateway.do",
            //支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
            'alipay_public_key' => $this->payconfig['apw_alipay_public_key'],
            //日志路径
            'log_path' => $this->logdir.get_date(TIMESTAMP, "Y-m").'.txt',
        );
        $arr=$_POST;
        $alipaySevice = new \AlipayTradeService($config);
        $alipaySevice->writeLog(var_export($_POST,true));
        $this->payLog(var_export($_POST,true));
        $result = $alipaySevice->check($arr);
        /* 实际验证过程建议商户添加以下校验。
        1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
        2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
        3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email)
        4、验证app_id是否为该商户本身。
        */
        if($result) {//验证成功
            //请在这里加上商户的业务逻辑程序代
            //——请根据您的业务逻辑来编写程序(以下代码仅作参考)——
            //获取支付宝的通知返回参数,可参考技术文档中服务器异步通知参数列表
            //商户订单号
            $out_trade_no = $_POST['out_trade_no'];
            //支付宝交易号
            $trade_no = $_POST['trade_no'];
            //交易状态
            $trade_status = $_POST['trade_status'];
            $total_amount = $_POST['total_amount'];
            if($_POST['trade_status'] == 'TRADE_FINISHED') {
                $this->_processOrder($out_trade_no,$total_amount,3);
            }
            else if ($_POST['trade_status'] == 'TRADE_SUCCESS') {
                $this->_processOrder($out_trade_no,$total_amount,3);
            }
            //——请根据您的业务逻辑来编写程序(以上代码仅作参考)——
            echo "success";	//请不要修改或删除
        }else {
            //验证失败
            echo "fail";

        }

    }



    //检测订单是否存在
    private function _checkOrder($order_sn,$pay_method)
    {
        $exist = ShoppingPaycode::find()->where("order_sn='".$order_sn."' and pay_method='".$pay_method."'")->exists();
        if($exist)
        {
            return true;
        }
        else
        {
            $paycode = new ShoppingPaycode();
            $paycode->order_sn = $order_sn;
            $paycode->pay_method = $pay_method;
            $paycode->create_time = TIMESTAMP;
            $paycode->save();
            return false;
        }
    }

    //初始化订单
    private function _initOrder($initData)
    {
        extract($initData);
        $order = ShoppingOrder::find()->where("order_sn='".$order_sn."'")->one();
        if($order)
        {
            return $order;
        }
        else
        {
            //充值金币
            if($act=='coinrecharge'){
                $pay_credit = $act.'_'.$coin_num;
                $order_type = 2;
                $remark = '充值'.Yii::$app->params['coin']['coin_name'];
            }

            //开通VIP
            if($act=='buyvip'){
                $userVipType = UserVipType::findOne($vip_type);
                $pay_credit = $act.'_'.$vip_type;
                $order_type = 3;
                $remark = '开通VIP-'.$userVipType->title;
            }

            //购买文档
            if($act=='buydoc'){
                $pay_credit = $act.'_'.$id;
                $order_type = 1;
                $remark = '购买文档';
            }
            //百度搜索词
            $baidukw =  \app\common\helpers\Cookie::getCookie(Yii::$app->params['baidukwName']);
            $order = new ShoppingOrder();
            $order->user_id = intval($this->userInfo['user_id']);
            $order->order_sn = $order_sn;
            $order->pay_credit = $pay_credit;
            $order->total_price = $total_price;
            $order->discount_price = $discount_price;
            $order->remark = $remark;
            $order->order_type = $order_type;
            $order->status = 0;
            $order->ad_words = $baidukw?urldecode($baidukw):'';
            $order->request_from = REQUEST_FROM;
            $order->create_time = TIMESTAMP;

            $order->save();
            return $order;
        }

    }
    // 获取header头的方法
    private function _getAllHeader()
    {
        // 忽略获取的header数据。这个函数后面会用到。主要是起过滤作用
        $ignore = array('host','accept','content-length','content-type','connection','accept-encoding');
        $headers = array();    //这里大家有兴趣的话,可以打印一下。会出来很多的header头信息。咱们想要的部分,都是‘http_'开头的。所以下面会进行过滤输出。
        foreach($_SERVER as $key=>$value){
            if(substr($key, 0, 5)==='HTTP_'){      //这里取到的都是'http_'开头的数据。
                //前去开头的前5位
                $key = substr($key, 5);        //把$key中的'_'下划线都替换为空字符串
                $key = str_replace('_', ' ', $key);        //再把$key中的空字符串替换成‘-’
                $key = str_replace(' ', '-', $key);        //把$key中的所有字符转换为小写
                $key = strtolower($key);    //这里主要是过滤上面写的$ignore数组中的数据
                if(!in_array($key, $ignore)){
                    $headers[$key] = $value;
                }
            }
        }//输出获取到的header
        return $headers;
    }

    // 记录日志
    public function payLog($word) {
        $logFile = $this->logdir.get_date(TIMESTAMP, "Y-m").'.txt';
        $fp = fopen($logFile, "a");
        flock($fp, LOCK_EX) ;
        fwrite($fp, get_date(TIMESTAMP, "Y-m-d H:i:s").' | '.$word."\r\n");
        flock($fp, LOCK_UN);
        fclose($fp);
    }

    //支付成功后处理业务逻辑
    public function _processOrder($order_sn,$total_price,$pay_method,$openid='')
    {
        $order = ShoppingOrder::find()->where("order_sn='".$order_sn."'")->one();
        if($order&&$order->status==0)
        {
            $order->status = $order->is_virtual==1?9:1;
            $order->pay_time = strval(TIMESTAMP);
            $order->pay_method = $pay_method;
            if($order->save())
            {
                //充值金币
                if(strpos($order->pay_credit,'coinrecharge')!==false)
                {
                    $coin_num = str_replace('coinrecharge_','',$order->pay_credit);
                    Wallet::coinChange($order->user_id,$coin_num,$order->remark,1);
                }

                //开通VIP
                if(strpos($order->pay_credit,'buyvip')!==false)
                {
                    $vip_type = str_replace('buyvip_','',$order->pay_credit);
                    $userVipType = UserVipType::findOne($vip_type);
                    $userVipOrder = UserVipOrder::findOne($order->order_id);
                    //付款金额校验
                    if($userVipType&&$order->total_price==$userVipType->price)
                    {
                        //判断是否是续费
                        $vipInfo = UserVipOrder::find()->where("user_id='".$order->user_id."' and vip_type=$vip_type and status=1 and (expire_time>=".TIMESTAMP." or expire_time=0) and order_id!='".$order->order_id."'")->orderBy(['order_id'=>SORT_DESC])->limit(1)->one();
                        if($vipInfo)
                        {
                            $startTime = $vipInfo->expire_time;
                        }
                        else
                        {
                            $startTime = TIMESTAMP;
                        }

                        if(empty($userVipOrder))
                        {
                            $userVipOrder = new UserVipOrder();
                        }
                        $userVipOrder->order_id = $order->order_id;
                        $userVipOrder->user_id = $order->user_id;
                        $userVipOrder->vip_type = $vip_type;
                        $userVipOrder->money = $total_price;
                        $userVipOrder->days = $userVipType->days;
                        $userVipOrder->settings = $userVipType->settings;
                        $userVipOrder->expire_time =  $userVipType->forever==1?0:$startTime+$userVipType->days*24*3600;
                        $userVipOrder->create_time = TIMESTAMP;
                        $userVipOrder->status = 1;
                        if($userVipOrder->save())
                        {
                            $vipSettings = string2array($userVipType->settings);
                            //如果有赠送金币
                            if(intval($vipSettings['coin_num'])>0)
                            {
                                Wallet::coinChange($order->user_id,$vipSettings['coin_num'],'开通会员赠送金币',1);
                            }
                            //处理分销
                            Wallet::vipCommission($order->user_id,$userVipOrder);
                        }
                    }

                }

                //购买文档
                if(strpos($order->pay_credit,'buydoc')!==false)
                {
                    $id = str_replace('buydoc_','',$order->pay_credit);
                    $this->addDownCode($id,$order);
                }
                //百度竞价跟踪
                $bd_vid =  \app\common\helpers\Cookie::getCookie('bd_vid');
                if(!empty($bd_vid))
                {
                    $higherconfigResult = \app\modules\admin\models\Config::find()->where("name='higherconfig'")->one();
                    $higherconfig = string2array($higherconfigResult->value);
                    $token = $higherconfig['cpc_token'];
                    if(!empty($token))
                    {
                        $cv = array(
                            'logidUrl' => APP_URL.'?bd_vid='.$bd_vid, // 您的落地页url
                            'newType' => 10 // 转化类型请按实际情况填写
                        );
                        $conversionTypes = array($cv);
                        $baiducpc = new \app\common\components\BaiduCpc();
                        $baiducpc->sendConvertData($token, $conversionTypes);
                    }

                }

            }
            return true;
        }
        else
        {
            return false;
        }
    }

    //获取订单状态
    public function actionOrderstatus()
    {
        $order_sn = Yii::$app->request->get('order_sn');
        if($order_sn)
        {
            $order = ShoppingOrder::find()->where("order_sn='".$order_sn."'")->one();
            if(!empty($order))
            {
                if($order->status==1||$order->status==9)
                {
                    $data = [];
                    //购买文档
                    if(strpos($order->pay_credit,'buydoc')!==false)
                    {
                       $downCode = DocDowncode::find()->where("openid='".$order_sn."'")->one();
                       $data['downurl'] = SiteUrl::docDownByCode($downCode->downcode,1);
                       $data['downcode'] = $downCode->downcode;
                    }

                    $result =  [
                        'error' => 0,
                        'msg' => '支付成功',
                        'data' => $data,
                        'code'=>200
                    ];
                    echo_json($result);
                }
            }
            else
            {
                $result =  [
                    'error' => 1,
                    'msg' => '订单不存在',
                    'code'=>200
                ];
                echo_json($result);
            }
        }
        else
        {
            $result =  [
                'error' => 1,
                'msg' => '缺少参数',
                'code'=>200
            ];
            echo_json($result);
        }

    }

    //购买文档
    public function addDownCode($doc_id,$order)
    {
        try
        {
            $doc = DocReal::findOne($doc_id);
            $downCode = new \app\modules\doc\models\DocDowncode();
            $downCode->doc_id = $doc_id;
            $downCode->user_id = intval($order->user_id);
            $downCode->openid = $order->order_sn;
            $downCode->downcode =  strval(getDowncode($doc->id));
            $downCode->doc_user_id = $doc->user_id;
            $downCode->type = 2;
            $downCode->create_time = TIMESTAMP;
            $downCode->save();
            //判断用户VIP权限情况
            if($order->user_id) $vipSettings = User::findOne($order->user_id)->vipSettings();
            //如果是机构推广文档,标记推广文档订单
            if($doc->is_ad)
            {
                $store = \app\modules\shopping\models\ShoppingStore::find()->where("user_id=".$doc->user_id)->one();
                if($store)
                {
                    $order->store_id = $store->store_id;
                    $order->save();
                }

            }

            //将价格转成金币数量
            $coin_num =  $order->total_price*Yii::$app->params['coin']['coin_recharge_rate'];
            //生成支付记录
            $paylog = new \app\modules\doc\models\DocPaylog();
            $paylog->user_id = intval($order->user_id);
            $paylog->doc_user_id = intval($doc->user_id);
            $paylog->doc_id = $doc->id;
            $paylog->cat_id = $doc->cat_id;
            $paylog->cat_ids = $doc->cat_ids;
            $paylog->doc_type = $doc->doc_type;
            $paylog->is_vip = ($doc->is_vip||$vipSettings['buy_doc_discount']<100)?1:0;
            $paylog->coin_price = $doc->coin_price;
            $paylog->coin_num = $coin_num;
            $paylog->agent_id = intval($order->user->referer_id);
            $paylog->agent_ids = strval($order->user->referer_ids);
            $paylog->create_time = TIMESTAMP;
            if($paylog->save())
            {
                $doc->updateCounters(['sales'=>1]);
                $left_coin = $coin_num;
                $point_num = intval($order->total_price*Yii::$app->params['point']['rmb_price_rate']);
                //购买方
                $logTitleBuy = '购买'.DocReal::typeOptions($doc->doc_type);
                if($order->user_id)
                {
                    Wallet::pointChange($order->user_id,$point_num,$logTitleBuy,1,'point',DocReal::shortTableName(),$doc->id);
                    //处理分销
                    $left_coin = Wallet::docCommission($order->user_id,$doc,$paylog,$left_coin);
                }

                //出售方
                $logTitleSell = '出售'.DocReal::typeOptions($doc->doc_type);

                if($left_coin>0&&$doc->user_id)
                {
                    //金币变化
                    Wallet::coinChange($doc->user_id,$left_coin,$logTitleSell,1,'coin_income',DocReal::shortTableName(),$doc->id);
                    //消息通知
                    MessageOne::soldDoc($logTitleSell,$doc,$left_coin);
                }
                return true;
            }
            else
            {
                $this->payLog($paylog->returnFirstError());
            }
        }
        catch(\Exception $e)
        {
            $this->payLog($e->getMessage());exit;
        }
    }


    //初始化视图
    public function initForm($pay_method)
    {
        $view = $pay_method;
        $this->setView($view);
        $this->setData(array("return_url"=>$this->return_url));
        $this->getFormHtml();
    }


    //微信支付签名
    public function getSign($data = [], $url, $randstr, $time)
    {
        $str = "POST" . "\n" . $url . "\n" . $time . "\n" . $randstr . "\n" . $data . "\n";
        $key = file_get_contents($this->payconfig['weixin_apiclient_key']);//在商户平台下载的秘钥
        $str = $this->getSha256WithRSA($str, $key);
        return $str;
    }

    //调起支付的签名
    public function getWechartSign($appid, $timeStamp, $noncestr, $prepay_id)
    {
        $str = $appid . "\n" . $timeStamp . "\n" . $noncestr . "\n" . $prepay_id . "\n";
        $key = file_get_contents($this->payconfig['weixin_apiclient_key']);
        $str = $this->getSha256WithRSA($str, $key);
        return $str;
    }

    public function getSha256WithRSA($content, $privateKey)
    {
        $binary_signature = "";
        $algo = "SHA256";
        openssl_sign($content, $binary_signature, $privateKey, $algo);
        $sign = base64_encode($binary_signature);
        return $sign;
    }

    function curl_post_https($url,$data,$header){ // 模拟提交数据函数
        $curl = curl_init(); // 启动一个CURL会话
        curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0); // 从证书中检查SSL加密算法是否存在,如果出错则修改为0,默认为1
        curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
        curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
        curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data); // Post提交的数据包
        curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
        curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回

        curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
        $tmpInfo = curl_exec($curl); // 执行操作
        if (curl_errno($curl)) {
            echo 'Errno'.curl_error($curl);//捕抓异常
        }
        curl_close($curl); // 关闭CURL会话
        return $tmpInfo; // 返回数据,json格式
    }
}